source: trunk/src/sh_utils.c

Last change on this file was 570, checked in by katerina, 3 months ago

Fixes for some compile/cppcheck warnings, version 4.4.6.

File size: 54.5 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  /* cppcheck-suppress uninitvar */
830  h2 = sh_tiger_hash_uint32 ( inner, TIGER_DATA,
831                              (unsigned long) KEY_BLOCK+textlen,
832                              kbuf, KEY_BYT/sizeof(UINT32));
833  for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
834    copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
835
836  /* cppcheck-suppress uninitvar */
837  SH_FREE(inner);
838 
839  (void) sh_tiger_hash ((char *) &cc[0],
840                        TIGER_DATA,
841                        (unsigned long) (KEY_LEN/4 * sizeof(UINT32)),
842                        hashbuf, sizeof(hashbuf));
843
844  sl_strlcpy(res, hashbuf, len);
845  SL_RETURN(res, _("sh_util_hmac_tiger"));
846}
847
848static char * sh_util_hash_tiger ( char * hexkey, 
849                                   char * text, size_t textlen,
850                                   char * res, size_t len)
851{
852  char           h2[2*KEY_LEN+1];
853  char hashbuf[KEYBUF_SIZE];
854
855  SL_ENTER(_("sh_util_hash_tiger"));
856
857  (void) sl_strlcpy(h2, hexkey, KEY_LEN+1); 
858  (void) sl_strlcat(h2, 
859                    sh_tiger_hash(text, TIGER_DATA, 
860                                  (unsigned long) textlen,
861                                  hashbuf, sizeof(hashbuf)), 
862                    2*KEY_LEN+1
863                    );
864
865  (void) sh_tiger_hash(h2, TIGER_DATA, 2*KEY_LEN, hashbuf, sizeof(hashbuf));
866
867  sl_strlcpy(res, hashbuf, len);
868  SL_RETURN(res, _("sh_util_hash_tiger"));
869}
870
871/* --- compute signature on data ---
872 */
873#define TYPE_HMAC 0
874#define TYPE_HASH 1
875
876static int sigtype = TYPE_HMAC;
877
878int sh_util_sigtype (const char * c)
879{
880  SL_ENTER(_("sh_util_sigtype"));
881  if (c == NULL)
882    SL_RETURN( -1, _("sh_util_sigtype"));
883
884  if (0 == strcmp(_("HMAC-TIGER"), c))
885    sigtype = TYPE_HMAC;
886  else if  (0 == strcmp(_("HASH-TIGER"), c))
887    sigtype = TYPE_HASH;
888  else
889    SL_RETURN( -1, _("sh_util_sigtype"));
890
891  SL_RETURN( 0, _("sh_util_sigtype"));
892}
893
894char * sh_util_siggen (char * hexkey, 
895                       char * text, size_t textlen,
896                       char * res, size_t len) 
897{
898  char * p;
899 
900  SL_ENTER(_("sh_util_siggen"));
901  if (sigtype == TYPE_HMAC)
902    p = sh_util_hmac_tiger (hexkey, 
903                            text, textlen, res, len);
904  else
905    p = sh_util_hash_tiger (hexkey, 
906                            text, textlen, res, len);
907  SL_RETURN(p, _("sh_util_siggen"));
908}   
909
910 
911/* a simple compressor
912 */
913size_t sh_util_compress (char * dest, char * src, size_t dest_size)
914{
915  char * add;
916  char * get;
917  size_t   count = 0;
918  size_t   dest_end;
919
920  SL_ENTER(_("sh_util_compress"));
921
922  if (dest_size == 0)
923    SL_RETURN((0), _("sh_util_compress"));
924 
925  if ((dest == NULL) || (src == NULL))
926    SL_RETURN((0), _("sh_util_compress"));
927 
928  dest_end = sl_strlen(dest);
929
930  if (dest_end > dest_size)
931    SL_RETURN((0), _("sh_util_compress"));
932
933  add      = &dest[dest_end];
934  get      = src;
935
936  while (count < (dest_size-dest_end))
937    {
938      if (isalnum((int) *get)) 
939        {
940          *add = *get;
941          ++add;
942          ++count;
943        }
944      ++get; 
945      if (*get == '\0' && (count < (dest_size-dest_end))) 
946        /* end of src reached */
947        {
948          *add = *get;  /* copy the '\0'      */
949          break;        /* and stop copying   */
950        }
951    }
952
953  dest[dest_size-1] = '\0'; /* paranoia       */
954  SL_RETURN((count), _("sh_util_compress")); /* no of chars copied */   
955}
956
957
958/* copy the four least significant bytes
959 */
960void sh_util_cpylong (char * dest, const char * src, int len )
961{
962  int i, j;
963  union
964  {
965    long l;
966    char c[sizeof(long)];
967  } u;
968#ifdef WORDS_BIGENDIAN
969  unsigned char swap;
970  unsigned char * ii = (unsigned char *) dest;
971#endif
972
973  SL_ENTER(_("sh_util_cpylong"));   
974
975  u.l = 1;
976
977  /* MSB is first
978   */
979  if (sizeof(long)>4 &&/*@+charint@*/(u.c[sizeof(long)-1] == 1)/*@-charint@*/)
980    {
981      j = (int) (sizeof(long)-4);
982      for (i = 0; i < j; ++i) ++src;
983    }
984
985  i = 0;
986
987  while (i < 4)
988    {
989      *dest = (*src);
990      ++dest; ++src;
991      if (i == (len-1)) break;
992      ++i;
993    }
994#ifdef WORDS_BIGENDIAN
995  swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
996  swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
997#endif
998  SL_RET0(_("sh_util_cpylong"));
999}
1000
1001/*  This is a maximally equidistributed combined Tausworthe
1002 *  generator. The sequence is,
1003 *
1004 *   x_n = (s1_n ^ s2_n ^ s3_n)
1005 *
1006 *   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
1007 *   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
1008 *   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
1009 *
1010 *   computed modulo 2^32. In the three formulas above '^' means
1011 *   exclusive-or (C-notation), not exponentiation. Note that the
1012 *   algorithm relies on the properties of 32-bit unsigned integers (it
1013 *   is formally defined on bit-vectors of length 32).
1014 *
1015 *   Stolen from GSL (GNU scientific library) and modified somewhat.
1016 *   I am using UINT32, which is guaranteed to be 32 bits. Also made
1017 *   sure that the initialization vector is valid.
1018 */
1019
1020
1021/* interval [0, 4294967295]
1022 */
1023static UINT32 taus_get_long (void *vstate)
1024{
1025  UINT32 * state = (UINT32 *) vstate;
1026
1027  /*
1028  if (skey->rngI == BAD)
1029    (void)taus_seed();
1030  */
1031
1032#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
1033  /*@+ignorequals@*/
1034  state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
1035  state[1] = TAUSWORTHE (state[1],  2, 25, 4294967288UL,  4);
1036  state[2] = TAUSWORTHE (state[2],  3, 11, 4294967280UL, 17);
1037  /*@-ignorequals@*/
1038  return (state[0] ^ state[1] ^ state[2]);
1039}
1040
1041/* Hide the internal state of the PRNG by using its output as
1042 * input for a one-way hash function.
1043 */
1044
1045UINT32 taus_get ()
1046{
1047#define TAUS_SAMPLE 12
1048
1049  UINT32   taus_svec[TAUS_SAMPLE];
1050  UINT32   retval;
1051  UINT32 * res;
1052  UINT32 * res_vec = &(skey->res_vec[0]);
1053  static   int      res_num = 0;
1054  register int i;
1055  UINT32       kbuf[KEY_BYT/sizeof(UINT32)];
1056
1057  SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1058  if (res_num > 0)
1059    {
1060      retval  = res_vec[res_num];
1061      res_num = (res_num == 5) ? 0 : (res_num + 1);
1062      SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); /* alternative path */
1063      return  retval;
1064    }
1065  SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1066
1067  (void)taus_seed();
1068
1069  SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1070  for (i = 0; i < (TAUS_SAMPLE/3); ++i)
1071    {
1072      taus_svec[i*3]   = taus_get_long (&(skey->rng0[0]));
1073      taus_svec[i*3+1] = taus_get_long (&(skey->rng1[0]));
1074      taus_svec[i*3+2] = taus_get_long (&(skey->rng2[0]));
1075    }
1076  SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1077
1078  res     = sh_tiger_hash_uint32 ( (char *) &taus_svec[0], 
1079                                   TIGER_DATA, 
1080                                   (unsigned long)(TAUS_SAMPLE * sizeof(UINT32)),
1081                                   kbuf, KEY_BYT/sizeof(UINT32));
1082
1083  SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1084  for (i = 1; i < 6; ++i)
1085    { 
1086      res_vec[i] = res[i];
1087    }
1088  retval  = res[0];
1089  res_num = 1;
1090  SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1091
1092  memset(taus_svec, 0, TAUS_SAMPLE * sizeof(UINT32));
1093
1094  return retval;
1095}
1096
1097/* interval [0,1)
1098 */
1099double taus_get_double (void *vstate)
1100{
1101  return taus_get_long (vstate) / (4294967296.0 + 1.0) ;
1102}
1103
1104#define LCG(n) ((69069 * n) & 0xffffffffUL)
1105
1106/* TAKE CARE: state[0], state[1], state[2] must be > 2,8,16, respectively
1107 */
1108static void taus_set_from_ulong (void *vstate, unsigned long int s)
1109{
1110  UINT32  *state = (UINT32  *) vstate;
1111
1112  if (s == 0)
1113    s = 1;      /* default seed is 1 */
1114
1115  state[0] = (UINT32)(LCG (s)        | (UINT32) 0x03);
1116  state[1] = (UINT32)(LCG (state[0]) | (UINT32) 0x09);
1117  state[2] = (UINT32)(LCG (state[1]) | (UINT32) 0x17);
1118
1119  /* 'warm up'
1120   */
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  (void) taus_get_long (state);
1126  (void) taus_get_long (state);
1127
1128  return;
1129}
1130
1131static void taus_set_from_state (void *vstate, void *init_state)
1132{
1133  UINT32  *state  = (UINT32  *) vstate;
1134  UINT32  *state0 = (UINT32  *) init_state;
1135
1136  state[0] = state0[0]  | (UINT32) 0x03;
1137  state[1] = state0[1]  | (UINT32) 0x09;
1138  state[2] = state0[2]  | (UINT32) 0x17;
1139 
1140  return;
1141}
1142
1143 
1144int taus_seed ()
1145{
1146  char                 bufx[9 * sizeof(UINT32) + 1];
1147  int                  status;
1148  static unsigned long seed_time    = 0;
1149  static unsigned long seed_counter = 3000;
1150  unsigned long        gtime;
1151
1152  SL_ENTER(_("taus_seed"));
1153
1154  if (skey->rngI == GOOD)
1155    {
1156      ++seed_counter;
1157
1158      if ( ((sh_unix_longtime () - seed_time) < 1800) &&
1159           ( seed_counter                     < 3000))
1160        SL_RETURN( (0), _("taus_seed"));
1161    }
1162 
1163  seed_time    = sh_unix_longtime ();
1164  seed_counter = 0;
1165
1166  status = sh_entropy (24, bufx);
1167
1168  if (!SL_ISERROR(status))
1169    {
1170      SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1171      memcpy (&skey->rng0[0], &bufx[0],                  2*sizeof(UINT32));
1172      memcpy (&skey->rng1[0], &bufx[2*sizeof(UINT32)],   2*sizeof(UINT32));
1173      memcpy (&skey->rng2[0], &bufx[4*sizeof(UINT32)],   2*sizeof(UINT32));
1174      memset (bufx, 0, 9 * sizeof(UINT32) + 1);
1175
1176      skey->rng0[2] = 0;
1177      skey->rng1[2] = 0;
1178      skey->rng2[2] = 0;
1179
1180      taus_set_from_state( &(skey->rng0[0]), &(skey->rng0[0]));
1181      taus_set_from_state( &(skey->rng1[0]), &(skey->rng1[0]));
1182      taus_set_from_state( &(skey->rng2[0]), &(skey->rng2[0]));
1183
1184      skey->rngI = GOOD;
1185      SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1186      SL_RETURN( (0), _("taus_seed"));
1187    }
1188
1189  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_ES_ENT,
1190                   _("sh_entropy"));
1191
1192  /* emergency backup - unsafe !
1193   */
1194#ifdef HAVE_GETTIMEOFDAY
1195  gtime = sh_unix_notime();
1196#else
1197  gtime = seed_time;
1198#endif
1199
1200  SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1201  taus_set_from_ulong ( &(skey->rng0[0]), LCG (gtime)          );
1202  taus_set_from_ulong ( &(skey->rng1[0]), LCG (skey->rng0[0])  );
1203  taus_set_from_ulong ( &(skey->rng2[0]), LCG (skey->rng1[0])  );
1204  skey->rngI = BAD;
1205  SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1206
1207  SL_RETURN( (-1), _("taus_seed"));
1208}
1209
1210/*@+charint@*/
1211static unsigned char new_key[] = { 0xA7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xA7 };
1212/*@-charint@*/
1213static void copy_four (unsigned char * dest, UINT32 in);
1214
1215int sh_util_set_newkey (const char * new_in)
1216{
1217  size_t i, j = 0;
1218  size_t len;
1219  SL_TICKET fp;
1220  SL_TICKET fout;
1221  char * key;
1222  char * path = NULL;
1223  char * outpath = NULL;
1224  unsigned char * image = NULL;
1225  long s = 0;
1226  long ilen = 0;
1227  long ii, k = 0;
1228  UINT32    * h1;
1229  char * new = NULL;
1230
1231  if (0 != sl_is_suid())
1232    {
1233      fprintf(stderr, "%s", _("ERROR: insufficient privilege\n"));
1234      _exit (EXIT_FAILURE);
1235      /*@notreached@*/
1236      return -1;  /* braindead MAC OSX compiler needs this */
1237    }
1238       
1239  if (new_in == NULL || new_in[0] == '\0')
1240    {
1241      fprintf(stderr, "%s", 
1242              _("ERROR: no key given\n Argument must be 'key@path'\n"));
1243      _exit (EXIT_FAILURE);
1244      /*@notreached@*/
1245      return -1;
1246    }
1247
1248  len = strlen(new_in) + 1;
1249  if (NULL == (new = calloc(1, len)))
1250    goto bail_mem;
1251  memcpy(new, new_in, len);
1252
1253  key = new;
1254  len = strlen(new);
1255  for (i = 1; i < (len-2); ++i)
1256    {
1257      if (new[i] == '@' && new[i+1] == '/')
1258        {
1259          j = i+1; new[i] = '\0'; break;
1260        }
1261    }
1262  if (j == 0)
1263    {
1264      fprintf(stderr, "%s",
1265              _("ERROR: no path to executable given\n Argument must be 'key@path'\n"));
1266      free(new);
1267      _exit (EXIT_FAILURE);
1268      /*@notreached@*/
1269      return -1;
1270    }
1271  else
1272    path = &new[j];
1273
1274  len = strlen(path) + 1 + 4;
1275  /*@-usedef@*/
1276  if (NULL == (outpath = calloc(1,len)))
1277    goto bail_mem;
1278  /*@-usedef@*/
1279  sl_snprintf (outpath, len, _("%s.out"), path);
1280
1281  fp = sl_open_read(FIL__, __LINE__, path, SL_NOPRIV);
1282  if (SL_ISERROR(fp))
1283    {
1284      fprintf(stderr, 
1285              _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp);
1286      free(new); free (outpath);
1287      _exit (EXIT_FAILURE);
1288      /*@notreached@*/
1289      return -1;
1290    }
1291 
1292  fout = sl_open_write(FIL__, __LINE__, outpath, SL_NOPRIV);
1293  if (SL_ISERROR(fout))
1294    {
1295      fprintf(stderr, 
1296              _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout);
1297      free(new); free (outpath);
1298      _exit (EXIT_FAILURE);
1299      /*@notreached@*/
1300      return -1;
1301    }
1302
1303
1304  image = calloc(1,4096);
1305  if (!image)
1306    goto bail_mem;
1307  while (0 < (ii = sl_read (fp, &image[s], 4096)))
1308    {
1309      unsigned char * ptr;
1310      ilen += ii;
1311      s    += 4096;
1312      ptr = realloc (image, (size_t) (4096 + s));
1313      if (ptr)
1314        image = ptr;
1315      else
1316        { free(image); image = NULL; }
1317      if (!image)
1318        goto bail_mem;
1319    }
1320
1321  printf(_("%ld bytes read\n"), ilen);
1322
1323 
1324  for (k = 0; k < (ilen - 8); ++k) 
1325    {
1326      if (image[k]   == new_key[0] &&
1327          image[k+1] == new_key[1] &&
1328          image[k+2] == new_key[2] &&
1329          image[k+3] == new_key[3] &&
1330          image[k+4] == new_key[4] &&
1331          image[k+5] == new_key[5] &&
1332          image[k+6] == new_key[6] &&
1333          image[k+7] == new_key[7])
1334        {
1335          UINT32 kbuf[KEY_BYT/sizeof(UINT32)];
1336
1337          printf("%s", _("old key found\n")); 
1338          h1 = sh_tiger_hash_uint32 (key, TIGER_DATA, 
1339                                     (unsigned long)strlen(key),
1340                                     kbuf, KEY_BYT/sizeof(UINT32));
1341          copy_four( (unsigned char *) &(image[k]),   h1[0]);
1342          copy_four( (unsigned char *) &(image[k+4]), h1[1]);
1343          (void) sl_write (fout, image, ilen);
1344          (void) sl_close (fout);
1345          printf(_("new file %s written\n"), outpath);
1346          free(new); free (outpath); free(image);
1347          _exit (EXIT_SUCCESS);
1348          /*@notreached@*/
1349          return 0;
1350        }
1351    }
1352
1353  fprintf(stderr, "%s",
1354          _("ERROR: old key not found\n"));
1355  free(new); free (outpath); free(image);
1356  _exit (EXIT_FAILURE);
1357  /*@notreached@*/
1358  return -1;
1359
1360
1361 bail_mem:
1362  fprintf(stderr, "%s",
1363          _("ERROR: out of memory\n"));
1364  if (new) free(new); 
1365  if (outpath) free (outpath);
1366  if (image) free (image);
1367  _exit (EXIT_FAILURE);
1368  /*@notreached@*/
1369  return -1;
1370}
1371
1372 
1373
1374       
1375/* A simple en-/decoder, based on Vernam cipher. We use the
1376 * message as salt to hide the key by obtaining a different one-time
1377 * pad each time.
1378 * Should be safe against a listener on the network, but not against someone
1379 * with read access to the binary.
1380 */
1381void sh_util_encode (char * data, char * salt, int mode, char fill)
1382{
1383  static char     cc1[17] = N_("0123456789ABCDEF");
1384  char            cc[17] = "\0";
1385  register int    i, j, j1 = 0, j2 = 0, j3;
1386  char          * dez; 
1387  char hashbuf[KEYBUF_SIZE];
1388
1389  SL_ENTER(_("sh_util_encode"));
1390
1391  /* init
1392   */
1393  (void) sl_strlcpy( cc, _(cc1), sizeof(cc));
1394
1395  /* max 128 bits keyspace
1396   */
1397  memset (skey->vernam, (int)fill, KEY_LEN+1);
1398
1399  dez    = (char *) &(skey->ErrFlag[0]);
1400  sh_util_cpylong (skey->vernam,     dez, 4);
1401  dez    = (char *) &(skey->ErrFlag[1]);
1402  sh_util_cpylong (&skey->vernam[4], dez, 4);
1403
1404  skey->vernam[KEY_LEN] = '\0';
1405
1406  (void) sl_strlcpy(skey->vernam, 
1407                    sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN,
1408                                  hashbuf, sizeof(hashbuf)), 
1409                    KEY_LEN+1);
1410
1411  (void) sl_strlcpy(skey->vernam, 
1412                    sh_util_hmac_tiger (skey->vernam, salt, strlen(salt),
1413                                        hashbuf, sizeof(hashbuf)),
1414                    KEY_LEN+1);
1415
1416  (void) sl_strlcpy(skey->vernam, 
1417                    sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8,
1418                                        hashbuf, sizeof(hashbuf)),
1419                    KEY_LEN+1);
1420
1421  /* The following routine adds/subtracts  data[j] and vernam[j] mod 16.
1422   */
1423  j = 0;
1424  while (j < KEY_LEN)
1425    {
1426      for (i = 0; i < 16; ++i)
1427        {
1428          if (cc[i] == data[j])   j1 = i;
1429          if (cc[i] == skey->vernam[j])    j2 = i;
1430        }
1431      if (mode == 0)
1432        {
1433          j3 = j1 + j2;
1434          if (j3 > 15) j3 -= 16;
1435          data[j] = cc[j3];
1436        }
1437      else
1438        {
1439          j3 = j1 - j2;
1440          if (j3 <  0) j3 += 16;
1441          data[j] = cc[j3];
1442        }
1443      ++j;
1444    }
1445  SL_RET0(_("sh_util_encode"));
1446}
1447
1448/* server mode
1449 */
1450int sh_util_setserver (const char * dummy)
1451{
1452  SL_ENTER(_("sh_util_setserver"));
1453
1454  (void) dummy;
1455  sh.flag.isserver = GOOD;
1456  SL_RETURN((0),_("sh_util_setserver"));
1457}
1458
1459
1460int sh_util_setlooptime (const char * str)
1461{
1462  int i = atoi (str);
1463 
1464  SL_ENTER(_("sh_util_setlooptime"));
1465
1466  if (i >= 0 && i < INT_MAX) {
1467    sh.looptime = i;
1468    SL_RETURN((0),_("sh_util_setlooptime"));
1469  } else {
1470    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1471                     _("loop time"), str);
1472    SL_RETURN((-1),_("sh_util_setlooptime"));
1473  }
1474}
1475
1476#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1477int  sh_util_setchecksum (const char * str)
1478{
1479  static int reject = 0;
1480
1481  SL_ENTER(_("sh_util_setchecksum"));
1482
1483  if (reject == 1)
1484    SL_RETURN((0), _("sh_util_setchecksum"));
1485  reject = 1;
1486
1487  if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0)
1488    {
1489      sh.flag.checkSum = SH_CHECK_INIT;
1490    }
1491  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1492    {
1493      if (S_TRUE == file_is_remote()) 
1494        {
1495          sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1496                           _("checksum testing"), str);
1497          SL_RETURN((-1), _("sh_util_setchecksum"));
1498        }
1499      else
1500        {
1501          sh.flag.checkSum = SH_CHECK_CHECK;
1502          sh.flag.update   = S_TRUE;
1503        }
1504    }
1505  else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0)
1506    {
1507      sh.flag.checkSum = SH_CHECK_CHECK;
1508    }
1509  /*
1510  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1511    {
1512      sh.flag.checkSum = SH_CHECK_INIT;
1513      sh.flag.update   = S_TRUE;
1514    }
1515  */
1516  else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0)
1517    {
1518      sh.flag.checkSum = SH_CHECK_NONE;
1519    }
1520  else 
1521    {
1522      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1523                       _("checksum testing"), str);
1524      SL_RETURN((-1), _("sh_util_setchecksum"));
1525    }
1526  SL_RETURN((0), _("sh_util_setchecksum"));
1527}
1528#endif
1529 
1530/*@+charint@*/
1531unsigned char TcpFlag[8][PW_LEN+1] = { 
1532#if (POS_TF == 1)
1533  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1534#endif
1535  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1536#if (POS_TF == 2)
1537  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1538#endif
1539  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1540#if (POS_TF == 3)
1541  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1542#endif
1543  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1544#if (POS_TF == 4)
1545  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1546#endif
1547  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1548#if (POS_TF == 5)
1549  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1550#endif
1551  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1552#if (POS_TF == 6)
1553  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1554#endif
1555  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1556#if (POS_TF == 7)
1557  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1558#endif
1559  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1560#if (POS_TF == 8)
1561  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1562#endif
1563};
1564/*@-charint@*/
1565
1566/* initialize a key to a random value
1567 * rev 0.8
1568 */
1569int sh_util_keyinit (char * buf, long size)
1570{
1571  UINT32       bufy[6];
1572  int          i;
1573  int          status = 0;
1574  char       * p;
1575  char hashbuf[KEYBUF_SIZE];
1576
1577  SL_ENTER(_("sh_util_keyinit"));
1578
1579  ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1"))
1580
1581  if (size > KEY_LEN+1)
1582    size = KEY_LEN+1;
1583
1584  /* seed / re-seed the PRNG if required
1585   */
1586  status = taus_seed ();
1587
1588  if (status == -1)
1589    sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1,
1590                     _("taus_seed"));
1591
1592  for (i = 0; i < 6; ++i)
1593    bufy[i] = taus_get();
1594
1595  p = sh_tiger_hash ((char *) bufy, TIGER_DATA, 
1596                     (unsigned long)(6*sizeof(UINT32)),
1597                     hashbuf, sizeof(hashbuf));
1598
1599  i = sl_strlcpy(buf, p, (size_t)size);
1600
1601  memset (bufy, 0, 6*sizeof(UINT32));
1602
1603  if ((status == 0) && (!SL_ISERROR(i)) )
1604    SL_RETURN((0),_("sh_util_keyinit"));
1605
1606  if (SL_ISERROR(i))
1607    sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2, 
1608                     _("sl_strlcpy"));
1609
1610  SL_RETURN((-1),_("sh_util_keyinit"));
1611}
1612
1613#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1614
1615static unsigned char sh_obscure_index[256];
1616static int sh_obscure_no_check = S_FALSE;
1617
1618int sh_util_valid_utf8 (const unsigned char * str) 
1619{
1620  const int     sh_val_utf8_1 = 1;
1621  const int     sh_val_utf8_2 = 2;
1622  const int     sh_val_utf8_3 = 3;
1623  const int     sh_val_utf8_4 = 4;
1624
1625  size_t        len = strlen((const char *)str);
1626  size_t        l   = 0;
1627  int           typ = 0;
1628  unsigned char c     = '\0';
1629  unsigned char c2[2] = { 0x00, 0x00 };
1630  unsigned char c3[3] = { 0x00, 0x00, 0x00 };
1631
1632
1633#define SH_VAL_UTF8_1 ((c != '\0') && ((c & 0x80) == 0x00))
1634#define SH_VAL_UTF8_2 ((c != '\0') && ((c & 0xE0) == 0xC0)) /* 110x xxxx */
1635#define SH_VAL_UTF8_3 ((c != '\0') && ((c & 0xF0) == 0xE0)) /* 1110 xxxx */
1636#define SH_VAL_UTF8_4 ((c != '\0') && ((c & 0xF8) == 0xF0)) /* 1111 0xxx */
1637#define SH_VAL_UTF8_N ((c != '\0') && ((c & 0xC0) == 0x80)) /* 10xx xxxx */
1638#define SH_VAL_BAD    ((c == '"')  || (c == '\t') || (c == '\b') || \
1639                       (c == '\f') || (c == '\n') || \
1640                       (c == '\r') || (c == '\v') || iscntrl((int) c) || \
1641                       (c != ' ' && !isgraph ((int) c)))
1642   
1643  while(l < len) 
1644    {
1645      c = str[l];
1646
1647      if      (SH_VAL_UTF8_1) 
1648        {
1649          if (!(SH_VAL_BAD && (sh_obscure_index[c] != 1)))
1650            {
1651              typ = sh_val_utf8_1;
1652              ++l; continue;
1653            }
1654          else
1655            {
1656              return S_FALSE;
1657            }
1658        } 
1659      else if (SH_VAL_UTF8_2) 
1660        { 
1661          typ = sh_val_utf8_2;
1662          c2[0] = c;
1663          if ((c & 0x3e) != 0x00) /* !(overlong 2-byte seq.) */
1664            {
1665              ++l; 
1666              if (l != len) {
1667                c = str[l];
1668                if(SH_VAL_UTF8_N) {
1669                  c2[1] = c;
1670                  ++l; continue;
1671                } 
1672                else {
1673                  return S_FALSE;
1674                } 
1675              } 
1676              else {
1677                return S_FALSE; 
1678              }
1679            }
1680          else
1681            {
1682              return S_FALSE; /* overlong 2-byte seq. */
1683            }
1684        } 
1685      else if (SH_VAL_UTF8_3) 
1686        {
1687          typ = sh_val_utf8_3;
1688          c3[0] = c;
1689          ++l; if (l == len) return S_FALSE; c = str[l];
1690          if(!SH_VAL_UTF8_N) return S_FALSE;
1691          if (((str[l-1] & 0x1F) == 0x00) && ((c & 0x60) == 0x00))
1692            return S_FALSE; /* overlong 3-byte seq. */
1693          c3[1] = c;
1694          ++l; if (l == len) return S_FALSE; c = str[l];
1695          if(!SH_VAL_UTF8_N) return S_FALSE;
1696          c3[2] = c;
1697          ++l; continue;
1698        } 
1699      else if (SH_VAL_UTF8_4) 
1700        {
1701          typ = sh_val_utf8_4;
1702          ++l; if (l == len) return S_FALSE; c = str[l];
1703          if(!SH_VAL_UTF8_N) return S_FALSE;
1704          if (((str[l-1] & 0x0F) == 0x00) && ((c & 0x70) == 0x00))
1705            return S_FALSE; /* overlong 4-byte seq. */
1706          ++l; if (l == len) return S_FALSE; c = str[l];
1707          if(!SH_VAL_UTF8_N) return S_FALSE;
1708          ++l; if (l == len) return S_FALSE; c = str[l];
1709          if(!SH_VAL_UTF8_N) return S_FALSE;
1710          ++l; continue;
1711        }
1712      return S_FALSE;
1713    }
1714
1715  /* last character is invisible (space or else)
1716   */
1717  if (typ == sh_val_utf8_1)
1718    { 
1719      if (c != ' ')
1720        return S_TRUE;
1721      else
1722        return S_FALSE;
1723    }
1724  else if (typ == sh_val_utf8_2)
1725    {
1726      if (c2[0] == 0xC2 && c2[1] == 0xA0) /* nbsp */
1727        return S_FALSE;
1728      else
1729        return S_TRUE;
1730    }
1731  else if (typ == sh_val_utf8_3)
1732    {
1733      if (c3[0] == 0xE2) 
1734        {
1735          if (c3[1] == 0x80 && c3[2] >= 0x80 && c3[2] <= 0x8F)
1736            return S_FALSE; /* various spaces, left-to-right, right-to-left */
1737          else if (c3[1] == 0x80 && (c3[2] == 0xA8 || c3[2] == 0xA9 || 
1738                                     c3[2] == 0xAD || c3[2] == 0xAF))
1739            return S_FALSE; /* line sep, para sep, zw word joiner, nnbsp */
1740          else if (c3[1] == 0x81 && (c3[2] == 0xA0 || c3[2] == 0xA1 || 
1741                                     c3[2] == 0x9F))
1742            return S_FALSE; /* word joiner, function app, math space */
1743          else
1744            return S_TRUE;
1745        }
1746      else if (c3[0] == 0xE3 && c3[1] == 0x80 && c3[2] == 0x80)
1747        {
1748          return S_FALSE; /* ideographic space */
1749        }
1750      else if (c3[0] == 0xEF && c3[1] == 0xBB && c3[2] == 0xBF)
1751        {
1752          return S_FALSE; /* zwnbsp */
1753        }
1754      else
1755        {
1756          return S_TRUE;
1757        }
1758    }
1759  else
1760    {
1761      return S_TRUE;
1762    }
1763}
1764
1765
1766int sh_util_obscure_ok (const char * str)
1767{
1768  unsigned long   i;
1769  char * endptr = NULL;
1770
1771  SL_ENTER(_("sh_util_obscure_ok"));
1772
1773  if (0 == sl_strncmp("all", str, 3))
1774    {
1775      for (i = 0; i < 255; ++i)
1776        {
1777          sh_obscure_index[i] = (unsigned char)1;
1778        }
1779      sh_obscure_no_check = S_TRUE;
1780      SL_RETURN(0, _("sh_util_obscure_ok"));
1781    }
1782
1783  sh_obscure_no_check = S_FALSE;
1784
1785  for (i = 0; i < 255; ++i)
1786    {
1787      sh_obscure_index[i] = (unsigned char)0;
1788    }
1789
1790  i = strtoul (str, &endptr, 0);
1791  if (i > 255)
1792    {
1793      SL_RETURN(-1, _("sh_util_obscure_ok"));
1794    }
1795  sh_obscure_index[i] = (unsigned char)1;
1796  if (*endptr == ',')
1797    ++endptr;
1798
1799  while (*endptr != '\0')
1800    {
1801      i = strtoul (endptr, &endptr, 0);
1802      if (i > 255)
1803        {
1804          SL_RETURN(-1, _("sh_util_obscure_ok"));
1805        }
1806      sh_obscure_index[i] = (unsigned char)1;
1807      if (*endptr == ',')
1808        ++endptr;
1809    }
1810  SL_RETURN(0, _("sh_util_obscure_ok"));
1811}
1812
1813static int sh_obscure_check_utf8 = S_FALSE;
1814
1815int sh_util_obscure_utf8 (const char * c)
1816{
1817  int i;
1818  SL_ENTER(_("sh_util_obscure_utf8"));
1819  i = sh_util_flagval(c, &(sh_obscure_check_utf8));
1820  if (sh_obscure_check_utf8 == S_TRUE)
1821    sh_obscure_no_check = S_FALSE;
1822  SL_RETURN(i, _("sh_util_obscure_utf8"));
1823}
1824
1825
1826int sh_util_obscurename (ShErrLevel level, const char * name_orig, int flag)
1827{
1828  const unsigned char * name = (const unsigned char *) name_orig;
1829  char * safe;
1830  unsigned int i;
1831  size_t len = 0;
1832
1833  SL_ENTER(_("sh_util_obscurename"));
1834
1835  ASSERT_RET((name != NULL), _("name != NULL"), (0))
1836
1837  if (sh_obscure_no_check == S_FALSE)
1838    {
1839      if (sh_obscure_check_utf8 != S_TRUE)
1840        {
1841          /* -- Check name. --
1842           */
1843          while (*name != '\0') 
1844            {
1845              if ( (*name) >  0x7F || (*name) == '"'  || (*name) == '\t' ||
1846                   (*name) == '\b' || (*name) == '\f' || 
1847                   (*name) == '\n' || (*name) == '\r' ||
1848                   (*name) == '\v' || iscntrl((int) *name) || 
1849                   ((*name) != ' ' && !isgraph ((int) *name)) ) 
1850                {
1851                  i = (unsigned char) *name;
1852                  if (sh_obscure_index[i] != (unsigned char)1)
1853                    {
1854                      goto err;
1855                    }
1856                }
1857              name++; ++len;
1858            }
1859
1860          /* Check for blank at end of name
1861           */
1862          if ((len > 0) && (name_orig[len-1] == ' '))
1863            {
1864              goto err;
1865            }
1866        }
1867      else
1868        {
1869          if (S_FALSE == sh_util_valid_utf8(name))
1870            {
1871              goto err;
1872            }
1873          SL_RETURN((0),_("sh_util_obscurename"));
1874        }
1875    }
1876     
1877  SL_RETURN((0),_("sh_util_obscurename"));
1878
1879 err:
1880 
1881  if (flag == S_TRUE)
1882    {
1883      safe = sh_util_safe_name (name_orig); 
1884      sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, 
1885                       safe);
1886      SH_FREE(safe);
1887    }
1888  SL_RETURN((-1),_("sh_util_obscurename"));
1889}
1890
1891#endif
1892
1893/* returns freshly allocated memory, return value should be free'd
1894 */
1895char * sh_util_dirname(const char * fullpath)
1896{
1897  char * retval;
1898  size_t len;
1899  char * tmp;
1900
1901  SL_ENTER(_("sh_util_dirname"));
1902
1903  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1904  ASSERT_RET ((*fullpath == '/'), _("*fullpath == '/'"), (NULL))
1905
1906  retval = sh_util_strdup(fullpath);
1907
1908  tmp    = retval;
1909  while (*tmp == '/') ++tmp;
1910
1911  /* (1) only leading slashes -- return exact copy
1912   */
1913  if (*tmp == '\0')
1914    {
1915      SL_RETURN(retval, _("sh_util_dirname"));
1916    }
1917
1918  /* (2) there are non-slash characters, so delete trailing slashes
1919   */
1920  len    = sl_strlen (retval);     /* retval[len] is terminating '\0' */
1921
1922  while (len > 1 && retval[len-1] == '/')    /* delete trailing slash */
1923    {
1924      retval[len-1] = '\0';
1925      --len;
1926    }
1927
1928  /* (3) now delete all non-slash characters up to the preceding slash
1929   */
1930  while (len > 1 && retval[len-1] != '/') {
1931    retval[len-1] = '\0';
1932    --len;
1933  }
1934
1935  /* (4a) only leading slashes left, so return this
1936   */
1937  if (&(retval[len]) == tmp)
1938    {
1939      SL_RETURN(retval, _("sh_util_dirname"));
1940    }
1941
1942  /* (4b) strip trailing slash(es) of parent directory
1943   */
1944  while (len > 1 && retval[len-1] == '/') {
1945    retval[len-1] = '\0';
1946    --len;
1947  }
1948  SL_RETURN(retval, _("sh_util_dirname"));
1949
1950}
1951
1952/* returns freshly allocated memory, return value should be free'd
1953 */
1954char * sh_util_basename(const char * fullpath)
1955{
1956  char       * retval = NULL;
1957  const char * tmp;
1958  char       * tmp2;
1959  char       * c;
1960  size_t       len;
1961
1962  SL_ENTER(_("sh_util_basename"));
1963
1964  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1965
1966  tmp = fullpath; while (*tmp == '/') ++tmp;
1967  if (*tmp == '\0')
1968    {
1969      retval = sh_util_strdup(fullpath);
1970    }
1971  else
1972    {
1973      tmp2 = sh_util_strdup(tmp);
1974      len  = sl_strlen (tmp2);
1975
1976      while (len > 1 && tmp2[len-1] == '/')
1977        {
1978          tmp2[len-1] = '\0';
1979          --len;
1980        }
1981
1982      if (tmp2) /* for llvm/clang analyzer */
1983        {
1984          c = strrchr(tmp2, '/');
1985          if (c)
1986            {
1987              retval = sh_util_strdup(++c);
1988              SH_FREE(tmp2);
1989            }
1990          else
1991            {
1992              retval = tmp2;
1993            }
1994        }
1995    }
1996
1997  SL_RETURN(retval, _("sh_util_basename"));
1998}
1999
2000#define SH_ESCAPE_SPACE      1
2001#define SH_DONT_ESCAPE_SPACE 0   
2002char * sh_util_safe_name_int (const char * name, int escape_space);
2003
2004char * sh_util_safe_name (const char * name)
2005{
2006  return sh_util_safe_name_int (name, SH_ESCAPE_SPACE); 
2007}
2008
2009char * sh_util_safe_name_keepspace (const char * name)
2010{
2011  return sh_util_safe_name_int (name, SH_DONT_ESCAPE_SPACE); 
2012}
2013
2014/* returns freshly allocated memory, return value should be free'd
2015 */
2016char * sh_util_safe_name_int (const char * name, int escape_space)
2017{
2018  register int  i = 0;
2019  const char  * p;
2020  char        * retval;
2021  char          oct[32];
2022  char          format[16];
2023  size_t        len;
2024
2025  SL_ENTER(_("sh_util_safe_name"));
2026
2027  if (name == NULL)
2028    {
2029      /* return an allocated array
2030       */
2031      retval = SH_ALLOC(7);
2032      (void) sl_strlcpy(retval, _("(null)"), 7);
2033      SL_RETURN(retval, _("sh_util_safe_name"));
2034    }
2035
2036  /*
2037  ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL"))
2038  */
2039
2040  len = sl_strlen(name);
2041  p   = name;
2042
2043#ifdef SH_USE_XML
2044  if (sl_ok_muls (6, len) && sl_ok_adds ((6*len), 2))
2045    { retval = SH_ALLOC(6 * len + 2); }
2046  else
2047    {
2048      /* return an allocated array
2049       */
2050      retval = SH_ALLOC(11);
2051      (void) sl_strlcpy(retval, _("(overflow)"), 11);
2052      SL_RETURN(retval, _("sh_util_safe_name"));
2053    }
2054#else
2055  if (sl_ok_muls (4, len) && sl_ok_adds ((4*len), 2))
2056    { retval = SH_ALLOC(4 * len + 2); }
2057  else
2058    {
2059      /* return an allocated array
2060       */
2061      retval = SH_ALLOC(11);
2062      (void) sl_strlcpy(retval, _("(overflow)"), 11);
2063      SL_RETURN(retval, _("sh_util_safe_name"));
2064    }
2065#endif
2066
2067  (void) sl_strncpy(format, _("%c%03o"), 16);
2068
2069  while (*p != '\0') {
2070    /* Most frequent cases first
2071     */
2072    if ( ((*p) >= 'a' && (*p) <= 'z')  || ((*p) == '/') || ((*p) == '.') ||
2073         ((*p) >= '0' && (*p) <= '9')  || 
2074         ((*p) >= 'A' && (*p) <= 'Z')) {
2075      retval[i] = *p; 
2076    } else if ( (*p) == '\\') {           /* backslash        */
2077      retval[i] = '\\'; ++i; 
2078      retval[i] = '\\';
2079    } else if ( (*p) == '\n') {    /* newline          */
2080      retval[i] = '\\'; ++i; 
2081      retval[i] = 'n';
2082    } else if ( (*p) == '\b') {    /* backspace        */
2083      retval[i] = '\\'; ++i; 
2084      retval[i] = 'b';
2085    } else if ( (*p) == '\r') {    /* carriage  return */
2086      retval[i] = '\\'; ++i; 
2087      retval[i] = 'r';
2088    } else if ( (*p) == '\t') {    /* horizontal tab   */
2089      retval[i] = '\\'; ++i; 
2090      retval[i] = 't';
2091    } else if ( (*p) == '\v') {    /* vertical tab     */
2092      retval[i] = '\\'; ++i; 
2093      retval[i] = 'v';
2094    } else if ( (*p) == '\f') {    /* form-feed        */
2095      retval[i] = '\\'; ++i; 
2096      retval[i] = 'f';
2097#ifdef WITH_DATABASE
2098    } else if ( (*p) == '\'') {    /* single quote     */
2099      retval[i] = '\\'; ++i; 
2100      retval[i] = '\'';
2101#endif
2102    } else if ( (*p) == ' ') {     /* space            */
2103      if (escape_space) {
2104        retval[i] = '\\'; ++i; 
2105        retval[i] = ' ';
2106      }
2107      else {
2108        retval[i] = *p;
2109      }
2110#ifdef SH_USE_XML
2111    } else if ( (*p) == '"') {     /* double quote     */
2112      retval[i] = '&'; ++i; 
2113      retval[i] = 'q'; ++i;
2114      retval[i] = 'u'; ++i;
2115      retval[i] = 'o'; ++i;
2116      retval[i] = 't'; ++i;
2117      retval[i] = ';';
2118    } else if ( (*p) == '&') {     /* ampersand        */
2119      retval[i] = '&'; ++i; 
2120      retval[i] = 'a'; ++i;
2121      retval[i] = 'm'; ++i;
2122      retval[i] = 'p'; ++i;
2123      retval[i] = ';';
2124    } else if ( (*p) == '<') {     /* left angle       */
2125      retval[i] = '&'; ++i; 
2126      retval[i] = 'l'; ++i;
2127      retval[i] = 't'; ++i;
2128      retval[i] = ';';
2129    } else if ( (*p) == '>') {     /* right angle      */
2130      retval[i] = '&'; ++i; 
2131      retval[i] = 'g'; ++i;
2132      retval[i] = 't'; ++i;
2133      retval[i] = ';';
2134#else
2135    } else if ( (*p) == '"') {     /* double quote     */
2136      retval[i] = '\\'; ++i; 
2137      retval[i] = '\"';
2138#endif
2139    } else if (!isgraph ((int) *p)) {    /* not printable    */
2140      /*@-bufferoverflowhigh -formatconst@*/
2141      /* flawfinder: ignore */
2142      sprintf(oct, format, '\\',                 /* known to fit  */
2143              (unsigned char) *p);
2144      /*@+bufferoverflowhigh +formatconst@*/
2145      retval[i] = oct[0]; ++i;
2146      retval[i] = oct[1]; ++i;
2147      retval[i] = oct[2]; ++i;
2148      retval[i] = oct[3]; 
2149    } else {
2150      retval[i] = *p;
2151    }
2152    ++p;
2153    ++i;
2154  }
2155  retval[i] = '\0';
2156  SL_RETURN(retval, _("sh_util_safe_name"));
2157}
2158
2159int sh_util_isnum (const char *str)
2160{
2161  const char *p = str;
2162
2163  SL_ENTER(_("sh_util_isnum"));
2164
2165  ASSERT_RET ((str != NULL), _("str != NULL"), (-1))
2166
2167  while (p) {
2168    if (!isdigit((int) *p) ) 
2169      SL_RETURN((-1), _("sh_util_isnum"));
2170    ++p;
2171  }
2172  SL_RETURN((0), _("sh_util_isnum"));
2173}
2174
2175char * sh_util_strconcat (const char * arg1, ...)
2176{
2177  size_t    length, l2;
2178  char    * s;
2179  char    * strnew;
2180  va_list vl;
2181
2182  SL_ENTER(_("sh_util_strconcat"));
2183
2184  ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL))
2185
2186  length = sl_strlen (arg1) + 1;
2187
2188  va_start (vl, arg1);
2189  s = va_arg (vl, char * );
2190  while (s != NULL)
2191    {
2192      l2 = sl_strlen (s);
2193      if (sl_ok_adds(length, l2))
2194        length += l2;
2195      else
2196        SL_RETURN(NULL, _("sh_util_strconcat"));
2197      s = va_arg (vl, char * );
2198    }
2199  va_end (vl);
2200
2201  if (sl_ok_adds(length, 2))
2202    strnew = SH_ALLOC( length + 2 );
2203  else
2204    SL_RETURN(NULL, _("sh_util_strconcat"));
2205
2206  /* cppcheck-suppress uninitvar */
2207  strnew[0] = '\0';
2208
2209  (void) sl_strlcpy (strnew, arg1, length + 2); 
2210
2211  va_start (vl, arg1);
2212  s = va_arg (vl, char * );
2213  while (s)
2214    {
2215      (void) sl_strlcat (strnew, s, length + 2);
2216      s = va_arg (vl, char * );
2217    }
2218  va_end (vl);
2219
2220  SL_RETURN(strnew, _("sh_util_strconcat"));
2221}
2222
2223static const char bto64_0[] = N_("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()");
2224static char bto64[65] = { '\0' };
2225
2226 
2227size_t sh_util_base64_enc (unsigned char * out, 
2228                           const unsigned char * instr, 
2229                           size_t lin)
2230{
2231  int             ll;
2232  unsigned char   a, b, c;
2233  size_t          len  = 0;
2234  size_t          j    = 0;
2235
2236 start:
2237  if (bto64[0] != '\0')
2238    {
2239      if (instr /* && *instr *//* need to handle binary data */)
2240        {
2241          if (lin == 0)
2242            lin = strlen((const char *)instr);
2243
2244          if (lin > 0)
2245            {
2246              do {
2247                ll = 0;
2248               
2249                if (len < lin) 
2250                  { a = *instr; ++instr; ++len; ++ll; }
2251                else 
2252                  { a = 0; }
2253                if (len < lin) 
2254                  { b = *instr; ++instr; ++len; ++ll; }
2255                else 
2256                  { b = 0; }
2257                if (len < lin) 
2258                  { c = *instr; ++instr; ++len; ++ll; }
2259                else 
2260                  { c = 0; }
2261               
2262                *out = bto64[ a >> 2 ];
2263                ++j; ++out;
2264                *out = bto64[ ((a & 0x03) << 4) | ((b & 0xf0) >> 4) ];
2265                ++j; ++out;
2266                *out = (unsigned char) (ll > 1 ? bto64[ ((b & 0x0f) << 2) | ((c & 0xc0) >> 6) ] : '?');
2267                ++j; ++out;
2268                *out = (unsigned char) (ll > 2 ? bto64[ c & 0x3f ] : '?');
2269                ++j; ++out;
2270              } while (len < lin);
2271            }
2272        }
2273      *out = '\0';
2274      return j;
2275    }
2276
2277  memcpy(bto64, _(bto64_0), 65);
2278  goto start;
2279}
2280
2281size_t sh_util_base64_enc_alloc (char **out, const char *in, size_t inlen)
2282{
2283  size_t outlen = SH_B64_SIZ(inlen);
2284
2285  if (inlen > outlen) /* overflow */
2286    {
2287      *out = NULL;
2288      return 0;
2289    }
2290
2291  *out = SH_ALLOC(outlen);
2292  return sh_util_base64_enc((unsigned char *)*out, (const unsigned char *)in, inlen);
2293}
2294
2295size_t sh_util_base64_dec (unsigned char *out, 
2296                           const unsigned char *in, 
2297                           size_t lin)
2298{
2299  size_t i;
2300  unsigned char c;
2301  unsigned char b;
2302  size_t lout = 0;
2303  unsigned int  w = 0;
2304
2305  if (out && in)
2306    {
2307      if (lin == 0)
2308        lin = strlen((const char *)in);
2309
2310      for (i = 0; i < lin; i++)
2311        {
2312          c = *in; ++in;
2313          b = 0;
2314         
2315          if ((c >= 'A') && (c <= 'Z'))
2316            {
2317              b = (c - 'A');
2318            }
2319          else if ((c >= 'a') && (c <= 'z'))
2320            {
2321              b = (c - 'a' + 26);
2322            }
2323          else if ((c >= '0') && (c <= '9'))
2324            {
2325              b = (c - '0' + 52);
2326            }
2327          else if (c == '(' || c == '+')
2328            {
2329              b = 62;
2330            }
2331          else if (c == ')' || c == '/')
2332            {
2333              b = 63;
2334            }
2335          else if (c == '?' || c == '=')
2336            {
2337              /* last byte was written to, but will now get
2338               * truncated
2339               */
2340              if (lout > 0) --lout;
2341              break;
2342            }
2343         
2344          if (w == 0)
2345            {
2346              *out = (b << 2) & 0xfc;
2347              ++lout;
2348            }
2349          else if (w == 1)
2350            {
2351              *out |= (b >> 4) & 0x03;
2352              ++out;
2353              *out = (b << 4) & 0xf0;
2354              ++lout;
2355            }
2356          else if (w == 2)
2357            {
2358              *out |= (b >> 2) & 0x0f;
2359              ++out;
2360              *out = (b << 6) & 0xc0;
2361              ++lout;
2362            }
2363          else if (w == 3)
2364            {
2365              *out |= b & 0x3f;
2366              ++out;
2367            }
2368         
2369          ++w;
2370         
2371          if (w == 4)
2372            {
2373              w = 0;
2374            }
2375        }
2376      *out = '\0';
2377    }
2378  return lout;
2379}
2380
2381size_t sh_util_base64_dec_alloc (unsigned char **out, const unsigned char *in, 
2382                                 size_t lin)
2383{
2384  size_t lout = 3 * (lin / 4) + 2;
2385
2386  *out = SH_ALLOC(lout);
2387
2388  return sh_util_base64_dec (*out, in, lin);
2389}
2390
2391
2392#ifdef HAVE_REGEX_H
2393
2394#include <regex.h>
2395
2396int sh_util_regcmp (char * regex_str, char * in_str)
2397{
2398#if defined(REG_ESPACE)
2399  int        status = REG_ESPACE;
2400#else
2401  int        status = -1;
2402#endif
2403  regex_t    preg;
2404  char     * errbuf;
2405
2406  SL_ENTER(_("sh_util_regcmp"));
2407
2408  status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED);
2409
2410  if (status == 0)
2411    {
2412      if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0) 
2413        {
2414          regfree (&preg);
2415          SL_RETURN((0), _("sh_util_regcmp"));
2416        }
2417    }
2418
2419  if (status != 0 && status != REG_NOMATCH) 
2420    {
2421      errbuf = SH_ALLOC(BUFSIZ);
2422      (void) regerror(status, &preg, errbuf, BUFSIZ); 
2423      errbuf[BUFSIZ-1] = '\0';
2424      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX,
2425                       errbuf, regex_str);
2426      SH_FREE(errbuf);
2427    }
2428       
2429  regfree (&preg);
2430  SL_RETURN((-1), _("sh_util_regcmp"));
2431}
2432
2433#endif
2434
2435
2436
2437
2438
2439
2440
2441
Note: See TracBrowser for help on using the repository browser.