source: trunk/src/sh_utils.c

Last change on this file was 541, checked in by katerina, 11 months ago

Fix for ticket #433 (coding standardisation).

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