source: trunk/src/sh_utils.c@ 16

Last change on this file since 16 was 13, checked in by rainer, 19 years ago

minor optimization

File size: 38.2 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <ctype.h>
27#include <unistd.h>
28
29#if TIME_WITH_SYS_TIME
30#include <sys/time.h>
31#include <time.h>
32#else
33#if HAVE_SYS_TIME_H
34#include <sys/time.h>
35#else
36#include <time.h>
37#endif
38#endif
39
40
41#include "samhain.h"
42#include "sh_error.h"
43#include "sh_utils.h"
44#include "sh_unix.h"
45#include "sh_tiger.h"
46#include "sh_entropy.h"
47
48#undef FIL__
49#define FIL__ _("sh_utils.c")
50
51UINT32 ErrFlag[2];
52
53int sh_util_flagval(char * c, int * fval)
54{
55 SL_ENTER(_("sh_util_flagval"));
56 if (c == NULL)
57 SL_RETURN( (-1), _("sh_util_flagval"));
58 if ( c[0] == '1' || c[0] == 'y' || c[0] == 'Y' ||
59 c[0] == 't' || c[0] == 'T')
60 {
61 *fval = S_TRUE;
62 SL_RETURN( (0), _("sh_util_flagval"));
63 }
64 if ( c[0] == '0' || c[0] == 'n' || c[0] == 'N' ||
65 c[0] == 'f' || c[0] == 'F')
66 {
67 *fval = S_FALSE;
68 SL_RETURN( (0), _("sh_util_flagval"));
69 }
70 SL_RETURN( (-1), _("sh_util_flagval"));
71}
72
73int sh_util_timeout_check (SH_TIMEOUT * sh_timer)
74{
75 UINT64 now = (UINT64) time(NULL);
76 UINT64 dif;
77
78 if (sh_timer->flag_ok == S_FALSE)
79 {
80 /* first time
81 */
82 if (sh_timer->time_last == 0)
83 {
84 sh_timer->time_last = now;
85 return S_TRUE;
86 }
87 /* later on
88 */
89 dif = now - sh_timer->time_last;
90 if (dif < sh_timer->time_dist)
91 {
92 return S_FALSE;
93 }
94 sh_timer->time_last = now;
95 return S_TRUE;
96 }
97 sh_timer->time_last = now;
98 return S_FALSE;
99}
100
101static int sh_ask_update = S_FALSE;
102
103int sh_util_set_interactive(char * str)
104{
105 if (str == NULL)
106 sh_ask_update = S_TRUE;
107 else
108 sh_ask_update = S_TRUE;
109
110 sh_unix_setnodeamon(NULL);
111
112 return 0;
113}
114
115#if !defined(STDIN_FILENO)
116#define STDIN_FILENO 0
117#endif
118#if !defined(STDERR_FILENO)
119#define STDERR_FILENO 0
120#endif
121
122int sh_util_ask_update(char * path)
123{
124 int inchar, c;
125 int i = S_TRUE;
126 char * tmp = NULL;
127
128 SL_ENTER(_("sh_util_ask_update"));
129
130 if (sh_ask_update != S_TRUE)
131 {
132 SL_RETURN(i, _("sh_util_ask_update"));
133 }
134
135#ifdef HAVE_TTYNAME
136 if (!ttyname(STDIN_FILENO))
137 {
138 if (NULL != ttyname(STDERR_FILENO))
139 {
140 if (NULL == freopen(ttyname(STDERR_FILENO), "r", stdin))
141 {
142 sh_error_handle ((-1), FIL__, __LINE__, 0,
143 MSG_E_SUBGEN,
144 _("Cannot continue: stdin is not a terminal"),
145 _("sh_util_ask_update"));
146 exit(EXIT_FAILURE);
147 }
148 }
149 else
150 {
151 sh_error_handle ((-1), FIL__, __LINE__, 0,
152 MSG_E_SUBGEN,
153 _("Cannot continue: stdin is not a terminal"),
154 _("sh_util_ask_update"));
155 exit(EXIT_FAILURE);
156 }
157 }
158#endif
159
160 if (sh_ask_update == S_TRUE)
161 {
162 tmp = sh_util_safe_name (path);
163 fprintf (stderr, _("Update %s [Y/n] ? "), tmp);
164 SH_FREE(tmp);
165 while (1 == 1)
166 {
167 c = fgetc(stdin); inchar = c;
168 /*@+charintliteral@*/
169 while (c != '\n' && c != EOF)
170 c = fgetc(stdin);
171 /* fprintf(stderr, "CHAR (1): %c\n", inchar); */
172 if (inchar == 'Y' || inchar == 'y' || inchar == '\n')
173 {
174 break;
175 }
176 else if (inchar == 'n' || inchar == 'N')
177 {
178 i = S_FALSE;
179 break;
180 }
181 else
182 {
183 fprintf(stderr, _("Please answer y(es) or n(o)\n"));
184 }
185 /*@-charintliteral@*/
186 }
187 }
188
189 SL_RETURN(i, _("sh_util_ask_update"));
190}
191
192int sh_util_hidesetup(char * c)
193{
194 int i;
195 SL_ENTER(_("sh_util_hidesetup"));
196 i = sh_util_flagval(c, &(sh.flag.hidefile));
197
198 SL_RETURN(i, _("sh_util_hidesetup"));
199}
200
201char * sh_util_strdup (const char * str)
202{
203 char * p = NULL;
204 size_t len;
205
206 SL_ENTER(_("sh_util_strdup"));
207
208 if (str != NULL)
209 {
210 len = sl_strlen(str);
211 p = SH_ALLOC (len + 1);
212 (void) sl_strlcpy (p, str, len+1);
213 }
214 SL_RETURN( p, _("sh_util_strdup"));
215}
216
217/* by the eircom.net computer incident
218 * response team
219 */
220char * sh_util_strsep (char **str, const char *delim)
221{
222 char *ret, *c, *d;
223
224 SL_ENTER(_("sh_util_strsep"));
225 ret = *str;
226
227 if (ret == NULL) {
228 SL_RETURN(ret, _("sh_util_strsep"));
229 }
230
231 for (c = *str; *c != '\0'; c++) {
232 for (d = (char *) delim; *d != '\0'; d++) {
233 if (*c == *d) {
234 *c = '\0';
235 *str = c + 1;
236 SL_RETURN(ret, _("sh_util_strsep"));
237 }
238 }
239 }
240
241 /* If we get to here, there's no delimiters in the string */
242 *str = NULL;
243 SL_RETURN(ret, _("sh_util_strsep"));
244}
245
246
[13]247/* returned string must be free'd by caller.
[1]248 */
249char * sh_util_formatted (const char * formatt, st_format * ftab)
250{
251 struct tm * time_ptr;
252 size_t size;
253 size_t isiz;
254 char * fmt = NULL;
255 char * p;
256 char * q;
257 char * outstr;
258 int i;
259 int j;
260 time_t inpp;
261
[13]262 char * clist[16] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
263 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
[1]264 int nn = 0;
265
266 SL_ENTER(_("sh_util_formatted"));
267
[13]268 if (formatt == NULL || ftab == NULL || *formatt == '\0')
[1]269 SL_RETURN(NULL, _("sh_util_formatted"));
270
271 /* -- save the format (we overwrite it !!) --
272 */
273 size = sl_strlen(formatt);
274
[13]275 fmt = (char *) SH_ALLOC(size + 1);
276 (void) sl_strlcpy(fmt, formatt, size + 1);
277
[1]278 p = fmt;
279
280 j = 0;
[13]281 while (ftab[j].fchar != '\0') {
282 if (ftab[j].type != S_FMT_STRING)
283 ftab[j].data_str = NULL;
284 ++j;
285 }
286
[1]287 while (p != NULL && *p != '\0' && NULL != (q = strchr(p, '%')))
288 {
289 ++q;
290
291 /* fprintf(stderr, "p == %s q == %s\n", p, q); */
292
293 /* -- end of string is a '%' --
294 */
295 if (*q == '\0')
296 {
297 --q;
298 *q = '\0';
299 break;
300 }
301
302 i = 0;
303 j = 0;
304
305 /* -- search the format char in input table --
306 * put (nn < 16) here -> all remaining %foo will be
307 * converted to %%
308 */
309 while (ftab[j].fchar != '\0' && nn < 16)
310 {
311 if (ftab[j].fchar == *q)
312 {
313 /* -- Convert it to a string format (%s). --
314 */
315 *q = 's'
316;
317 i = 1;
318
[13]319 switch(ftab[j].type) {
320
321 case S_FMT_STRING:
[1]322 {
323 isiz = sl_strlen(ftab[j].data_str);
324 if (isiz > 0)
325 {
326 size += isiz;
327 clist[nn] = ftab[j].data_str;
328 ++nn;
329 }
330 else
331 *q = '%';
[13]332 goto endsrch;
[1]333 }
[13]334 break;
335
336 case S_FMT_ULONG:
[1]337 {
338 ftab[j].data_str = (char *) SH_ALLOC(64);
339 /*@-bufferoverflowhigh@*/
340 sprintf (ftab[j].data_str, "%lu", /* known to fit */
341 ftab[j].data_ulong);
342 /*@+bufferoverflowhigh@*/
343 isiz = sl_strlen(ftab[j].data_str);
344 if (isiz > 0)
345 {
346 size += isiz;
347 clist[nn] = ftab[j].data_str;
348 ++nn;
349 }
350 else
351 *q = '%';
[13]352 goto endsrch;
[1]353 }
[13]354 break;
355
356 case S_FMT_LONG:
[1]357 {
358 ftab[j].data_str = (char *) SH_ALLOC(64);
359 /*@-bufferoverflowhigh@*/
360 sprintf (ftab[j].data_str, "%ld", /* known to fit */
361 ftab[j].data_long);
362 /*@+bufferoverflowhigh@*/
363 isiz = sl_strlen(ftab[j].data_str);
364 if (isiz > 0)
365 {
366 size += isiz;
367 clist[nn] = ftab[j].data_str;
368 ++nn;
369 }
370 else
371 *q = '%';
[13]372 goto endsrch;
[1]373 }
[13]374 break;
375
376 case S_FMT_TIME:
[1]377 {
378 ftab[j].data_str = (char *) SH_ALLOC(64);
379 inpp = (time_t)ftab[j].data_ulong;
380 if (inpp != 0)
381 {
382 time_ptr = localtime (&(inpp));
383 if (time_ptr != NULL)
384 (void) strftime(ftab[j].data_str, 64,
385 _("%d-%m-%Y %H:%M:%S"), time_ptr);
386 else
387 (void) sl_strlcpy(ftab[j].data_str,
388 _("00-00-0000 00:00:00"), 64);
389 }
390 else
391 {
392 (void) sl_strlcpy(ftab[j].data_str,
393 _("(None)"), 64);
394 }
395 isiz = sl_strlen(ftab[j].data_str);
396 if (isiz > 0)
397 {
398 size += isiz;
399 clist[nn] = ftab[j].data_str;
400 ++nn;
401 }
402 else
403 *q = '%';
[13]404 goto endsrch;
[1]405 }
[13]406 break;
[1]407
[13]408 default:
409 /* do nothing */;
410 }
411
[1]412 }
[13]413 ++j;
[1]414 }
415
[13]416 endsrch:
417
418 p = q;
419
[1]420 /* -- not found -- */
421 if (i == 0)
422 {
423 *q = '%';
424 ++p;
425 }
[13]426
[1]427 }
428
429 /* -- Format string evaluated.
430 clist[] List of strings
431 size Total size of format string + clist[] strings
432 -- */
433
434 /* -- closing '\0' --
435 */
436 size++;
437 outstr = (char *) SH_ALLOC(size);
438
439 /* -- print it --
440 */
441 (void) sl_snprintf( outstr, size, fmt,
442 clist[0], clist[1], clist[2], clist[3],
443 clist[4], clist[5], clist[6], clist[7],
444 clist[8], clist[9], clist[10], clist[11],
445 clist[12], clist[13], clist[14], clist[15]);
446
447 /* -- cleanup --
448 */
449 j = 0;
[13]450 while (ftab[j].fchar != '\0') {
451 if (ftab[j].type != S_FMT_STRING && ftab[j].data_str != NULL)
452 SH_FREE(ftab[j].data_str);
453 ++j;
454 }
[1]455 SH_FREE(fmt);
456
457 SL_RETURN(outstr, _("sh_util_formatted"));
458}
459
460/* can't inline (AIX)
461 */
[12]462int sh_util_hexchar( const char c )
[1]463{
464 /*@+charint@*/
465 if ( c >= '0' && c <= '9' )
466 return c - '0';
467 else if ( c >= 'a' && c <= 'f' )
468 return c - 'a' + 10;
469 else if ( c >= 'A' && c <= 'F' )
470 return c - 'A' + 10;
471 else return -1;
472 /*@-charint@*/
473}
474
475/* read a hexadecimal key, convert to binary
476 */
[12]477int sh_util_hextobinary (char * binary, const char * hex, int bytes)
[1]478{
479 int i = 0, j, k, l = 0;
[13]480 char c;
[1]481
[13]482#define SH_HEXCHAR(x, y) \
483 c = (x); \
484 if ( c >= '0' && c <= '9' ) \
485 y = c - '0'; \
486 else if ( c >= 'a' && c <= 'f' ) \
487 y = c - 'a' + 10; \
488 else if ( c >= 'A' && c <= 'F' ) \
489 y = c - 'A' + 10; \
490 else \
491 SL_RETURN((-1), _("sh_util_hextobinary"))
492
493
[1]494 SL_ENTER(_("sh_util_hextobinary"));
495
496 while (i < bytes)
497 {
[13]498 SH_HEXCHAR(hex[i], k);
499 SH_HEXCHAR(hex[i+1], j);
500
501 binary[l] = (char)(k * 16 + j);
502 ++l; i+= 2;
503
504 /* k = sh_util_hexchar(hex[i]); j = sh_util_hexchar(hex[i+1]);
[1]505 if (k != -1 && j != -1)
506 {
507 binary[l] = (char)(k * 16 + j);
508 ++l; i+= 2;
509 }
510 else
511 {
512 SL_RETURN((-1), _("sh_util_hextobinary"));
513 }
[13]514 */
[1]515 }
516
517 SL_RETURN((0), _("sh_util_hextobinary"));
518}
519
520static void copy_four (unsigned char * dest, UINT32 in)
521{
522 UINT32 i, j;
523 int count;
524
525 SL_ENTER(_("copy_four"));
526 for (count = 0; count < 4; ++count)
527 {
528 i = in / 256;
529 j = in - (i*256);
530 dest[count] = (unsigned char) j;
531 in = i;
532 }
533 SL_RET0(_("copy_four"));
534}
535
536/* compute HMAC-TIGER
537 */
538static char * sh_util_hmac_tiger (char * hexkey,
539 char * text, size_t textlen)
540{
541 static char opad[KEY_BLOCK] = {
542 (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C,
543 (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C,
544 (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C,
545 (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C
546 };
547 static char ipad[KEY_BLOCK] = {
548 (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36,
549 (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36,
550 (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36,
551 (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36
552 };
[11]553 static char zap[KEY_BLOCK] = {
554 (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00,
555 (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00,
556 (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00,
557 (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00
558 };
[1]559 char K[KEY_BLOCK];
560 char outer[KEY_BLOCK];
561 char * inner;
562 UINT32 * h1;
563 UINT32 * h2;
564 UINT32 cc[KEY_LEN/4];
565 char * res;
566
567 size_t i;
568
569 SL_ENTER(_("sh_util_hmac_tiger"));
570 ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)"))
571
572 if (KEY_BLOCK > (KEY_LEN/2))
573 {
574 res = sh_tiger_hash (NULL, TIGER_DATA, 0);
575 SL_RETURN(res, _("sh_util_hmac_tiger"));
576 }
577
[11]578 memcpy (K, zap, KEY_BLOCK);
[1]579
580 if (sh_util_hextobinary (K, hexkey, KEY_LEN) < 0)
581 {
582 res = sh_tiger_hash (NULL, TIGER_DATA, 0);
583 SL_RETURN(res, _("sh_util_hmac_tiger"));
584 }
585
586 inner = (char *) SH_ALLOC (textlen + KEY_BLOCK);
587
588 for (i = 0; i < KEY_BLOCK; ++i)
589 {
590 outer[i] = K[i] ^ opad[i];
591 inner[i] = K[i] ^ ipad[i];
592 }
593 for (i = KEY_BLOCK; i < (KEY_BLOCK+textlen); ++i)
594 {
595 inner[i] = text[i - KEY_BLOCK];
596 }
597
598 /* now compute the hash
599 */
600 h1 = sh_tiger_hash_uint32 ( outer,
601 TIGER_DATA,
602 KEY_BLOCK);
603 for (i = 0; i < (KEY_LEN/8); ++i)
604 {
605 /* cc[i] = h1[i]; */
606 copy_four ( (unsigned char *) &(cc[i]), h1[i]);
607 }
608
609 h2 = sh_tiger_hash_uint32 ( inner,
610 TIGER_DATA,
611 (unsigned long) KEY_BLOCK+textlen);
612 for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
613 {
614 copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
615 /* cc[i] = h2[i - (KEY_LEN/8)]; */
616 }
617 SH_FREE(inner);
618
619 res = sh_tiger_hash ((char *) &cc[0],
620 TIGER_DATA,
621 (unsigned long) (KEY_LEN/4 * sizeof(UINT32)));
622
623 SL_RETURN(res, _("sh_util_hmac_tiger"));
624}
625
626static char * sh_util_hash_tiger ( char * hexkey,
627 char * text, size_t textlen)
628{
629 char * res;
630 char h2[2*KEY_LEN+1];
631 SL_ENTER(_("sh_util_hash_tiger"));
632
633 (void) sl_strlcpy(h2, hexkey, KEY_LEN+1);
634 (void) sl_strlcat(h2, sh_tiger_hash(text, TIGER_DATA,
635 (unsigned long) textlen), 2*KEY_LEN+1);
636
637 res = sh_tiger_hash(h2, TIGER_DATA, 2*KEY_LEN);
638
639 SL_RETURN(res, _("sh_util_hash_tiger"));
640}
641
642/* --- compute signature on data ---
643 */
644#define TYPE_HMAC 0
645#define TYPE_HASH 1
646
647static int sigtype = TYPE_HMAC;
648
649int sh_util_sigtype (char * c)
650{
651 SL_ENTER(_("sh_util_sigtype"));
652 if (c == NULL)
653 SL_RETURN( -1, _("sh_util_sigtype"));
654
655 if (0 == strcmp(_("HMAC-TIGER"), c))
656 sigtype = TYPE_HMAC;
657 else if (0 == strcmp(_("HASH-TIGER"), c))
658 sigtype = TYPE_HASH;
659 else
660 SL_RETURN( -1, _("sh_util_sigtype"));
661
662 SL_RETURN( 0, _("sh_util_sigtype"));
663}
664
665char * sh_util_siggen (char * hexkey,
666 char * text, size_t textlen)
667{
668 char * p;
669
670 SL_ENTER(_("sh_util_siggen"));
671 if (sigtype == TYPE_HMAC)
672 p = sh_util_hmac_tiger (hexkey,
673 text, textlen);
674 else
675 p = sh_util_hash_tiger (hexkey,
676 text, textlen);
677 SL_RETURN(p, _("sh_util_siggen"));
678}
679
680
681/* a simple compressor
682 */
683long sh_util_compress (char * dest, char * src, size_t dest_size)
684{
685 char * add;
686 char * get;
687 size_t count = 0;
688 size_t dest_end;
689
690 SL_ENTER(_("sh_util_compress"));
691
692 if (dest_size == 0)
693 SL_RETURN((0), _("sh_util_compress"));
694
695 if ((dest == NULL) || (src == NULL))
696 SL_RETURN((0), _("sh_util_compress"));
697
698 dest_end = sl_strlen(dest);
699
700 if (dest_end > dest_size)
701 SL_RETURN((0), _("sh_util_compress"));
702
703 add = &dest[dest_end];
704 get = src;
705
706 while (count < (dest_size-dest_end))
707 {
708 if (isalnum((int) *get))
709 {
710 *add = *get;
711 ++add;
712 ++count;
713 }
714 ++get;
715 if (*get == '\0' && (count < (dest_size-dest_end)))
716 /* end of src reached */
717 {
718 *add = *get; /* copy the '\0' */
719 break; /* and stop copying */
720 }
721 }
722
723 dest[dest_size-1] = '\0'; /* paranoia */
724 SL_RETURN(((long)count), _("sh_util_compress")); /* no of chars copied */
725}
726
727
728/* copy the four least significant bytes
729 */
730void sh_util_cpylong (char * dest, const char * src, int len )
731{
732 int i, j;
733 union
734 {
735 long l;
736 char c[sizeof(long)];
737 } u;
738
739 SL_ENTER(_("sh_util_cpylong"));
740
741 u.l = 1;
742
743 /* MSB is first
744 */
745 if (sizeof(long)>4 &&/*@+charint@*/(u.c[sizeof(long)-1] == 1)/*@-charint@*/)
746 {
747 j = (int) (sizeof(long)-4);
748 for (i = 0; i < j; ++i) ++src;
749 }
750
751 i = 0;
752
753 while (i < 4)
754 {
755 *dest = (*src);
756 ++dest; ++src;
757 if (i == (len-1)) break;
758 ++i;
759 }
760 SL_RET0(_("sh_util_cpylong"));
761}
762
763/* This is a maximally equidistributed combined Tausworthe
764 * generator. The sequence is,
765 *
766 * x_n = (s1_n ^ s2_n ^ s3_n)
767 *
768 * s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
769 * s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
770 * s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
771 *
772 * computed modulo 2^32. In the three formulas above '^' means
773 * exclusive-or (C-notation), not exponentiation. Note that the
774 * algorithm relies on the properties of 32-bit unsigned integers (it
775 * is formally defined on bit-vectors of length 32).
776 *
777 * Stolen from GSL (GNU scientific library) and modified somewhat.
778 * I am using UINT32, which is guaranteed to be 32 bits. Also made
779 * sure that the initialization vector is valid.
780 */
781
782
783/* interval [0, 4294967296]
784 */
785static UINT32 taus_get_long (void *vstate)
786{
787 UINT32 * state = (UINT32 *) vstate;
788
789 if (skey->rngI == BAD)
790 (void)taus_seed();
791
792#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
793 /*@+ignorequals@*/
794 state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
795 state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4);
796 state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17);
797 /*@-ignorequals@*/
798 return (state[0] ^ state[1] ^ state[2]);
799}
800
801/* Hide the internal state of the PRNG by using its output as
802 * input for a one-way hash function.
803 */
[11]804UINT32 taus_svec[6];
805
[1]806UINT32 taus_get (void *state1, void *state2, void *state3)
807{
808 UINT32 retval;
809 UINT32 * res;
[13]810 static UINT32 res_vec[6];
811 static int res_num = 0;
[1]812 register int i;
813
[13]814 if (res_num > 0)
815 {
816 retval = res_vec[res_num];
817 res_num = (res_num == 5) ? 0 : (res_num + 1);
818 return retval;
819 }
820
[11]821 taus_svec[0] = taus_get_long (state1);
822 taus_svec[1] = taus_get_long (state2);
823 taus_svec[2] = taus_get_long (state3);
824 taus_svec[3] = taus_get_long (state1);
825 taus_svec[4] = taus_get_long (state2);
826 taus_svec[5] = taus_get_long (state3);
[1]827
[11]828 res = sh_tiger_hash_uint32 ( (char *) &taus_svec[0],
[1]829 TIGER_DATA,
830 (unsigned long)(6 * sizeof(UINT32)));
831
[13]832 for (i = 1; i < 6; ++i)
[11]833 {
[13]834 res_vec[i] = res[i];
[11]835 }
[13]836 retval = taus_svec[0];
837 res_num = 1;
[1]838
[11]839 taus_svec[0] = 0; taus_svec[1] = 0; taus_svec[2] = 0;
840 taus_svec[3] = 0; taus_svec[4] = 0; taus_svec[5] = 0;
[1]841
842 return retval;
843}
844
845/* interval [0,1)
846 */
847double taus_get_double (void *vstate)
848{
849 return taus_get_long (vstate) / (4294967296.0 + 1.0) ;
850}
851
852#define LCG(n) ((69069 * n) & 0xffffffffUL)
853
854/* TAKE CARE: state[0], state[1], state[2] must be > 2,8,16, respectively
855 */
856static void taus_set_from_ulong (void *vstate, unsigned long int s)
857{
858 UINT32 *state = (UINT32 *) vstate;
859
860 if (s == 0)
861 s = 1; /* default seed is 1 */
862
863 state[0] = (UINT32)(LCG (s) | (UINT32) 0x03);
864 state[1] = (UINT32)(LCG (state[0]) | (UINT32) 0x09);
865 state[2] = (UINT32)(LCG (state[1]) | (UINT32) 0x17);
866
867 /* 'warm up'
868 */
869 (void) taus_get_long (state);
870 (void) taus_get_long (state);
871 (void) taus_get_long (state);
872 (void) taus_get_long (state);
873 (void) taus_get_long (state);
874 (void) taus_get_long (state);
875
876 return;
877}
878
879static void taus_set_from_state (void *vstate, void *init_state)
880{
881 UINT32 *state = (UINT32 *) vstate;
882 UINT32 *state0 = (UINT32 *) init_state;
883
884 state[0] = state0[0] | (UINT32) 0x03;
885 state[1] = state0[1] | (UINT32) 0x09;
886 state[2] = state0[2] | (UINT32) 0x17;
887
888 return;
889}
890
891
892int taus_seed ()
893{
894 char bufx[9 * sizeof(UINT32) + 1];
895 int status;
896 static unsigned long seed_time = 0;
897
898 SL_ENTER(_("taus_seed"));
899
900 if (skey->rngI == GOOD)
901 {
902 if ( (sh_unix_longtime () - seed_time) < 3600)
903 SL_RETURN( (0), _("taus_seed"));
904 }
905
906 seed_time = sh_unix_longtime ();
907
908 status = sh_entropy (24, bufx);
909
910 if (!SL_ISERROR(status))
911 {
912 skey->rngI = GOOD;
913 memcpy (&skey->rng0[0], &bufx[0], 2*sizeof(UINT32));
914 memcpy (&skey->rng1[0], &bufx[2*sizeof(UINT32)], 2*sizeof(UINT32));
915 memcpy (&skey->rng2[0], &bufx[4*sizeof(UINT32)], 2*sizeof(UINT32));
916 memset (bufx, 0, 9 * sizeof(UINT32) + 1);
917
918 skey->rng0[2] = 0;
919 skey->rng1[2] = 0;
920 skey->rng2[2] = 0;
921
922 taus_set_from_state( &(skey->rng0[0]), &(skey->rng0[0]));
923 taus_set_from_state( &(skey->rng1[0]), &(skey->rng1[0]));
924 taus_set_from_state( &(skey->rng2[0]), &(skey->rng2[0]));
925
926 SL_RETURN( (0), _("taus_seed"));
927 }
928
929 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_ES_ENT,
930 _("sh_entropy"));
931
932 /* emergency backup - unsafe !
933 */
934 skey->rngI = GOOD;
935#ifdef HAVE_GETTIMEOFDAY
936 taus_set_from_ulong ( &(skey->rng0[0]), LCG (sh_unix_notime()) );
937#else
938 taus_set_from_ulong ( &(skey->rng0[0]), LCG (seed_time) );
939#endif
940 taus_set_from_ulong ( &(skey->rng1[0]), LCG (skey->rng0[0]) );
941 taus_set_from_ulong ( &(skey->rng2[0]), LCG (skey->rng1[0]) );
942 skey->rngI = BAD;
943
944 SL_RETURN( (-1), _("taus_seed"));
945}
946
947/*@+charint@*/
948static unsigned char new_key[] = { 0xA7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xA7 };
949/*@-charint@*/
950static void copy_four (unsigned char * dest, UINT32 in);
951
952int sh_util_set_newkey (char * new)
953{
954 size_t i, j = 0;
955 size_t len;
956 SL_TICKET fp;
957 SL_TICKET fout;
958 char * key;
959 char * path;
960 char * outpath;
961 unsigned char * image = NULL;
962 long s = 0;
963 long ilen = 0;
964 long ii, k = 0;
965 UINT32 * h1;
966
967 if (0 != sl_is_suid())
968 {
969 fprintf(stderr, _("ERROR: insufficient privilege\n"));
970 _exit (EXIT_FAILURE);
971 /*@notreached@*/
972 return -1; /* braindead MAC OSX compiler needs this */
973 }
974
975 if (new == NULL || new[0] == '\0')
976 {
977 fprintf(stderr,
978 _("ERROR: no key given\n Argument must be 'key@path'\n"));
979 _exit (EXIT_FAILURE);
980 /*@notreached@*/
981 return -1;
982 }
983 key = new;
984 len = strlen(new);
985 for (i = 1; i < (len-2); ++i)
986 {
987 if (new[i] == '@' && new[i+1] == '/')
988 {
989 j = i+1; new[i] = '\0'; break;
990 }
991 }
992 if (j == 0)
993 {
994 fprintf(stderr,
995 _("ERROR: no path to executable given\n Argument must be 'key@path'\n"));
996 _exit (EXIT_FAILURE);
997 /*@notreached@*/
998 return -1;
999 }
1000 else
1001 path = &new[j];
1002 /*@-usedef@*/
1003 if (NULL == (outpath = malloc(strlen(path) + 1 + 4)))
1004 goto bail_mem;
1005 /*@-usedef@*/
1006 /*@-bufferoverflowhigh@*/
1007 sprintf (outpath, _("%s.out"), path); /* known to fit */
1008 /*@+bufferoverflowhigh@*/
1009
1010 fp = sl_open_read(path, SL_NOPRIV);
1011 if (SL_ISERROR(fp))
1012 {
1013 fprintf(stderr,
1014 _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp);
1015 _exit (EXIT_FAILURE);
1016 /*@notreached@*/
1017 return -1;
1018 }
1019
1020 fout = sl_open_write(outpath, SL_NOPRIV);
1021 if (SL_ISERROR(fout))
1022 {
1023 fprintf(stderr,
1024 _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout);
1025 _exit (EXIT_FAILURE);
1026 /*@notreached@*/
1027 return -1;
1028 }
1029
1030
1031 image = malloc (4096);
1032 if (!image)
1033 goto bail_mem;
1034 while (0 < (ii = sl_read (fp, &image[s], 4096)))
1035 {
1036 ilen += ii;
1037 s += 4096;
1038 image = realloc (image, (size_t) (4096 + s));
1039 if (!image)
1040 goto bail_mem;
1041 }
1042
1043 printf(_("%ld bytes read\n"), ilen);
1044
1045
1046 for (k = 0; k < (ilen - 8); ++k)
1047 {
1048 if (image[k] == new_key[0] &&
1049 image[k+1] == new_key[1] &&
1050 image[k+2] == new_key[2] &&
1051 image[k+3] == new_key[3] &&
1052 image[k+4] == new_key[4] &&
1053 image[k+5] == new_key[5] &&
1054 image[k+6] == new_key[6] &&
1055 image[k+7] == new_key[7])
1056 {
1057 printf(_("old key found\n"));
1058 h1 = sh_tiger_hash_uint32 (key, TIGER_DATA,
1059 (unsigned long)strlen(key));
1060 copy_four( (unsigned char *) &(image[k]), h1[0]);
1061 copy_four( (unsigned char *) &(image[k+4]), h1[1]);
1062 (void) sl_write (fout, image, ilen);
1063 (void) sl_close (fout);
1064 printf(_("new file %s written\n"), outpath);
1065 _exit (EXIT_SUCCESS);
1066 /*@notreached@*/
1067 return 0;
1068 }
1069 }
1070
1071 fprintf(stderr,
1072 _("ERROR: old key not found\n"));
1073 _exit (EXIT_FAILURE);
1074 /*@notreached@*/
1075 return -1;
1076
1077
1078 bail_mem:
1079 fprintf(stderr,
1080 _("ERROR: out of memory\n"));
1081 _exit (EXIT_FAILURE);
1082 /*@notreached@*/
1083 return -1;
1084}
1085
1086
1087
1088
1089/* A simple en-/decoder, based on Vernam cipher. We use the
1090 * message as salt to hide the key by obtaining a different one-time
1091 * pad each time.
1092 * Should be safe against a listener on the network, but not against someone
1093 * with read access to the binary.
1094 */
1095void sh_util_encode (char * data, char * salt, int mode, char fill)
1096{
1097 static char cc1[17] = N_("0123456789ABCDEF");
1098 char cc[17] = "\0";
1099 register int i, j, j1 = 0, j2 = 0, j3;
1100 char * dez;
1101
1102 SL_ENTER(_("sh_util_encode"));
1103
1104 /* init
1105 */
1106 (void) sl_strlcpy( cc, _(cc1), sizeof(cc));
1107
1108 /* max 128 bits keyspace
1109 */
1110 memset (skey->vernam, (int)fill, KEY_LEN+1);
1111
1112 dez = (char *) &(skey->ErrFlag[0]);
1113 sh_util_cpylong (skey->vernam, dez, 4);
1114 dez = (char *) &(skey->ErrFlag[1]);
1115 sh_util_cpylong (&skey->vernam[4], dez, 4);
1116
1117 skey->vernam[KEY_LEN] = '\0';
1118
1119 (void) sl_strlcpy(skey->vernam,
1120 sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN),
1121 KEY_LEN+1);
1122
1123 (void) sl_strlcpy(skey->vernam,
1124 sh_util_hmac_tiger (skey->vernam, salt, strlen(salt)),
1125 KEY_LEN+1);
1126
1127 (void) sl_strlcpy(skey->vernam,
1128 sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8),
1129 KEY_LEN+1);
1130
1131 /* The following routine adds/subtracts data[j] and vernam[j] mod 16.
1132 */
1133 j = 0;
1134 while (j < KEY_LEN)
1135 {
1136 for (i = 0; i < 16; ++i)
1137 {
1138 if (cc[i] == data[j]) j1 = i;
1139 if (cc[i] == skey->vernam[j]) j2 = i;
1140 }
1141 if (mode == 0)
1142 {
1143 j3 = j1 + j2;
1144 if (j3 > 15) j3 -= 16;
1145 data[j] = cc[j3];
1146 }
1147 else
1148 {
1149 j3 = j1 - j2;
1150 if (j3 < 0) j3 += 16;
1151 data[j] = cc[j3];
1152 }
1153 ++j;
1154 }
1155 SL_RET0(_("sh_util_encode"));
1156}
1157
1158/* server mode
1159 */
1160int sh_util_setserver (char * dummy)
1161{
1162 SL_ENTER(_("sh_util_setserver"));
1163
1164 if (dummy)
1165 sh.flag.isserver = GOOD;
1166 else
1167 sh.flag.isserver = GOOD;
1168 SL_RETURN((0),_("sh_util_setserver"));
1169}
1170
1171
1172int sh_util_setlooptime (char * str)
1173{
1174 int i = atoi (str);
1175
1176 SL_ENTER(_("sh_util_setlooptime"));
1177
1178 if (i >= 0 && i < INT_MAX) {
1179 sh.looptime = i;
1180 SL_RETURN((0),_("sh_util_setlooptime"));
1181 } else {
1182 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1183 _("loop time"), str);
1184 SL_RETURN((-1),_("sh_util_setlooptime"));
1185 }
1186}
1187
1188#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1189int sh_util_setchecksum (char * str)
1190{
1191 static int reject = 0;
1192
1193 SL_ENTER(_("sh_util_setchecksum"));
1194
1195 if (reject == 1)
1196 SL_RETURN((0), _("sh_util_setchecksum"));
1197 reject = 1;
1198
1199 if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0)
1200 {
1201 sh.flag.checkSum = SH_CHECK_INIT;
1202 }
1203 else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1204 {
1205 if (S_TRUE == file_is_remote())
1206 {
1207 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1208 _("checksum testing"), str);
1209 SL_RETURN((-1), _("sh_util_setchecksum"));
1210 }
1211 else
1212 {
1213 sh.flag.checkSum = SH_CHECK_CHECK;
1214 sh.flag.update = S_TRUE;
1215 }
1216 }
1217 else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0)
1218 {
1219 sh.flag.checkSum = SH_CHECK_CHECK;
1220 }
1221 /*
1222 else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1223 {
1224 sh.flag.checkSum = SH_CHECK_INIT;
1225 sh.flag.update = S_TRUE;
1226 }
1227 */
1228 else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0)
1229 {
1230 sh.flag.checkSum = SH_CHECK_NONE;
1231 }
1232 else
1233 {
1234 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1235 _("checksum testing"), str);
1236 SL_RETURN((-1), _("sh_util_setchecksum"));
1237 }
1238 SL_RETURN((0), _("sh_util_setchecksum"));
1239}
1240#endif
1241
1242/*@+charint@*/
1243unsigned char TcpFlag[8][PW_LEN+1] = {
1244#if (POS_TF == 1)
1245 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1246#endif
1247 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1248#if (POS_TF == 2)
1249 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1250#endif
1251 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1252#if (POS_TF == 3)
1253 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1254#endif
1255 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1256#if (POS_TF == 4)
1257 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1258#endif
1259 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1260#if (POS_TF == 5)
1261 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1262#endif
1263 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1264#if (POS_TF == 6)
1265 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1266#endif
1267 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1268#if (POS_TF == 7)
1269 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1270#endif
1271 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1272#if (POS_TF == 8)
1273 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1274#endif
1275};
1276/*@-charint@*/
1277
1278/* initialize a key to a random value
1279 * rev 0.8
1280 */
1281int sh_util_keyinit (char * buf, long size)
1282{
1283 UINT32 bufy[6];
1284 int i;
1285 int status = 0;
1286 char * p;
1287
1288 SL_ENTER(_("sh_util_keyinit"));
1289
1290 ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1"))
1291
1292 if (size > KEY_LEN+1)
1293 size = KEY_LEN+1;
1294
1295 /* seed / re-seed the PRNG if required
1296 */
1297 status = taus_seed ();
1298
1299 if (status == -1)
1300 sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1,
1301 _("taus_seed"));
1302
1303 for (i = 0; i < 6; ++i)
1304 bufy[i] = taus_get(&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1305
1306 p = sh_tiger_hash ((char *) bufy, TIGER_DATA,
1307 (unsigned long)(6*sizeof(UINT32)));
1308 p[size-1] = '\0';
1309
1310 i = sl_strlcpy(buf, p, (size_t)size);
1311
1312 memset (bufy, 0, 6*sizeof(UINT32));
1313
1314 if ((status == 0) && (!SL_ISERROR(i)) )
1315 SL_RETURN((0),_("sh_util_keyinit"));
1316
1317 if (SL_ISERROR(i))
1318 sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2,
1319 _("sl_strlcpy"));
1320
1321 SL_RETURN((-1),_("sh_util_keyinit"));
1322}
1323
1324#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1325
1326static unsigned char sh_obscure_index[256];
1327
1328int sh_util_obscure_ok (char * str)
1329{
1330 unsigned long i;
1331 char * endptr = str;
1332
1333 SL_ENTER(_("sh_util_obscure_ex"));
1334
1335 if (0 == sl_strncmp("all", str, 3))
1336 {
1337 for (i = 0; i < 255; ++i)
1338 {
1339 sh_obscure_index[i] = (unsigned char)1;
1340 }
1341 SL_RETURN(0, _("sh_util_obscure_ex"));
1342 }
1343
1344 for (i = 0; i < 255; ++i)
1345 {
1346 sh_obscure_index[i] = (unsigned char)0;
1347 }
1348
1349 while (*endptr != '\0')
1350 {
1351 i = strtoul (endptr, &endptr, 0);
1352 if (i > 255)
1353 {
1354 SL_RETURN(-1, _("sh_util_obscure_ex"));
1355 }
1356 sh_obscure_index[i] = (unsigned char)1;
1357 if (*endptr == ',')
1358 ++endptr;
1359 }
1360 SL_RETURN(0, _("sh_util_obscure_ex"));
1361}
1362
1363int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
1364{
1365 char * name = name_orig;
1366 char * safe;
1367 unsigned int i;
1368
1369 SL_ENTER(_("sh_util_obscurename"));
1370
1371 ASSERT_RET((name != NULL), _("name != NULL"), (0))
1372
1373 /* -- Check name. --
1374 */
1375 while (*name != '\0')
1376 {
1377 if ( (*name) == '"' || (*name) == '\t' ||
1378 (*name) == '\b' || (*name) == '\f' ||
1379 (*name) == '\n' || (*name) == '\r' ||
1380 (*name) == '\v' || iscntrl((int) *name) ||
1381 ((*name) != ' ' && !isgraph ((int) *name)) )
1382 {
1383 i = (unsigned char) *name;
1384 if (sh_obscure_index[i] != (unsigned char)1)
1385 {
1386 if (flag == S_TRUE)
1387 {
1388 safe = sh_util_safe_name (name_orig);
1389 sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC,
1390 safe);
1391 SH_FREE(safe);
1392 }
1393 SL_RETURN((-1),_("sh_util_obscurename"));
1394 }
1395 }
1396 name++;
1397 }
1398
1399 SL_RETURN((0),_("sh_util_obscurename"));
1400}
1401#endif
1402
1403/* returns freshly allocated memory, return value should be free'd
1404 */
1405char * sh_util_basename(char * fullpath)
1406{
1407 char * retval;
1408 size_t i;
1409
1410 SL_ENTER(_("sh_util_basename"));
1411
1412 ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1413
1414 i = sl_strlen (fullpath); /* fullpath[i] is terminating '\0' */
1415
1416 while (i > 0) {
1417 --i;
1418 if (fullpath[i] == '/') break;
1419 }
1420
1421 /* -- Not a valid path. --
1422 */
1423 if ((fullpath[i] != '/') && (i == 0) )
1424 SL_RETURN(NULL, _("sh_util_basename"));
1425
1426 retval = SH_ALLOC(i + 1);
1427
1428 (void) sl_strlcpy (retval, fullpath, i+1);
1429
1430 SL_RETURN(retval, _("sh_util_basename"));
1431}
1432
1433/* returns freshly allocated memory, return value should be free'd
1434 */
1435char * sh_util_filename(char * fullpath)
1436{
1437 char * retval;
1438 char * c;
1439 size_t i;
1440
1441 SL_ENTER(_("sh_util_filename"));
1442
1443 ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1444
1445 c = strrchr(fullpath, '/');
1446 i = sl_strlen (c);
1447 if (i <= 1) SL_RETURN(NULL, _("sh_util_filename")); /* ends in '/' */
1448 ++c;
1449 --i;
1450
1451 retval = SH_ALLOC(i + 1);
1452
1453 (void) sl_strlcpy (retval, c, i+1);
1454
1455 SL_RETURN(retval, _("sh_util_filename"));
1456}
1457
1458
1459/* returns freshly allocated memory, return value should be free'd
1460 */
1461char * sh_util_safe_name (const char * name)
1462{
1463 register int i = 0;
1464 const char * p;
1465 char * retval;
1466 char oct[32];
1467 char format[16];
1468
1469 SL_ENTER(_("sh_util_safe_name"));
1470
1471 if (name == NULL)
1472 {
1473 /* return an allocated array
1474 */
1475 retval = SH_ALLOC(7);
1476 (void) sl_strlcpy(retval, _("(null)"), 7);
1477 SL_RETURN(retval, _("sh_util_safe_name"));
1478 }
1479
1480 /*
1481 ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL"))
1482 */
1483
1484#ifdef SH_USE_XML
1485 retval = SH_ALLOC(6 * sl_strlen(name) + 2);
1486#else
1487 retval = SH_ALLOC(4 * sl_strlen(name) + 2);
1488#endif
1489
1490 (void) sl_strncpy(format, _("%c%03o"), 16);
1491
1492 p = name;
1493
1494 while (*p != '\0') {
1495 /* Most frequent cases first
1496 */
1497 if ( ((*p) >= 'a' && (*p) <= 'z') || ((*p) == '/') || ((*p) == '.') ||
1498 ((*p) >= '0' && (*p) <= '9') ||
1499 ((*p) >= 'A' && (*p) <= 'Z')) {
1500 retval[i] = *p;
1501 } else if ( (*p) == '\\') { /* backslash */
1502 retval[i] = '\\'; ++i;
1503 retval[i] = '\\';
1504 } else if ( (*p) == '\n') { /* newline */
1505 retval[i] = '\\'; ++i;
1506 retval[i] = 'n';
1507 } else if ( (*p) == '\b') { /* backspace */
1508 retval[i] = '\\'; ++i;
1509 retval[i] = 'b';
1510 } else if ( (*p) == '\r') { /* carriage return */
1511 retval[i] = '\\'; ++i;
1512 retval[i] = 'r';
1513 } else if ( (*p) == '\t') { /* horizontal tab */
1514 retval[i] = '\\'; ++i;
1515 retval[i] = 't';
1516 } else if ( (*p) == '\v') { /* vertical tab */
1517 retval[i] = '\\'; ++i;
1518 retval[i] = 'v';
1519 } else if ( (*p) == '\f') { /* form-feed */
1520 retval[i] = '\\'; ++i;
1521 retval[i] = 'f';
1522#ifdef WITH_DATABASE
1523 } else if ( (*p) == '\'') { /* single quote */
1524 retval[i] = '\\'; ++i;
1525 retval[i] = '\'';
1526#endif
1527 } else if ( (*p) == ' ') { /* space */
1528 retval[i] = '\\'; ++i;
1529 retval[i] = ' ';
1530#ifdef SH_USE_XML
1531 } else if ( (*p) == '"') { /* double quote */
1532 retval[i] = '&'; ++i;
1533 retval[i] = 'q'; ++i;
1534 retval[i] = 'u'; ++i;
1535 retval[i] = 'o'; ++i;
1536 retval[i] = 't'; ++i;
1537 retval[i] = ';';
1538 } else if ( (*p) == '&') { /* ampersand */
1539 retval[i] = '&'; ++i;
1540 retval[i] = 'a'; ++i;
1541 retval[i] = 'm'; ++i;
1542 retval[i] = 'p'; ++i;
1543 retval[i] = ';';
1544 } else if ( (*p) == '<') { /* left angle */
1545 retval[i] = '&'; ++i;
1546 retval[i] = 'l'; ++i;
1547 retval[i] = 't'; ++i;
1548 retval[i] = ';';
1549 } else if ( (*p) == '>') { /* right angle */
1550 retval[i] = '&'; ++i;
1551 retval[i] = 'g'; ++i;
1552 retval[i] = 't'; ++i;
1553 retval[i] = ';';
1554#else
1555 } else if ( (*p) == '"') { /* double quote */
1556 retval[i] = '\\'; ++i;
1557 retval[i] = '\"';
1558#endif
1559 } else if (!isgraph ((int) *p)) { /* not printable */
1560 /*@-bufferoverflowhigh -formatconst@*/
1561 sprintf(oct, format, '\\', /* known to fit */
1562 (unsigned char) *p);
1563 /*@+bufferoverflowhigh +formatconst@*/
1564 retval[i] = oct[0]; ++i;
1565 retval[i] = oct[1]; ++i;
1566 retval[i] = oct[2]; ++i;
1567 retval[i] = oct[3];
1568 } else {
1569 retval[i] = *p;
1570 }
1571 ++p;
1572 ++i;
1573 }
1574 retval[i] = '\0';
1575 SL_RETURN(retval, _("sh_util_safe_name"));
1576}
1577
1578int sh_util_isnum (char *str)
1579{
1580 char *p = str;
1581
1582 SL_ENTER(_("sh_util_isnum"));
1583
1584 ASSERT_RET ((str != NULL), _("str != NULL"), (-1))
1585
1586 while (p) {
1587 if (!isdigit((int) *p) )
1588 SL_RETURN((-1), _("sh_util_isnum"));
1589 ++p;
1590 }
1591 SL_RETURN((0), _("sh_util_isnum"));
1592}
1593
1594char * sh_util_strconcat (const char * arg1, ...)
1595{
1596 size_t length;
1597 char * s;
1598 char * strnew;
1599 va_list vl;
1600
1601 SL_ENTER(_("sh_util_strconcat"));
1602
1603 ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL))
1604
1605 length = sl_strlen (arg1) + 1;
1606
1607 va_start (vl, arg1);
1608 s = va_arg (vl, char * );
1609 while (s != NULL)
1610 {
1611 length = length + sl_strlen (s);
1612 s = va_arg (vl, char * );
1613 }
1614 va_end (vl);
1615
1616 strnew = SH_ALLOC( length + 2 );
1617 strnew[0] = '\0';
1618
1619 (void) sl_strlcpy (strnew, arg1, length + 2);
1620
1621 va_start (vl, arg1);
1622 s = va_arg (vl, char * );
1623 while (s)
1624 {
1625 (void) sl_strlcat (strnew, s, length + 2);
1626 s = va_arg (vl, char * );
1627 }
1628 va_end (vl);
1629
1630 SL_RETURN(strnew, _("sh_util_strconcat"));
1631}
1632
1633
1634#ifdef HAVE_REGEX_H
1635
1636#include <regex.h>
1637
1638int sh_util_regcmp (char * regex_str, char * in_str)
1639{
1640#if defined(REG_ESPACE)
1641 int status = REG_ESPACE;
1642#else
1643 int status = -1;
1644#endif
1645 regex_t preg;
1646 char * errbuf;
1647
1648 SL_ENTER(_("sh_util_regcmp"));
1649
1650 status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED);
1651
1652 if (status == 0)
1653 {
1654 if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0)
1655 {
1656 regfree (&preg);
1657 SL_RETURN((0), _("sh_util_regcmp"));
1658 }
1659 }
1660
1661 if (status != 0 && status != REG_NOMATCH)
1662 {
1663 errbuf = SH_ALLOC(BUFSIZ+2);
1664 (void) regerror(status, &preg, errbuf, BUFSIZ);
1665 errbuf[BUFSIZ] = '\0';
1666 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX,
1667 errbuf, regex_str);
1668 SH_FREE(errbuf);
1669 }
1670
1671 regfree (&preg);
1672 SL_RETURN((-1), _("sh_util_regcmp"));
1673}
1674
1675#endif
1676
1677
1678
1679
1680
1681
1682
1683
Note: See TracBrowser for help on using the repository browser.