source: trunk/src/sh_utils.c @ 133

Last change on this file since 133 was 133, checked in by rainer, 12 years ago

Reentrant checksum/hash functions.

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