source: trunk/src/sh_tools.c @ 452

Last change on this file since 452 was 425, checked in by katerina, 9 years ago

Fix for tickets #329, #330, #331, #332

File size: 49.1 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#include "sh_pthread.h"
91#include "sh_ipvx.h"
92
93#undef  FIL__
94#define FIL__  _("sh_tools.c")
95
96#ifdef SH_ENCRYPT
97#include "rijndael-api-fst.h"
98char * errorExplain (int err_num, char * buffer, size_t len)
99{
100  char * p;
101
102  if      (err_num == BAD_KEY_DIR)
103    p = (_("Key direction is invalid"));
104  else if (err_num == BAD_KEY_MAT) 
105    p = (_("Key material not of correct length"));
106  else if (err_num == BAD_KEY_INSTANCE) 
107    p = (_("Key passed is not valid"));
108  else if (err_num == BAD_CIPHER_MODE) 
109    p = (_("Params struct passed to cipherInit invalid"));
110  else if (err_num == BAD_CIPHER_STATE) 
111    p = (_("Cipher in wrong state"));
112  else if (err_num == BAD_BLOCK_LENGTH) 
113    p = (_("Bad block length"));
114  else if (err_num == BAD_CIPHER_INSTANCE) 
115    p = (_("Bad cipher instance"));
116  else if (err_num == BAD_DATA) 
117    p = (_("Data contents are invalid"));
118  else 
119    p = (_("Unknown error"));
120  sl_strlcpy (buffer, p, len);
121  return buffer;
122}
123
124#endif
125
126/* --- check for an interface ---
127 */
128int sh_tools_iface_is_present(char *str)
129{
130#if defined(USE_IPVX)
131  struct addrinfo *ai;
132  struct addrinfo hints;
133  int             res;
134
135  memset (&hints, '\0', sizeof (hints));
136  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
137  hints.ai_socktype = SOCK_STREAM;
138  res = getaddrinfo (str, _("2543"), &hints, &ai);
139 
140  if (res == 0)
141    {
142      struct addrinfo *p = ai;
143      while (p != NULL)
144        {
145          int fd = socket (p->ai_family, p->ai_socktype,
146                           p->ai_protocol);
147
148          if (fd < 0)
149            {
150              freeaddrinfo (ai);
151              return 0;
152            }
153
154          if (bind (fd, p->ai_addr, p->ai_addrlen) != 0)
155            {
156              /* bind() fails for access reasons, iface exists
157               */
158              if (errno == EACCES || errno == EADDRINUSE)
159                {
160                  sl_close_fd (FIL__, __LINE__, fd);
161                  freeaddrinfo (ai);
162                  return 1;
163                }
164
165              sl_close_fd (FIL__, __LINE__, fd);
166              freeaddrinfo (ai);
167              return 0;
168            }
169
170          sl_close_fd (FIL__, __LINE__, fd);
171          freeaddrinfo (ai);
172          return 1;
173          /* p = p->ai_next; */ 
174        }
175    }
176#else
177  struct sockaddr_in sin;
178  int sd;
179
180  memset(&sin, '\0', sizeof(sin));
181  sin.sin_family = AF_INET;
182  if (inet_aton(str, &(sin.sin_addr)))
183    {
184      sin.sin_port = htons(2543);
185
186      if (-1 == (sd = socket(AF_INET, SOCK_STREAM, 0)))
187        {
188          return 0;
189        }
190
191      if (-1 == bind(sd, (struct sockaddr *)&sin, sizeof(sin)))
192        {
193          int retval = 0;
194
195          /* bind() fails for access reasons, iface exists
196           */
197          if (errno == EACCES || errno == EADDRINUSE)
198            retval = 1;
199          sl_close_fd (FIL__, __LINE__, sd);
200          return retval;
201        }
202
203      /* bind() succeeds, iface exists
204       */
205      sl_close_fd(FIL__, __LINE__, sd);
206      return 1;
207    }
208#endif
209  return 0;
210}
211
212/* --- recode all \blah escapes to qp (quoted printable) '=XX' format, and
213 *     also code all remaining unprintable chars                           ---
214 */
215#define SH_PUT_4(p, a, b, c) (p)[0] = (a); (p)[1] = (b); (p)[2] = (c);
216 
217char * sh_tools_safe_name (const char * instr, int flag)
218{
219  unsigned char c, d;
220  const  char * p;
221  char   tmp[4];
222  char * outstr;
223  size_t len = 1;
224  int    i = 0;
225  unsigned char   val_octal = '\0';
226  static char ctable[16] = { '0', '1', '2', '3', '4', '5', '6', '7', 
227                             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 
228
229  SL_ENTER(_("sh_tools_safe_name"));
230
231  if (instr)
232    {
233      len = strlen(instr);
234      if (sl_ok_muls (3, len) && sl_ok_adds ((3*len), 4))
235        {
236          len = (3 * len) + 4;
237          p = instr;
238        }
239      else
240        {
241          len = 1;
242          p   = NULL;
243        }
244    }
245  else
246    {
247      p = NULL;
248    }
249
250  outstr = SH_ALLOC(len);
251
252  outstr[0] = '\0';
253  tmp[3]    = '\0';
254
255#if !defined(SH_USE_XML)
256  (void) flag; /* fix compiler warning */
257#endif
258
259  if (!p)
260    goto end;
261
262  while (*p)
263    {
264      c = *p;
265
266      if (*p == '\n')
267        {
268          outstr[i] = ' '; ++i; ++p;
269          continue;
270        }
271
272#ifdef SH_USE_XML
273      if (flag == 1)
274        {
275          if ((*p) == '"')
276            { 
277              SH_PUT_4(&outstr[i], '=', '2', '2');
278              i+=3; ++p;
279              continue;
280            } 
281          else if ((*p) == '&')
282            { 
283              SH_PUT_4(&outstr[i], '=', '2', '6');
284              i+=3; ++p;
285              continue;
286            } 
287          else if ((*p) == '<') 
288            {     /* left angle       */
289              SH_PUT_4(&outstr[i], '=', '3', 'c');
290              i+=3; ++p;
291              continue;
292            } 
293          else if ((*p) == '>') 
294            {     /* right angle      */
295              SH_PUT_4(&outstr[i], '=', '3', 'e');
296              i+=3; ++p;
297              continue;
298            }
299        }
300#endif
301
302      if ( (*p) != '\\' && (*p) != '&' && (*p) != '='  && (*p) != '\'') 
303        {
304          outstr[i] = *p; ++i;
305          ++p;
306             
307          if (c < 32 || c > 126)
308            {
309              --i;
310              d = c % 16; c = c / 16;
311              outstr[i] = '=';       ++i;
312              outstr[i] = ctable[c]; ++i;
313              outstr[i] = ctable[d]; ++i;
314            }
315
316          continue;
317        }
318      else if ((*p) == '\'')
319        {
320          SH_PUT_4(&outstr[i], '=', '2', '7');
321          i+=3; ++p;
322        }
323      else if (*p == '=')
324        {
325          if (p[1] != '"' && p[1] != '<')
326            { 
327              SH_PUT_4(&outstr[i], '=', '3', 'd');
328              i+=3; ++p;
329            }
330          else
331            { outstr[i] = *p; ++i; ++p; }
332        }
333      else if (*p == '\\')
334        {
335          ++p;
336          if (!p)
337            break;
338          if (!(*p))
339            break;
340
341
342
343          switch (*p) {
344          case '\\':
345            SH_PUT_4(&outstr[i], '=', '5', 'c');
346            i+=3; ++p;
347            break;
348          case 'n':
349            SH_PUT_4(&outstr[i], '=', '0', 'a');
350            i+=3; ++p;
351            break;
352          case 'b':
353            SH_PUT_4(&outstr[i], '=', '0', '8');
354            i+=3; ++p;
355            break;                     
356          case 'r':                   
357            SH_PUT_4(&outstr[i], '=', '0', 'd');
358            i+=3; ++p;
359            break;                     
360          case 't':                   
361            SH_PUT_4(&outstr[i], '=', '0', '9');
362            i+=3; ++p;
363            break;                     
364          case 'v':                   
365            SH_PUT_4(&outstr[i], '=', '0', 'b');
366            i+=3; ++p;
367            break;                     
368          case 'f':                   
369            SH_PUT_4(&outstr[i], '=', '0', 'c');
370            i+=3; ++p;
371            break;                     
372          case '\'':                   
373            SH_PUT_4(&outstr[i], '=', '2', '7');
374            i+=3; ++p;
375            break;                     
376          case '"':     /* also encode quoted '"' */           
377            SH_PUT_4(&outstr[i], '=', '2', '2');
378            i+=3; ++p;
379            break;                     
380          case ' ':                   
381            SH_PUT_4(&outstr[i], '=', '2', '0');
382            i+=3; ++p;
383            break;
384          default:
385            if (strlen(p) < 3) /* certainly not an octal number, skip */
386              {
387                p += strlen(p);
388              }
389            else
390              {
391                tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2]; 
392                val_octal = (unsigned char) strtoul(tmp, (char **)NULL, 8);
393                if (val_octal != '\0') { 
394                  c = val_octal;
395                  d = c % 16; c = c / 16;
396                  outstr[i] = '=';       ++i;
397                  outstr[i] = ctable[c]; ++i;
398                  outstr[i] = ctable[d]; ++i;
399                } 
400                p += 3;
401              }
402          }
403        }
404      else if (*p == '&')
405        {
406          ++p;
407          if (!p || !(*p))
408            {
409              outstr[i] = '&'; ++i;
410              break;
411            }
412
413          if (p[0] == 'a' && p[1] == 'm' && p[2] == 'p' && p[3] == ';')
414            {
415              SH_PUT_4(&outstr[i], '=', '2', '6');
416              i+=3; p += 4;
417            }
418          else if (p[0] == 'q' && p[1] == 'u' && p[2] == 'o' && p[3] == 't' &&
419                   p[4] == ';')
420            {
421              SH_PUT_4(&outstr[i], '=', '2', '2');
422              i+=3; p += 5;
423            }
424          else if (p[0] == 'l' && p[1] == 't' && p[2] == ';')
425            {
426              SH_PUT_4(&outstr[i], '=', '3', 'c');
427              i+=3; p += 3;
428            }
429          else if (p[0] == 'g' && p[1] == 't' && p[2] == ';')
430            {
431              SH_PUT_4(&outstr[i], '=', '3', 'e');
432              i+=3; p += 3;
433            }
434          else /* conserve the '&' */
435            {
436              outstr[i] = '&'; ++i;
437            }
438        }
439      else
440        {
441          outstr[i] = *p; ++i;
442          ++p;
443        }
444    } /* while (p && *p) */
445
446 end:
447 
448  outstr[i] = '\0';
449  SL_RETURN( outstr, _("sh_tools_safe_name"));
450}
451
452
453/* extern int h_errno; */ 
454
455char * sh_tools_errmessage (int tellme, char * errbuf, size_t len)
456{
457  char * p = NULL;
458#ifdef HOST_NOT_FOUND
459    if (tellme == HOST_NOT_FOUND) 
460      p = _("The specified host is unknown: ");
461#endif
462#ifdef NO_ADDRESS
463    if (tellme == NO_ADDRESS) 
464      p = _("The requested name is valid but does not have an IP address: ");
465#endif
466#ifdef NO_RECOVERY
467    if (tellme == NO_RECOVERY) 
468      p = _("A non-recoverable name server error occurred: ");
469#endif
470#ifdef TRY_AGAIN
471    if (tellme == TRY_AGAIN) 
472      p = _("A temporary error occurred on an authoritative name server. The specified host is unknown: ");
473#endif
474    if (!p) p =  _("Unknown error");
475    sl_strlcpy(errbuf, p, len);
476    return errbuf;
477}
478
479#if defined (SH_WITH_SERVER)
480
481int get_open_max ()
482{
483  int value;
484
485#ifdef _SC_OPEN_MAX
486  value = sysconf (_SC_OPEN_MAX);
487#else
488#ifdef OPEN_MAX
489  value = OPEN_MAX;
490#else
491  value = _POSIX_OPEN_MAX;
492#endif
493#endif
494
495  if (value < 0)
496    value = 8;  /* POSIX lower limit */
497
498  if (value > 4096)
499    value = 4096;
500
501  return value;
502}
503
504#endif
505
506typedef struct _sin_cache {
507  char * address;
508  struct sh_sockaddr  saddr;
509  struct _sin_cache * next;
510} sin_cache;
511
512static sin_cache * conn_cache = NULL;
513static int cached_addr = 0;
514
515void delete_cache()
516{
517  sin_cache * check_cache = conn_cache;
518  sin_cache * old_entry;
519
520  SL_ENTER(_("delete_cache"));
521
522  while (check_cache != NULL)
523    {
524      old_entry   = check_cache;
525      check_cache = check_cache->next;
526      SH_FREE(old_entry->address);
527      SH_FREE(old_entry);
528    }
529
530  cached_addr = 0;
531
532  conn_cache = NULL;
533  SL_RET0(_("delete_cache"));
534}
535     
536int DoReverseLookup = S_TRUE;
537
538int set_reverse_lookup (const char * c)
539{
540  return sh_util_flagval(c, &DoReverseLookup);
541}
542
543#if !defined(USE_IPVX)
544int connect_port (char * address, int port, 
545                  char * ecall, int * errnum, char * errmsg, int errsiz)
546{
547  struct in_addr       haddr;   /* host address from numeric                */
548                                /* host details returned by the DNS         */
549  struct hostent *host_entry = NULL;   
550  struct sockaddr_in sinr;      /* socket to the remote host                */
551
552  char   * host_name;
553
554  volatile int    fd = (-1);
555  int    status;
556  volatile int    fail   = 0;
557  int    cached = 0;
558
559  int    retval;
560  char   errbuf[SH_ERRBUF_SIZE];
561
562  sin_cache * check_cache = conn_cache;
563
564  SL_ENTER(_("connect_port"));
565
566  if (errsiz > 0) errmsg[0] = '\0';
567
568  /* paranoia -- should not happen
569   */
570  if (cached_addr > 128)
571    delete_cache();
572
573  if (check_cache != NULL)
574    {
575      while (check_cache && check_cache->address)
576        {
577          if ( 0 == sl_strncmp(check_cache->address, 
578                               address, sl_strlen(address)) )
579            {
580              memcpy (&sinr, &((check_cache->saddr).sin), sizeof(struct sockaddr_in));
581              sinr.sin_family = AF_INET;
582              sinr.sin_port   = htons (port);
583              cached = 1;
584              break;
585            }
586          if (check_cache->next)
587            check_cache = check_cache->next;
588          else
589            check_cache = NULL;
590        }
591    }
592
593  /* only use gethostbyname() if neccessary
594   */
595  if (cached == 0)
596    {
597#ifdef HAVE_INET_ATON
598      if (0 == inet_aton(address, &haddr))
599#else
600      if ((unsigned long)-1  == (haddr.s_addr = inet_addr(address)))
601#endif
602        {
603          SH_MUTEX_LOCK(mutex_resolv);
604
605          host_name = NULL;
606
607          host_entry = sh_gethostbyname(address);
608
609          if (host_entry == NULL || host_entry->h_addr == NULL) 
610            {
611              sl_strlcpy(ecall, _("gethostbyname"), SH_MINIBUF);
612#ifndef NO_H_ERRNO
613              *errnum = h_errno;
614#else
615              *errnum = 666;
616#endif
617              (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
618              sl_strlcat(errmsg, address, errsiz); 
619              fail = (-1);
620            }
621          else
622            {
623              sinr.sin_family = AF_INET;
624              sinr.sin_port   = htons (port);
625              sinr.sin_addr   = *(struct in_addr *) host_entry->h_addr;
626
627
628              /* reverse DNS lookup
629               */
630              if (DoReverseLookup == S_TRUE)
631                {
632                  if (host_entry->h_name == NULL)
633                    {
634                      host_name = SH_ALLOC(1);
635                      host_name[0] = '\0';
636                    }
637                  else
638                    {
639                      host_name = sh_util_strdup(host_entry->h_name);
640                    }
641
642                  host_entry = sh_gethostbyaddr ((char *) &sinr.sin_addr, 
643                                              sizeof(struct in_addr),
644                                              AF_INET);
645                  if (host_entry == NULL || host_entry->h_name == NULL)
646                    {
647                      sl_strlcpy(ecall, _("gethostbyaddr"), SH_MINIBUF);
648#ifndef NO_H_ERRNO
649                      *errnum = h_errno;
650#else
651                      *errnum = 666;
652#endif
653                      (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
654                      sl_strlcat(errmsg, 
655                                 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
656                                 errsiz); 
657                      fail = (-1);
658                    }
659                  else
660                    {
661                      *errnum = 0;
662                      if (sl_strlen(host_entry->h_name) == 0 || 
663                          (*errnum = sl_strcasecmp(host_name,host_entry->h_name)) != 0)
664                        { 
665                          if (*errnum)
666                            sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
667                          else
668                            sl_strlcpy(ecall, _("strlen"), SH_MINIBUF);
669                          sl_strlcpy(errmsg, _("Reverse lookup failed: "), 
670                                     errsiz);
671                          sl_strlcat(errmsg, address, errsiz);
672                          sl_strlcat(errmsg, _(" vs "), errsiz);
673                          sl_strlcat(errmsg, 
674                                     inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
675                                     errsiz);
676                          fail = -1;
677                        }
678                    }
679                }
680            }
681          SH_MUTEX_UNLOCK(mutex_resolv);
682          if (host_name) SH_FREE(host_name);
683        }
684 
685      else  /* address was numeric */
686        {
687          sinr.sin_family = AF_INET;
688          sinr.sin_port   = htons (port);
689          sinr.sin_addr   = haddr;
690        }
691
692
693      if (fail != -1)
694        {
695          /* put it into the cache
696           */
697          check_cache          = SH_ALLOC(sizeof(sin_cache));
698          check_cache->address = SH_ALLOC(sl_strlen(address) + 1);
699          sl_strlcpy (check_cache->address, address, sl_strlen(address) + 1);
700
701          sh_ipvx_save(&(check_cache->saddr), AF_INET, (struct sockaddr *) &sinr);
702
703          ++cached_addr;
704         
705          if (conn_cache)
706            {
707              if (conn_cache->next)
708                check_cache->next    = conn_cache->next;
709              else
710                check_cache->next    = NULL;
711              conn_cache->next     = check_cache;
712            }
713          else
714            {
715              check_cache->next    = NULL;
716              conn_cache           = check_cache;
717            }
718        }
719    }
720
721 
722  if (fail != (-1)) 
723    { 
724      fd = socket(AF_INET, SOCK_STREAM, 0);
725      if (fd < 0) {
726        fail   = (-1);
727        status = errno;
728        sl_strlcpy(ecall, _("socket"), SH_MINIBUF);
729        *errnum = status;
730        sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
731        sl_strlcat(errmsg, _(", address "), errsiz);
732        sl_strlcat(errmsg, address, errsiz);
733      }
734    }
735 
736  if (fail != (-1)) {
737   
738    if ( retry_connect(FIL__, __LINE__, fd, 
739                       (struct sockaddr *) &sinr, sizeof(sinr)) < 0) 
740      {
741        status = errno;
742        sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
743        *errnum = status;
744        sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
745        sl_strlcat(errmsg, _(", address "), errsiz);
746        sl_strlcat(errmsg, address, errsiz);
747        sl_close_fd(FIL__, __LINE__, fd);
748        fail = (-1); 
749      }
750  }
751
752  retval = (fail < 0) ? (-1) : fd;
753  SL_RETURN(retval, _("connect_port"));
754}
755#else
756int connect_port (char * address, int port, 
757                  char * ecall, int * errnum, char * errmsg, int errsiz)
758{
759  struct sockaddr_in *sin;
760  struct sockaddr_in6 *sin6;
761  struct sh_sockaddr ss;
762  sin_cache * check_cache = conn_cache;
763  int    cached = 0;
764  int    fail   = 0;
765  int    fd     = -1;
766  int    status = 0;
767
768  int    retval;
769  char   errbuf[SH_ERRBUF_SIZE];
770
771  SL_ENTER(_("connect_port"));
772
773  /* paranoia -- should not happen
774   */
775  if (cached_addr > 128)
776    delete_cache();
777
778  if (check_cache != NULL)
779    {
780      while (check_cache && check_cache->address)
781        {
782          if ( 0 == sl_strcmp(check_cache->address, address) )
783            {
784              memcpy (&ss, &(check_cache->saddr), sizeof(struct sh_sockaddr));
785              switch (ss.ss_family) 
786                {
787                case AF_INET:
788                  sin = &(ss.sin);
789                  sin->sin_port   = htons (port);
790                  cached = 1;
791                  break;
792                case AF_INET6:
793                  sin6 = &(ss.sin6);
794                  sin6->sin6_port  = htons (port);
795                  cached = 1;
796                  break;
797                default:
798                  break;
799                }
800              break;
801            }
802          if (check_cache->next)
803            check_cache = check_cache->next;
804          else
805            check_cache = NULL;
806        }
807    }
808
809  if (cached != 0)
810    {
811      fd = socket(ss.ss_family, SOCK_STREAM, 0);
812      if (fd < 0) 
813        {
814          status = errno;
815          fail   = (-1);
816          sl_strlcpy(ecall, _("socket"), SH_MINIBUF);
817          *errnum = status;
818          sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
819          sl_strlcat(errmsg, _(", address "), errsiz);
820          sl_strlcat(errmsg, address, errsiz);
821        }
822
823
824      if (fail != (-1)) 
825        {
826          int addrlen = SH_SS_LEN(ss);
827       
828          if ( retry_connect(FIL__, __LINE__, fd, 
829                             sh_ipvx_sockaddr_cast(&ss), addrlen) < 0) 
830            {
831              status = errno;
832              sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
833              *errnum = status;
834              sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
835              sl_strlcat(errmsg, _(", address "), errsiz);
836              sl_strlcat(errmsg, address, errsiz);
837              sl_close_fd(FIL__, __LINE__, fd);
838              fail = (-1); 
839            }
840        }
841
842      if (fail != 0)
843        {
844          delete_cache();
845          cached = 0;
846        }
847    }
848
849  if (cached == 0)
850    {
851      int    res;
852      char   sport[32];
853      struct addrinfo *ai;
854      struct addrinfo hints;
855
856      memset (&hints, '\0', sizeof (hints));
857      hints.ai_flags = AI_ADDRCONFIG;
858#if defined(AI_CANONNAME)
859      hints.ai_flags |= AI_CANONNAME;
860#endif
861      hints.ai_family   = AF_UNSPEC;
862      hints.ai_socktype = SOCK_STREAM;
863      sl_snprintf(sport, sizeof(sport), "%d", port);
864
865      res = getaddrinfo (address, sport, &hints, &ai);
866      if (res != 0)
867        {
868          fail = (-1);
869          status = errno;
870          sl_strlcpy(ecall, _("getaddrinfo"), SH_MINIBUF);
871          *errnum = status;
872          sl_strlcpy(errmsg, gai_strerror (res), errsiz);
873          sl_strlcat(errmsg, _(", address "), errsiz);
874          sl_strlcat(errmsg, address, errsiz);
875        }
876
877      if (fail != (-1) && (DoReverseLookup == S_TRUE) && !sh_ipvx_is_numeric(address))
878        {
879          struct addrinfo *p = ai;
880          int    success = 0;
881          char hostname[SH_BUFSIZE];
882          const char * canonical;
883
884#if defined(AI_CANONNAME)
885          if (ai->ai_canonname && strlen(ai->ai_canonname) > 0)
886            {
887              canonical = ai->ai_canonname;
888            }
889          else
890            {
891              canonical = address;
892            }
893#else
894          canonical = address;
895#endif
896
897          while (p != NULL)
898            {
899              int e = getnameinfo (p->ai_addr, p->ai_addrlen, 
900                                   hostname, sizeof(hostname),
901                                   NULL, 0, NI_NAMEREQD);
902             
903              if (e == 0)
904                {
905                  if (sl_strcasecmp(hostname, canonical) == 0)
906                    {
907                      success = 1;
908                      break;
909                    }
910                }
911           
912              p = p->ai_next;
913            }
914
915          if (success == 0)
916            {
917              sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
918              sl_strlcpy(errmsg, _("Reverse lookup failed: "), 
919                         errsiz);
920              sl_strlcat(errmsg, address, errsiz);
921              fail = -1;
922              freeaddrinfo (ai);
923            }
924        }
925
926      if (fail != (-1))
927        {
928          struct addrinfo *p = ai;
929
930          while (p != NULL)
931            {
932              if ( (SOCK_STREAM == p->ai_socktype) &&
933                   ((p->ai_family == AF_INET) || (p->ai_family == AF_INET6)) )
934                {
935               
936                  fd = socket(p->ai_family, SOCK_STREAM, 0);
937                 
938                  if (fd != (-1))
939                    {
940                      if (retry_connect(FIL__, __LINE__, fd, 
941                                        p->ai_addr, p->ai_addrlen) >= 0)
942                        {
943                          /* put it into the cache
944                           */
945                          check_cache          = SH_ALLOC(sizeof(sin_cache));
946                          check_cache->address = SH_ALLOC(sl_strlen(address) + 1);
947                          sl_strlcpy (check_cache->address, address, sl_strlen(address) + 1);
948                         
949                          sh_ipvx_save(&(check_cache->saddr), p->ai_family, p->ai_addr);
950                         
951                          ++cached_addr;
952                         
953                          if (conn_cache)
954                            {
955                              if (conn_cache->next)
956                                check_cache->next    = conn_cache->next;
957                              else
958                                check_cache->next    = NULL;
959                              conn_cache->next     = check_cache;
960                            }
961                          else
962                            {
963                              check_cache->next    = NULL;
964                              conn_cache           = check_cache;
965                            }
966                         
967                          freeaddrinfo (ai);
968                          goto end;
969                        }
970                      status = errno;
971                      sl_close_fd(FIL__, __LINE__, fd);
972                    }
973                  else
974                    {
975                      status = errno;
976                    }
977                }
978              p = p->ai_next;
979            }
980          fail = (-1);
981          freeaddrinfo (ai);
982
983          sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
984          *errnum = status;
985          sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
986          sl_strlcat(errmsg, _(", address "), errsiz);
987          sl_strlcat(errmsg, address, errsiz);
988        }
989    }
990
991 end:
992  retval = (fail < 0) ? (-1) : fd;
993  SL_RETURN(retval, _("connect_port"));
994
995}
996#endif
997
998int connect_port_2 (char * address1, char * address2, int port, 
999                    char * ecall, int * errnum, char * errmsg, int errsiz)
1000{
1001  int retval = (-1);
1002
1003  SL_ENTER(_("connect_port_2"));
1004
1005  errmsg[0] = '\0';
1006  *errnum = 0;
1007
1008  if (address1 != NULL && address1[0] != '\0')
1009    retval = connect_port (address1, port, 
1010                           ecall, errnum, 
1011                           errmsg, errsiz);
1012
1013  if (retval < 0 && address2 != NULL && address2[0] != '\0')
1014    {
1015      /* can't use sh_error_handle here, as this would cause an infinite
1016       * loop if called from sh_unix_time
1017       */
1018      TPT(( 0, FIL__, __LINE__, _("msg=<Using alternative server %s.>\n"),
1019            address2));
1020      retval = connect_port (address2, port, 
1021                             ecall, errnum, 
1022                             errmsg, errsiz);
1023    }
1024
1025  if ((retval < 0) &&
1026      (address1 == NULL || address1[0] == '\0') &&
1027      (address1 == NULL || address1[0] == '\0'))
1028    {
1029      sl_strlcpy(ecall, _("connect_port_2"), SH_MINIBUF);
1030      sl_strlcpy(errmsg, _("No server address known"), errsiz);
1031    }
1032  SL_RETURN(retval, _("connect_port_2"));
1033  /* return retval; */
1034}
1035
1036#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1037static
1038int sh_write_select(int type, int sockfd, 
1039                    char *buf, int nbytes, 
1040                    int * w_error, int timeout)
1041{
1042  int    countbytes, count;
1043  fd_set fds;
1044  struct timeval tv;
1045  int    select_now;
1046  int    num_sel;
1047 
1048  char    errbuf[SH_ERRBUF_SIZE];
1049
1050  SL_ENTER(_("sh_write_select"));
1051
1052  FD_ZERO(&fds);
1053  FD_SET(sockfd, &fds);
1054
1055  countbytes   = 0;
1056  tv.tv_sec    = 1;
1057  tv.tv_usec   = 0;
1058  select_now   = 0;
1059
1060  *w_error = 0;
1061
1062  while ( countbytes < nbytes ) {
1063
1064    FD_ZERO(&fds);
1065    FD_SET(sockfd, &fds);
1066
1067    if (type == SH_DO_WRITE) 
1068      {
1069        if ( (num_sel = select (sockfd+1, NULL, &fds, NULL, &tv)) == -1) 
1070          {
1071            if (sig_raised == 1)
1072              {
1073                sig_raised = 2;
1074                continue;
1075              }
1076            if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
1077              continue;
1078            *w_error = errno;
1079
1080            sh_error_message(*w_error, errbuf, sizeof(errbuf));
1081            sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1082                             errbuf,
1083                             _("sh_write_select (ws)") ); 
1084            TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
1085            SL_RETURN( countbytes, _("sh_write_select"));
1086          }
1087      }
1088    else
1089      {
1090        if ( (num_sel = select (sockfd+1, &fds, NULL, NULL, &tv)) == -1) 
1091          {
1092            if (sig_raised == 1)
1093              {
1094                sig_raised = 2;
1095                continue;
1096              }
1097            if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
1098              continue;
1099            *w_error = errno;
1100
1101            sh_error_message(*w_error, errbuf, sizeof(errbuf));
1102            sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1103                             errbuf,
1104                             _("sh_write_select (rs)") ); 
1105            TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
1106            SL_RETURN( countbytes, _("sh_write_select"));
1107          }
1108      }
1109     
1110    /* on Linux, timeout  is  modified to reflect the amount of
1111     * time not slept
1112     */
1113    tv.tv_sec    = 1;
1114    tv.tv_usec   = 0;
1115
1116
1117    /* let's not hang on forever
1118     */
1119    if (num_sel == 0) 
1120      {
1121        ++select_now;       /* timeout */
1122        if ( select_now > timeout )  /* 5 minutes */
1123          {
1124#ifdef ETIMEDOUT
1125            *w_error = ETIMEDOUT;
1126#else
1127            *w_error = 0;
1128#endif
1129
1130            TPT(( 0, FIL__, __LINE__, _("msg=<Timeout>\n")));
1131            SL_RETURN( countbytes, _("sh_write_select"));
1132          }
1133      }
1134   
1135    if ( FD_ISSET (sockfd, &fds) ) 
1136      {
1137        if (type == SH_DO_WRITE)
1138          count = write (sockfd, buf, nbytes-countbytes);
1139        else
1140          count = read  (sockfd, buf, nbytes-countbytes);
1141
1142        if (count > 0) 
1143        {
1144          countbytes += count;
1145          buf        += count;    /* move buffer pointer forward */
1146          if (countbytes < nbytes) FD_SET( sockfd, &fds );
1147        }
1148        else if (count < 0 && errno == EINTR)
1149          {
1150            FD_SET( sockfd, &fds );
1151          }
1152        else if (count < 0)
1153          {
1154            *w_error = errno;
1155
1156            sh_error_message(*w_error, errbuf, sizeof(errbuf));
1157            sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1158                             errbuf,
1159                             (type == SH_DO_WRITE) ? 
1160                             _("sh_write_select (w)") : _("sh_write_select (r)")); 
1161            TPT(( 0, FIL__, __LINE__, _("msg=<count < 0>\n")));
1162            SL_RETURN( countbytes, _("sh_write_select"));
1163          }
1164        else /* count == 0 */
1165          {
1166            *w_error = errno;
1167
1168            TPT(( 0, FIL__, __LINE__, _("msg=<count == 0>\n")));
1169            SL_RETURN( countbytes, _("sh_write_select"));
1170          }
1171      }
1172  }
1173
1174  *w_error = 0;
1175
1176  TPT(( 0, FIL__, __LINE__, _("msg=<count = %d>\n"), countbytes));
1177  SL_RETURN( countbytes, _("sh_write_select"));
1178}
1179#endif
1180
1181#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1182unsigned long write_port (int sockfd, char *buf, unsigned long nbytes, 
1183                          int * w_error, int timeout)
1184{
1185  unsigned long bytes;
1186
1187  SL_ENTER(_("write_port"));
1188
1189  bytes = sh_write_select(SH_DO_WRITE, sockfd, buf, nbytes, w_error, timeout);
1190  if (*w_error != 0)
1191    {
1192      char errbuf[SH_ERRBUF_SIZE];
1193      sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP, 
1194                      sh_error_message (*w_error, errbuf, sizeof(errbuf)),
1195                      (long) sockfd, _("write_port"));
1196    }
1197  SL_RETURN( bytes, _("write_port"));
1198}
1199#endif
1200
1201#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1202
1203unsigned long read_port (int sockfd, char *buf, unsigned long nbytes, 
1204               int * w_error, int timeout)
1205{
1206  unsigned long bytes;
1207
1208  SL_ENTER(_("read_port"));
1209
1210  bytes = sh_write_select(SH_DO_READ, sockfd, buf, nbytes, w_error, timeout);
1211  if (*w_error != 0)
1212    {
1213      char errbuf[SH_ERRBUF_SIZE];
1214      sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP, 
1215                      sh_error_message (*w_error, errbuf, sizeof(errbuf)),
1216                      (long) sockfd, _("read_port"));
1217    }
1218  SL_RETURN( bytes, _("read_port"));
1219}
1220#endif
1221
1222#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1223
1224int check_request_nerr (char * have, char * need)
1225{
1226  SL_ENTER(_("check_request_nerr"));
1227  ASSERT_RET((have != NULL && need != NULL), 
1228             _("have != NULL && need != NULL"), (-1))
1229
1230  if ( (have[0] == need[0]) && (have[1] == need[1]) &&
1231       (have[2] == need[2]) && (have[3] == need[3]))
1232    SL_RETURN(0, _("check_request_nerr"));
1233  SL_RETURN((-1), _("check_request_nerr"));
1234}
1235#endif
1236
1237#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1238
1239int check_request (char * have, char * need)
1240{
1241  char first[21], second[5];
1242  int  i;
1243
1244  SL_ENTER(_("check_request"));
1245  i = check_request_nerr (have, need);
1246
1247  if (i == 0)
1248    SL_RETURN(0, _("check_request"));
1249
1250  for (i = 0; i < 4; ++i)
1251    {
1252      second[i] = need[i];
1253      sprintf(&first[i*4], _("%c%03o"),               /* known to fit  */
1254              '\\', (unsigned char) have[i]);
1255    }
1256
1257  first[20] = '\0'; second[4] = '\0';
1258
1259  sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST, 
1260                  second, first);
1261  SL_RETURN((-1), _("check_request"));
1262}
1263#endif
1264
1265#if defined (SH_WITH_SERVER)
1266
1267int check_request_s (char * have, char * need, char * clt)
1268{
1269  char first[21], second[5];
1270  int  i;
1271
1272  SL_ENTER(_("check_request_s"));
1273  i = check_request_nerr (have, need);
1274
1275  if (i == 0)
1276    SL_RETURN( (0), _("check_request_s"));
1277
1278  for (i = 0; i < 4; ++i)
1279    {
1280      second[i] = need[i];
1281      sprintf(&first[i*4], _("%c%03o"),               /* known to fit  */
1282              '\\', (unsigned char) have[i]);
1283    }
1284  first[20] = '\0'; second[4] = '\0';
1285  sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST1, 
1286                  second, first, clt);
1287  SL_RETURN( (-1), _("check_request_s"));
1288}
1289#endif
1290
1291#if defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)
1292
1293void get_header (unsigned char * head, unsigned long * bytes, char * u)
1294{
1295  SL_ENTER(_("get_header"));
1296
1297  *bytes = 
1298    (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1299
1300  if (u != NULL)
1301    {
1302      u[0]     = head[3];
1303      u[1]     = head[4];
1304      u[2]     = head[5];
1305      u[3]     = head[6];
1306      u[4]     = '\0';
1307    }
1308
1309  SL_RET0(_("get_header"));
1310}
1311#endif
1312
1313#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1314
1315#ifdef  SH_ENCRYPT_2
1316#define TRANS_BYTES 65120
1317#else
1318#define TRANS_BYTES 65280
1319#endif
1320
1321void put_header (unsigned char * head, int protocol, 
1322                 unsigned long * length, char * u)
1323{
1324
1325  /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
1326  static unsigned long transfer_limit = TRANS_BYTES + 6 + KEY_LEN;
1327
1328  SL_ENTER(_("put_header"));
1329
1330  head[0]   = protocol;
1331
1332  ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
1333
1334  if (*length > transfer_limit)
1335    *length = transfer_limit;
1336
1337  head[1]   = (unsigned int)(*length/256);
1338  head[2]   = (unsigned int)(*length-256 * head[1]);
1339  if (u == NULL)
1340    {
1341      head[3] = 0x01;
1342      head[4] = 0x01;
1343      head[5] = 0x01;
1344      head[6] = 0x01;
1345    }
1346  else
1347    {
1348      head[3]   = u[0];
1349      head[4]   = u[1];
1350      head[5]   = u[2];
1351      head[6]   = u[3];
1352    }
1353
1354  SL_RET0(_("put_header"));
1355}
1356#endif
1357
1358/* ------------------------------------------
1359 *
1360 *  version 2 client/server protocol
1361 *
1362 * ------------------------------------------
1363 *
1364 * header :  flag size[2]
1365 *
1366 * payload:  random_pad[8] protocol[4] size[4] payload[payload_size] padding
1367 *
1368 * full_size <= 8192; payload_size <= 8176 (511*16); msg_size <= 8128 (508*16)
1369 * (msg_size = payload_size - key_len = payload_size - 48)
1370 */ 
1371
1372/*
1373 * only SH_V2_FULLSIZE is used, and only once
1374 */
1375#if 0
1376#ifdef SH_WITH_SERVER
1377#define SH_V2_FULLSIZE  240
1378#define SH_V2_PAYLOAD   224
1379#define SH_V2_MESSAGE   176
1380#else
1381#define SH_V2_FULLSIZE 1024
1382#define SH_V2_PAYLOAD  1008
1383#define SH_V2_MESSAGE   960
1384#endif
1385#endif
1386#define SH_V2_FULLSIZE 1024
1387
1388#ifdef SH_ENCRYPT
1389#include "rijndael-api-fst.h"
1390#endif
1391
1392void sh_tools_show_header (unsigned char * head, char sign)
1393{
1394#define SH_IS_ASCII(c) (((c) & ~0x7f) == 0)
1395
1396
1397  int    msg_size = (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1398  char   code[32]; 
1399  char * p = &code[0];
1400
1401  memset (code, ' ', 32); /* space */
1402 
1403  if ((head[0] & SH_PROTO_SRP) != 0) { p[0]='S';p[1]='R';p[2]='P';}
1404  p += 4;
1405  if ((head[0] & SH_PROTO_MSG) != 0) { p[0]='M';p[1]='S';p[2]='G';}
1406  p += 4;
1407  if ((head[0] & SH_PROTO_BIG) != 0) { p[0]='B';p[1]='I';p[2]='G';}
1408  p += 4;
1409  if ((head[0] & SH_PROTO_END) != 0) { p[0]='E';p[1]='N';p[2]='D';}
1410  p += 4;
1411  if ((head[0] & SH_PROTO_ENC) != 0) { p[0]='E';p[1]='N';p[2]='C';}
1412  p += 4;
1413  if ((head[0] & SH_PROTO_EN2) != 0) { p[0]='E';p[1]='N';p[2]='2';}
1414  code[23] = '\0';
1415
1416  if (SH_IS_ASCII(head[3]) && isalpha(head[3]) &&
1417      SH_IS_ASCII(head[4]) && isalpha(head[4]) &&                         
1418      SH_IS_ASCII(head[5]) && isalpha(head[5]) &&                         
1419      SH_IS_ASCII(head[6]) && isalpha(head[6])) {
1420    fprintf(stderr, "%c %3o %s %5d  %c  %c  %c  %c\n", sign,
1421            head[0], code, msg_size, head[3], head[4], head[5], head[6]); 
1422  } else {
1423    fprintf(stderr, "%c %3o %s %5d %2X %2X %2X %2X\n", sign,
1424            head[0], code, msg_size, head[3], head[4], head[5], head[6]); 
1425  }
1426  return;
1427}
1428
1429#ifdef SH_ENCRYPT
1430/*
1431 * #define DEBUG_EN2
1432 *
1433 * ingest version 1 7-byte header and payload, return version2 header/payload
1434 * last 4 bytes of outgoing header are set to dummy value
1435 */
1436char * sh_tools_makePack (unsigned char * header, 
1437                          char * payload, unsigned long payload_size,
1438                          keyInstance * keyInstE)
1439{
1440  UINT32 rpad[3];
1441  unsigned char   head[16];
1442  double epad;
1443  unsigned long    i_epad = 0;
1444  unsigned long    i_blk = payload_size / 16;
1445  unsigned long    i_blkmax = SH_V2_FULLSIZE / 16;
1446  unsigned long    pads = 0;
1447  size_t full_size;
1448  char * full_ret;
1449
1450  char                  * p;
1451  RIJ_BYTE                    inBlock[B_SIZ]; 
1452  RIJ_BYTE                    outBlock[B_SIZ];
1453  int                     j;
1454  cipherInstance          cipherInst;
1455  int                     err_num;
1456  int                     blkfac;
1457  int                     oflow = 0;
1458
1459  /*
1460     SL_REQUIRE (i_blk*16 == payload_size, _("payload_size % 16 != 0"));
1461  */
1462  if ((i_blk * 16) != payload_size) ++i_blk;
1463#ifdef DEBUG_EN2
1464  fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
1465#endif
1466  /* random_pad
1467   */
1468  rpad[1] = taus_get ();
1469  memcpy (head,      &rpad[1],    4);
1470  rpad[0] = taus_get ();
1471  memcpy (&head[4],  &rpad[0],    4);
1472  rpad[2] = taus_get ();
1473  memcpy (&head[8],  &rpad[2],    4);
1474
1475  /* protocol
1476   */
1477  /* memcpy (&head[8],  &header[3], 4); */
1478
1479  /* size (payload)
1480   */ 
1481  head[12] = header[1];
1482  head[13] = header[2];
1483  head[14] = '\0';
1484  head[15] = '\0';
1485
1486  if (i_blk < i_blkmax) 
1487  {
1488    pads = i_blkmax - i_blk;
1489    /* memcpy((char *) &rpad[2], &head[12], 4); */
1490    epad = taus_get_double (&rpad);
1491#ifdef DEBUG_EN2
1492    fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
1493#endif
1494    i_epad = (unsigned long) (pads * epad);
1495#ifdef DEBUG_EN2
1496    fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
1497#endif
1498  }
1499
1500  full_size =  16;                        /* head     */
1501  if (sl_ok_muls(i_blk, 16) && sl_ok_adds(full_size, (i_blk*16)))
1502    full_size =  full_size + (i_blk*16);  /* payload  */
1503  else
1504    oflow = 1;
1505  if (sl_ok_adds(full_size, (i_epad*16)))
1506    full_size =  full_size + (i_epad*16); /* pad      */
1507  else
1508    i_epad = 0;
1509
1510  if (oflow)
1511    {
1512      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1513                      _("integer overflow"), 
1514                      _("sh_tools_makePack"));
1515    }
1516
1517  full_ret = SH_ALLOC(full_size);
1518  memcpy(full_ret,                   head,    16);
1519  if (payload != NULL && !oflow)
1520    {
1521      memcpy(&full_ret[16],              payload, payload_size);
1522    }
1523  if ((i_blk*16) > payload_size && !oflow) 
1524    {
1525#ifdef DEBUG_EN2
1526      fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
1527#endif
1528      memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
1529      payload_size = i_blk * 16;
1530    }
1531  memset(&full_ret[16+payload_size], '\0', i_epad*16);
1532#ifdef DEBUG_EN2
1533  fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
1534#endif
1535
1536  /* rewrite header
1537   */
1538  header[1]   = (unsigned int)(full_size/256);
1539  header[2]   = (unsigned int)(full_size - (256 * header[1]));
1540  /* don't erase protocol from header
1541     memset(&header[3], '\0', 4);
1542  */
1543  p = full_ret; blkfac = full_size / 16;
1544
1545  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1546 
1547  if (err_num < 0) 
1548    {
1549      char expbuf[SH_ERRBUF_SIZE];
1550      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1551                      errorExplain(err_num, expbuf, sizeof(expbuf)), 
1552                      _("sh_tools_makePack: cipherInit"));
1553    }
1554  for (j = 0; j < blkfac; ++j)
1555    {
1556      memcpy(inBlock, p, B_SIZ);
1557      err_num = blockEncrypt(&cipherInst, keyInstE, 
1558                             inBlock, 128 * BNUM, outBlock);
1559      if (err_num < 0)
1560        {
1561          char expbuf[SH_ERRBUF_SIZE];
1562          sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1563                          errorExplain(err_num, expbuf, sizeof(expbuf)), 
1564                          _("sh_tools_makePack: blockEncrypt"));
1565        }
1566      memcpy(p, outBlock, B_SIZ);
1567      p += B_SIZ;
1568    }
1569
1570  return full_ret;
1571}
1572
1573/* write a 7-byte header and return payload as expected by version 1
1574 * last 4 bytes of incoming header are dummy
1575 */
1576char * sh_tools_revertPack (unsigned char * header, char * message, 
1577                            keyInstance * keyInstD,
1578                            unsigned long message_size)
1579{
1580  unsigned long   msg_size;
1581  char          * msg_ret;
1582
1583  char                  * p;
1584  RIJ_BYTE                    inBlock[B_SIZ]; 
1585  RIJ_BYTE                    outBlock[B_SIZ];
1586  int                     j;
1587  cipherInstance          cipherInst;
1588  int                     err_num;
1589  int                     blkfac;
1590  char expbuf[SH_ERRBUF_SIZE];
1591
1592  msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1593#ifdef DEBUG_EN2
1594  fprintf(stderr, "RECV <%lu>\n", msg_size);
1595#endif
1596  if (msg_size > message_size) {
1597    msg_size = message_size;
1598#ifdef DEBUG_EN2
1599    fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
1600#endif
1601  }
1602
1603  p = message; blkfac = msg_size / 16;
1604
1605  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1606 
1607  if (err_num < 0) 
1608    {
1609      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1610                      errorExplain(err_num, expbuf, sizeof(expbuf)), 
1611                      _("sh_tools_revertPack: cipherInit"));
1612    }
1613  for (j = 0; j < blkfac; ++j)
1614    {
1615      memcpy(inBlock, p, B_SIZ);
1616      err_num = blockDecrypt(&cipherInst, keyInstD, 
1617                             inBlock, 128 * BNUM, outBlock);
1618      if (err_num < 0)
1619        {
1620          sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1621                          errorExplain(err_num, expbuf, sizeof(expbuf)), 
1622                          _("sh_tools_revertPack: blockDecrypt"));
1623        }
1624      memcpy(p, outBlock, B_SIZ);
1625      p += B_SIZ;
1626    }
1627 
1628  /* rewrite size in header
1629   */
1630  header[1]   = message[12];
1631  header[2]   = message[13];
1632  msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1633
1634  if (msg_size > (message_size-16)) 
1635    {
1636      msg_size    = message_size-16;
1637      header[1]   = (unsigned int)(msg_size/256);
1638      header[2]   = (unsigned int)(msg_size - (256 * header[1]));
1639#ifdef DEBUG_EN2
1640      fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
1641#endif
1642    }
1643#ifdef DEBUG_EN2
1644  fprintf(stderr, "REC2 <%lu>\n", msg_size);
1645#endif
1646  /* protocol
1647   */
1648  /* memcpy(&header[3], &message[8], 4); */
1649
1650  /* payload
1651   */
1652  msg_ret = SH_ALLOC(msg_size+1);
1653  if (msg_size > 0)
1654    {
1655      memcpy(msg_ret, &message[16], msg_size);
1656    }
1657  msg_ret[msg_size] = '\0';
1658#ifdef DEBUG_EN2
1659  fprintf(stderr, "REC3 <%lu>\n", msg_size);
1660#endif
1661  SH_FREE(message);
1662
1663  return msg_ret;
1664}
1665#endif
1666
1667int sh_tools_hash_add(char * key, char * buf, int buflen)
1668{
1669  char         * theSig;
1670  char sigbuf[KEYBUF_SIZE];
1671
1672  SL_ENTER(_("sh_tools_hash_add"));
1673
1674  theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
1675  sl_strlcat(buf, theSig, buflen + KEY_LEN + 1);
1676     
1677  SL_RETURN((0), _("sh_tools_hash_add"));
1678}
1679
1680
1681/* return 0 (== FALSE) if no match, else 1 (== TRUE)
1682 */
1683int sh_tools_hash_vfy(char * key, char * buf, int buflen)
1684{
1685  char           hash[KEY_LEN+1];
1686  register int   i;
1687  char         * theSig;
1688  char sigbuf[KEYBUF_SIZE];
1689
1690  SL_ENTER(_("sh_tools_hash_vfy"));
1691
1692  theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
1693  sl_strlcpy(hash, theSig, KEY_LEN+1);
1694
1695  for (i = 0; i < KEY_LEN; ++i)
1696    {
1697      if (buf[buflen + i] != hash[i])
1698        SL_RETURN((0), _("sh_tools_hash_vfy"));
1699    }
1700     
1701  SL_RETURN((1), _("sh_tools_hash_vfy"));
1702}
1703
1704/* ------------------------------------------ */
1705
1706#if defined (SH_WITH_SERVER)
1707
1708/* add a checksum to a buffer; put checksum in front
1709 */
1710char * hash_me (char * key, char * buf,   int buflen)
1711{
1712  char           hash[KEY_LEN+1];
1713  char         * temp = NULL;
1714  register int   i;
1715  int            total = 0;
1716  char         * theSig;
1717  char sigbuf[KEYBUF_SIZE];
1718
1719
1720  SL_ENTER(_("hash_me"));
1721
1722#ifdef DEBUG_EN2
1723  fprintf(stderr, "hash_me    <%s> <%d>\n", 
1724          (key == NULL) ? "NULL" : key, buflen);
1725#endif
1726  /* key = H(NSRV,NCLT,SK)
1727   */
1728  ASSERT_RET((key != NULL), _("key != NULL"), (NULL));
1729  ASSERT_RET((buflen >= 0), _("buflen >= 0"), (NULL));
1730
1731  theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
1732  sl_strlcpy(hash, theSig, KEY_LEN+1);
1733
1734  if (sl_ok_adds(buflen, KEY_LEN))
1735    {
1736      total = KEY_LEN + buflen;
1737      temp  = SH_ALLOC (total);
1738
1739      for (i = 0; i < KEY_LEN; ++i)
1740        temp[i] = hash[i];
1741
1742      for (i = 0; i < buflen; ++i)
1743        temp[i+KEY_LEN] = buf[i];
1744    }
1745  else
1746    {
1747      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1748                      _("integer overflow"), 
1749                      _("hash_me"));
1750      temp = sh_util_strdup(buf);
1751    }
1752  SL_RETURN(temp, _("hash_me"));
1753}
1754#endif
1755
1756#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1757
1758/* verify the checksum of a buffer; checksum comes first
1759 */
1760int hash_check(char * key, 
1761               char * buf,   int buflen)
1762{
1763  char           hash[KEY_LEN+1];
1764  register int   i;
1765  char         * theSig;
1766  char sigbuf[KEYBUF_SIZE];
1767
1768  SL_ENTER(_("hash_check"));
1769
1770#ifdef DEBUG_EN2
1771  fprintf(stderr, "hash_check <%s> <%d>\n", 
1772          (key == NULL) ? "NULL" : key, buflen);
1773#endif
1774  theSig = sh_util_siggen (key, &buf[KEY_LEN], buflen-KEY_LEN,
1775                           sigbuf, sizeof(sigbuf));
1776  sl_strlcpy(hash, theSig, KEY_LEN+1);
1777     
1778  for (i = 0; i < KEY_LEN; ++i)
1779    {
1780      if (buf[i] != hash[i])
1781        SL_RETURN((-1), _("hash_check"));
1782    }
1783  SL_RETURN((0), _("hash_check"));
1784}
1785
1786#endif
1787
1788#if defined (SH_WITH_SERVER)
1789
1790char * get_client_conf_file (char * peer, unsigned long * length)
1791{
1792  char * ret;
1793  int    status;
1794  struct stat buf;
1795  char * base;
1796  size_t size;
1797
1798  SL_ENTER(_("get_client_conf_file"));
1799
1800  base = sh_util_strdup(DEFAULT_DATAROOT);
1801
1802  size = sl_strlen(base);
1803  if (sl_ok_adds(size, sl_strlen(peer)))
1804      size += sl_strlen(peer);
1805  if (sl_ok_adds(size, 6))
1806    size += 6;
1807
1808  ret = SH_ALLOC(size);
1809  sl_strlcpy(ret, base, size);
1810  sl_strlcat(ret, _("/rc."), size);
1811  sl_strlcat(ret, peer, size);
1812 
1813  status = retry_stat (FIL__, __LINE__, ret, &buf);
1814
1815  if (status == 0)
1816    goto lab_end;
1817  else
1818    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1819                    (long) sh.effective.uid, ret);
1820
1821  sl_strlcpy(ret, base, size);
1822  sl_strlcat(ret, "/rc", size);
1823 
1824  status = retry_stat (FIL__, __LINE__, ret, &buf);
1825
1826  if (status == 0)
1827    goto lab_end;
1828  else
1829    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
1830                    (long) sh.effective.uid, ret);
1831
1832  SH_FREE(base);
1833  SH_FREE(ret);
1834  *length=0;
1835  SL_RETURN(NULL, _("get_client_conf_file"));
1836
1837 lab_end:
1838  if (buf.st_size > 0x7fffffff)
1839    {
1840      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1841                    _("File too large"), _("get_client_conf_file"));
1842      SH_FREE(base);
1843      SL_RETURN(NULL, _("get_client_conf_file"));
1844    }
1845  *length = (unsigned long) buf.st_size;
1846  SH_FREE(base);
1847  SL_RETURN(ret, _("get_client_conf_file"));
1848}
1849
1850char * get_client_data_file (char * peer, unsigned long * length)
1851{
1852  char * ret;
1853  int    status;
1854  struct stat buf;
1855
1856  char * base;
1857  size_t size;
1858
1859  SL_ENTER(_("get_client_data_file"));
1860
1861  base = sh_util_strdup(DEFAULT_DATAROOT);
1862
1863  size = sl_strlen(base);
1864  if (sl_ok_adds(size, sl_strlen(peer)))
1865      size += sl_strlen(peer);
1866  if (sl_ok_adds(size, 8))
1867    size += 8;
1868
1869  ret = SH_ALLOC(size);
1870  sl_strlcpy(ret, base, size);
1871  sl_strlcat(ret, _("/file."), size);
1872  sl_strlcat(ret, peer, size);
1873 
1874  status = retry_stat (FIL__, __LINE__, ret, &buf);
1875
1876  if (status == 0)
1877    goto lab1_end;
1878  else
1879    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1880                    (long) sh.effective.uid, ret);
1881
1882
1883  sl_strlcpy(ret, base, size);
1884  sl_strlcat(ret, _("/file"), size);
1885 
1886  status = retry_stat (FIL__, __LINE__, ret, &buf);
1887
1888  if (status == 0)
1889    goto lab1_end;
1890  else
1891    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1892                    (long) sh.effective.uid, ret);
1893
1894
1895  *length = 0;
1896  SH_FREE(base);
1897  SH_FREE(ret);
1898  SL_RETURN(NULL, _("get_client_data_file"));
1899
1900 lab1_end:
1901  if (buf.st_size > 0x7fffffff)
1902    {
1903      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1904                    _("File too large"), _("get_client_data_file"));
1905      SH_FREE(base);
1906      SL_RETURN(NULL, _("get_client_data_file"));
1907    }
1908  *length = (unsigned long) buf.st_size;
1909  SH_FREE(base);
1910  SL_RETURN(ret, _("get_client_data_file"));
1911 
1912}
1913#endif
1914
1915#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
1916
1917/* --------- secure temporary file ------------ */
1918
1919SL_TICKET open_tmp ()
1920{
1921  SL_TICKET     fd;
1922  UINT32        ticks;
1923  char        * file;
1924  struct stat   buf;
1925  int           error;
1926  int           status = BAD;
1927  char        * my_tmp_dir;
1928  char hashbuf[KEYBUF_SIZE];
1929
1930  SL_ENTER(_("open_tmp"));
1931
1932#if defined(SH_TMPDIR)
1933  my_tmp_dir = sh_util_strdup(SH_TMPDIR); 
1934#else
1935#if defined(SH_WITH_SERVER)
1936  my_tmp_dir = sh_util_strdup(DEFAULT_LOGDIR); 
1937#else
1938  my_tmp_dir = sh_util_strdup(sh.effective.home);
1939#endif
1940#endif
1941
1942  if (0 !=  tf_trust_check (my_tmp_dir, SL_YESPRIV))
1943      {
1944        dlog(1, FIL__, __LINE__, 
1945             _("The directory for temporary files: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"), 
1946             my_tmp_dir);
1947        sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST,
1948                         (long) sh.effective.uid,
1949                         my_tmp_dir);
1950        SH_FREE(my_tmp_dir);
1951        aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1952      }
1953
1954  do {
1955
1956    /* create random filename in effective users home directory
1957     */
1958    ticks = taus_get ();
1959    if (my_tmp_dir[0] == '/' && my_tmp_dir[1] == '\0')
1960      file = sh_util_strconcat (my_tmp_dir, 
1961                                sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1962                                               hashbuf, sizeof(hashbuf)),
1963                                NULL);
1964    else
1965      file = sh_util_strconcat (my_tmp_dir, 
1966                                "/", 
1967                                sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1968                                               hashbuf, sizeof(hashbuf)),
1969                                NULL);
1970
1971    /* check whether it already exists (paranoia)
1972     */
1973    errno  = 0;
1974    status = retry_lstat(FIL__, __LINE__, file, &buf);
1975    error  = errno;
1976
1977    if ( (status < 0) && (error == ENOENT) ) /* file does not exist        */
1978      status = GOOD;
1979    else if (status < 0)                     /* unexpected error condition */
1980      {
1981        SH_FREE (file);
1982        SH_FREE(my_tmp_dir);
1983        sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
1984                        _("Error (lstat) while opening temporary file"), _("open_tmp"));
1985        TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
1986        SL_RETURN((-1), _("open_tmp"));
1987      }
1988    else                                     /* file exists                */
1989      {
1990        status = BAD;
1991        TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file exists already>\n")));
1992      }
1993   
1994    if (status == GOOD)
1995      { 
1996        if (0 ==  tf_trust_check (file, SL_YESPRIV))
1997          status = GOOD;
1998        else
1999          {
2000            status = BAD;
2001            TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file untrusted>\n")));
2002          }
2003      }
2004
2005    if (status == BAD)
2006      SH_FREE (file);
2007
2008  } while (status == BAD);
2009
2010  fd = sl_open_safe_rdwr (FIL__, __LINE__, file, SL_YESPRIV);
2011  if (SL_ISERROR(fd))
2012    {
2013      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN, 
2014                      _("Error opening temporary file"), _("open_tmp"));
2015      TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"), 
2016            fd, file));
2017    }
2018 
2019
2020  SH_FREE (file);
2021  SH_FREE(my_tmp_dir);
2022
2023  if (!SL_ISERROR(fd)) {
2024    sl_unlink(fd);
2025  } 
2026
2027  if (!SL_ISERROR(fd))
2028    SL_RETURN((fd), _("open_tmp"));
2029  else
2030    SL_RETURN((-1), _("open_tmp"));
2031}
2032
2033
2034int close_tmp (SL_TICKET fd)
2035{
2036  SL_ENTER(_("close_tmp"));
2037
2038  if (SL_ISERROR(sl_close (fd)))
2039    SL_RETURN((-1), _("close_tmp"));
2040  SL_RETURN((0), _("close_tmp")); 
2041}
2042
2043int rewind_tmp (SL_TICKET fd)
2044{
2045  SL_ENTER(_("rewind_tmp"));
2046
2047  if (SL_ISERROR(sl_rewind (fd)))
2048    SL_RETURN((-1), _("rewind_tmp"));
2049  SL_RETURN((0), _("rewind_tmp"));
2050}
2051#endif
2052
2053/********************************************************
2054 * Search rotated logfile
2055 */
2056#include <unistd.h>
2057#include <libgen.h>
2058#include <dirent.h>
2059
2060char * sh_rotated_log_search(const char * path, struct stat * buf)
2061{
2062
2063  size_t size;
2064  int    i;
2065  char * searchpath;
2066  struct stat sbuf;
2067  DIR  * dp;
2068  char * dname;
2069  char * bname;
2070
2071  dname  = sh_util_dirname(path);
2072  bname  = sh_util_basename(path);
2073
2074  size = strlen(dname) + strlen(bname) + 4;
2075  searchpath = SH_ALLOC(size);
2076
2077  for (i = 0; i < 2; ++i)
2078    {
2079      snprintf(searchpath, size, "%s/%s.%1d", dname, bname, i);
2080      if (0 == stat(searchpath, &sbuf) && sbuf.st_ino == buf->st_ino)
2081        {
2082          SH_FREE(dname);
2083          SH_FREE(bname);
2084          return searchpath;
2085        }
2086    }
2087
2088  SH_FREE(searchpath);
2089
2090  if (NULL != (dp = opendir(dname)))
2091    {
2092      struct dirent * de;
2093
2094      while (NULL != (de = readdir(dp)))
2095        {
2096          if (0 == strcmp(de->d_name, ".") || 0 == strcmp(de->d_name, ".."))
2097            continue;
2098
2099          size = strlen(dname) + strlen(de->d_name) + 2;
2100          searchpath = SH_ALLOC(size);
2101          snprintf(searchpath, size, "%s/%s", dname, de->d_name);
2102
2103          if (0 == stat(searchpath, &sbuf) && sbuf.st_ino == buf->st_ino)
2104            {
2105              SH_FREE(dname);
2106              SH_FREE(bname);
2107              closedir(dp);
2108              return searchpath;
2109            }
2110         
2111          SH_FREE(searchpath);
2112        }
2113      closedir(dp);
2114    }
2115
2116  SH_FREE(dname);
2117  SH_FREE(bname);
2118
2119  return NULL;
2120}
2121
Note: See TracBrowser for help on using the repository browser.