source: branches/samhain_3_1/src/sh_utils.c

Last change on this file was 473, checked in by katerina, 9 years ago

Fix for ticket #371 (use cppcheck instead of uno for static checking).

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