source: trunk/src/sh_utils.c@ 293

Last change on this file since 293 was 293, checked in by katerina, 15 years ago

Fix for ticket #221 (client/server problem if client hostname has uppercase chars).

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