source: trunk/src/sh_tools.c @ 132

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

Make utility functions thread-safe.

File size: 40.6 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 <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27
28/* Must be early on FreeBSD
29 */
30#include <sys/types.h>
31
32#ifdef HAVE_MEMORY_H
33#include <memory.h>
34#endif
35
36#ifdef HAVE_SYS_SELECT_H
37#include <sys/select.h>
38#endif
39
40#ifdef  HAVE_UNISTD_H
41#include <errno.h>
42#include <signal.h>
43#include <setjmp.h>
44#include <pwd.h>
45#include <grp.h>
46#include <sys/stat.h>
47#include <sys/resource.h>
48#include <fcntl.h>
49#include <sys/wait.h>
50#include <unistd.h>
51#endif
52
53#include <sys/socket.h>
54
55#ifdef  HOST_IS_HPUX
56#define _XOPEN_SOURCE_EXTENDED
57#endif
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#include <netdb.h>
61
62#ifndef FD_SET
63#define NFDBITS         32
64#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
65#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
66#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
67#endif /* !FD_SET */
68#ifndef FD_SETSIZE
69#define FD_SETSIZE      32
70#endif
71#ifndef FD_ZERO
72#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
73#endif
74
75
76#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
77#include <sys/mman.h>
78#endif
79
80#define SH_REAL_SET
81
82#include "samhain.h"
83#include "sh_mem.h"
84#include "sh_error.h"
85#include "sh_tools.h"
86#include "sh_utils.h"
87#include "sh_tiger.h"
88#define SH_NEED_GETHOSTBYXXX
89#include "sh_static.h"
90
91#undef  FIL__
92#define FIL__  _("sh_tools.c")
93
94#ifdef SH_ENCRYPT
95#include "rijndael-api-fst.h"
96char * errorExplain (int err_num, char * buffer, size_t len)
97{
98  char * p;
99
100  if      (err_num == BAD_KEY_DIR)
101    p = (_("Key direction is invalid"));
102  else if (err_num == BAD_KEY_MAT) 
103    p = (_("Key material not of correct length"));
104  else if (err_num == BAD_KEY_INSTANCE) 
105    p = (_("Key passed is not valid"));
106  else if (err_num == BAD_CIPHER_MODE) 
107    p = (_("Params struct passed to cipherInit invalid"));
108  else if (err_num == BAD_CIPHER_STATE) 
109    p = (_("Cipher in wrong state"));
110  else if (err_num == BAD_BLOCK_LENGTH) 
111    p = (_("Bad block length"));
112  else if (err_num == BAD_CIPHER_INSTANCE) 
113    p = (_("Bad cipher instance"));
114  else if (err_num == BAD_DATA) 
115    p = (_("Data contents are invalid"));
116  else 
117    p = (_("Unknown error"));
118  sl_strlcpy (buffer, p, len);
119  return buffer;
120}
121
122#endif
123
124/* --- recode all \blah escapes to '=XX' format, and also code all
125 *     remaining unprintable chars                                 ---
126 */
127#define SH_PUT_4(p, a, b, c) (p)[0] = (a); (p)[1] = (b); (p)[2] = (c);
128 
129char * sh_tools_safe_name (const char * instr, int flag)
130{
131  unsigned char c, d;
132  const  char * p;
133  char   tmp[4];
134  char * outstr;
135  size_t len = 1;
136  int    i = 0;
137  unsigned char   val_octal = '\0';
138  static char ctable[16] = { '0', '1', '2', '3', '4', '5', '6', '7', 
139                             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 
140
141  SL_ENTER(_("sh_tools_safe_name"));
142
143  if (instr)
144    {
145      len = strlen(instr);
146      if (sl_ok_muls (3, len) && sl_ok_adds ((3*len), 4))
147        {
148          len = (3 * len) + 4;
149          p = instr;
150        }
151      else
152        {
153          len = 1;
154          p   = NULL;
155        }
156    }
157  else
158    {
159      p = NULL;
160    }
161
162  outstr = SH_ALLOC(len);
163
164  outstr[0] = '\0';
165  tmp[3]    = '\0';
166
167#if !defined(SH_USE_XML)
168  (void) flag; /* fix compiler warning */
169#endif
170
171  if (!p)
172    goto end;
173
174  while (*p)
175    {
176      c = *p;
177
178      if (*p == '\n')
179        {
180          outstr[i] = ' '; ++i; ++p;
181          continue;
182        }
183
184#ifdef SH_USE_XML
185      if (flag == 1)
186        {
187          if ((*p) == '"')
188            { 
189              SH_PUT_4(&outstr[i], '=', '2', '2');
190              i+=3; ++p;
191              continue;
192            } 
193          else if ((*p) == '&')
194            { 
195              SH_PUT_4(&outstr[i], '=', '2', '6');
196              i+=3; ++p;
197              continue;
198            } 
199          else if ((*p) == '<') 
200            {     /* left angle       */
201              SH_PUT_4(&outstr[i], '=', '3', 'c');
202              i+=3; ++p;
203              continue;
204            } 
205          else if ((*p) == '>') 
206            {     /* right angle      */
207              SH_PUT_4(&outstr[i], '=', '3', 'e');
208              i+=3; ++p;
209              continue;
210            }
211        }
212#endif
213
214      if ( (*p) != '\\' && (*p) != '&' && (*p) != '='  && (*p) != '\'') 
215        {
216          outstr[i] = *p; ++i;
217          ++p;
218             
219          if (c < 32 || c > 126)
220            {
221              --i;
222              d = c % 16; c = c / 16;
223              outstr[i] = '=';       ++i;
224              outstr[i] = ctable[c]; ++i;
225              outstr[i] = ctable[d]; ++i;
226            }
227
228          continue;
229        }
230      else if ((*p) == '\'')
231        {
232          SH_PUT_4(&outstr[i], '=', '2', '7');
233          i+=3; ++p;
234        }
235      else if (*p == '=')
236        {
237          if (p[1] != '"' && p[1] != '<')
238            { 
239              SH_PUT_4(&outstr[i], '=', '3', 'd');
240              i+=3; ++p;
241            }
242          else
243            { outstr[i] = *p; ++i; ++p; }
244        }
245      else if (*p == '\\')
246        {
247          ++p;
248          if (!p)
249            break;
250          if (!(*p))
251            break;
252
253          c = *p;
254
255          switch (*p) {
256          case '\\':
257            SH_PUT_4(&outstr[i], '=', '5', 'c');
258            i+=3; ++p;
259            break;
260          case 'n':
261            SH_PUT_4(&outstr[i], '=', '0', 'a');
262            i+=3; ++p;
263            break;
264          case 'b':
265            SH_PUT_4(&outstr[i], '=', '0', '8');
266            i+=3; ++p;
267            break;                     
268          case 'r':                   
269            SH_PUT_4(&outstr[i], '=', '0', 'd');
270            i+=3; ++p;
271            break;                     
272          case 't':                   
273            SH_PUT_4(&outstr[i], '=', '0', '9');
274            i+=3; ++p;
275            break;                     
276          case 'v':                   
277            SH_PUT_4(&outstr[i], '=', '0', 'b');
278            i+=3; ++p;
279            break;                     
280          case 'f':                   
281            SH_PUT_4(&outstr[i], '=', '0', 'c');
282            i+=3; ++p;
283            break;                     
284          case '\'':                   
285            SH_PUT_4(&outstr[i], '=', '2', '7');
286            i+=3; ++p;
287            break;                     
288          case '"':     /* also encode quoted '"' */           
289            SH_PUT_4(&outstr[i], '=', '2', '2');
290            i+=3; ++p;
291            break;                     
292          case ' ':                   
293            SH_PUT_4(&outstr[i], '=', '2', '0');
294            i+=3; ++p;
295            break;
296          default:
297            if (strlen(p) < 3) /* certainly not an octal number, skip */
298              {
299                p += strlen(p);
300              }
301            else
302              {
303                tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; 
304                val_octal = (unsigned char) strtoul(tmp, (char **)NULL, 8);
305                if (val_octal != '\0') { 
306                  c = val_octal;
307                  d = c % 16; c = c / 16;
308                  outstr[i] = '=';       ++i;
309                  outstr[i] = ctable[c]; ++i;
310                  outstr[i] = ctable[d]; ++i;
311                } 
312                p += 3;
313              }
314          }
315        }
316      else if (*p == '&')
317        {
318          ++p;
319          if (!p || !(*p))
320            {
321              outstr[i] = '&'; ++i;
322              break;
323            }
324
325          if (p[0] == 'a' && p[1] == 'm' && p[2] == 'p' && p[3] == ';')
326            {
327              SH_PUT_4(&outstr[i], '=', '2', '6');
328              i+=3; p += 4;
329            }
330          else if (p[0] == 'q' && p[1] == 'u' && p[2] == 'o' && p[3] == 't' &&
331                   p[4] == ';')
332            {
333              SH_PUT_4(&outstr[i], '=', '2', '2');
334              i+=3; p += 5;
335            }
336          else if (p[0] == 'l' && p[1] == 't' && p[2] == ';')
337            {
338              SH_PUT_4(&outstr[i], '=', '3', 'c');
339              i+=3; p += 3;
340            }
341          else if (p[0] == 'g' && p[1] == 't' && p[2] == ';')
342            {
343              SH_PUT_4(&outstr[i], '=', '3', 'e');
344              i+=3; p += 3;
345            }
346          else /* conserve the '&' */
347            {
348              outstr[i] = '&'; ++i;
349            }
350        }
351      else
352        {
353          outstr[i] = *p; ++i;
354          ++p;
355        }
356    } /* while (p && *p) */
357
358 end:
359 
360  outstr[i] = '\0';
361  SL_RETURN( outstr, _("sh_tools_safe_name"));
362}
363
364
365/* extern int h_errno; */ 
366
367char * sh_tools_errmessage (int tellme, char * errbuf, size_t len)
368{
369  char * p = NULL;
370#ifdef HOST_NOT_FOUND
371    if (tellme == HOST_NOT_FOUND) 
372      p = _("The specified host is unknown: ");
373#endif
374#ifdef NO_ADDRESS
375    if (tellme == NO_ADDRESS) 
376      p = _("The requested name is valid but does not have an IP address: ");
377#endif
378#ifdef NO_RECOVERY
379    if (tellme == NO_RECOVERY) 
380      p = _("A non-recoverable name server error occurred: ");
381#endif
382#ifdef TRY_AGAIN
383    if (tellme == TRY_AGAIN) 
384      p = _("A temporary error occurred on an authoritative name server. The specified host is unknown: ");
385#endif
386    if (!p) p =  _("Unknown error");
387    sl_strlcpy(errbuf, p, len);
388    return errbuf;
389}
390
391int is_numeric (const char * address)
392{
393  int j;
394  int len = sl_strlen(address);
395 
396  for (j = 0; j < len; ++j)
397    if ( (address[j] < '0' || address[j] > '9') && address[j] != '.')
398      return (1 == 0);
399  return (1 == 1);
400}
401
402#if defined (SH_WITH_SERVER)
403
404int get_open_max ()
405{
406  int value;
407
408#ifdef _SC_OPEN_MAX
409  value = sysconf (_SC_OPEN_MAX);
410#else
411#ifdef OPEN_MAX
412  value = OPEN_MAX;
413#else
414  value = _POSIX_OPEN_MAX;
415#endif
416#endif
417
418  if (value < 0)
419    value = 8;  /* POSIX lower limit */
420
421  if (value > 4096)
422    value = 4096;
423
424  return value;
425}
426
427#endif
428
429typedef struct _sin_cache {
430  char * address;
431  struct sockaddr_in sin;
432  struct _sin_cache * next;
433} sin_cache;
434
435static sin_cache * conn_cache = NULL;
436static int cached_addr = 0;
437
438void delete_cache()
439{
440  sin_cache * check_cache = conn_cache;
441  sin_cache * old_entry   = conn_cache;
442
443  SL_ENTER(_("delete_cache"));
444
445  while (check_cache != NULL)
446    {
447      old_entry   = check_cache;
448      check_cache = check_cache->next;
449      SH_FREE(old_entry->address);
450      SH_FREE(old_entry);
451    }
452
453  cached_addr = 0;
454
455  conn_cache = NULL;
456  SL_RET0(_("delete_cache"));
457}
458     
459int DoReverseLookup = S_TRUE;
460
461int set_reverse_lookup (const char * c)
462{
463  return sh_util_flagval(c, &DoReverseLookup);
464}
465
466int connect_port (char * address, int port, 
467                  char * ecall, int * errnum, char * errmsg, int errsiz)
468{
469  struct in_addr       haddr;   /* host address from numeric                */
470                                /* host details returned by the DNS         */
471  struct hostent *host_entry = NULL;   
472  struct sockaddr_in sinr;      /* socket to the remote host                */
473
474  char   * host_name;
475
476  int    fd = (-1);
477  int    status;
478  int    fail   = 0;
479  int    cached = 0;
480
481  int    retval;
482  char   errbuf[SH_ERRBUF_SIZE];
483
484  sin_cache * check_cache = conn_cache;
485
486  SL_ENTER(_("connect_port"));
487
488  /* paranoia -- should not happen
489   */
490  if (cached_addr > 128)
491    delete_cache();
492
493  if (check_cache != NULL)
494    {
495      while (check_cache && check_cache->address)
496        {
497          if ( 0 == sl_strncmp(check_cache->address, 
498                               address, sl_strlen(address)))
499            {
500              memcpy (&sinr, &(check_cache->sin), sizeof(struct sockaddr_in));
501              sinr.sin_family = AF_INET;
502              sinr.sin_port   = htons (port);
503              cached = 1;
504              break;
505            }
506          if (check_cache->next)
507            check_cache = check_cache->next;
508          else
509            check_cache = NULL;
510        }
511    }
512
513  /* only use gethostbyname() if neccessary
514   */
515  if (cached == 0)
516    {
517#ifdef HAVE_INET_ATON
518      if (0 == inet_aton(address, &haddr))
519#else
520      if ((unsigned long)-1  == (haddr.s_addr = inet_addr(address)))
521#endif
522        {
523     
524          host_entry = sh_gethostbyname(address);
525
526          if (host_entry == NULL || host_entry->h_addr == NULL) 
527            {
528              sl_strlcpy(ecall, _("gethostbyname"), SH_MINIBUF);
529#ifndef NO_H_ERRNO
530              *errnum = h_errno;
531#else
532              *errnum = 666;
533#endif
534              (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
535              sl_strlcat(errmsg, address, errsiz); 
536              fail = (-1);
537            }
538          else
539            {
540              sinr.sin_family = AF_INET;
541              sinr.sin_port   = htons (port);
542              sinr.sin_addr   = *(struct in_addr *) host_entry->h_addr;
543
544
545              /* reverse DNS lookup
546               */
547              if (DoReverseLookup == S_TRUE)
548                {
549                  if (host_entry->h_name == NULL)
550                    {
551                      host_name = SH_ALLOC(1);
552                      host_name[0] = '\0';
553                    }
554                  else
555                    {
556                      host_name = sh_util_strdup(host_entry->h_name);
557                    }
558
559                  host_entry = sh_gethostbyaddr ((char *) &sinr.sin_addr, 
560                                              sizeof(struct in_addr),
561                                              AF_INET);
562                  if (host_entry == NULL || host_entry->h_name == NULL)
563                    {
564                      sl_strlcpy(ecall, _("gethostbyaddr"), SH_MINIBUF);
565#ifndef NO_H_ERRNO
566                      *errnum = h_errno;
567#else
568                      *errnum = 666;
569#endif
570                      (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
571                      sl_strlcat(errmsg, 
572                                 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
573                                 errsiz); 
574                      fail = (-1);
575                    }
576                  else
577                    {
578                      *errnum = 0;
579                      if (sl_strlen(host_entry->h_name) == 0 || 
580                          (*errnum = sl_strcmp(host_name,host_entry->h_name)) != 0)
581                        { 
582                          if (*errnum)
583                            sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
584                          else
585                            sl_strlcpy(ecall, _("strlen"), SH_MINIBUF);
586                          sl_strlcpy(errmsg, _("Reverse lookup failed."), 
587                                     errsiz);
588                          sl_strlcat(errmsg, address, errsiz);
589                          sl_strlcat(errmsg, _(" vs "), errsiz);
590                          sl_strlcat(errmsg, 
591                                     inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
592                                     errsiz);
593                          fail = -1;
594                        }
595                    }
596
597                  SH_FREE(host_name);
598                }
599            }
600        }
601 
602      else  /* address was numeric */
603        {
604          sinr.sin_family = AF_INET;
605          sinr.sin_port   = htons (port);
606          sinr.sin_addr   = haddr;
607        }
608
609
610      if (fail != -1)
611        {
612          /* put it into the cache
613           */
614          check_cache          = SH_ALLOC(sizeof(sin_cache));
615          check_cache->address = SH_ALLOC(sl_strlen(address) + 1);
616          sl_strlcpy (check_cache->address, address, sl_strlen(address) + 1);
617          memcpy(&(check_cache->sin), &sinr, sizeof(struct sockaddr_in));
618          ++cached_addr;
619         
620          if (conn_cache)
621            {
622              if (conn_cache->next)
623                check_cache->next    = conn_cache->next;
624              else
625                check_cache->next    = NULL;
626              conn_cache->next     = check_cache;
627            }
628          else
629            {
630              check_cache->next    = NULL;
631              conn_cache           = check_cache;
632            }
633        }
634    }
635
636 
637  if (fail != (-1)) 
638    { 
639      fd = socket(AF_INET, SOCK_STREAM, 0);
640      if (fd < 0) {
641        fail   = (-1);
642        status = errno;
643        sl_strlcpy(ecall, _("socket"), SH_MINIBUF);
644        *errnum = status;
645        sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
646        sl_strlcat(errmsg, _(", address "), errsiz);
647        sl_strlcat(errmsg, address, errsiz);
648      }
649    }
650 
651  if (fail != (-1)) {
652   
653    if ( retry_connect(FIL__, __LINE__, fd, 
654                       (struct sockaddr *) &sinr, sizeof(sinr)) < 0) 
655      {
656        status = errno;
657        sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
658        *errnum = status;
659        sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
660        sl_strlcat(errmsg, _(", address "), errsiz);
661        sl_strlcat(errmsg, address, errsiz);
662        close(fd);
663        fail = (-1); 
664      }
665  }
666
667  retval = (fail < 0) ? (-1) : fd;
668  SL_RETURN(retval, _("connect_port"));
669}
670
671int connect_port_2 (char * address1, char * address2, int port, 
672                    char * ecall, int * errnum, char * errmsg, int errsiz)
673{
674  int retval = (-1);
675
676  SL_ENTER(_("connect_port_2"));
677
678  errmsg[0] = '\0';
679  *errnum = 0;
680
681  if (address1 != NULL && address1[0] != '\0')
682    retval = connect_port (address1, port, 
683                           ecall, errnum, 
684                           errmsg, errsiz);
685
686  if (retval < 0 && address2 != NULL && address2[0] != '\0')
687    {
688      /* can't use sh_error_handle here, as this would cause an infinite
689       * loop if called from sh_unix_time
690       */
691      TPT(( 0, FIL__, __LINE__, _("msg=<Using alternative server %s.>\n"),
692            address2));
693      retval = connect_port (address2, port, 
694                             ecall, errnum, 
695                             errmsg, errsiz);
696    }
697
698  if ((retval < 0) &&
699      (address1 == NULL || address1[0] == '\0') &&
700      (address1 == NULL || address1[0] == '\0'))
701    {
702      sl_strlcpy(ecall, _("connect_port_2"), SH_MINIBUF);
703      sl_strlcpy(errmsg, _("No server address known"), errsiz);
704    }
705  SL_RETURN(retval, _("connect_port_2"));
706  /* return retval; */
707}
708
709#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
710static
711int sh_write_select(int type, int sockfd, 
712                    char *buf, int nbytes, 
713                    int * w_error, int timeout)
714{
715  int    countbytes, count;
716  fd_set fds;
717  struct timeval tv;
718  int    select_now;
719  int    num_sel;
720 
721  struct  sigaction  new_act;
722  struct  sigaction  old_act;
723  char    errbuf[SH_ERRBUF_SIZE];
724
725  SL_ENTER(_("sh_write_select"));
726
727  /* ignore SIGPIPE (instead get EPIPE if connection is closed)
728   */
729  new_act.sa_handler = SIG_IGN;
730  sigemptyset( &new_act.sa_mask );         /* set an empty mask       */
731  new_act.sa_flags = 0;                    /* init sa_flags           */
732  sigaction (SIGPIPE, &new_act, &old_act);
733 
734  FD_ZERO(&fds);
735  FD_SET(sockfd, &fds);
736
737  countbytes   = 0;
738  tv.tv_sec    = 1;
739  tv.tv_usec   = 0;
740  select_now   = 0;
741
742  *w_error = 0;
743
744  while ( countbytes < nbytes ) {
745
746    FD_ZERO(&fds);
747    FD_SET(sockfd, &fds);
748
749    if (type == SH_DO_WRITE) 
750      {
751        if ( (num_sel = select (sockfd+1, NULL, &fds, NULL, &tv)) == -1) 
752          {
753            if (sig_raised == 1)
754              {
755                sig_raised = 2;
756                continue;
757              }
758            if ( errno == EINTR) /* try again */
759              continue;
760            *w_error = errno;
761            TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), 
762                  sh_error_message(*w_error, errbuf, sizeof(errbuf))));
763            sigaction (SIGPIPE, &old_act, NULL);
764            SL_RETURN( countbytes, _("sh_write_select"));
765          }
766      }
767    else
768      {
769        if ( (num_sel = select (sockfd+1, &fds, NULL, NULL, &tv)) == -1) 
770          {
771            if (sig_raised == 1)
772              {
773                sig_raised = 2;
774                continue;
775              }
776            if ( errno == EINTR ) /* try again */
777              continue;
778            *w_error = errno;
779            TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), 
780                  sh_error_message(*w_error, errbuf, sizeof(errbuf))));
781            sigaction (SIGPIPE, &old_act, NULL);
782            SL_RETURN( countbytes, _("sh_write_select"));
783          }
784      }
785     
786    /* on Linux, timeout  is  modified to reflect the amount of
787     * time not slept
788     */
789    tv.tv_sec    = 1;
790    tv.tv_usec   = 0;
791
792
793    /* let's not hang on forever
794     */
795    if (num_sel == 0) 
796      {
797        ++select_now;       /* timeout */
798        if ( select_now > timeout )  /* 5 minutes */
799          {
800#ifdef ETIMEDOUT
801            *w_error = ETIMEDOUT;
802#else
803            *w_error = 0;
804#endif
805            sigaction (SIGPIPE, &old_act, NULL);
806            TPT(( 0, FIL__, __LINE__, _("msg=<Timeout>\n")));
807            SL_RETURN( countbytes, _("sh_write_select"));
808          }
809      }
810   
811    if ( FD_ISSET (sockfd, &fds) ) 
812      {
813        if (type == SH_DO_WRITE)
814          count = write (sockfd, buf, nbytes-countbytes);
815        else
816          count = read  (sockfd, buf, nbytes-countbytes);
817
818        if (count > 0) 
819        {
820          countbytes += count;
821          buf        += count;    /* move buffer pointer forward */
822          if (countbytes < nbytes) FD_SET( sockfd, &fds );
823        }
824        else if (count < 0 && errno == EINTR)
825          {
826            FD_SET( sockfd, &fds );
827          }
828        else if (count < 0)
829          {
830            *w_error = errno;
831            sigaction (SIGPIPE, &old_act, NULL);
832            TPT(( 0, FIL__, __LINE__, _("msg=<count < 0>\n")));
833            SL_RETURN( countbytes, _("sh_write_select"));
834          }
835        else /* count == 0 */
836          {
837            *w_error = errno;
838            sigaction (SIGPIPE, &old_act, NULL);
839            TPT(( 0, FIL__, __LINE__, _("msg=<count == 0>\n")));
840            SL_RETURN( countbytes, _("sh_write_select"));
841          }
842      }
843  }
844
845
846  /* restore signal handler
847   */
848  sigaction (SIGPIPE, &old_act, NULL);
849
850  *w_error = 0;
851
852  TPT(( 0, FIL__, __LINE__, _("msg=<count = %d>\n"), countbytes));
853  SL_RETURN( countbytes, _("sh_write_select"));
854}
855#endif
856
857#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
858unsigned long write_port (int sockfd, char *buf, unsigned long nbytes, 
859                          int * w_error, int timeout)
860{
861  unsigned long bytes;
862
863  SL_ENTER(_("write_port"));
864
865  bytes = sh_write_select(SH_DO_WRITE, sockfd, buf, nbytes, w_error, timeout);
866  if (*w_error != 0)
867    {
868      char errbuf[SH_ERRBUF_SIZE];
869      sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP, 
870                      sh_error_message (*w_error, errbuf, sizeof(errbuf)),
871                      (long) sockfd, _("write_port"));
872    }
873  SL_RETURN( bytes, _("write_port"));
874}
875#endif
876
877#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
878
879unsigned long read_port (int sockfd, char *buf, unsigned long nbytes, 
880               int * w_error, int timeout)
881{
882  unsigned long bytes;
883
884  SL_ENTER(_("read_port"));
885
886  bytes = sh_write_select(SH_DO_READ, sockfd, buf, nbytes, w_error, timeout);
887  if (*w_error != 0)
888    {
889      char errbuf[SH_ERRBUF_SIZE];
890      sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP, 
891                      sh_error_message (*w_error, errbuf, sizeof(errbuf)),
892                      (long) sockfd, _("read_port"));
893    }
894  SL_RETURN( bytes, _("read_port"));
895}
896#endif
897
898#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
899
900int check_request_nerr (char * have, char * need)
901{
902  SL_ENTER(_("check_request_nerr"));
903  ASSERT_RET((have != NULL && need != NULL), 
904             _("have != NULL && need != NULL"), (-1))
905
906  if ( (have[0] == need[0]) && (have[1] == need[1]) &&
907       (have[2] == need[2]) && (have[3] == need[3]))
908    SL_RETURN(0, _("check_request_nerr"));
909  SL_RETURN((-1), _("check_request_nerr"));
910}
911#endif
912
913#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
914
915int check_request (char * have, char * need)
916{
917  char first[21], second[5];
918  int  i;
919
920  SL_ENTER(_("check_request"));
921  i = check_request_nerr (have, need);
922
923  if (i == 0)
924    SL_RETURN(0, _("check_request"));
925
926  for (i = 0; i < 4; ++i)
927    {
928      second[i] = need[i];
929      sprintf(&first[i*4], _("%c%03o"),               /* known to fit  */
930              '\\', (unsigned char) have[i]);
931    }
932
933  first[20] = '\0'; second[4] = '\0';
934
935  sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST, 
936                  second, first);
937  SL_RETURN((-1), _("check_request"));
938}
939#endif
940
941#if defined (SH_WITH_SERVER)
942
943int check_request_s (char * have, char * need, char * clt)
944{
945  char first[21], second[5];
946  int  i;
947
948  SL_ENTER(_("check_request_s"));
949  i = check_request_nerr (have, need);
950
951  if (i == 0)
952    SL_RETURN( (0), _("check_request_s"));
953
954  for (i = 0; i < 4; ++i)
955    {
956      second[i] = need[i];
957      sprintf(&first[i*4], _("%c%03o"),               /* known to fit  */
958              '\\', (unsigned char) have[i]);
959    }
960  first[20] = '\0'; second[4] = '\0';
961  sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST1, 
962                  second, first, clt);
963  SL_RETURN( (-1), _("check_request_s"));
964}
965#endif
966
967#if defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)
968
969void get_header (unsigned char * head, unsigned long * bytes, char * u)
970{
971  SL_ENTER(_("get_header"));
972
973  *bytes = 
974    (256 * (unsigned int)head[1] + (unsigned int)head[2]);
975
976  if (u != NULL)
977    {
978      u[0]     = head[3];
979      u[1]     = head[4];
980      u[2]     = head[5];
981      u[3]     = head[6];
982      u[4]     = '\0';
983    }
984
985  SL_RET0(_("get_header"));
986}
987#endif
988
989#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
990
991#ifdef  SH_ENCRYPT_2
992#define TRANS_BYTES 65120
993#else
994#define TRANS_BYTES 65280
995#endif
996
997void put_header (unsigned char * head, int protocol, 
998                 unsigned long * length, char * u)
999{
1000
1001  /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
1002  static unsigned long transfer_limit = TRANS_BYTES + 6 + KEY_LEN;
1003
1004  SL_ENTER(_("put_header"));
1005
1006  head[0]   = protocol;
1007
1008  ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
1009
1010  if (*length > transfer_limit)
1011    *length = transfer_limit;
1012
1013  head[1]   = (unsigned int)(*length/256);
1014  head[2]   = (unsigned int)(*length-256 * head[1]);
1015  if (u == NULL)
1016    {
1017      head[3] = 0x01;
1018      head[4] = 0x01;
1019      head[5] = 0x01;
1020      head[6] = 0x01;
1021    }
1022  else
1023    {
1024      head[3]   = u[0];
1025      head[4]   = u[1];
1026      head[5]   = u[2];
1027      head[6]   = u[3];
1028    }
1029
1030  SL_RET0(_("put_header"));
1031}
1032#endif
1033
1034/* ------------------------------------------
1035 *
1036 *  version 2 client/server protocol
1037 *
1038 * ------------------------------------------
1039 *
1040 * header :  flag size[2]
1041 *
1042 * payload:  random_pad[8] protocol[4] size[4] payload[payload_size] padding
1043 *
1044 * full_size <= 8192; payload_size <= 8176 (511*16); msg_size <= 8128 (508*16)
1045 * (msg_size = payload_size - key_len = payload_size - 48)
1046 */ 
1047
1048/*
1049 * only SH_V2_FULLSIZE is used, and only once
1050 */
1051#if 0
1052#ifdef SH_WITH_SERVER
1053#define SH_V2_FULLSIZE  240
1054#define SH_V2_PAYLOAD   224
1055#define SH_V2_MESSAGE   176
1056#else
1057#define SH_V2_FULLSIZE 1024
1058#define SH_V2_PAYLOAD  1008
1059#define SH_V2_MESSAGE   960
1060#endif
1061#endif
1062#define SH_V2_FULLSIZE 1024
1063
1064#ifdef SH_ENCRYPT
1065#include "rijndael-api-fst.h"
1066#endif
1067
1068void sh_tools_show_header (unsigned char * head, char sign)
1069{
1070#define SH_IS_ASCII(c) (((c) & ~0x7f) == 0)
1071
1072
1073  int    msg_size = (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1074  char   code[32]; 
1075  char * p = &code[0];
1076
1077  memset (code, ' ', 32); /* space */
1078 
1079  if ((head[0] & SH_PROTO_SRP) != 0) { p[0]='S';p[1]='R';p[2]='P';}
1080  p += 4;
1081  if ((head[0] & SH_PROTO_MSG) != 0) { p[0]='M';p[1]='S';p[2]='G';}
1082  p += 4;
1083  if ((head[0] & SH_PROTO_BIG) != 0) { p[0]='B';p[1]='I';p[2]='G';}
1084  p += 4;
1085  if ((head[0] & SH_PROTO_END) != 0) { p[0]='E';p[1]='N';p[2]='D';}
1086  p += 4;
1087  if ((head[0] & SH_PROTO_ENC) != 0) { p[0]='E';p[1]='N';p[2]='C';}
1088  p += 4;
1089  if ((head[0] & SH_PROTO_EN2) != 0) { p[0]='E';p[1]='N';p[2]='2';}
1090  code[23] = '\0';
1091
1092  if (SH_IS_ASCII(head[3]) && isalpha(head[3]) &&
1093      SH_IS_ASCII(head[4]) && isalpha(head[4]) &&                         
1094      SH_IS_ASCII(head[5]) && isalpha(head[5]) &&                         
1095      SH_IS_ASCII(head[6]) && isalpha(head[6])) {
1096    fprintf(stderr, "%c %3o %s %5d  %c  %c  %c  %c\n", sign,
1097            head[0], code, msg_size, head[3], head[4], head[5], head[6]); 
1098  } else {
1099    fprintf(stderr, "%c %3o %s %5d %2X %2X %2X %2X\n", sign,
1100            head[0], code, msg_size, head[3], head[4], head[5], head[6]); 
1101  }
1102  return;
1103}
1104
1105#ifdef SH_ENCRYPT
1106/*
1107 * #define DEBUG_EN2
1108 *
1109 * ingest version 1 7-byte header and payload, return version2 header/payload
1110 * last 4 bytes of outgoing header are set to dummy value
1111 */
1112char * sh_tools_makePack (unsigned char * header, 
1113                          char * payload, unsigned long payload_size,
1114                          keyInstance * keyInstE)
1115{
1116  UINT32 rpad[3];
1117  unsigned char   head[16];
1118  double epad;
1119  unsigned long    i_epad = 0;
1120  unsigned long    i_blk = payload_size / 16;
1121  unsigned long    i_blkmax = SH_V2_FULLSIZE / 16;
1122  unsigned long    pads = 0;
1123  size_t full_size;
1124  char * full_ret;
1125
1126  char                  * p;
1127  RIJ_BYTE                    inBlock[B_SIZ]; 
1128  RIJ_BYTE                    outBlock[B_SIZ];
1129  int                     j;
1130  cipherInstance          cipherInst;
1131  int                     err_num;
1132  int                     blkfac;
1133  int                     oflow = 0;
1134
1135  /*
1136     SL_REQUIRE (i_blk*16 == payload_size, _("payload_size % 16 != 0"));
1137  */
1138  if ((i_blk * 16) != payload_size) ++i_blk;
1139#ifdef DEBUG_EN2
1140  fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
1141#endif
1142  /* random_pad
1143   */
1144  rpad[1] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1145  memcpy (head,      &rpad[1],    4);
1146  rpad[0] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1147  memcpy (&head[4],  &rpad[0],    4);
1148  rpad[2] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1149  memcpy (&head[8],  &rpad[2],    4);
1150
1151  /* protocol
1152   */
1153  /* memcpy (&head[8],  &header[3], 4); */
1154
1155  /* size (payload)
1156   */ 
1157  head[12] = header[1];
1158  head[13] = header[2];
1159  head[14] = '\0';
1160  head[15] = '\0';
1161
1162  if (i_blk < i_blkmax) 
1163  {
1164    pads = i_blkmax - i_blk;
1165    /* memcpy((char *) &rpad[2], &head[12], 4); */
1166    epad = taus_get_double (&rpad);
1167#ifdef DEBUG_EN2
1168    fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
1169#endif
1170    i_epad = (unsigned long) (pads * epad);
1171#ifdef DEBUG_EN2
1172    fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
1173#endif
1174  }
1175
1176  full_size =  16;                        /* head     */
1177  if (sl_ok_muls(i_blk, 16) && sl_ok_adds(full_size, (i_blk*16)))
1178    full_size =  full_size + (i_blk*16);  /* payload  */
1179  else
1180    oflow = 1;
1181  if (sl_ok_adds(full_size, (i_epad*16)))
1182    full_size =  full_size + (i_epad*16); /* pad      */
1183  else
1184    i_epad = 0;
1185
1186  if (oflow)
1187    {
1188      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1189                      _("integer overflow"), 
1190                      _("sh_tools_makePack"));
1191    }
1192
1193  full_ret = SH_ALLOC(full_size);
1194  memcpy(full_ret,                   head,    16);
1195  if (payload != NULL && !oflow)
1196    {
1197      memcpy(&full_ret[16],              payload, payload_size);
1198    }
1199  if ((i_blk*16) > payload_size && !oflow) 
1200    {
1201#ifdef DEBUG_EN2
1202      fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
1203#endif
1204      memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
1205      payload_size = i_blk * 16;
1206    }
1207  memset(&full_ret[16+payload_size], '\0', i_epad*16);
1208#ifdef DEBUG_EN2
1209  fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
1210#endif
1211
1212  /* rewrite header
1213   */
1214  header[1]   = (unsigned int)(full_size/256);
1215  header[2]   = (unsigned int)(full_size - (256 * header[1]));
1216  /* don't erase protocol from header
1217     memset(&header[3], '\0', 4);
1218  */
1219  p = full_ret; blkfac = full_size / 16;
1220
1221  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1222 
1223  if (err_num < 0) 
1224    {
1225      char expbuf[SH_ERRBUF_SIZE];
1226      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1227                      errorExplain(err_num, expbuf, sizeof(expbuf)), 
1228                      _("sh_tools_makePack: cipherInit"));
1229    }
1230  for (j = 0; j < blkfac; ++j)
1231    {
1232      memcpy(inBlock, p, B_SIZ);
1233      err_num = blockEncrypt(&cipherInst, keyInstE, 
1234                             inBlock, 128 * BNUM, outBlock);
1235      if (err_num < 0)
1236        {
1237          char expbuf[SH_ERRBUF_SIZE];
1238          sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1239                          errorExplain(err_num, expbuf, sizeof(expbuf)), 
1240                          _("sh_tools_makePack: blockEncrypt"));
1241        }
1242      memcpy(p, outBlock, B_SIZ);
1243      p += B_SIZ;
1244    }
1245
1246  return full_ret;
1247}
1248
1249/* write a 7-byte header and return payload as expected by version 1
1250 * last 4 bytes of incoming header are dummy
1251 */
1252char * sh_tools_revertPack (unsigned char * header, char * message, 
1253                            keyInstance * keyInstD,
1254                            unsigned long message_size)
1255{
1256  unsigned long   msg_size;
1257  char          * msg_ret;
1258
1259  char                  * p;
1260  RIJ_BYTE                    inBlock[B_SIZ]; 
1261  RIJ_BYTE                    outBlock[B_SIZ];
1262  int                     j;
1263  cipherInstance          cipherInst;
1264  int                     err_num;
1265  int                     blkfac;
1266  char expbuf[SH_ERRBUF_SIZE];
1267
1268  msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1269#ifdef DEBUG_EN2
1270  fprintf(stderr, "RECV <%lu>\n", msg_size);
1271#endif
1272  if (msg_size > message_size) {
1273    msg_size = message_size;
1274#ifdef DEBUG_EN2
1275    fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
1276#endif
1277  }
1278
1279  p = message; blkfac = msg_size / 16;
1280
1281  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1282 
1283  if (err_num < 0) 
1284    {
1285      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1286                      errorExplain(err_num, expbuf, sizeof(expbuf)), 
1287                      _("sh_tools_revertPack: cipherInit"));
1288    }
1289  for (j = 0; j < blkfac; ++j)
1290    {
1291      memcpy(inBlock, p, B_SIZ);
1292      err_num = blockDecrypt(&cipherInst, keyInstD, 
1293                             inBlock, 128 * BNUM, outBlock);
1294      if (err_num < 0)
1295        {
1296          sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1297                          errorExplain(err_num, expbuf, sizeof(expbuf)), 
1298                          _("sh_tools_revertPack: blockDecrypt"));
1299        }
1300      memcpy(p, outBlock, B_SIZ);
1301      p += B_SIZ;
1302    }
1303 
1304  /* rewrite size in header
1305   */
1306  header[1]   = message[12];
1307  header[2]   = message[13];
1308  msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1309
1310  if (msg_size > (message_size-16)) 
1311    {
1312      msg_size    = message_size-16;
1313      header[1]   = (unsigned int)(msg_size/256);
1314      header[2]   = (unsigned int)(msg_size - (256 * header[1]));
1315#ifdef DEBUG_EN2
1316      fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
1317#endif
1318    }
1319#ifdef DEBUG_EN2
1320  fprintf(stderr, "REC2 <%lu>\n", msg_size);
1321#endif
1322  /* protocol
1323   */
1324  /* memcpy(&header[3], &message[8], 4); */
1325
1326  /* payload
1327   */
1328  msg_ret = SH_ALLOC(msg_size+1);
1329  if (msg_size > 0)
1330    {
1331      memcpy(msg_ret, &message[16], msg_size);
1332    }
1333  msg_ret[msg_size] = '\0';
1334#ifdef DEBUG_EN2
1335  fprintf(stderr, "REC3 <%lu>\n", msg_size);
1336#endif
1337  SH_FREE(message);
1338
1339  return msg_ret;
1340}
1341#endif
1342
1343int sh_tools_hash_add(char * key, char * buf, int buflen)
1344{
1345  char         * theSig;
1346
1347  SL_ENTER(_("sh_tools_hash_add"));
1348
1349  theSig = sh_util_siggen (key, buf, buflen);
1350  sl_strlcat(buf, theSig, buflen + KEY_LEN + 1);
1351     
1352  SL_RETURN((0), _("sh_tools_hash_add"));
1353}
1354
1355
1356/* return 0 (== FALSE) if no match, else 1 (== TRUE)
1357 */
1358int sh_tools_hash_vfy(char * key, char * buf, int buflen)
1359{
1360  char           hash[KEY_LEN+1];
1361  register int   i;
1362  char         * theSig;
1363
1364  SL_ENTER(_("sh_tools_hash_vfy"));
1365
1366  theSig = sh_util_siggen (key, buf, buflen);
1367  sl_strlcpy(hash, theSig, KEY_LEN+1);
1368
1369  for (i = 0; i < KEY_LEN; ++i)
1370    {
1371      if (buf[buflen + i] != hash[i])
1372        SL_RETURN((0), _("sh_tools_hash_vfy"));
1373    }
1374     
1375  SL_RETURN((1), _("sh_tools_hash_vfy"));
1376}
1377
1378/* ------------------------------------------ */
1379
1380#if defined (SH_WITH_SERVER)
1381
1382/* add a checksum to a buffer; put checksum in front
1383 */
1384char * hash_me (char * key, char * buf,   int buflen)
1385{
1386  char           hash[KEY_LEN+1];
1387  char         * temp = NULL;
1388  register int   i;
1389  int            total = 0;
1390  char         * theSig;
1391
1392
1393  SL_ENTER(_("hash_me"));
1394
1395#ifdef DEBUG_EN2
1396  fprintf(stderr, "hash_me    <%s> <%d>\n", 
1397          (key == NULL) ? "NULL" : key, buflen);
1398#endif
1399  /* key = H(NSRV,NCLT,SK)
1400   */
1401  ASSERT_RET((key != NULL), _("key != NULL"), (NULL));
1402  ASSERT_RET((buflen >= 0), _("buflen >= 0"), (NULL));
1403
1404  theSig = sh_util_siggen (key, buf, buflen);
1405  sl_strlcpy(hash, theSig, KEY_LEN+1);
1406
1407  if (sl_ok_adds(buflen, KEY_LEN))
1408    {
1409      total = KEY_LEN + buflen;
1410      temp  = SH_ALLOC (total);
1411
1412      for (i = 0; i < KEY_LEN; ++i)
1413        temp[i] = hash[i];
1414
1415      for (i = 0; i < buflen; ++i)
1416        temp[i+KEY_LEN] = buf[i];
1417    }
1418  else
1419    {
1420      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1421                      _("integer overflow"), 
1422                      _("hash_me"));
1423      temp = sh_util_strdup(buf);
1424    }
1425  SL_RETURN(temp, _("hash_me"));
1426}
1427#endif
1428
1429#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1430
1431/* verify the checksum of a buffer; checksum comes first
1432 */
1433int hash_check(char * key, 
1434               char * buf,   int buflen)
1435{
1436  char           hash[KEY_LEN+1];
1437  register int   i;
1438  char         * theSig;
1439
1440  SL_ENTER(_("hash_check"));
1441
1442#ifdef DEBUG_EN2
1443  fprintf(stderr, "hash_check <%s> <%d>\n", 
1444          (key == NULL) ? "NULL" : key, buflen);
1445#endif
1446  theSig = sh_util_siggen (key, &buf[KEY_LEN], buflen-KEY_LEN);
1447  sl_strlcpy(hash, theSig, KEY_LEN+1);
1448     
1449  for (i = 0; i < KEY_LEN; ++i)
1450    {
1451      if (buf[i] != hash[i])
1452        SL_RETURN((-1), _("hash_check"));
1453    }
1454  SL_RETURN((0), _("hash_check"));
1455}
1456
1457#endif
1458
1459#if defined (SH_WITH_SERVER)
1460
1461char * get_client_conf_file (char * peer, unsigned long * length)
1462{
1463  char * ret;
1464  int    status;
1465  struct stat buf;
1466  char * base;
1467  size_t size;
1468
1469  SL_ENTER(_("get_client_conf_file"));
1470
1471  base = sh_util_strdup(DEFAULT_DATAROOT);
1472
1473  size = sl_strlen(base);
1474  if (sl_ok_adds(size, sl_strlen(peer)))
1475      size += sl_strlen(peer);
1476  if (sl_ok_adds(size, 6))
1477    size += 6;
1478
1479  ret = SH_ALLOC(size);
1480  sl_strlcpy(ret, base, size);
1481  sl_strlcat(ret, _("/rc."), size);
1482  sl_strlcat(ret, peer, size);
1483 
1484  status = retry_stat (FIL__, __LINE__, ret, &buf);
1485
1486  if (status == 0)
1487    goto lab_end;
1488  else
1489    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1490                    (long) sh.effective.uid, ret);
1491
1492  sl_strlcpy(ret, base, size);
1493  sl_strlcat(ret, "/rc", size);
1494 
1495  status = retry_stat (FIL__, __LINE__, ret, &buf);
1496
1497  if (status == 0)
1498    goto lab_end;
1499  else
1500    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
1501                    (long) sh.effective.uid, ret);
1502
1503  SH_FREE(base);
1504  SH_FREE(ret);
1505  *length=0;
1506  SL_RETURN(NULL, _("get_client_conf_file"));
1507
1508 lab_end:
1509  if (buf.st_size > 0x7fffffff)
1510    {
1511      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1512                    _("File too large"), _("get_client_conf_file"));
1513      SH_FREE(base);
1514      SL_RETURN(NULL, _("get_client_conf_file"));
1515    }
1516  *length = (unsigned long) buf.st_size;
1517  SH_FREE(base);
1518  SL_RETURN(ret, _("get_client_conf_file"));
1519}
1520
1521char * get_client_data_file (char * peer, unsigned long * length)
1522{
1523  char * ret;
1524  int    status;
1525  struct stat buf;
1526
1527  char * base;
1528  size_t size;
1529
1530  SL_ENTER(_("get_client_data_file"));
1531
1532  base = sh_util_strdup(DEFAULT_DATAROOT);
1533
1534  size = sl_strlen(base);
1535  if (sl_ok_adds(size, sl_strlen(peer)))
1536      size += sl_strlen(peer);
1537  if (sl_ok_adds(size, 8))
1538    size += 8;
1539
1540  ret = SH_ALLOC(size);
1541  sl_strlcpy(ret, base, size);
1542  sl_strlcat(ret, _("/file."), size);
1543  sl_strlcat(ret, peer, size);
1544 
1545  status = retry_stat (FIL__, __LINE__, ret, &buf);
1546
1547  if (status == 0)
1548    goto lab1_end;
1549  else
1550    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1551                    (long) sh.effective.uid, ret);
1552
1553
1554  sl_strlcpy(ret, base, size);
1555  sl_strlcat(ret, _("/file"), size);
1556 
1557  status = retry_stat (FIL__, __LINE__, ret, &buf);
1558
1559  if (status == 0)
1560    goto lab1_end;
1561  else
1562    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1563                    (long) sh.effective.uid, ret);
1564
1565
1566  *length = 0;
1567  SH_FREE(base);
1568  SH_FREE(ret);
1569  SL_RETURN(NULL, _("get_client_data_file"));
1570
1571 lab1_end:
1572  if (buf.st_size > 0x7fffffff)
1573    {
1574      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1575                    _("File too large"), _("get_client_data_file"));
1576      SH_FREE(base);
1577      SL_RETURN(NULL, _("get_client_data_file"));
1578    }
1579  *length = (unsigned long) buf.st_size;
1580  SH_FREE(base);
1581  SL_RETURN(ret, _("get_client_data_file"));
1582 
1583}
1584#endif
1585
1586#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
1587
1588/* --------- secure temporary file ------------ */
1589
1590SL_TICKET open_tmp ()
1591{
1592  SL_TICKET     fd;
1593  UINT32        ticks;
1594  char        * file;
1595  struct stat   buf;
1596  int           error;
1597  int           status = BAD;
1598  char        * my_tmp_dir;
1599
1600  SL_ENTER(_("open_tmp"));
1601
1602#if defined(SH_TMPDIR)
1603  my_tmp_dir = sh_util_strdup(SH_TMPDIR); 
1604#else
1605#if defined(SH_WITH_SERVER)
1606  my_tmp_dir = sh_util_strdup(DEFAULT_LOGDIR); 
1607#else
1608  my_tmp_dir = sh_util_strdup(sh.effective.home);
1609#endif
1610#endif
1611
1612  if (0 !=  tf_trust_check (my_tmp_dir, SL_YESPRIV))
1613      {
1614        dlog(1, FIL__, __LINE__, 
1615             _("The directory for temporary files: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"), 
1616             my_tmp_dir);
1617        sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST,
1618                         (long) sh.effective.uid,
1619                         my_tmp_dir);
1620        SH_FREE(my_tmp_dir);
1621        aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1622      }
1623
1624  do {
1625
1626    /* create random filename in effective users home directory
1627     */
1628    ticks = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1629    if (my_tmp_dir[0] == '/' && my_tmp_dir[1] == '\0')
1630      file = sh_util_strconcat (my_tmp_dir, 
1631                                sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4),
1632                                NULL);
1633    else
1634      file = sh_util_strconcat (my_tmp_dir, 
1635                                "/", 
1636                                sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4),
1637                                NULL);
1638
1639    /* check whether it already exists (paranoia)
1640     */
1641    errno  = 0;
1642    status = retry_lstat(FIL__, __LINE__, file, &buf);
1643    error  = errno;
1644
1645    if ( (status < 0) && (error == ENOENT) ) /* file does not exist        */
1646      status = GOOD;
1647    else if (status < 0)                     /* unexpected error condition */
1648      {
1649        SH_FREE (file);
1650        SH_FREE(my_tmp_dir);
1651        TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
1652        SL_RETURN((-1), _("open_tmp"));
1653      }
1654    else                                     /* file exists                */
1655      {
1656        status = BAD;
1657        TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file exists already>\n")));
1658      }
1659   
1660    if (status == GOOD)
1661      { 
1662        if (0 ==  tf_trust_check (file, SL_YESPRIV))
1663          status = GOOD;
1664        else
1665          {
1666            status = BAD;
1667            TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file untrusted>\n")));
1668          }
1669      }
1670
1671    if (status == BAD)
1672      SH_FREE (file);
1673
1674  } while (status == BAD);
1675
1676  fd = sl_open_safe_rdwr (file, SL_YESPRIV);
1677  if (SL_ISERROR(fd))
1678    {
1679      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN, 
1680                      _("Error opening temporary file"), _("open_tmp"));
1681      TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"), 
1682            fd, file));
1683    }
1684 
1685
1686  SH_FREE (file);
1687  SH_FREE(my_tmp_dir);
1688
1689  if (!SL_ISERROR(fd)) {
1690    sl_unlink(fd);
1691  } 
1692
1693  if (!SL_ISERROR(fd))
1694    SL_RETURN((fd), _("open_tmp"));
1695  else
1696    SL_RETURN((-1), _("open_tmp"));
1697}
1698
1699
1700int close_tmp (SL_TICKET fd)
1701{
1702  SL_ENTER(_("close_tmp"));
1703
1704  if (SL_ISERROR(sl_close (fd)))
1705    SL_RETURN((-1), _("close_tmp"));
1706  SL_RETURN((0), _("close_tmp")); 
1707}
1708
1709int rewind_tmp (SL_TICKET fd)
1710{
1711  SL_ENTER(_("rewind_tmp"));
1712
1713  if (SL_ISERROR(sl_rewind (fd)))
1714    SL_RETURN((-1), _("rewind_tmp"));
1715  SL_RETURN((0), _("rewind_tmp"));
1716}
1717#endif
Note: See TracBrowser for help on using the repository browser.