source: trunk/src/sh_utils.c@ 23

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

Minor code revisions.

File size: 38.7 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
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
[22]648int sh_util_sigtype (const char * c)
[1]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;
[22]959 char * outpath = NULL;
[1]960 unsigned char * image = NULL;
961 long s = 0;
962 long ilen = 0;
963 long ii, k = 0;
964 UINT32 * h1;
[22]965 char * new = NULL;
[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"));
[22]1001 free(new);
[1]1002 _exit (EXIT_FAILURE);
1003 /*@notreached@*/
1004 return -1;
1005 }
1006 else
1007 path = &new[j];
[22]1008
1009 len = strlen(path) + 1 + 4;
[1]1010 /*@-usedef@*/
[22]1011 if (NULL == (outpath = malloc(len)))
[1]1012 goto bail_mem;
1013 /*@-usedef@*/
[22]1014 sl_snprintf (outpath, len, _("%s.out"), path);
[1]1015
1016 fp = sl_open_read(path, SL_NOPRIV);
1017 if (SL_ISERROR(fp))
1018 {
1019 fprintf(stderr,
1020 _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp);
[22]1021 free(new); free (outpath);
[1]1022 _exit (EXIT_FAILURE);
1023 /*@notreached@*/
1024 return -1;
1025 }
1026
1027 fout = sl_open_write(outpath, SL_NOPRIV);
1028 if (SL_ISERROR(fout))
1029 {
1030 fprintf(stderr,
1031 _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout);
[22]1032 free(new); free (outpath);
[1]1033 _exit (EXIT_FAILURE);
1034 /*@notreached@*/
1035 return -1;
1036 }
1037
1038
1039 image = malloc (4096);
1040 if (!image)
1041 goto bail_mem;
1042 while (0 < (ii = sl_read (fp, &image[s], 4096)))
1043 {
1044 ilen += ii;
1045 s += 4096;
1046 image = realloc (image, (size_t) (4096 + s));
1047 if (!image)
1048 goto bail_mem;
1049 }
1050
1051 printf(_("%ld bytes read\n"), ilen);
1052
1053
1054 for (k = 0; k < (ilen - 8); ++k)
1055 {
1056 if (image[k] == new_key[0] &&
1057 image[k+1] == new_key[1] &&
1058 image[k+2] == new_key[2] &&
1059 image[k+3] == new_key[3] &&
1060 image[k+4] == new_key[4] &&
1061 image[k+5] == new_key[5] &&
1062 image[k+6] == new_key[6] &&
1063 image[k+7] == new_key[7])
1064 {
1065 printf(_("old key found\n"));
1066 h1 = sh_tiger_hash_uint32 (key, TIGER_DATA,
1067 (unsigned long)strlen(key));
1068 copy_four( (unsigned char *) &(image[k]), h1[0]);
1069 copy_four( (unsigned char *) &(image[k+4]), h1[1]);
1070 (void) sl_write (fout, image, ilen);
1071 (void) sl_close (fout);
1072 printf(_("new file %s written\n"), outpath);
[22]1073 free(new); free (outpath); free(image);
[1]1074 _exit (EXIT_SUCCESS);
1075 /*@notreached@*/
1076 return 0;
1077 }
1078 }
1079
1080 fprintf(stderr,
1081 _("ERROR: old key not found\n"));
[22]1082 free(new); free (outpath); free(image);
[1]1083 _exit (EXIT_FAILURE);
1084 /*@notreached@*/
1085 return -1;
1086
1087
1088 bail_mem:
1089 fprintf(stderr,
1090 _("ERROR: out of memory\n"));
[22]1091 if (new) free(new);
1092 if (outpath) free (outpath);
1093 if (image) free (image);
[1]1094 _exit (EXIT_FAILURE);
1095 /*@notreached@*/
1096 return -1;
1097}
1098
1099
1100
1101
1102/* A simple en-/decoder, based on Vernam cipher. We use the
1103 * message as salt to hide the key by obtaining a different one-time
1104 * pad each time.
1105 * Should be safe against a listener on the network, but not against someone
1106 * with read access to the binary.
1107 */
1108void sh_util_encode (char * data, char * salt, int mode, char fill)
1109{
1110 static char cc1[17] = N_("0123456789ABCDEF");
1111 char cc[17] = "\0";
1112 register int i, j, j1 = 0, j2 = 0, j3;
1113 char * dez;
1114
1115 SL_ENTER(_("sh_util_encode"));
1116
1117 /* init
1118 */
1119 (void) sl_strlcpy( cc, _(cc1), sizeof(cc));
1120
1121 /* max 128 bits keyspace
1122 */
1123 memset (skey->vernam, (int)fill, KEY_LEN+1);
1124
1125 dez = (char *) &(skey->ErrFlag[0]);
1126 sh_util_cpylong (skey->vernam, dez, 4);
1127 dez = (char *) &(skey->ErrFlag[1]);
1128 sh_util_cpylong (&skey->vernam[4], dez, 4);
1129
1130 skey->vernam[KEY_LEN] = '\0';
1131
1132 (void) sl_strlcpy(skey->vernam,
1133 sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN),
1134 KEY_LEN+1);
1135
1136 (void) sl_strlcpy(skey->vernam,
1137 sh_util_hmac_tiger (skey->vernam, salt, strlen(salt)),
1138 KEY_LEN+1);
1139
1140 (void) sl_strlcpy(skey->vernam,
1141 sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8),
1142 KEY_LEN+1);
1143
1144 /* The following routine adds/subtracts data[j] and vernam[j] mod 16.
1145 */
1146 j = 0;
1147 while (j < KEY_LEN)
1148 {
1149 for (i = 0; i < 16; ++i)
1150 {
1151 if (cc[i] == data[j]) j1 = i;
1152 if (cc[i] == skey->vernam[j]) j2 = i;
1153 }
1154 if (mode == 0)
1155 {
1156 j3 = j1 + j2;
1157 if (j3 > 15) j3 -= 16;
1158 data[j] = cc[j3];
1159 }
1160 else
1161 {
1162 j3 = j1 - j2;
1163 if (j3 < 0) j3 += 16;
1164 data[j] = cc[j3];
1165 }
1166 ++j;
1167 }
1168 SL_RET0(_("sh_util_encode"));
1169}
1170
1171/* server mode
1172 */
[20]1173int sh_util_setserver (const char * dummy)
[1]1174{
1175 SL_ENTER(_("sh_util_setserver"));
1176
[20]1177 (void) dummy;
1178 sh.flag.isserver = GOOD;
[1]1179 SL_RETURN((0),_("sh_util_setserver"));
1180}
1181
1182
[20]1183int sh_util_setlooptime (const char * str)
[1]1184{
1185 int i = atoi (str);
1186
1187 SL_ENTER(_("sh_util_setlooptime"));
1188
1189 if (i >= 0 && i < INT_MAX) {
1190 sh.looptime = i;
1191 SL_RETURN((0),_("sh_util_setlooptime"));
1192 } else {
1193 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1194 _("loop time"), str);
1195 SL_RETURN((-1),_("sh_util_setlooptime"));
1196 }
1197}
1198
1199#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
[20]1200int sh_util_setchecksum (const char * str)
[1]1201{
1202 static int reject = 0;
1203
1204 SL_ENTER(_("sh_util_setchecksum"));
1205
1206 if (reject == 1)
1207 SL_RETURN((0), _("sh_util_setchecksum"));
1208 reject = 1;
1209
1210 if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0)
1211 {
1212 sh.flag.checkSum = SH_CHECK_INIT;
1213 }
1214 else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1215 {
1216 if (S_TRUE == file_is_remote())
1217 {
1218 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1219 _("checksum testing"), str);
1220 SL_RETURN((-1), _("sh_util_setchecksum"));
1221 }
1222 else
1223 {
1224 sh.flag.checkSum = SH_CHECK_CHECK;
1225 sh.flag.update = S_TRUE;
1226 }
1227 }
1228 else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0)
1229 {
1230 sh.flag.checkSum = SH_CHECK_CHECK;
1231 }
1232 /*
1233 else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1234 {
1235 sh.flag.checkSum = SH_CHECK_INIT;
1236 sh.flag.update = S_TRUE;
1237 }
1238 */
1239 else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0)
1240 {
1241 sh.flag.checkSum = SH_CHECK_NONE;
1242 }
1243 else
1244 {
1245 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1246 _("checksum testing"), str);
1247 SL_RETURN((-1), _("sh_util_setchecksum"));
1248 }
1249 SL_RETURN((0), _("sh_util_setchecksum"));
1250}
1251#endif
1252
1253/*@+charint@*/
1254unsigned char TcpFlag[8][PW_LEN+1] = {
1255#if (POS_TF == 1)
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 == 2)
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 == 3)
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 == 4)
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 == 5)
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 == 6)
1276 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1277#endif
1278 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1279#if (POS_TF == 7)
1280 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1281#endif
1282 { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1283#if (POS_TF == 8)
1284 { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1285#endif
1286};
1287/*@-charint@*/
1288
1289/* initialize a key to a random value
1290 * rev 0.8
1291 */
1292int sh_util_keyinit (char * buf, long size)
1293{
1294 UINT32 bufy[6];
1295 int i;
1296 int status = 0;
1297 char * p;
1298
1299 SL_ENTER(_("sh_util_keyinit"));
1300
1301 ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1"))
1302
1303 if (size > KEY_LEN+1)
1304 size = KEY_LEN+1;
1305
1306 /* seed / re-seed the PRNG if required
1307 */
1308 status = taus_seed ();
1309
1310 if (status == -1)
1311 sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1,
1312 _("taus_seed"));
1313
1314 for (i = 0; i < 6; ++i)
1315 bufy[i] = taus_get(&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1316
1317 p = sh_tiger_hash ((char *) bufy, TIGER_DATA,
1318 (unsigned long)(6*sizeof(UINT32)));
1319 p[size-1] = '\0';
1320
1321 i = sl_strlcpy(buf, p, (size_t)size);
1322
1323 memset (bufy, 0, 6*sizeof(UINT32));
1324
1325 if ((status == 0) && (!SL_ISERROR(i)) )
1326 SL_RETURN((0),_("sh_util_keyinit"));
1327
1328 if (SL_ISERROR(i))
1329 sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2,
1330 _("sl_strlcpy"));
1331
1332 SL_RETURN((-1),_("sh_util_keyinit"));
1333}
1334
1335#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1336
1337static unsigned char sh_obscure_index[256];
1338
[22]1339int sh_util_obscure_ok (const char * str)
[1]1340{
1341 unsigned long i;
[22]1342 char * endptr = NULL;
[1]1343
1344 SL_ENTER(_("sh_util_obscure_ex"));
1345
1346 if (0 == sl_strncmp("all", str, 3))
1347 {
1348 for (i = 0; i < 255; ++i)
1349 {
1350 sh_obscure_index[i] = (unsigned char)1;
1351 }
1352 SL_RETURN(0, _("sh_util_obscure_ex"));
1353 }
1354
1355 for (i = 0; i < 255; ++i)
1356 {
1357 sh_obscure_index[i] = (unsigned char)0;
1358 }
1359
[22]1360 i = strtoul (str, &endptr, 0);
1361 if (i > 255)
1362 {
1363 SL_RETURN(-1, _("sh_util_obscure_ex"));
1364 }
1365 sh_obscure_index[i] = (unsigned char)1;
1366 if (*endptr == ',')
1367 ++endptr;
1368
[1]1369 while (*endptr != '\0')
1370 {
1371 i = strtoul (endptr, &endptr, 0);
1372 if (i > 255)
1373 {
1374 SL_RETURN(-1, _("sh_util_obscure_ex"));
1375 }
1376 sh_obscure_index[i] = (unsigned char)1;
1377 if (*endptr == ',')
1378 ++endptr;
1379 }
1380 SL_RETURN(0, _("sh_util_obscure_ex"));
1381}
1382
1383int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
1384{
1385 char * name = name_orig;
1386 char * safe;
1387 unsigned int i;
1388
1389 SL_ENTER(_("sh_util_obscurename"));
1390
1391 ASSERT_RET((name != NULL), _("name != NULL"), (0))
1392
1393 /* -- Check name. --
1394 */
1395 while (*name != '\0')
1396 {
1397 if ( (*name) == '"' || (*name) == '\t' ||
1398 (*name) == '\b' || (*name) == '\f' ||
1399 (*name) == '\n' || (*name) == '\r' ||
1400 (*name) == '\v' || iscntrl((int) *name) ||
1401 ((*name) != ' ' && !isgraph ((int) *name)) )
1402 {
1403 i = (unsigned char) *name;
1404 if (sh_obscure_index[i] != (unsigned char)1)
1405 {
1406 if (flag == S_TRUE)
1407 {
1408 safe = sh_util_safe_name (name_orig);
1409 sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC,
1410 safe);
1411 SH_FREE(safe);
1412 }
1413 SL_RETURN((-1),_("sh_util_obscurename"));
1414 }
1415 }
1416 name++;
1417 }
1418
1419 SL_RETURN((0),_("sh_util_obscurename"));
1420}
1421#endif
1422
1423/* returns freshly allocated memory, return value should be free'd
1424 */
1425char * sh_util_basename(char * fullpath)
1426{
1427 char * retval;
1428 size_t i;
1429
1430 SL_ENTER(_("sh_util_basename"));
1431
1432 ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1433
1434 i = sl_strlen (fullpath); /* fullpath[i] is terminating '\0' */
1435
1436 while (i > 0) {
1437 --i;
1438 if (fullpath[i] == '/') break;
1439 }
1440
1441 /* -- Not a valid path. --
1442 */
1443 if ((fullpath[i] != '/') && (i == 0) )
1444 SL_RETURN(NULL, _("sh_util_basename"));
1445
1446 retval = SH_ALLOC(i + 1);
1447
1448 (void) sl_strlcpy (retval, fullpath, i+1);
1449
1450 SL_RETURN(retval, _("sh_util_basename"));
1451}
1452
1453/* returns freshly allocated memory, return value should be free'd
1454 */
1455char * sh_util_filename(char * fullpath)
1456{
1457 char * retval;
1458 char * c;
1459 size_t i;
1460
1461 SL_ENTER(_("sh_util_filename"));
1462
1463 ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1464
1465 c = strrchr(fullpath, '/');
1466 i = sl_strlen (c);
1467 if (i <= 1) SL_RETURN(NULL, _("sh_util_filename")); /* ends in '/' */
1468 ++c;
1469 --i;
1470
1471 retval = SH_ALLOC(i + 1);
1472
1473 (void) sl_strlcpy (retval, c, i+1);
1474
1475 SL_RETURN(retval, _("sh_util_filename"));
1476}
1477
1478
1479/* returns freshly allocated memory, return value should be free'd
1480 */
1481char * sh_util_safe_name (const char * name)
1482{
1483 register int i = 0;
1484 const char * p;
1485 char * retval;
1486 char oct[32];
1487 char format[16];
1488
1489 SL_ENTER(_("sh_util_safe_name"));
1490
1491 if (name == NULL)
1492 {
1493 /* return an allocated array
1494 */
1495 retval = SH_ALLOC(7);
1496 (void) sl_strlcpy(retval, _("(null)"), 7);
1497 SL_RETURN(retval, _("sh_util_safe_name"));
1498 }
1499
1500 /*
1501 ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL"))
1502 */
1503
1504#ifdef SH_USE_XML
1505 retval = SH_ALLOC(6 * sl_strlen(name) + 2);
1506#else
1507 retval = SH_ALLOC(4 * sl_strlen(name) + 2);
1508#endif
1509
1510 (void) sl_strncpy(format, _("%c%03o"), 16);
1511
1512 p = name;
1513
1514 while (*p != '\0') {
1515 /* Most frequent cases first
1516 */
1517 if ( ((*p) >= 'a' && (*p) <= 'z') || ((*p) == '/') || ((*p) == '.') ||
1518 ((*p) >= '0' && (*p) <= '9') ||
1519 ((*p) >= 'A' && (*p) <= 'Z')) {
1520 retval[i] = *p;
1521 } else if ( (*p) == '\\') { /* backslash */
1522 retval[i] = '\\'; ++i;
1523 retval[i] = '\\';
1524 } else if ( (*p) == '\n') { /* newline */
1525 retval[i] = '\\'; ++i;
1526 retval[i] = 'n';
1527 } else if ( (*p) == '\b') { /* backspace */
1528 retval[i] = '\\'; ++i;
1529 retval[i] = 'b';
1530 } else if ( (*p) == '\r') { /* carriage return */
1531 retval[i] = '\\'; ++i;
1532 retval[i] = 'r';
1533 } else if ( (*p) == '\t') { /* horizontal tab */
1534 retval[i] = '\\'; ++i;
1535 retval[i] = 't';
1536 } else if ( (*p) == '\v') { /* vertical tab */
1537 retval[i] = '\\'; ++i;
1538 retval[i] = 'v';
1539 } else if ( (*p) == '\f') { /* form-feed */
1540 retval[i] = '\\'; ++i;
1541 retval[i] = 'f';
1542#ifdef WITH_DATABASE
1543 } else if ( (*p) == '\'') { /* single quote */
1544 retval[i] = '\\'; ++i;
1545 retval[i] = '\'';
1546#endif
1547 } else if ( (*p) == ' ') { /* space */
1548 retval[i] = '\\'; ++i;
1549 retval[i] = ' ';
1550#ifdef SH_USE_XML
1551 } else if ( (*p) == '"') { /* double quote */
1552 retval[i] = '&'; ++i;
1553 retval[i] = 'q'; ++i;
1554 retval[i] = 'u'; ++i;
1555 retval[i] = 'o'; ++i;
1556 retval[i] = 't'; ++i;
1557 retval[i] = ';';
1558 } else if ( (*p) == '&') { /* ampersand */
1559 retval[i] = '&'; ++i;
1560 retval[i] = 'a'; ++i;
1561 retval[i] = 'm'; ++i;
1562 retval[i] = 'p'; ++i;
1563 retval[i] = ';';
1564 } else if ( (*p) == '<') { /* left angle */
1565 retval[i] = '&'; ++i;
1566 retval[i] = 'l'; ++i;
1567 retval[i] = 't'; ++i;
1568 retval[i] = ';';
1569 } else if ( (*p) == '>') { /* right angle */
1570 retval[i] = '&'; ++i;
1571 retval[i] = 'g'; ++i;
1572 retval[i] = 't'; ++i;
1573 retval[i] = ';';
1574#else
1575 } else if ( (*p) == '"') { /* double quote */
1576 retval[i] = '\\'; ++i;
1577 retval[i] = '\"';
1578#endif
1579 } else if (!isgraph ((int) *p)) { /* not printable */
1580 /*@-bufferoverflowhigh -formatconst@*/
[22]1581 /* flawfinder: ignore */
[1]1582 sprintf(oct, format, '\\', /* known to fit */
1583 (unsigned char) *p);
1584 /*@+bufferoverflowhigh +formatconst@*/
1585 retval[i] = oct[0]; ++i;
1586 retval[i] = oct[1]; ++i;
1587 retval[i] = oct[2]; ++i;
1588 retval[i] = oct[3];
1589 } else {
1590 retval[i] = *p;
1591 }
1592 ++p;
1593 ++i;
1594 }
1595 retval[i] = '\0';
1596 SL_RETURN(retval, _("sh_util_safe_name"));
1597}
1598
1599int sh_util_isnum (char *str)
1600{
1601 char *p = str;
1602
1603 SL_ENTER(_("sh_util_isnum"));
1604
1605 ASSERT_RET ((str != NULL), _("str != NULL"), (-1))
1606
1607 while (p) {
1608 if (!isdigit((int) *p) )
1609 SL_RETURN((-1), _("sh_util_isnum"));
1610 ++p;
1611 }
1612 SL_RETURN((0), _("sh_util_isnum"));
1613}
1614
1615char * sh_util_strconcat (const char * arg1, ...)
1616{
1617 size_t length;
1618 char * s;
1619 char * strnew;
1620 va_list vl;
1621
1622 SL_ENTER(_("sh_util_strconcat"));
1623
1624 ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL))
1625
1626 length = sl_strlen (arg1) + 1;
1627
1628 va_start (vl, arg1);
1629 s = va_arg (vl, char * );
1630 while (s != NULL)
1631 {
1632 length = length + sl_strlen (s);
1633 s = va_arg (vl, char * );
1634 }
1635 va_end (vl);
1636
1637 strnew = SH_ALLOC( length + 2 );
1638 strnew[0] = '\0';
1639
1640 (void) sl_strlcpy (strnew, arg1, length + 2);
1641
1642 va_start (vl, arg1);
1643 s = va_arg (vl, char * );
1644 while (s)
1645 {
1646 (void) sl_strlcat (strnew, s, length + 2);
1647 s = va_arg (vl, char * );
1648 }
1649 va_end (vl);
1650
1651 SL_RETURN(strnew, _("sh_util_strconcat"));
1652}
1653
1654
1655#ifdef HAVE_REGEX_H
1656
1657#include <regex.h>
1658
1659int sh_util_regcmp (char * regex_str, char * in_str)
1660{
1661#if defined(REG_ESPACE)
1662 int status = REG_ESPACE;
1663#else
1664 int status = -1;
1665#endif
1666 regex_t preg;
1667 char * errbuf;
1668
1669 SL_ENTER(_("sh_util_regcmp"));
1670
1671 status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED);
1672
1673 if (status == 0)
1674 {
1675 if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0)
1676 {
1677 regfree (&preg);
1678 SL_RETURN((0), _("sh_util_regcmp"));
1679 }
1680 }
1681
1682 if (status != 0 && status != REG_NOMATCH)
1683 {
1684 errbuf = SH_ALLOC(BUFSIZ+2);
1685 (void) regerror(status, &preg, errbuf, BUFSIZ);
1686 errbuf[BUFSIZ] = '\0';
1687 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX,
1688 errbuf, regex_str);
1689 SH_FREE(errbuf);
1690 }
1691
1692 regfree (&preg);
1693 SL_RETURN((-1), _("sh_util_regcmp"));
1694}
1695
1696#endif
1697
1698
1699
1700
1701
1702
1703
1704
Note: See TracBrowser for help on using the repository browser.