source: trunk/src/sh_utils.c@ 134

Last change on this file since 134 was 133, checked in by rainer, 17 years ago

Reentrant checksum/hash functions.

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