source: branches/samhain-2_2-branch/src/sh_utils.c@ 560

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

Code cleanup and minor fixes

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