source: trunk/src/sh_utils.c@ 71

Last change on this file since 71 was 68, checked in by rainer, 18 years ago

Update trunk to samhain 2.3

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