source: trunk/src/sh_utils.c @ 473

Last change on this file since 473 was 473, checked in by katerina, 7 years ago

Fix for ticket #371 (use cppcheck instead of uno for static checking).

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