source: trunk/src/sh_utils.c@ 25

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

More tests; fix for update+schedule issue.

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