source: trunk/src/sh_utils.c@ 583

Last change on this file since 583 was 583, checked in by katerina, 32 hours ago

Fix for ticket #471 (autoreconf throws warnings/errors).

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