source: trunk/src/sh_utils.c@ 578

Last change on this file since 578 was 570, checked in by katerina, 3 years ago

Fixes for some compile/cppcheck warnings, version 4.4.6.

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