source: trunk/src/sh_tools.c @ 481

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

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

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