source: trunk/src/sh_utils.c@ 20

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

Enable command-line parsing for prelude, and make prelude regression test safer.

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