source: trunk/src/sh_tools.c

Last change on this file was 562, checked in by katerina, 5 months ago

Fix for ticket #450 (compiler warnings) and fixes for tests.

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