source: trunk/src/sh_utils.c@ 160

Last change on this file since 160 was 156, checked in by katerina, 17 years ago

Put result vector of rng in skey struct, fix HP-UX compile error.

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