source: trunk/src/sh_utils.c@ 11

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

Minor optimisations for server

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