source: trunk/src/sh_utils.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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