source: trunk/src/sh_utils.c@ 381

Last change on this file since 381 was 373, checked in by katerina, 13 years ago

Patch for ticket #265 (inotify). Handling of added subdirectories and file list rescan.

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