source: trunk/src/sh_forward.c @ 407

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

Fix for tickets #309, #310.

File size: 150.3 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22#include <string.h>
23#include <stdio.h>
24#include <stdlib.h>
25
26
27/* Must be early on FreeBSD
28 */
29#include <sys/types.h>
30
31/* must be .le. than (1020 * 64)
32 * (see sh_tools.c -- put_header)
33 *
34 * also: must be  (N * 16), otherwise
35 * binary files cannot be transferred encrypted
36 *
37 * 65280 = (1020*64)
38 * #define TRANS_BYTES 8000  V0.8
39 */
40#ifdef  SH_ENCRYPT_2
41#define TRANS_BYTES 65120
42#else
43#define TRANS_BYTES 65280
44#endif
45
46/* timeout for session key
47 */
48#define TIMEOUT_KEY 7200
49
50/* max time between connection attempts
51 */
52#define TIMEOUT_CON 2048
53
54/* #undef  SRP_DEBUG */
55/* #define SRP_DEBUG */
56
57#ifdef HAVE_MEMORY_H
58#include <memory.h>
59#endif
60
61#if TIME_WITH_SYS_TIME
62#include <sys/time.h>
63#include <time.h>
64#else
65#if HAVE_SYS_TIME_H
66#include <sys/time.h>
67#else
68#include <time.h>
69#endif
70#endif
71
72/*
73#ifdef TM_IN_SYS_TIME
74#include <sys/time.h>
75#else
76#include <time.h>
77#endif
78*/
79
80#ifdef HAVE_SYS_SELECT_H
81#include <sys/select.h>
82#endif
83
84#ifdef  HAVE_UNISTD_H
85#include <errno.h>
86#include <signal.h>
87#include <setjmp.h>
88#include <pwd.h>
89#include <grp.h>
90#include <sys/stat.h>
91#include <sys/resource.h>
92#include <fcntl.h>
93#include <sys/wait.h>
94#include <unistd.h>
95#endif
96
97#ifndef FD_SET
98#define NFDBITS         32
99#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
100#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
101#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
102#endif /* !FD_SET */
103#ifndef FD_SETSIZE
104#define FD_SETSIZE      32
105#endif
106#ifndef FD_ZERO
107#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
108#endif
109
110#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
111#include <sys/mman.h>
112#endif
113
114
115#include <netdb.h> 
116#include <sys/types.h> 
117#include <netinet/in.h> 
118#include <sys/socket.h> 
119#ifndef S_SPLINT_S
120#include <arpa/inet.h>
121#endif
122
123#include "sh_ipvx.h"
124#include "samhain.h"
125#include "sh_tiger.h"
126#include "sh_utils.h"
127#include "sh_unix.h"
128#include "sh_forward.h"
129#include "sh_srp.h"
130#include "sh_fifo.h"
131#include "sh_tools.h"
132#include "sh_entropy.h"
133#include "sh_html.h"
134#include "sh_nmail.h"
135#include "sh_socket.h"
136#define SH_NEED_GETHOSTBYXXX
137#include "sh_static.h"
138
139#ifdef SH_ENCRYPT
140#include "rijndael-api-fst.h"
141char * sh_tools_makePack (unsigned char * header, 
142                          char * payload, unsigned long payload_size,
143                          keyInstance * keyInstE);
144char * sh_tools_revertPack (unsigned char * header, char * message,
145                            keyInstance * keyInstE, 
146                            unsigned long message_size);
147#endif
148
149/* define this if you want to debug the client/server communication */
150/* #define SH_DBG_PROT 1 */
151
152#ifdef  SH_DBG_PROT
153#define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d))
154#else
155#define SH_SHOWPROT(c,d)
156#endif
157
158/* the port client will be connecting to
159 */
160#ifndef SH_DEFAULT_PORT
161#define SH_DEFAULT_PORT 49777   
162#endif
163
164#ifndef SH_SELECT_REPEAT
165#define SH_SELECT_REPEAT 60
166#endif
167
168#ifndef SH_HEADER_SIZE
169#define SH_HEADER_SIZE 7
170#endif
171
172#ifndef SH_CHALLENGE_SIZE
173#define SH_CHALLENGE_SIZE 9
174#endif
175
176#undef  FIL__
177#define FIL__  _("sh_forward.c")
178
179int     clt_class = (-1);
180
181extern int flag_err_debug;
182extern int flag_err_info;
183
184#ifndef SH_STANDALONE
185
186#if defined(WITH_TRACE) || defined(WITH_TPT)
187char * hu_trans(const char * ihu)
188{
189  static char ohu[17];
190  sprintf(ohu, _("%c%03o"), '\\',                   /* known to fit  */
191          (unsigned char) ihu[0]);
192  sprintf(&(ohu[4]), _("%c%03o"), '\\',             /* known to fit  */
193          (unsigned char) ihu[1]);
194  sprintf(&(ohu[8]), _("%c%03o"), '\\',             /* known to fit  */
195          (unsigned char) ihu[2]);
196  sprintf(&(ohu[12]), _("%c%03o"), '\\',            /* known to fit  */
197          (unsigned char) ihu[3]);
198  ohu[16] = '\0';
199  return ohu;
200}
201#endif
202
203static int StripDomain = S_TRUE;
204
205int sh_forward_set_strip (const char * str)
206{
207  static int fromcl = 0;
208  char dummy[2] = "F";
209
210  if (fromcl == 1)
211    return 0;
212
213  if (str == NULL)
214    {
215      fromcl = 1;
216      return (sh_util_flagval(dummy, &StripDomain));
217    }
218  else
219    return (sh_util_flagval(str, &StripDomain));
220}
221
222#include <ctype.h>
223
224const char * sh_strip_domain (char *name)
225{
226  char *          first;
227  static char     name_2[SH_MINIBUF+1];
228  register int    i = 0;
229
230  SL_ENTER(_("sh_strip_domain"));
231
232  if (StripDomain == S_FALSE || (first  = strchr(name, '.')) == NULL) 
233    {
234      SL_RETURN( name, _("sh_strip_domain"));
235    }
236  else
237    {
238
239      /* check whether it is in dotted number format
240       * --> last part must be kept
241       */
242      if (0 != sh_ipvx_is_numeric(name))
243        {
244          SL_RETURN( name, _("sh_strip_domain"));
245          /*
246          i = sl_strlen(name) - 1;
247          while (name[i] != '.' && i >= 0)
248            --i;
249          if (name[i] == '.') ++i;
250          sl_strlcpy( name_2, &name[i], SH_MINIBUF +1 );
251          */
252        }
253      else
254        {
255          first = name;
256          while (i < SH_MINIBUF && *first != '.' && *first != '\0')
257            {
258              name_2[i] = *first;
259              ++first; ++i;
260            }
261          name_2[i] = '\0';
262        }
263    }
264
265  SL_RETURN( name_2, _("sh_strip_domain"));
266}
267
268/* #ifndef SH_STANDALONE */
269#endif
270
271#ifndef USE_SRP_PROTOCOL
272static
273void sh_passwd (char * salt, char * password, char * nounce, char *hash)
274{
275
276  char           *combi;
277  size_t          len;
278  register int i;
279  unsigned char * dez = NULL;
280  char hashbuf[KEYBUF_SIZE];
281
282  if (password == NULL)
283    dez = (unsigned char *) &(skey->pw[0]);
284  else if (sl_strlen(password) < PW_LEN)
285    {
286      fprintf(stderr, _("Password has less than %d chars !\n"),
287                   PW_LEN);
288      _exit(EXIT_FAILURE);
289    }
290
291  if (password == NULL)
292    {
293      /* --- copy password ---
294       */
295      for (i = 0; i < PW_LEN; ++i)
296        { 
297          skey->vernam[i] = (char)(*dez); 
298          ++dez; 
299        }
300      (void) sl_strlcpy (skey->vernam,
301                         sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN,
302                                       hashbuf, sizeof(hashbuf)), 
303                         KEY_LEN+1);
304    }
305  else
306    {
307      (void) sl_strlcpy (skey->vernam, password, KEY_LEN+1);
308    }
309
310  len = sl_strlen(salt) + 1;
311  if (sl_ok_adds(len, sl_strlen(skey->vernam)))
312    len += sl_strlen(skey->vernam);
313  if (nounce != NULL && sl_ok_adds(len, sl_strlen(nounce))) 
314    len += sl_strlen(nounce);
315 
316  /* H(s,P)
317   */
318  combi = SH_ALLOC(len);
319  (void) sl_strlcpy (combi, salt, len);
320  (void) sl_strlcat (combi, skey->vernam, len);
321  if (nounce != NULL)
322    (void) sl_strlcat (combi, nounce, len);
323  (void) sl_strlcpy (hash, 
324                     sh_tiger_hash(combi, TIGER_DATA, 
325                                   (unsigned long) sl_strlen(combi),
326                                   hashbuf, sizeof(hashbuf)),
327                     KEY_LEN+1);
328
329  /*
330    fprintf(stderr, "DD: A: <%s>\n", salt);
331    fprintf(stderr, "DD: P: <%s>\n", skey->pw);
332    fprintf(stderr, "DD: V: <%s>\n", skey->vernam);
333    fprintf(stderr, "DD: C: <%s>\n", combi);
334    fprintf(stderr, "DD: H: <%s>\n", hash);
335  */
336
337  SH_FREE (combi);
338  hash[KEY_LEN] = '\0';
339  return;
340}
341#endif
342
343#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
344
345static int count_dev_server = 0;
346
347void reset_count_dev_server(void)
348{
349  count_dev_server = 0;
350  return;
351}
352
353int sh_forward_setlogserver (const char * address)
354{
355  SL_ENTER(_("sh_forward_setlogserver"));
356
357  if (address != NULL && count_dev_server < 2 
358      && sl_strlen(address) < SH_PATHBUF && sl_strlen(address) > 0) 
359    {
360      if (count_dev_server == 0)
361        (void) sl_strlcpy (sh.srvexport.name, address, SH_PATHBUF);
362      else
363        (void) sl_strlcpy (sh.srvexport.alt,  address, SH_PATHBUF);
364
365      ++count_dev_server;
366      SL_RETURN (0, _("sh_forward_setlogserver"));
367    }
368  SL_RETURN (-1, _("sh_forward_setlogserver"));
369}
370
371static
372int sh_forward_send_intern (int mysocket, char protocol, char * micro, 
373                            char * msgbuf, unsigned long length, int docrypt)
374{
375  unsigned long           numbytes, countbytes;
376  int                     flag_err = 0;
377  unsigned char           head[SH_HEADER_SIZE];
378  char                  * outbuf;
379
380#ifdef SH_ENCRYPT
381
382  unsigned long           blkfac;
383  int                     rem;
384  unsigned long           length2;
385  char                  * msg2buf = NULL;
386  char                  * p, * q;
387  RIJ_BYTE                    inBlock[B_SIZ]; 
388  RIJ_BYTE                    outBlock[B_SIZ];
389  unsigned long           j;
390  cipherInstance          cipherInst;
391  int                     err_num;
392  char expbuf[SH_ERRBUF_SIZE];
393#else
394  docrypt = SL_FALSE; /* dummy to fix compiler warning */
395#endif
396
397  SL_ENTER(_("sh_forward_send_intern"));
398
399#ifdef SH_ENCRYPT
400  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != (char)0))
401    {
402      put_header (head, (int)protocol, &length, micro);
403      msg2buf  = sh_tools_makePack (head, msgbuf, length, 
404                                    &(skey->keyInstE));
405      /*@-usedef@*/
406      length   = (unsigned long) (256 * (unsigned int)head[1] + 
407                                  (unsigned int)head[2]);
408      /*@+usedef@*/
409      outbuf   = msg2buf;
410    }
411  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != (char)0))
412    {
413      blkfac  = length/B_SIZ;
414      rem     = (int) (length - (B_SIZ * blkfac));
415      length2 = (B_SIZ * blkfac);
416      if ((rem > 0) && (length2+B_SIZ) > length2) 
417        length2 += B_SIZ;
418      else
419        rem = 0;
420
421      msg2buf = SH_ALLOC((size_t)length2);
422      p       = msgbuf;
423      q       = msg2buf;
424     
425      err_num = cipherInit (&cipherInst, (RIJ_BYTE)MODE_CBC, NULL);
426
427      if (err_num < 0)
428        sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
429                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
430                        _("sh_forward_send_intern: cipherInit"));
431
432
433      for (j = 0; j < blkfac; ++j)
434        {
435          memcpy(inBlock, p, B_SIZ);
436          err_num = blockEncrypt(&cipherInst, &(skey->keyInstE), 
437                                 inBlock, 128 * BNUM, outBlock);
438          if (err_num < 0)
439            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
440                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
441                            _("sh_forward_send_intern: blockEncrypt"));
442          memcpy(q, outBlock, B_SIZ);
443          p += B_SIZ;
444          q += B_SIZ;
445        }
446      if (rem > 0)
447        {
448          memset(inBlock, 0, B_SIZ);
449          memcpy(inBlock, p, (size_t)rem);
450          err_num = blockEncrypt(&cipherInst, &(skey->keyInstE), 
451                                 inBlock, 128 * BNUM, outBlock);
452          if (err_num < 0)
453            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
454                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
455                            _("sh_forward_send_intern: blockEncrypt"));
456          memcpy(q, outBlock, B_SIZ);
457          /* q += B_SIZ; *//* never read */
458        }
459
460      outbuf = msg2buf;
461      length = length2;
462      put_header (head, (int)protocol, &length, micro);
463    }
464  else
465    {
466      outbuf = msgbuf;
467      put_header (head, (int)protocol, &length, micro);
468    }
469#else
470  outbuf = msgbuf;
471  put_header (head, (int)protocol, &length, micro);
472#endif
473
474  SH_SHOWPROT(head,'>');
475 
476  numbytes     = SH_HEADER_SIZE;
477  countbytes   = write_port (mysocket, 
478                             (char *) head, numbytes,
479                             &flag_err, 300);
480
481  if (countbytes == numbytes && outbuf != NULL)
482    {
483      numbytes     = (length);
484      countbytes   = write_port (mysocket, 
485                                 outbuf, numbytes,
486                                 &flag_err, 300);
487    }
488
489#ifdef SH_ENCRYPT
490  /*@-usedef@*/
491  if (msg2buf != NULL)
492    SH_FREE(msg2buf);
493  /*@+usedef@*/
494#endif
495
496  if (countbytes == numbytes)
497    {
498      SL_RETURN( 0, _("sh_forward_send_intern"));
499    }
500  else
501    {
502      SL_RETURN( flag_err, _("sh_forward_send_intern"));
503    }
504}
505static
506int sh_forward_send (int mysocket, char protocol, char * micro, 
507                     char * msgbuf, unsigned long length)
508{
509  int i;
510  SL_ENTER(_("sh_forward_send"));
511  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
512  i =  sh_forward_send_intern (mysocket, protocol, micro, 
513                               msgbuf, length, S_FALSE);
514  SL_RETURN(i, _("sh_forward_send"));
515}
516static
517int sh_forward_send_crypt (int mysocket, char protocol, char * micro, 
518                           char * msgbuf, unsigned long length)
519{
520  int i;
521  SL_ENTER(_("sh_forward_send_crypt"));
522#ifdef SH_ENCRYPT
523  TPT(( 0, FIL__, __LINE__, _("msg=<Send encrypted.>\n")));
524#else
525  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
526#endif
527  i = sh_forward_send_intern (mysocket, protocol, micro, 
528                              msgbuf, length, S_TRUE);
529  SL_RETURN(i, _("sh_forward_send_crypt"));
530}
531
532
533/* receive answer, add a trailing NULL to terminate string
534 * rev 0.8
535 */
536static
537long sh_forward_receive_intern (int mysocket, char protocol, char * micro,     
538                                char *  msgbuf, unsigned long length, 
539                                int docrypt)
540{
541  unsigned long numbytes, countbytes;
542  int           flag_err = -1;
543  unsigned char head[SH_HEADER_SIZE];
544
545#ifdef SH_ENCRYPT
546
547  unsigned long           head_length;
548  unsigned long           blkfac;
549  /* unsigned long           length2; */
550  char                  * p, * q, * tmp;
551  RIJ_BYTE                    inBlock[B_SIZ]; 
552  RIJ_BYTE                    outBlock[B_SIZ];
553  unsigned long           j;
554  cipherInstance          cipherInst;
555  int                     err_num;
556  char expbuf[SH_ERRBUF_SIZE];
557#else
558  docrypt = SL_FALSE; /* dummy to fix compiler warning */
559#endif
560
561  SL_ENTER(_("sh_forward_receive_intern"));
562
563#ifdef SH_ENCRYPT
564  /* make sure length is not multiple of B_SIZ, see below
565   */
566  ASSERT_RET((length % B_SIZ != 0), _("length % 16 != 0"), flag_err);
567#endif
568
569  if (micro != NULL)
570    micro[4]     = '\0';
571
572  if (msgbuf != NULL)
573    msgbuf[0]     = '\0';
574
575  numbytes     = SH_HEADER_SIZE;
576  countbytes   = read_port (mysocket, 
577                            (char *) head, numbytes,
578                            &flag_err, 300);
579
580  if (countbytes != numbytes)
581    {
582      TPT(( 0, FIL__, __LINE__, _("msg=<countbytes != numbytes>\n")));
583      SL_RETURN(flag_err, _("sh_forward_receive_intern"));
584    }
585  /*@-usedef +ignoresigns@*/
586  else if (msgbuf == NULL)
587    {
588      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
589                      _("msgbuf is NULL"), _("sh_forward_receive_intern"));
590      SL_RETURN((-1), _("sh_forward_receive_intern"));
591    }
592  else if (head[0] != protocol && 
593           (head[0] & SH_PROTO_SRP) == (char)0 /* not set */)
594    {
595      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISMATCH);
596      SL_RETURN((-1), _("sh_forward_receive_intern"));
597    }
598  /*@+usedef -ignoresigns@*/
599  else
600    {
601      get_header (head, &numbytes, micro);
602      SH_SHOWPROT(head, '<');
603
604      if (numbytes > 0)
605        {
606          numbytes = (numbytes > length ? length : numbytes);
607
608          countbytes   = read_port (mysocket, 
609                                    msgbuf, numbytes,
610                                    &flag_err, 300);
611
612          if (countbytes < length)
613            msgbuf[countbytes] = '\0';
614          else
615            msgbuf[length-1] = '\0';
616
617          if (flag_err != 0)
618            {
619              TPT(( 0, FIL__, __LINE__, _("msg=<read error>\n")));
620              SL_RETURN((-1), _("sh_forward_receive_intern"));
621            }
622        }
623    }
624
625#ifdef SH_ENCRYPT
626  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != (char)0))
627    {
628      tmp = SH_ALLOC((size_t)length);
629      memcpy(tmp, msgbuf, (size_t)length);
630      tmp = sh_tools_revertPack (head, tmp, &(skey->keyInstD), countbytes);
631
632      head_length = (unsigned long) (256 * (unsigned int)head[1] + 
633                                     (unsigned int)head[2]);
634
635      /*
636       * revertPack returns header with length <= (original_length-16), so
637       * the following msgbuf[length] = '\0' is always safe.
638       * Nevertheless, check for proper length.
639       */
640      if (head_length <= (length-1))
641        length      = head_length;
642      else
643        --length;
644
645      memcpy(msgbuf, tmp, (size_t)length);
646      msgbuf[length] = '\0';
647      SH_FREE(tmp);
648      if (countbytes == numbytes) 
649        {
650          countbytes = length; /* to avoid error on return, see below */
651        }
652      numbytes = length;
653    }
654  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != (char)0))
655    {
656      /* Decrypt only complete blocks. If there is an incomplete block,
657       * something is wrong anyway.
658       * Decrypt in place.
659       */
660      blkfac  = countbytes/B_SIZ;
661
662      p       = msgbuf;
663      q       = msgbuf;
664     
665      err_num = cipherInit (&cipherInst, (RIJ_BYTE)MODE_CBC, NULL);
666
667      if (err_num < 0)
668        sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
669                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
670                        _("sh_forward_receive_intern: cipherInit"));
671
672      /* here we want to have (length % B_SIZ != 0), such that the
673       * terminating '\0' cannot be overwritten
674       */
675      for (j = 0; j < blkfac; ++j)
676        {
677          memcpy(inBlock, p, B_SIZ);
678          err_num = blockDecrypt(&cipherInst, &(skey->keyInstD), 
679                                 inBlock, 128 * BNUM, outBlock);
680          if (err_num < 0)
681            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
682                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
683                            _("sh_forward_receive_intern: blockDecrypt"));
684          memcpy(q, outBlock, B_SIZ);
685          p += B_SIZ;
686          q += B_SIZ;
687        }
688    }
689#endif
690
691  if (countbytes == numbytes)
692    {
693      SL_RETURN(((long)numbytes), _("sh_forward_receive_intern"));
694    }
695  else
696    {
697      TPT(( 0, FIL__, __LINE__, _("msg=<short read>\n")));
698      SL_RETURN(flag_err, _("sh_forward_receive_intern"));
699    }
700}
701
702static
703long sh_forward_receive (int mysocket, char protocol, char * micro,     
704                         char * msgbuf, unsigned long length)
705{
706  long i;
707  SL_ENTER(_("sh_forward_receive"));
708  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
709  i = sh_forward_receive_intern (mysocket, protocol, micro, 
710                                 msgbuf, length, S_FALSE);
711  SL_RETURN(i, _("sh_forward_receive"));
712}
713
714static
715long sh_forward_receive_crypt (int mysocket, char protocol, char * micro,     
716                               char * msgbuf, unsigned long length)
717{
718  long i;
719  SL_ENTER(_("sh_forward_receive_crypt"));
720#ifdef SH_ENCRYPT
721  TPT(( 0, FIL__, __LINE__, _("msg=<Receive encrypted.>\n")));
722#else
723  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
724#endif
725  i = sh_forward_receive_intern (mysocket, protocol, micro, 
726                                 msgbuf, length, S_TRUE);
727  SL_RETURN(i, _("sh_forward_receive"));
728}
729
730/**************************************************
731 *
732 *
733 *  C L I E N T 
734 *
735 *
736 ***************************************************/
737
738
739#include <time.h>
740
741static SH_FIFO * fifo = NULL;
742
743static long sh_forward_try (char * errmsg);
744
745static unsigned int ServerPort = SH_DEFAULT_PORT;
746
747int sh_forward_server_port (const char * str)
748{
749  unsigned long l;
750  char * endptr;
751
752  SL_ENTER(_("sh_forward_server_port"));
753
754  l = strtoul (str, &endptr, 0);
755  if (l > 65535 || endptr == str)
756    {
757      SL_RETURN (-1, _("sh_forward_server_port"));
758    }
759  ServerPort = (unsigned int) l;
760  SL_RETURN (0, _("sh_forward_server_port"));
761}
762
763long sh_forward (char * errmsg)
764{
765  static int           have_server = GOOD;
766  long   status;
767  char * popmsg;
768  static int failed = GOOD;
769
770  SL_ENTER(_("sh_forward"));
771
772  /* --- No log server available. ---
773   */
774  if (have_server == GOOD && sh.srvexport.name[0] == '\0')
775    {
776      have_server = BAD;
777      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NONAME);
778      SL_RETURN (-1, _("sh_forward"));
779    }
780  else if (have_server == BAD)
781    {
782      SL_RETURN (-1, _("sh_forward"));
783    }
784
785  /* --- Allocate fifo. ---
786   */
787  if (fifo == NULL)
788    {
789      fifo = SH_ALLOC(sizeof(SH_FIFO));
790      fifo_init(fifo);
791    }
792
793  /* --- Check for messages on the queue, and send them first. ---
794   */
795  while (NULL != (popmsg = pop_list(fifo)) )
796    {
797      status = sh_forward_try (popmsg);
798      if (status != 0)
799        {
800          (void) push_tail_list (fifo, popmsg, 0, NULL); 
801          SH_FREE(popmsg);
802          if (SH_FIFO_MAX == push_list (fifo, errmsg, 0,NULL))
803            {
804              SL_RETURN (-2, _("sh_forward"));
805            }
806          SL_RETURN (-1, _("sh_forward"));
807        }
808      SH_FREE(popmsg);
809    }
810
811  /* --- Now send the error message. ---
812   */ 
813  status = sh_forward_try (errmsg);
814  if (status != 0)
815    {
816      if (failed == GOOD)
817        sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
818                         _("log server"), 
819                         sh.srvexport.name);
820      failed = BAD;
821      if (SH_FIFO_MAX == push_list (fifo, errmsg, 0, NULL))/* push on stack */
822        {
823          SL_RETURN (-2, _("sh_forward"));
824        }
825      SL_RETURN (-1, _("sh_forward"));
826    }
827
828  failed = GOOD;
829  SL_RETURN (0, _("sh_forward")); 
830}
831
832static long sh_forward_try_impl (char * errmsg, char what);
833
834static long sh_forward_try (char * errmsg)
835{
836  long i;
837  SL_ENTER(_("sh_forward_try"));
838  i = sh_forward_try_impl (errmsg, (char)SH_PROTO_MSG);
839  SL_RETURN(i, _("sh_forward_try")); 
840}
841
842long sh_forward_req_file (char * file)
843{
844  long i;
845  char tmp_file[8];
846  SL_ENTER(_("sh_forward_req_file"));
847  (void) sl_strlcpy(tmp_file, file, 8);
848  i = sh_forward_try_impl (tmp_file, (char)SH_PROTO_BIG);
849  SL_RETURN(i, _("sh_forward_req_file")); 
850}
851
852static unsigned long sh_throttle_delay = 0;
853
854int sh_forward_set_throttle_delay (const char * c)
855{
856  long val;
857
858  SL_ENTER(_("sh_forward_set_throttle_delay"));
859
860  val = strtol (c, (char **)NULL, 10);
861  if (val < 0)
862    SL_RETURN( (-1), _("sh_forward_set_throttle_delay"));
863
864  val = (val > 1000) ? 1000 : val;
865
866  sh_throttle_delay = (unsigned long) val;
867  SL_RETURN( (0), _("sh_forward_set_throttle_delay"));
868}
869
870
871static  long sh_forward_try_impl (char * errmsg, char what)
872{
873  static int           initialized = BAD;
874  static int           conn_state  = GOOD;
875  int                  sockfd;
876  int                  flag_err;
877  char               * answer;
878
879  unsigned char        theProto;
880
881  char                 hash[KEY_LEN+1];
882  size_t               len;
883  char               * buffer;
884#ifdef SH_ENCRYPT_2
885  size_t               pos;  /* for the server command */
886#endif
887  char   head_u[5];
888
889  char   nsrv[KEY_LEN+1];
890  char   nclt[KEY_LEN+1];
891  SL_TICKET sfd = -1;
892  int    transfercount;
893
894  char   foo_M1[KEY_LEN+1];
895  UINT32 ticks;
896
897  char         error_msg[256];
898  char         error_call[SH_MINIBUF];
899  int          error_num = 0;
900
901#ifdef USE_SRP_PROTOCOL
902  char   u_real[SH_CHALLENGE_SIZE];
903  char * foo_A;
904  char * foo_Sc;
905  char * M;
906#else
907  char   nounce[KEY_LEN+1];
908  char   temp[2*KEY_LEN+1];
909  char   nonce_u[KEY_LEN+1];
910#endif
911 
912#ifdef SH_ENCRYPT
913  int err_num;
914  char expbuf[SH_ERRBUF_SIZE];
915#endif
916
917  static time_t time_now  = 1200;
918  static time_t time_last =    0;
919
920  static time_t timeout_val =  1;
921  char hashbuf[KEYBUF_SIZE];
922  char sigbuf[KEYBUF_SIZE];
923
924  SL_ENTER(_("sh_forward_try_impl"));
925
926  /* --- No message to transmit. ---
927   */
928  if (errmsg == NULL && initialized == GOOD)
929    SL_RETURN( 0, _("sh_forward_try_impl"));
930 
931  /* --- Connection in bad state. ---
932   */
933  if (initialized == BAD || conn_state == BAD)
934    {
935      timeout_val = 
936        (time_t)((timeout_val > TIMEOUT_CON) ? TIMEOUT_CON : timeout_val);
937
938      /* --- Retry bad attempt only after some time. ---
939       */
940      time_now  = time (NULL);
941      if ((time_now - time_last) < timeout_val) 
942        {
943          TPT(( 0, FIL__, __LINE__, _("msg=<Within deadtime, no retry.>\n")));
944          SL_RETURN( (-1), _("sh_forward_try_impl"));
945        }
946      TPT(( 0, FIL__, __LINE__, _("msg=<Retry.>\n")));
947    }
948  time_last  = time (NULL);
949
950
951  /* --- Try to connect to log server. ---
952   */
953  error_call[0] = '\0';
954
955  sockfd = connect_port_2 (sh.srvexport.name, sh.srvexport.alt, 
956                           ServerPort, 
957                           error_call, &error_num, error_msg, 256);
958
959  if (sockfd < 0)
960    {
961      conn_state = BAD;
962      timeout_val *= 2;
963      sh_error_handle ((-1), FIL__, __LINE__, error_num, 
964                       MSG_E_NET, error_msg, error_call,
965                       _("export"), sh.srvexport.name);
966      SL_RETURN( (-1), _("sh_forward_try_impl"));
967    }
968
969  conn_state = GOOD;
970
971  /*************************
972   *
973   *  initialization
974   *
975   */
976
977  flag_err = 0;
978  answer   = SH_ALLOC(512);
979  MLOCK(answer, 512);
980
981
982#ifndef USE_SRP_PROTOCOL
983
984  /**************************************************
985   *
986   * --- challenge/response authentication ---
987   *
988   **************************************************/
989
990  if (initialized == BAD)
991    {
992      theProto = (unsigned char) SH_PROTO_SRP;
993
994      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: entry>\n")));
995
996      (void) sl_strlcpy (answer, sh.host.name, 512);
997
998      flag_err = sh_forward_send (sockfd, (char) theProto, _("SALT"), 
999                                  answer,  (unsigned long)sl_strlen(answer));
1000
1001      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent SALT, flag_err = %d>\n"), 
1002            flag_err));
1003
1004      /* get nonce from server
1005       */
1006      if (flag_err == 0)
1007        {
1008          flag_err = (int) sh_forward_receive (sockfd, (char)theProto, head_u, 
1009                                               answer,  511);
1010          flag_err = (flag_err < 0) ? flag_err : 0;
1011          TPT(( 0, FIL__, __LINE__, 
1012                _("msg=<c/r: rcvt nonce, flag_err = %d>\n"), 
1013                flag_err));
1014        }
1015
1016      /* entry point for jump from message forward if session key must
1017       * be re-initialized
1018       */       
1019 initBlock:
1020
1021      if (0 == check_request (head_u, _("INIT")) && 
1022          flag_err == 0                         &&
1023          sl_strlen(answer) >  KEY_LEN )
1024        (void) sl_strlcpy(nounce, &answer[KEY_LEN], KEY_LEN+1);
1025      else
1026        flag_err = (-1);
1027
1028      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: rcvt INIT, flag_err = %d>\n"), 
1029            flag_err));
1030
1031      /* verify random nonce v from server H(v, P)v
1032       */
1033      sh_passwd (nounce, NULL, NULL, temp);
1034      if ( 0 != sl_strncmp(temp, answer, KEY_LEN))
1035        flag_err = (-1);
1036
1037      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: vrfy nonce, flag_err = %d>\n"), 
1038            flag_err));
1039
1040
1041      /* --- Create own nonce. ---
1042       */
1043      ticks = (UINT32) taus_get ();
1044
1045      (void) sl_strlcpy(nonce_u, 
1046                        sh_tiger_hash((char *) &ticks, 
1047                                      TIGER_DATA, 
1048                                      (unsigned long)sizeof(UINT32), 
1049                                      hashbuf, sizeof(hashbuf)),
1050                        KEY_LEN+1);
1051
1052      /* --- Form the message H(H(u,v),P)u ---
1053       */
1054      (void) sl_strlcpy(temp, nonce_u, 2*KEY_LEN+1); 
1055      (void) sl_strlcat(temp,  nounce, 2*KEY_LEN+1); 
1056      (void) sl_strlcpy(temp, 
1057                        sh_tiger_hash(temp, 
1058                                      TIGER_DATA, 
1059                                      (unsigned long)sl_strlen(temp), 
1060                                      hashbuf, sizeof(hashbuf)),
1061                        KEY_LEN+1);
1062      sh_passwd (temp, NULL, NULL, foo_M1);
1063      (void) sl_strlcpy(temp, foo_M1, 2*KEY_LEN+1);
1064      (void) sl_strlcat(temp, nonce_u, 2*KEY_LEN+1);
1065
1066      /* --- Send it to server. ---
1067       */
1068      if (flag_err == 0)
1069        {
1070          flag_err = (int) sh_forward_send (sockfd, 
1071                                            (char)(theProto|SH_PROTO_SRP), 
1072                                            _("PASS"), temp, 
1073                                            (unsigned long)sl_strlen(temp));
1074          TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent PASS, flag_err = %d>\n"),
1075                flag_err));
1076        }
1077
1078      if (flag_err == 0)
1079        {
1080          flag_err = (int)sh_forward_receive (sockfd,
1081                                              (char)(theProto|SH_PROTO_SRP), 
1082                                              head_u, answer,  511); 
1083          sh_passwd (nounce, NULL, nonce_u, foo_M1);
1084          (void) sl_strlcpy (skey->session, foo_M1, KEY_LEN+1);
1085#ifdef SH_ENCRYPT
1086          err_num = makeKey(&(skey->keyInstE), 
1087                            (RIJ_BYTE)DIR_ENCRYPT, 192, skey->session);
1088          if (err_num < 0)
1089            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1090                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
1091                            _("sh_forward_try_impl: makeKey"));
1092
1093          err_num = makeKey(&(skey->keyInstD), 
1094                            (RIJ_BYTE)DIR_DECRYPT, 192, skey->session);
1095          if (err_num < 0)
1096            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1097                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
1098                            _("sh_forward_try_impl: make_key"));
1099#endif
1100          initialized = GOOD;
1101        }
1102
1103      if (initialized == BAD)
1104        {
1105          timeout_val *= 2;
1106          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
1107          memset(answer, 0, 512);
1108          MUNLOCK(answer, 512);
1109          SH_FREE(answer);
1110          SL_RETURN( (-1), _("sh_forward_try_impl"));
1111        }
1112      else
1113        {
1114          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
1115        }
1116    }   
1117
1118#else
1119
1120
1121  /* This is the SRP authenticated key exchange protocol.
1122   * Produces a session key skey->session.
1123   */
1124  if (initialized == BAD)
1125    {
1126      TPT(( 0, FIL__, __LINE__, _("msg=<srp: entry>\n")));
1127
1128      theProto = SH_PROTO_SRP;
1129
1130      sl_strlcpy (answer, sh.host.name, 512);
1131      flag_err = sh_forward_send    (sockfd, theProto, _("SALT "), 
1132                                     answer,  sl_strlen(answer)); 
1133
1134      TPT(( 0, FIL__, __LINE__, _("msg=<srp: sent SALT, flag_err = %d>\n"), 
1135            flag_err));
1136
1137      if (flag_err == 0)
1138        {
1139          flag_err = sh_forward_receive (sockfd, theProto, head_u, 
1140                                         answer,  511);
1141          flag_err = (flag_err < 0) ? flag_err : 0;
1142          TPT(( 0, FIL__, __LINE__, 
1143                _("msg=<srp: rcvt nonce, flag_err = %d>\n"), 
1144                flag_err));
1145        }
1146
1147      /* Entry point for jump from message forward if session key must
1148       * be re-initialized.
1149       */       
1150    initBlock:
1151      TPT(( 0, FIL__, __LINE__, _("msg=<srp: INIT>\n")));
1152
1153      if (flag_err == 0 &&
1154          (0 == check_request (head_u, _("INIT"))))
1155        {
1156          if (0 != sh_srp_init())
1157            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EBGN);
1158          else /* if (0 == sh_srp_init()) */
1159            {
1160              TPT(( 0, FIL__, __LINE__, _("msg=<srp: bignum initialized>\n")));
1161
1162              sh_srp_x (answer, NULL);  /* x        password      */
1163              sh_srp_make_a ();         /* a        random number */
1164              foo_A = sh_srp_A();       /* g^a                    */
1165
1166              TPT(( 0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), foo_A));
1167
1168              if (foo_A == NULL)
1169                flag_err = (-1);
1170
1171              if (flag_err == 0)
1172                flag_err = sh_forward_send    (sockfd, 
1173                                               (theProto|SH_PROTO_SRP), 
1174                                               _("PC01"),
1175                                               foo_A, sl_strlen(foo_A)+1); 
1176              if (flag_err == 0)
1177                {
1178                  flag_err = sh_forward_receive (sockfd, 
1179                                                 (theProto|SH_PROTO_SRP),
1180                                                 head_u,
1181                                                 answer, 511);
1182                  flag_err = (flag_err < 0) ? flag_err : 0;
1183                  TPT(( 0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), answer));
1184                  TPT(( 0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), head_u[0], head_u[1], head_u[2], head_u[3]));
1185                }
1186
1187              /*                     u        nounce        */
1188              /*                     B        answer        */
1189              /*                     S = (B-g^x)^(a+ux)     */
1190             
1191              if (flag_err == 0)
1192                { 
1193                  if (0 != sh_srp_check_zero (answer))
1194                    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EZERO);
1195                  else /* if (0 != sh_srp_check_zero (answer)) */
1196                    {
1197                      sl_strlcpy(u_real, sh_tiger_hash(head_u, TIGER_DATA, 4, 
1198                                                       hashbuf, sizeof(hashbuf)), 
1199                                 SH_CHALLENGE_SIZE);
1200                      foo_Sc = sh_srp_S_c (u_real, answer);
1201
1202                      TPT(( 0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
1203                            u_real));
1204                      TPT(( 0, FIL__, __LINE__, _("msg=<srp:Sc = %s>\n"), 
1205                            foo_Sc));
1206
1207                      /* --- Now send H(A,B,H(Sc)) and check. ---
1208                       */
1209                      if (foo_Sc != NULL && 0 == sh_srp_check_zero (foo_Sc))
1210                        {
1211                          sh_srp_M(foo_A, 
1212                                   answer, 
1213                                   sh_tiger_hash(foo_Sc, 
1214                                                 TIGER_DATA, 
1215                                                 sl_strlen(foo_Sc), 
1216                                                 hashbuf, sizeof(hashbuf)),
1217                                   foo_M1, KEY_LEN+1);
1218
1219
1220                          TPT(( 0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"), 
1221                                foo_M1));
1222
1223                          flag_err = sh_forward_send(sockfd, 
1224                                                     (theProto|SH_PROTO_SRP), 
1225                                                     _("PC02"),
1226                                                     foo_M1, KEY_LEN+1);
1227                        }
1228                      else
1229                        {
1230                          flag_err = (-1);
1231                        }
1232
1233                      if (flag_err == 0)
1234                        {
1235                          flag_err =sh_forward_receive(sockfd, 
1236                                                       (theProto|SH_PROTO_SRP),
1237                                                       head_u, 
1238                                                       answer, 511);
1239                          flag_err = (flag_err < 0) ? flag_err : 0;
1240                          TPT(( 0, FIL__, __LINE__, _("msg=<srp: M = %s>\n"), 
1241                                answer));
1242                        }
1243
1244                      if (flag_err == 0   &&
1245                          (0 == check_request (head_u, _("PARP"))))
1246                        {
1247                          /* ------  verify M2 = H(A, M1, K) --------
1248                           */
1249                          char M_buf[KEY_LEN+1];
1250                          M = sh_srp_M (foo_A, foo_M1,
1251                                        sh_tiger_hash(foo_Sc,
1252                                                      TIGER_DATA,
1253                                                      sl_strlen(foo_Sc), 
1254                                                      hashbuf, sizeof(hashbuf)),
1255                                        M_buf, sizeof(M_buf)
1256                                        );
1257                          if (M != NULL && 
1258                              0 == sl_strncmp (answer, M, KEY_LEN+1))
1259                            {
1260                              sl_strlcpy (skey->session, 
1261                                          sh_tiger_hash(foo_Sc, 
1262                                                        TIGER_DATA,
1263                                                        sl_strlen(foo_Sc), 
1264                                                        hashbuf, sizeof(hashbuf)),
1265                                          KEY_LEN+1);
1266                              TPT(( 0, FIL__, __LINE__, 
1267                                    _("msg=<srp: Key = %s>\n"), 
1268                                    skey->session));
1269
1270#ifdef SH_ENCRYPT
1271                              err_num = makeKey(&(skey->keyInstE), 
1272                                                DIR_ENCRYPT, 
1273                                                192, skey->session);
1274                              if (err_num < 0)
1275                                sh_error_handle((-1), FIL__, __LINE__, -1, 
1276                                                MSG_E_SUBGEN,
1277                                                errorExplain(err_num, expbuf, sizeof(expbuf)), 
1278                                                _("sh_forward_try_impl: makeKey"));
1279                              err_num = makeKey(&(skey->keyInstD), 
1280                                                DIR_DECRYPT, 
1281                                                192, skey->session);
1282                              if (err_num < 0)
1283                                sh_error_handle((-1), FIL__, __LINE__, -1, 
1284                                                MSG_E_SUBGEN,
1285                                                errorExplain(err_num, expbuf, sizeof(expbuf)), 
1286                                                _("sh_forward_try_impl: makeKey"));
1287#endif
1288                              initialized = GOOD;
1289                            }
1290                        }
1291                      if (foo_Sc != NULL)
1292                        SH_FREE(foo_Sc);
1293                    }
1294                }
1295              if (foo_A != NULL)
1296                SH_FREE(foo_A);
1297              sh_srp_exit();
1298            }
1299        }
1300
1301      if (initialized == BAD)
1302        {
1303          timeout_val *= 2;
1304          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
1305          memset(answer, '\0', 512);
1306          MUNLOCK(answer, 512);
1307          SH_FREE(answer);
1308          SL_RETURN( (-1), _("sh_forward_try_impl"));
1309        }
1310      else
1311        {
1312          if (flag_err_info == SL_TRUE)
1313            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
1314        }
1315    }
1316
1317#endif
1318
1319  /* no message, just session key negotiated
1320   */
1321  if (errmsg == NULL)
1322    {
1323      timeout_val = 1;
1324      memset(answer, 0, 512);
1325      MUNLOCK(answer, 512);
1326      SH_FREE(answer);
1327      TPT(( 0, FIL__, __LINE__, _("msg=<No message.>\n")));
1328      SL_RETURN( (0), _("sh_forward_try_impl"));
1329    }
1330  else if (what == (char)SH_PROTO_BIG)
1331    {
1332      MUNLOCK(answer, 512);
1333      SH_FREE (answer);
1334      answer   = SH_ALLOC(TRANS_BYTES + 256);
1335      MLOCK(answer, TRANS_BYTES + 256);
1336      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer.>\n")));
1337    }
1338
1339
1340  (void) sl_strlcpy (answer, sh_util_siggen(skey->session,
1341                                            sh.host.name,
1342                                            sl_strlen(sh.host.name),
1343                                            sigbuf, sizeof(sigbuf)), 
1344              KEY_LEN+1);
1345  TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"), sh.host.name));
1346  TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"), skey->session));
1347  TPT((0, FIL__, __LINE__, _("msg=<sign %s>\n"), answer));
1348
1349   
1350  (void) sl_strlcat (answer, sh.host.name, 512);
1351
1352  TPT((0, FIL__, __LINE__, _("msg=<mesg %s>\n"), answer));
1353
1354  /***********************************************
1355   *
1356   * send the message
1357   *
1358   */
1359
1360  if (what == (char) SH_PROTO_MSG)
1361    {
1362      theProto = (unsigned char)SH_PROTO_MSG;
1363
1364      /* say HELO       
1365       */
1366
1367      flag_err = sh_forward_send    (sockfd, 
1368                                     (char)theProto, _("HELO"),
1369                                     answer, 
1370                                     (unsigned long)sl_strlen(answer)); 
1371      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
1372            answer, flag_err));
1373      if (flag_err == 0)
1374        { 
1375          /* --- Get challenge. --- 
1376           */
1377          flag_err = (int) sh_forward_receive (sockfd, 
1378                                               (char)SH_PROTO_MSG, head_u, 
1379                                               answer, 255);   
1380          TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s, u %s, status %d.>\n"), 
1381            answer, hu_trans(head_u), flag_err));
1382          flag_err = (flag_err < 0) ? flag_err : 0;
1383         
1384          if (flag_err == 0)
1385            {
1386             
1387              /* --- Re-negotiate key. ---
1388               */
1389              if (0 == check_request_nerr(head_u, _("INIT")))
1390                {
1391                  flag_err    = 0;
1392                  initialized = BAD;
1393                  goto initBlock;
1394                }
1395             
1396              else if (0 == check_request(head_u, _("TALK")))
1397                {
1398
1399                  /* --- Save the challenge. --- 
1400                   */
1401                  (void) sl_strlcpy(nsrv, answer, KEY_LEN + 1);
1402                 
1403                  /* --- Hash(msg,challenge,sessionkey). --- 
1404                   */
1405                  len    = sl_strlen(errmsg) + sl_strlen(answer) 
1406                    + KEY_LEN + 1;
1407                  len = (size_t)((len < 256) ? 256 : len);
1408                  buffer = SH_ALLOC(len);
1409                  MLOCK(buffer, len);
1410                  (void) sl_strlcpy(buffer, errmsg, len);
1411                  (void) sl_strlcat(buffer, answer, len);
1412                  (void) sl_strlcpy(hash, 
1413                                    sh_util_siggen (skey->session, 
1414                                                    buffer, 
1415                                                    sl_strlen(buffer),
1416                                                    sigbuf, sizeof(sigbuf)), 
1417                                    KEY_LEN+1);
1418                  TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
1419                       sh_util_siggen(skey->session, buffer, 
1420                                      sl_strlen(buffer), sigbuf, sizeof(sigbuf))));                   
1421
1422                  (void) sl_strlcpy(buffer, errmsg, len);
1423                  (void) sl_strlcat(buffer, hash,   len);
1424
1425                  flag_err = 
1426                    sh_forward_send_crypt (sockfd, 
1427#ifdef SH_ENCRYPT
1428#ifdef SH_ENCRYPT_2
1429                                           (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_EN2),
1430#else
1431                                           (char)(SH_PROTO_MSG|SH_PROTO_ENC),
1432#endif
1433#else
1434                                           (char)(SH_PROTO_MSG),
1435#endif
1436                                           _("MESG"),
1437                                           buffer, 
1438                                           (unsigned long)(sl_strlen(buffer)+1));
1439                  TPT(( 0, FIL__, __LINE__, 
1440                        _("msg=<Sent %s, status %d.>\n"), 
1441                        answer, flag_err));
1442
1443                  /* --- Get confirmation. ---
1444                   */
1445                  if (flag_err == 0)
1446                    {
1447                      flag_err = (int)
1448                        sh_forward_receive_crypt (sockfd, 
1449#ifdef SH_ENCRYPT
1450#ifdef SH_ENCRYPT_2
1451                                                  (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_EN2|SH_PROTO_END),
1452#else
1453                                                  (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_END),
1454#endif
1455#else
1456                                                  (char)(SH_PROTO_MSG|SH_PROTO_END),
1457#endif
1458                                                  head_u, 
1459                                                  answer, 255);   
1460                      TPT(( 0, FIL__, __LINE__, 
1461                            _("msg=<Rcvt %s, u %s, status %d.>\n"), 
1462                            answer, hu_trans(head_u), flag_err));
1463                      flag_err = (flag_err < 0) ? flag_err : 0;
1464                    }
1465
1466
1467                  /* --- Check confirmation. ---
1468                   */
1469                  if (flag_err == 0)
1470                    {
1471                      /*   CLIENT CONF RECV
1472                       *
1473                       *   first KEY_LEN bytes must be
1474                       *   sig(skey->session (errmsg nsrv))
1475                       *
1476                       */
1477                      (void) sl_strlcpy(buffer, errmsg, len);
1478                      (void) sl_strlcat(buffer, nsrv,   len);
1479                      flag_err = sl_strncmp(answer,
1480                                            sh_util_siggen(skey->session, 
1481                                                           buffer,
1482                                                           sl_strlen(buffer),
1483                                                           sigbuf, sizeof(sigbuf)),
1484                                            KEY_LEN);
1485                      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
1486                           sh_util_siggen(skey->session, buffer, 
1487                                          sl_strlen(buffer), sigbuf, sizeof(sigbuf))));
1488
1489                      if (flag_err != 0)
1490                        {
1491#ifdef ENOMSG
1492                          flag_err = ENOMSG;
1493#else
1494                          flag_err = EIO;
1495#endif
1496                          sh_error_handle((-1), FIL__, __LINE__, flag_err,
1497                                          MSG_TCP_NOCONF);
1498                        }
1499                      else
1500                        {
1501#ifdef SH_ENCRYPT_2
1502                          /* --- SERVER CMD --- */
1503                          if (answer[KEY_LEN] != '\0' && 
1504                              sl_strlen(answer) > (2*KEY_LEN))
1505                            {
1506                              pos = sl_strlen(answer) - (2*KEY_LEN);
1507                              /*
1508                               * buffer is  >= 256
1509                               * answer has <= 255 bytes
1510                               */
1511                              (void) sl_strlcpy(buffer, &answer[KEY_LEN], 
1512                                                pos+1);
1513                              flag_err = 
1514                                sl_strncmp(&answer[KEY_LEN+pos],
1515                                           sh_util_siggen(skey->session, 
1516                                                          buffer,
1517                                                          pos,
1518                                                          sigbuf, sizeof(sigbuf)),
1519                                           KEY_LEN);
1520                             
1521                              TPT((0, FIL__, __LINE__, 
1522                                   _("CONF RECV <%d> <%s>\n"),
1523                                   flag_err, &answer[KEY_LEN]));
1524                             
1525                              if (flag_err != 0) {
1526                                sh_error_handle((-1), FIL__, __LINE__, 
1527                                                flag_err,
1528                                                MSG_TCP_NOCONF);
1529                              } 
1530#ifdef SH_WITH_CLIENT
1531                              else {
1532                                sh_socket_server_cmd(buffer);
1533                              }
1534#endif
1535                              flag_err = 0;
1536
1537                            } else {
1538                             
1539                              TPT((0, FIL__, __LINE__, 
1540                                   _("CONF RECV <0> <[null]>\n")));
1541                             
1542                            }
1543                          /* --- SERVER CMD END --- */
1544#endif
1545                          if (flag_err_debug == SL_TRUE)
1546                            sh_error_handle((-1), FIL__, __LINE__, 0,
1547                                            MSG_TCP_CONF);
1548                        }
1549                    }
1550
1551                  memset(buffer, 0, len);
1552                  MUNLOCK(buffer, len);
1553                  SH_FREE(buffer);
1554                }
1555              else
1556                {
1557                  /* --- Unexpected reply from server. ---
1558                   */
1559                  sh_error_handle((-1), FIL__, __LINE__, 0,
1560                                  MSG_TCP_UNEXP);
1561                  flag_err = (-1);
1562                }
1563            }
1564        }
1565    }
1566
1567
1568  else if (what == (char)SH_PROTO_BIG)
1569    {
1570      theProto = (unsigned char) SH_PROTO_BIG;
1571
1572      /* --- Say HELO  ---       
1573       */
1574      flag_err = sh_forward_send    (sockfd, (char) theProto, _("HELO"),
1575                                     answer, (unsigned long)sl_strlen(answer));
1576      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
1577            answer, flag_err));
1578
1579      if (flag_err == 0)
1580        { 
1581          /* --- Get NSRV. --- 
1582           */
1583          flag_err = (int) sh_forward_receive (sockfd, 
1584                                               (char)SH_PROTO_BIG, head_u, 
1585                                               answer, 255);
1586          TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s, u %s, status %d.>\n"), 
1587            answer, hu_trans(head_u), flag_err));
1588          flag_err = (flag_err < 0) ? flag_err : 0;
1589        }   
1590
1591      if (flag_err == 0)
1592        {
1593         
1594          /* --- Re-negotiate key. ---
1595           */
1596          if (0 == check_request_nerr(head_u, _("INIT")))
1597            {
1598              flag_err    = 0;
1599              initialized = BAD;
1600              goto initBlock;
1601            }
1602         
1603 
1604          else if (0 == check_request(head_u, _("NSRV")))
1605            {
1606#ifdef SH_ENCRYPT
1607              /* --- Set encryption flag. ---
1608               */
1609#ifdef SH_ENCRYPT_2
1610              theProto = 
1611                (unsigned char)(SH_PROTO_BIG | SH_PROTO_ENC | SH_PROTO_EN2);
1612#else
1613              theProto = (unsigned char)(SH_PROTO_BIG | SH_PROTO_ENC);
1614#endif
1615#endif
1616
1617              (void) sl_strlcpy(nsrv, answer, KEY_LEN+1);
1618             
1619              /* --- Generate a nonce. ---
1620               */
1621              ticks = (UINT32) taus_get ();
1622             
1623              (void) sl_strlcpy(nclt, 
1624                                sh_tiger_hash((char *) &ticks, 
1625                                              TIGER_DATA, 
1626                                              (unsigned long)sizeof(UINT32), 
1627                                              hashbuf, sizeof(hashbuf)),
1628                                KEY_LEN+1);
1629
1630              /* --- Compute H(nsrv, nclt, skey). ---
1631               */
1632              buffer = sh_util_strconcat (nsrv, nclt, 
1633                                          skey->session, NULL);
1634              (void)sl_strlcpy(foo_M1, 
1635                               sh_tiger_hash(buffer, TIGER_DATA,
1636                                             (unsigned long)sl_strlen(buffer), 
1637                                             hashbuf, sizeof(hashbuf)),
1638                               KEY_LEN+1);
1639              memset (buffer, 0, sl_strlen(buffer));
1640
1641              /* --- Send (nclt, msg) ---
1642               */
1643              (void) sl_strlcpy(buffer, nclt, KEY_LEN+1);
1644              (void) sl_strlcat(buffer, errmsg, KEY_LEN+5);
1645
1646#ifndef SH_ENCRYPT
1647              buffer[KEY_LEN+4] = theProto;
1648              buffer[KEY_LEN+5] = '\0';
1649              sh_tools_hash_add(foo_M1, buffer, KEY_LEN+5);
1650#endif
1651
1652              flag_err = 
1653                sh_forward_send_crypt (sockfd, (char) theProto, _("NCLT"),
1654                                       buffer, 
1655                                       (unsigned long) sl_strlen(buffer));
1656 
1657              TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
1658                    buffer, flag_err));
1659              SH_FREE (buffer);
1660            }   
1661        }
1662
1663      if (flag_err == 0)
1664        {
1665          /* --- Receive the file. ---
1666           */
1667
1668          /* --- Open a temporary file. ---
1669           */
1670         
1671          if ( (sfd = open_tmp ()) < 0)
1672            {
1673              flag_err = (-1);
1674              sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_EFIL);
1675            }
1676          else
1677            {
1678              /* --- Read from socket into tmp file. ---
1679               */
1680              transfercount = 0;
1681              /* flag_err      = 0; *//* never read */
1682
1683              do {
1684                flag_err = (int)
1685                  sh_forward_receive_crypt (sockfd, 
1686#ifdef SH_ENCRYPT
1687#ifdef SH_ENCRYPT_2
1688                                            (char)(SH_PROTO_BIG|SH_PROTO_EN2|SH_PROTO_ENC),
1689#else
1690                                            (char)(SH_PROTO_BIG|SH_PROTO_ENC),
1691#endif
1692#else
1693                                            (char)(SH_PROTO_BIG),
1694#endif
1695                                            head_u, 
1696                                            answer, 
1697                                            TRANS_BYTES + 255);
1698
1699                TPT(( 0, FIL__, __LINE__, 
1700                      _("msg=<Received: %d bytes, marked %s.>\n"),
1701                      flag_err, hu_trans(head_u)));
1702
1703                if (flag_err > 0 && 0 == check_request_nerr(head_u, _("FILE")))
1704                  {
1705                    if (0 == hash_check (foo_M1, answer, flag_err))
1706                      {
1707                        (void) sl_write(sfd, &answer[KEY_LEN], 
1708                                        flag_err-KEY_LEN);
1709                        ++transfercount;
1710                        /***
1711                         ***  --- Delay for throughput throttling ---
1712                         ***/
1713                        if (sh_throttle_delay > 0)
1714                          retry_msleep(sh_throttle_delay/1000, sh_throttle_delay % 1000);
1715                        /***
1716                         ***  --- End delay                       ---
1717                         ***/
1718                        flag_err = 
1719                          sh_forward_send_crypt (sockfd, (char) theProto, 
1720                                                 _("RECV"),
1721                                                 nclt, 
1722                                                 (unsigned long)sl_strlen(nclt));
1723
1724                      }
1725                    else
1726                      {
1727                        TPT(( 0, FIL__, __LINE__, 
1728                              _("msg=<File transfer: Hash check failed.>\n")));
1729                        break;
1730                      }
1731                  }
1732                else
1733                  {
1734                    TPT(( 0, FIL__, __LINE__, 
1735                          _("msg=<File transfer: No more data.>\n")));
1736                    break;
1737                  }
1738              } while (transfercount < 32000); /* 64 Mbyte */
1739                   
1740              if (0 == check_request_nerr(head_u, _("EEOT")) &&
1741                  0 <  flag_err                             &&
1742                  0 == hash_check (foo_M1, answer, (int)sl_strlen(answer)))
1743                {
1744                  flag_err = 
1745                    sh_forward_send_crypt (sockfd, (char) theProto, 
1746                                           _("EOTE"),
1747                                           nclt, 
1748                                           (unsigned int) sl_strlen(nclt));
1749
1750                  (void) rewind_tmp (sfd);
1751                  (void) sl_sync(sfd);
1752                  if (flag_err_info == SL_TRUE)
1753                    sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_FOK);
1754                }
1755              else
1756                {
1757                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
1758                  (void) sl_close (sfd);
1759                  sfd = (-1);
1760                }
1761
1762              (void) sl_close_fd (FIL__, __LINE__, sockfd);
1763              memset(answer, 0, TRANS_BYTES + 256);
1764              MUNLOCK(answer, TRANS_BYTES + 256);
1765              SH_FREE(answer);
1766              timeout_val = 1;
1767
1768              SL_RETURN( (sfd), _("sh_forward_try_impl"));
1769            }
1770        }
1771
1772      (void) sl_close_fd (FIL__, __LINE__, sockfd);
1773      memset(answer, 0, TRANS_BYTES + 256);
1774      MUNLOCK(answer, TRANS_BYTES + 256);
1775      SH_FREE(answer);
1776      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
1777      timeout_val *= 2;
1778
1779      SL_RETURN( (-1), _("sh_forward_try_impl"));
1780    }
1781                 
1782     
1783 
1784  (void) sl_close_fd (FIL__, __LINE__, sockfd);
1785  memset(answer, 0, 512);
1786  MUNLOCK(answer, 512);
1787  SH_FREE(answer);
1788
1789#ifndef EIO
1790#define EIO 5
1791#endif
1792 
1793
1794#ifdef SH_ERROR_H 
1795  if (flag_err != 0)
1796    {
1797      char errbuf[SH_ERRBUF_SIZE];
1798      conn_state = BAD;
1799      timeout_val *= 2;
1800      if (flag_err < 0 || NULL == sh_error_message(flag_err, errbuf, sizeof(errbuf)))
1801        flag_err = EIO;
1802      sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_ECONN,
1803                      sh_error_message(flag_err, errbuf, sizeof(errbuf)));
1804      SL_RETURN( (-1), _("sh_forward_try_impl"));
1805    }
1806#endif
1807  timeout_val = 1;
1808
1809  SL_RETURN( (0), _("sh_forward_try_impl"));
1810}
1811
1812/* #ifdef SH_WITH_CLIENT */
1813#endif
1814
1815
1816#if defined (SH_WITH_SERVER)
1817
1818#ifndef USE_SRP_PROTOCOL
1819
1820int sh_forward_make_client (const char * str)
1821{
1822  /* char *          safer; */
1823  char            key[KEY_LEN+1];
1824  unsigned char   in[PW_LEN+1];
1825  int    i = 0, j, k, l = 0;
1826  char hashbuf[KEYBUF_SIZE];
1827 
1828  if (sl_strlen(str) != (PW_LEN * 2)) 
1829    {
1830      fprintf(stderr, 
1831              _("Input must be a %d digit hexadecimal number"\
1832                " (only 0-9, a-f, A-F allowed in input)\n"),
1833              (PW_LEN * 2));
1834      _exit(EXIT_FAILURE);
1835    }
1836 
1837  while (i < (PW_LEN * 2))
1838    {
1839      k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
1840      if (k != -1 && j != -1) 
1841        {
1842          in[l] = (k * 16 + j);
1843          ++l; i+= 2;
1844        }
1845      else
1846        {
1847          fprintf(stderr, _("Invalid char %c\n"), str[i]);
1848          _exit(EXIT_FAILURE);
1849        }
1850    }
1851  in[PW_LEN] = '\0';
1852
1853  sl_strlcpy ((char *)key, 
1854              sh_tiger_hash ((char*)in, TIGER_DATA, PW_LEN, 
1855                             hashbuf, sizeof(hashbuf)), 
1856              KEY_LEN+1);
1857  key[KEY_LEN] = '\0';
1858 
1859  fprintf(stdout, _("Client entry: Client=HOSTNAME@00000000@%s\n"), 
1860          key);
1861  fflush(stdout);
1862
1863  _exit(EXIT_SUCCESS);
1864  return 0;
1865}
1866
1867#else
1868
1869int sh_forward_make_client (const char * str)
1870{
1871  char * foo_v;
1872
1873  char   salt[17];
1874  char   key[KEY_LEN+1];
1875  char   in[PW_LEN];
1876  int    i = 0, j, k, l = 0;
1877  char hashbuf[KEYBUF_SIZE];
1878 
1879  if (sl_strlen(str) != (PW_LEN*2)) 
1880    {
1881      fprintf(stderr, 
1882              _("Input must be a %d digit hexadecimal number"\
1883                " (only 0-9, a-f, A-F allowed in input)\n"),
1884              (PW_LEN*2));
1885      _exit(EXIT_FAILURE);
1886    }
1887
1888    while (i < (PW_LEN*2))
1889      {
1890        k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
1891        if (k != -1 && j != -1) 
1892          {
1893            in[l] = (k * 16 + j);
1894            ++l; i+= 2;
1895          }
1896        else
1897          {
1898            fprintf(stderr, _("Invalid char %c\n"), str[i]);
1899            _exit(EXIT_FAILURE);
1900          }
1901      }
1902   
1903 
1904    if (0 == sh_srp_init())
1905      {
1906        sh_util_keyinit(key, KEY_LEN);
1907        sl_strlcpy(salt, sh_tiger_hash(key, TIGER_DATA, KEY_LEN, 
1908                                       hashbuf, sizeof(hashbuf)), 
1909                   17); 
1910        sh_srp_x (salt, in);
1911        foo_v  = sh_srp_verifier ();
1912        fprintf(stdout, _("Client=HOSTNAME@%s@%s\n"), 
1913                salt, foo_v);
1914        fflush(stdout);
1915        SH_FREE(foo_v);
1916        sh_srp_exit();
1917        _exit(EXIT_SUCCESS);
1918      }
1919    fprintf(stdout, "%s",_("ERROR initializing BigNum library.\n"));
1920    fflush (stdout);
1921    _exit(EXIT_FAILURE);
1922    return -1;
1923}
1924#endif
1925
1926
1927int sh_forward_create_password (const char * dummy)
1928{
1929  UINT32   val[2]; 
1930  char     output[KEY_LEN+1];
1931  char hashbuf[KEYBUF_SIZE];
1932
1933  val[0] = taus_get ();
1934  val[1] = taus_get ();
1935
1936  sl_strlcpy (output, 
1937              sh_tiger_hash((char *)(&val[0]), TIGER_DATA, 2*sizeof(UINT32),
1938                            hashbuf, sizeof(hashbuf)),
1939              KEY_LEN);
1940
1941  output[16] = '\0';
1942
1943  fprintf(stdout, _("%s\n"), output);
1944  fflush (stdout);
1945
1946  if (dummy)
1947    _exit(EXIT_SUCCESS);
1948  else
1949    _exit(EXIT_SUCCESS); 
1950  return (0);  /* avoid compiler warning */
1951}
1952
1953/* #if defined (SH_WITH_SERVER) */
1954#endif
1955
1956/**************************************************
1957 *
1958 *
1959 *  S E R V E R   
1960 *
1961 *
1962 ***************************************************/
1963
1964#ifdef SH_WITH_SERVER
1965
1966#include "sh_readconf.h"
1967
1968
1969#define CONN_FREE    0
1970#define CONN_READING 1
1971#define CONN_SENDING 2
1972#define CONN_PAUSE   3
1973#define CONN_BUSY    4
1974
1975char * clt_stat[] = {
1976  N_("Inactive"),
1977  N_("Started"),
1978  N_("ILLEGAL"),
1979  N_("FAILED"),
1980  N_("Exited"),
1981  N_("PANIC"),
1982  N_("POLICY"),
1983  N_("File_transfer"),
1984  N_("Message"),
1985  N_("TIMEOUT_EXCEEDED"),
1986  N_("Suspended"),
1987  N_("Filecheck"),
1988};
1989
1990#include <time.h>
1991
1992/* in sh_html.h:
1993 *  typedef struct client_entry {
1994 *  } client_t;
1995 */
1996
1997#include "zAVLTree.h"
1998
1999static char * sh_tolower (char * s)
2000{
2001  char * ret = s;
2002  if (s)
2003    {
2004      for (; *s; ++s)
2005        { 
2006          *s = tolower((unsigned char) *s);
2007        }
2008    }
2009  return ret;
2010}
2011
2012/* Function to return the key for indexing
2013 * the argument
2014 */
2015zAVLKey sh_avl_key (void const * arg)
2016{
2017  const client_t * sa = (const client_t *) arg;
2018  return (zAVLKey) sa->hostname;
2019}
2020
2021zAVLTree * all_clients = NULL;
2022
2023void sh_forward_html_write()
2024{
2025  SL_ENTER(_("sh_forward_html_write"));
2026  sh_html_write(all_clients);
2027  SL_RET0(_("sh_forward_html_write"));
2028}
2029
2030
2031int sh_forward_use_clt_class (const char * c)
2032{
2033  int i;
2034  SL_ENTER(_("sh_forward_use_clt_class"));
2035  i = sh_util_flagval(c, &(sh.flag.client_class));
2036  SL_RETURN(i, _("sh_forward_use_clt_class"));
2037}
2038
2039int sh_forward_use_clt_sev (const char * c)
2040{
2041  int i;
2042  SL_ENTER(_("sh_forward_use_clt_sev"));
2043  i = sh_util_flagval(c, &(sh.flag.client_severity));
2044  SL_RETURN(i, _("sh_forward_use_clt_sev")); 
2045}
2046
2047
2048/* the destructor
2049 */
2050void free_client(void * inptr)
2051{
2052  client_t * here;
2053
2054  SL_ENTER(_("free_client"));
2055  if (inptr == NULL)
2056    SL_RET0(_("free_client"));
2057  else
2058    here = (client_t *) inptr;
2059
2060  if (here->hostname != NULL)
2061    SH_FREE(here->hostname);
2062  if (here->salt != NULL)
2063    SH_FREE(here->salt);
2064  if (here->verifier != NULL)
2065    SH_FREE(here->verifier);
2066  SH_FREE(here);
2067  SL_RET0(_("free_client"));
2068}
2069
2070
2071int sh_forward_register_client (const char * str)
2072{
2073  client_t   * newclt;
2074  client_t   * testclt;
2075
2076  const char * ptr;
2077  int          sepnum = 0;
2078  int          sep[2];
2079  register int i = 0;
2080  int          siz_str = 0;
2081
2082  SL_ENTER(_("sh_forward_register_client"));
2083
2084  ptr = str; 
2085  while (*ptr) {
2086    if (*ptr == '@' && sepnum < 2 ) 
2087      { 
2088        sep[sepnum] = i;
2089        ++sepnum;
2090      } 
2091    ++ptr; ++i; 
2092  }
2093
2094  if (all_clients == NULL)
2095    {
2096      all_clients = zAVLAllocTree (sh_avl_key, zAVL_KEY_STRING);
2097      if (all_clients == NULL) 
2098        {
2099          (void) safe_logger (0, 0, NULL);
2100          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
2101        }
2102    }
2103 
2104  if ((sepnum == 2) && (sep[0] > 0) && (sep[1] > sep[0]))
2105    {
2106      newclt = SH_ALLOC (sizeof(client_t));
2107      newclt->hostname = SH_ALLOC (sep[0]+1);
2108      newclt->salt     = SH_ALLOC (sep[1]-sep[0]);
2109      newclt->verifier = SH_ALLOC (sl_strlen(str)-sep[1]+1);
2110      newclt->exit_flag         = 0;
2111      newclt->dead_flag         = 0;
2112#ifdef SH_ENCRYPT
2113#ifdef SH_ENCRYPT_2
2114      newclt->encf_flag         = SH_PROTO_ENC|SH_PROTO_EN2;
2115      newclt->ency_flag         = SH_PROTO_ENC|SH_PROTO_EN2;
2116#else
2117      newclt->encf_flag         = SH_PROTO_ENC;
2118      newclt->ency_flag         = SH_PROTO_ENC;
2119#endif
2120#else
2121      newclt->encf_flag         = 0;
2122      newclt->ency_flag         = 0;
2123#endif
2124      newclt->session_key[0]    = '\0';
2125      newclt->last_connect      = (time_t) 0;
2126      newclt->session_key_timer = (time_t) 0;
2127      newclt->status_now        = CLT_INACTIVE;
2128      for (i = 0; i < CLT_MAX; ++i) 
2129        newclt->status_arr[i] = CLT_INACTIVE;
2130      (void) sh_unix_time(0, newclt->timestamp[CLT_INACTIVE], TIM_MAX);
2131
2132      /* truncate */
2133      sl_strlcpy(newclt->hostname,  &str[0],        sep[0]+1);
2134      sh_tolower(newclt->hostname);
2135
2136      /* truncate */
2137      sl_strlcpy(newclt->salt,      &str[sep[0]+1], sep[1]-sep[0]);
2138      sl_strlcpy(newclt->verifier,  &str[sep[1]+1], sl_strlen(str)-sep[1]+1);
2139
2140      testclt = (client_t *) zAVLSearch (all_clients, newclt->hostname);
2141
2142      if (testclt != NULL)
2143        {
2144          SH_FREE(testclt->verifier);
2145          siz_str = strlen (newclt->verifier) + 1;
2146          testclt->verifier = SH_ALLOC (siz_str);
2147          sl_strlcpy(testclt->verifier, newclt->verifier, siz_str);
2148
2149          SH_FREE(testclt->salt);
2150          siz_str = strlen (newclt->salt) + 1;
2151          testclt->salt = SH_ALLOC (siz_str);
2152          sl_strlcpy(testclt->salt, newclt->salt, siz_str);
2153
2154          testclt->dead_flag = 0;
2155             
2156          free_client(newclt);
2157          SL_RETURN( 0, _("sh_forward_register_client"));
2158        }
2159      else
2160        {
2161          if (0 == zAVLInsert (all_clients, newclt))
2162            {
2163              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CREG,
2164                              newclt->hostname, 
2165                              newclt->salt, newclt->verifier);
2166              SL_RETURN( 0, _("sh_forward_register_client"));
2167            }
2168        }
2169    }
2170  SL_RETURN (-1, _("sh_forward_register_client"));
2171}
2172
2173typedef struct {
2174  int             state;
2175  int             fd;
2176  char          * buf;
2177  unsigned char   head[SH_HEADER_SIZE];
2178  char            challenge[SH_CHALLENGE_SIZE];
2179  char            peer[SH_MINIBUF+1];
2180  client_t      * client_entry;
2181  char          * K;
2182  char          * M1;
2183  char          * A;
2184  int             headcount;
2185  unsigned long   bytecount;
2186  unsigned long   bytes_to_send;
2187  unsigned long   bytes_to_get;
2188  int             pass;
2189  unsigned long   timer;
2190
2191  char          * FileName;
2192  unsigned long   FileLength;
2193  unsigned long   FileSent;
2194  char            FileType[5];
2195
2196  struct sh_sockaddr addr_peer;
2197} sh_conn_t;
2198
2199
2200static char zap_challenge[SH_CHALLENGE_SIZE] = { 0 };
2201 
2202void sh_forward_do_free (sh_conn_t * conn)
2203{
2204  SL_ENTER(_("sh_forward_do_free"));
2205
2206  if (conn->K != NULL) 
2207    {
2208      SH_FREE(conn->K);
2209      conn->K           = NULL;
2210    }
2211  if (conn->A != NULL) 
2212    {
2213      SH_FREE(conn->A);
2214      conn->A           = NULL;
2215    }
2216  if (conn->M1 != NULL) 
2217    {
2218      SH_FREE(conn->M1);
2219      conn->M1           = NULL;
2220    }
2221  if (conn->buf != NULL) 
2222    {
2223      SH_FREE(conn->buf);
2224      conn->buf          = NULL;
2225    }
2226  if (conn->fd != (-1))
2227    {
2228      sl_close_fd (FIL__, __LINE__, conn->fd);
2229      conn->fd            = -1;
2230    }
2231  memcpy(conn->challenge, zap_challenge, SH_CHALLENGE_SIZE);
2232  conn->state         = CONN_FREE;
2233  conn->headcount     = 0;
2234  conn->bytecount     = 0;
2235  conn->bytes_to_send = 0;
2236  conn->bytes_to_get  = 0;
2237  conn->pass          = 0;
2238  conn->timer         = 0;
2239  conn->client_entry  = NULL;
2240
2241  if (conn->FileName != NULL) 
2242    {
2243      SH_FREE(conn->FileName);
2244      conn->FileName     = NULL;
2245    }
2246  conn->FileLength     = 0;
2247  conn->FileSent       = 0;
2248  conn->FileType[0] = '\0';
2249  conn->FileType[1] = '\0';
2250  conn->FileType[2] = '\0';
2251  conn->FileType[3] = '\0';
2252  conn->FileType[4] = '\0';
2253
2254  --server_status.conn_open;
2255 
2256  SL_RET0(_("sh_forward_do_free"));
2257}
2258
2259/****************************************
2260 *
2261 *   -- Reconfiguration. --
2262 *
2263 *   (1) Mark all clients as 'dead'.
2264 *   (2) Reload configuration - clients
2265 *       in config are non-dead now.
2266 *   (3) Remove all clients still
2267 *       marked as 'dead'.
2268 */
2269
2270/* -- Mark all clients as dead.
2271 */
2272void sh_forward_mark_dead (void)
2273{
2274  zAVLCursor avlcursor;
2275  client_t * item;
2276
2277  SL_ENTER(_("sh_forward_mark_dead"));
2278
2279  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
2280       item = (client_t *) zAVLNext(&avlcursor))
2281    {
2282      item->dead_flag = 1;
2283    }
2284  SL_RET0(_("sh_forward_mark_dead"));
2285}
2286
2287
2288/* -- Clean tree from dead clients.
2289 */
2290void sh_forward_clean_tree (void)
2291{
2292  zAVLCursor avlcursor;
2293  client_t * item;
2294
2295  SL_ENTER(_("sh_forward_clean_tree"));
2296
2297 repeat_search:
2298
2299  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
2300       item = (client_t *) zAVLNext(&avlcursor))
2301    {
2302      if (item->dead_flag == 1)
2303        {
2304          zAVLDelete (all_clients, item->hostname);
2305          free_client (item);
2306          goto repeat_search;
2307        }
2308    }
2309  SL_RET0(_("sh_forward_clean_tree"));
2310}
2311
2312/*
2313 *
2314 **********************************************/
2315
2316
2317
2318/* -- SERVER SEND FUNKTION. --
2319 */
2320void sh_forward_prep_send_int (sh_conn_t * conn, 
2321                               char * msg, unsigned long length,
2322                               char * u, char protocol,
2323                               int docrypt)
2324{
2325  /* register unsigned long i; */
2326  unsigned long           length2;
2327
2328#ifdef SH_ENCRYPT
2329  unsigned long           blkfac = 0;
2330  int                     rem = 0;
2331  char                  * p, * q;
2332  RIJ_BYTE                    inBlock[B_SIZ]; 
2333  RIJ_BYTE                    outBlock[B_SIZ];
2334  unsigned int            j;
2335  cipherInstance          cipherInst;
2336  int                     err_num;
2337  char expbuf[SH_ERRBUF_SIZE];
2338#else
2339  (void) docrypt;
2340#endif
2341
2342  SL_ENTER(_("sh_forward_prep_send_int"));
2343
2344  TPT((0, FIL__, __LINE__, _("msg=<%s>, docrypt=<%d>\n"), msg, docrypt ));
2345
2346#ifdef SH_ENCRYPT
2347  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != 0) )
2348    {
2349      length2 = length;
2350    }
2351  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0) )
2352    {
2353      blkfac  = length/B_SIZ;
2354      rem     = length - (B_SIZ * blkfac);
2355      length2 = (B_SIZ * blkfac);
2356      if (rem > 0 && (length2 + B_SIZ) > length2) 
2357        length2 += B_SIZ;
2358      else
2359        rem = 0;
2360    }
2361  else
2362    {
2363      length2 = length;
2364    }
2365#else
2366  length2 = length;
2367#endif
2368
2369  conn->headcount     = 0;
2370  conn->bytecount     = 0;
2371  conn->bytes_to_send = 0;
2372  conn->bytes_to_get  = 0;
2373
2374  if (conn->buf != NULL) 
2375    {
2376      SH_FREE(conn->buf);
2377      conn->buf           = NULL;
2378    }
2379
2380
2381  put_header (conn->head, protocol, &length2, u);
2382  SH_SHOWPROT(conn->head,'>');
2383
2384  TPT((0, FIL__, __LINE__, _("msg=<put_header done>\n") ));
2385
2386  if (msg == NULL) 
2387    length2 = 0;
2388 
2389#ifdef SH_ENCRYPT
2390  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != 0))
2391    {
2392      TPT((0, FIL__, __LINE__, _("encrypting (version 2)\n")));
2393     
2394      conn->buf = sh_tools_makePack (conn->head, msg, length2,
2395                                     &(conn->client_entry->keyInstE));
2396    }
2397  else if (msg == NULL)
2398    {
2399      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2400                      _("msg is NULL"), 
2401                      _("sh_forward_prep_send_int: cipherInit"));
2402    }
2403  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0) &&
2404           ((length2 + 1) > length2))
2405    {
2406      conn->buf       = SH_ALLOC(length2 + 1);
2407
2408      p       = msg;
2409      q       = conn->buf;
2410
2411      TPT((0, FIL__, __LINE__, _("encrypting (version 1)\n")));
2412
2413      err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
2414      if (err_num < 0)
2415        sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2416                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
2417                        _("sh_forward_prep_send_int: cipherInit"));
2418
2419      for (j = 0; j < blkfac; ++j)
2420        {
2421          memcpy(inBlock, p, B_SIZ);
2422          err_num = blockEncrypt(&cipherInst, &(conn->client_entry->keyInstE), 
2423                       inBlock, 128 * BNUM, outBlock);
2424          if (err_num < 0)
2425            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2426                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
2427                            _("sh_forward_prep_send_int: blockEncrypt"));
2428          memcpy(q, outBlock, B_SIZ);
2429          p += B_SIZ;
2430          q += B_SIZ;
2431        }
2432      if (rem > 0)
2433        {
2434          /* incomplete block at end
2435           */
2436          memset(inBlock, '\0', B_SIZ);
2437          memcpy(inBlock, p, rem);
2438          err_num = blockEncrypt(&cipherInst, &(conn->client_entry->keyInstE), 
2439                       inBlock, 128 * BNUM, outBlock);
2440          if (err_num < 0)
2441            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2442                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
2443                            _("sh_forward_prep_send_int: blockEncrypt"));
2444          memcpy(q, outBlock, B_SIZ);
2445          /* q += B_SIZ; *//* never read */
2446        }
2447
2448      TPT((0, FIL__, __LINE__, _("msg=<encryption done>\n") ));
2449    }
2450  else
2451    {
2452      if ((length2 + 1) < length2) --length2;
2453      conn->buf       = SH_ALLOC(length2 + 1);
2454
2455      memcpy(conn->buf, msg, length2);
2456      /*
2457      for (i = 0; i < length2; ++i)
2458        conn->buf[i] = msg[i];
2459      */
2460      conn->buf[length2] = '\0';
2461      TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
2462    }
2463#else
2464  if ((length2 + 1) < length2) --length2;
2465  conn->buf       = SH_ALLOC(length2 + 1);
2466
2467  memcpy(conn->buf, msg, length2);
2468  /*
2469  for (i = 0; i < length; ++i)
2470    conn->buf[i] = msg[i];
2471  */
2472  conn->buf[length2] = '\0';
2473  TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
2474#endif
2475
2476  conn->state     = CONN_SENDING;
2477  SL_RET0(_("sh_forward_prep_send_int"));
2478}
2479
2480/* -- Send/Receive. --
2481 */
2482void sh_forward_prep_send (sh_conn_t * conn, 
2483                           char * msg, unsigned long length,
2484                           char * u, char protocol)
2485{
2486  SL_ENTER(_("sh_forward_prep_send"));
2487  sh_forward_prep_send_int (conn,  msg, length, u, protocol, S_FALSE);
2488  SL_RET0(_("sh_forward_prep_send"));
2489} 
2490
2491void sh_forward_prep_send_crypt (sh_conn_t * conn, 
2492                                 char * msg, unsigned long length,
2493                                 char * u, char protocol)
2494{
2495  SL_ENTER(_("sh_forward_prep_send_crypt"));
2496  sh_forward_prep_send_int (conn,  msg, length, u, protocol, S_TRUE);
2497  SL_RET0(_("sh_forward_prep_send_crypt"));
2498} 
2499
2500/* #include <sys/times.h> */
2501
2502#if defined(WITH_EXTERNAL)
2503#include "sh_extern.h"
2504#endif
2505
2506/* -- Update the client status. --
2507 *
2508 * Update the status array for the client,
2509 * and eventually call external program.
2510 */
2511static void status_update (client_t * conn, int status)
2512{ 
2513#if defined(WITH_EXTERNAL)
2514  char msg[2 * SH_MINIBUF + TIM_MAX + 3];
2515#endif
2516
2517  SL_ENTER(_("status_update"));
2518
2519  if (conn == NULL || 
2520      status < 0   || status >= CLT_MAX)
2521    SL_RET0(_("status_update"));
2522
2523  conn->status_now = status;
2524  conn->status_arr[status] = status;
2525  (void) sh_unix_time(0, conn->timestamp[status], TIM_MAX);
2526
2527#if defined(WITH_EXTERNAL)
2528  sl_snprintf(msg, sizeof(msg), _("%s %s %s"),
2529              conn->hostname, conn->timestamp[status], _(clt_stat[status]));
2530  sh_ext_execute('s', 'r', 'v', msg, 0);
2531#endif
2532
2533  SL_RET0(_("status_update"));
2534}
2535
2536static time_t time_client_limit = 86400;
2537
2538int sh_forward_set_time_limit (const char * c)
2539{
2540  long val;
2541
2542  SL_ENTER(_("sh_forward_set_time_limit"));
2543
2544  val = strtol (c, (char **)NULL, 10);
2545  if (val <= 0)
2546    SL_RETURN( (-1), _("sh_forward_set_time_limit"));
2547
2548  time_client_limit = (time_t) val;
2549  SL_RETURN( (0), _("sh_forward_set_time_limit"));
2550}
2551
2552
2553/* -- Check for time limit exceeded. --
2554 */
2555static int client_time_check(void)
2556{
2557  zAVLCursor avlcursor;
2558  client_t * item;
2559
2560  SL_ENTER(_("client_time_check"));
2561
2562  if (time_client_limit == (time_t) 0)
2563    SL_RETURN( 0, _("client_time_check"));
2564
2565  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
2566       item = (client_t *) zAVLNext(&avlcursor))
2567    {
2568      if (item->exit_flag == 0 && item->last_connect != (time_t) 0)
2569        {
2570          if ( (time(NULL) - item->last_connect) > time_client_limit)
2571            {
2572              if (item->status_now != CLT_TOOLONG)
2573                {
2574                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMEXC,
2575                                  item->hostname);
2576                  status_update (item, CLT_TOOLONG);
2577                }
2578            }
2579        }
2580    }
2581  SL_RETURN( 0, _("client_time_check"));
2582}
2583
2584static int lookup_err = SH_ERR_SEVERE;
2585
2586int sh_forward_lookup_level (const char * c)
2587{
2588  int ci =  sh_error_convert_level (c);
2589
2590  SL_ENTER(_("sh_forward_lookup_level"));
2591
2592  if (ci >= 0)
2593    {
2594      lookup_err = ci;
2595      SL_RETURN( 0, _("sh_forward_lookup_level"));
2596    }
2597  else
2598    SL_RETURN( (-1), _("sh_forward_lookup_level"));
2599}
2600
2601#ifndef MAXHOSTNAMELEN
2602#define MAXHOSTNAMELEN  127
2603#endif
2604
2605int check_addr (const char * claim, struct sh_sockaddr * addr_peer)
2606{
2607  char               h_name[MAXHOSTNAMELEN + 1];
2608  char               h_peer[MAXHOSTNAMELEN + 1];
2609  char               h_peer_IP[SH_IP_BUF];
2610  char               tmp_peer_IP[SH_IP_BUF];
2611  char             * canonical;
2612  char               numeric[SH_IP_BUF];
2613
2614  SL_ENTER(_("check_addr"));
2615
2616  if (claim == NULL)
2617    {
2618      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
2619                      _("NULL input"), _("check_addr"));
2620      SL_RETURN ((-1), _("check_addr"));
2621    }
2622
2623  /* Make sure we have the canonical name for the client
2624   */
2625  canonical = sh_ipvx_canonical(claim, numeric, sizeof(numeric));
2626
2627  /* copy canonical name into h_name
2628   */
2629  if (canonical != NULL)
2630    {
2631      sl_strlcpy(h_name, canonical, MAXHOSTNAMELEN + 1);
2632      SH_FREE(canonical);
2633    }
2634  else
2635    {
2636      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESCLT,
2637                      claim);
2638      SL_RETURN ((0), _("check_addr"));
2639    }
2640
2641
2642  /* get canonical name of socket peer
2643   */
2644  canonical = sh_ipvx_addrtoname(addr_peer);
2645
2646  if (canonical)
2647    {
2648      if (0 == sl_strcmp(canonical, _("localhost")))
2649        sl_strlcpy(h_peer, sh.host.name, MAXHOSTNAMELEN + 1);
2650      else
2651        sl_strlcpy(h_peer, canonical, MAXHOSTNAMELEN + 1);
2652      SH_FREE(canonical);
2653    }
2654  else
2655    {
2656      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
2657      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESPEER,
2658                      claim, tmp_peer_IP);
2659      SL_RETURN ((0), _("check_addr"));
2660    }
2661
2662  sh_ipvx_ntoa (h_peer_IP, sizeof(h_peer_IP), addr_peer);
2663
2664#if 0
2665  if (S_FALSE == DoReverseLookup)
2666    {
2667      SL_RETURN ((0), _("check_addr"));
2668    }
2669#endif
2670
2671  /* reverse lookup
2672   */
2673  if (0 == sh_ipvx_reverse_check_ok (h_peer, ServerPort, addr_peer))
2674    {
2675      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
2676
2677      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKERS,
2678                      claim, h_peer, tmp_peer_IP);
2679      SL_RETURN ((0), _("check_addr"));
2680    }
2681
2682  /* Check whether claim and peer are identical
2683   */
2684
2685  sh_tolower(h_peer); /* Canonical name of what the peer is     */
2686  sh_tolower(h_name); /* Canonical name of what the peer claims */
2687
2688  if ((0 == sl_strcmp(h_peer, h_name)) || (0 == sl_strcmp(h_peer_IP, h_name)))
2689    {
2690      SL_RETURN ((0), _("check_addr"));
2691    }
2692#if !defined(USE_IPVX)
2693  else
2694    {
2695      struct hostent   * he = sh_gethostbyname(h_peer);
2696      int                i = 0;
2697      int                flag = 0;
2698
2699      while (he->h_aliases[i] != NULL)
2700        {
2701          if (0 == sl_strcmp(sh_tolower(he->h_aliases[i]), h_name))
2702            {
2703              flag = 1;
2704              break;
2705            }
2706          ++i;
2707        }
2708      if (flag == 0) 
2709        sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKUP,
2710                        claim, h_peer);
2711    }
2712#endif
2713
2714  SL_RETURN ((0), _("check_addr"));
2715}
2716
2717static int UseSocketPeer = S_FALSE;
2718
2719int set_socket_peer (const char * c)
2720{
2721  return sh_util_flagval(c, &UseSocketPeer);
2722}
2723
2724
2725/* -- Search register. --
2726 */
2727client_t * search_register(sh_conn_t * conn, int pos)
2728{
2729  client_t * this_client;
2730  char       peer_ip[SH_IP_BUF];
2731  char       numerical[SH_IP_BUF];
2732  char       peer_name[MAXHOSTNAMELEN+1];
2733  char     * search_string;
2734
2735  struct sh_sockaddr peer_addr;
2736  char             * canonical;
2737
2738  SL_ENTER(_("search_register"));
2739
2740  if (UseSocketPeer == S_TRUE)
2741    {
2742      memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr));
2743      sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr);
2744
2745      /* get canonical name of socket peer
2746       */
2747      canonical = sh_ipvx_canonical(peer_ip, numerical, sizeof(numerical));
2748
2749      if (canonical != NULL)
2750        {
2751          if (0 == sl_strcmp(canonical, _("localhost")))
2752            sl_strlcpy(peer_name, sh.host.name, MAXHOSTNAMELEN + 1);
2753          else
2754            sl_strlcpy(peer_name, canonical,    MAXHOSTNAMELEN + 1);
2755          SH_FREE(canonical);
2756        }
2757
2758      if (0 == sh_ipvx_reverse_check_ok (peer_name, ServerPort, &peer_addr))
2759        {
2760          sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
2761        }
2762
2763      search_string = peer_name;
2764    }
2765  else
2766    {
2767      search_string = &(conn->buf[pos]);
2768
2769      if (0 != check_addr (search_string, &(conn->addr_peer)))
2770        {
2771          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2772                          _("Reverse lookup failed"), search_string);
2773          sh_forward_do_free (conn);
2774          SL_RETURN( NULL, _("search_register"));
2775        } 
2776    }
2777
2778  sh_tolower(search_string);
2779
2780  /* ----  search the register  -----
2781   */
2782  this_client = zAVLSearch(all_clients, search_string);
2783
2784  if (this_client == NULL)
2785    {
2786      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2787                      _("Not in client list"), search_string);
2788      sh_forward_do_free (conn);
2789      SL_RETURN( NULL, _("search_register"));
2790    } 
2791  if (this_client->exit_flag == 1)
2792    {
2793      TPT((0, FIL__, __LINE__, _("msg=<this_client->exit_flag == 1>\n")));
2794      this_client->session_key_timer = (time_t) 0;
2795      this_client->session_key[0]    = '\0';
2796      this_client->exit_flag         = 0;   
2797    }
2798  TPT((0, FIL__, __LINE__, _("msg=<search_register: client %s>\n"), 
2799       this_client->hostname));
2800  TPT((0, FIL__, __LINE__, _("msg=<search_register: key %s>\n"), 
2801       this_client->session_key));
2802  SL_RETURN( this_client, _("search_register"));
2803} 
2804
2805
2806/************************************************************************
2807 *
2808 * Here we check the message received, and decide on the answer to send
2809 * (if any). The connection is in CONN_PAUSED state, thus we must:
2810 * (i)   define the proper reaction
2811 * (ii)  reset to CONN_READING or CONN_WRITING or CONN_FREE
2812 * (iii) eventually reset the connection entry
2813 *
2814 *************************************************************************/
2815static
2816void check_protocol(sh_conn_t * conn, int state)
2817{
2818  client_t * this_client; 
2819
2820  char     * cmd;
2821
2822  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
2823  char     * buffer;
2824
2825  int        clt_sev;
2826  char     * ptok;
2827
2828  UINT32     ticks;
2829  size_t     len;
2830  int        i;
2831  char     * test;
2832  char       u[5] = "OOOO";
2833
2834  SL_TICKET  sfd = -1;
2835  char     * read_buf = 0;
2836  char     * send_buf;
2837  int        bytes;
2838
2839#ifdef SH_ENCRYPT
2840  int        blkfac;
2841  int        rem;
2842  int        send_bytes;
2843  int        err_num;
2844  char expbuf[SH_ERRBUF_SIZE];
2845#endif
2846
2847
2848#ifdef USE_SRP_PROTOCOL
2849  char     * foo_B;
2850  char     * foo_Ss;
2851#endif
2852  char hashbuf[KEYBUF_SIZE];
2853  char sigbuf[KEYBUF_SIZE];
2854
2855  SL_ENTER(_("check_protocol"));
2856
2857  /* seed / re-seed the PRNG if required
2858   */
2859  (void) taus_seed();
2860
2861
2862  /* protocols:
2863   * -- (iii)    file transfer
2864   * -- (ii)     authenticated message transfer
2865   * -- (i)      SRP key exchange
2866   */
2867
2868  /* --------- FILE TRANSFER  -----------
2869   */
2870  if ( (conn->head[0] & SH_PROTO_SRP) == 0  &&
2871       (conn->head[0] & SH_PROTO_BIG) != 0  /* is set */ )
2872    {
2873
2874      if (state == SH_DO_READ)        /* finished reading */
2875        {
2876          TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
2877
2878          /* -- Client requests challenge. --
2879           */
2880          if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
2881            {
2882
2883              TPT(( 0, FIL__, __LINE__, 
2884                    _("msg=<File transfer - HELO (1).>\n")));
2885
2886              if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN)
2887                {
2888                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
2889                  sh_forward_do_free (conn);
2890                  SL_RET0(_("check_protocol"));
2891                } 
2892
2893              /* ----  search the register  -----
2894               */
2895             
2896              this_client = search_register (conn, KEY_LEN);
2897              if (this_client == NULL)
2898                SL_RET0(_("check_protocol"));
2899
2900              /* ---- force authentication -----
2901               */
2902
2903              if (this_client->session_key[0] == '\0' ||
2904                  (time(NULL) - this_client->session_key_timer) 
2905                  > (time_t) TIMEOUT_KEY )
2906                {
2907                  /* fake an auth request and jump there
2908                   */
2909                  conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
2910                  conn->head[3]  = 'S';
2911                  conn->head[4]  = 'A';
2912                  conn->head[5]  = 'L';
2913                  conn->head[6]  = 'T';
2914                  if (flag_err_info == SL_TRUE)
2915                    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
2916                                    &(conn->buf[KEY_LEN]));
2917                  len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
2918                  /* &(conn->buf[KEY_LEN]) is hostname         */
2919                  /* may overlap, thus only memmove is correct */
2920                  memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
2921                  this_client->session_key[0]    = '\0';
2922                  this_client->session_key_timer = (time_t) 1;
2923                  goto servInit;
2924                }
2925
2926              /* --- check whether hostname is properly signed ---
2927               */ 
2928              if (conn->K != NULL) 
2929                {
2930                  SH_FREE(conn->K);
2931                  conn->K = NULL;
2932                }
2933
2934              /* FIXME
2935              len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
2936              if (sl_ok_adds(len, KEY_LEN))
2937                len += KEY_LEN;
2938              len = (len < (KEY_LEN+1)) ? (KEY_LEN+1) : len;
2939              */
2940              conn->K = SH_ALLOC(KEY_LEN+1);
2941
2942              sl_strlcpy (conn->K, 
2943                          sh_util_siggen(this_client->session_key,
2944                                         &(conn->buf[KEY_LEN]),
2945                                         sl_strlen(&(conn->buf[KEY_LEN])),
2946                                         sigbuf, sizeof(sigbuf)),
2947                          KEY_LEN+1);
2948              TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"),
2949                   &(conn->buf[KEY_LEN])));
2950              TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"),
2951                   this_client->session_key));
2952              TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
2953                   sh_util_siggen(this_client->session_key, 
2954                                  &(conn->buf[KEY_LEN]), 
2955                                  sl_strlen(&(conn->buf[KEY_LEN])),
2956                                  sigbuf, sizeof(sigbuf))));
2957
2958              if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
2959                {
2960                  TPT((0, FIL__, __LINE__, _("msg=<clt %s>\n"), conn->buf));
2961                  TPT((0, FIL__, __LINE__, _("msg=<srv %s>\n"), conn->K));
2962                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2963                                  _("Signature mismatch"), 
2964                                  &(conn->buf[KEY_LEN]));
2965
2966                  this_client->session_key_timer =
2967                    time(NULL) - (2*TIMEOUT_KEY);
2968
2969                  sh_forward_do_free (conn);
2970                  SL_RET0(_("check_protocol"));
2971                }
2972              SH_FREE(conn->K); 
2973              conn->K = NULL;
2974
2975              /* --- create and send a nonce ---
2976               */
2977             
2978              conn->client_entry = this_client;
2979              sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
2980
2981              ticks = (UINT32) taus_get ();
2982
2983              if (conn->K != NULL) 
2984                {
2985                  SH_FREE(conn->K);
2986                  conn->K = NULL;
2987                }
2988              conn->K = SH_ALLOC(KEY_LEN+1);
2989              sl_strlcpy (conn->K, 
2990                          sh_tiger_hash ((char *) &ticks, 
2991                                         TIGER_DATA, sizeof(UINT32), 
2992                                         hashbuf, sizeof(hashbuf)), 
2993                          KEY_LEN+1);
2994
2995              TPT((0, FIL__, __LINE__, _("msg=<send nonce>\n")));
2996              sh_forward_prep_send (conn, conn->K, KEY_LEN+1, _("NSRV"), 
2997                                    SH_PROTO_BIG);
2998            }
2999
3000          /* --- Client has send a message. Check state and message. ---
3001           */
3002          else if (0 == check_request_nerr((char *)&(conn->head[3]), _("NCLT")) &&
3003                   conn->client_entry != NULL                           &&
3004                   sl_strlen(conn->buf) > KEY_LEN                       &&
3005                   conn->K != NULL)
3006            {
3007
3008              TPT(( 0, FIL__, __LINE__, 
3009                    _("msg=<File transfer - NCLT (3).>\n")));
3010
3011              /* --- get client nonce and compute hash ---
3012               */
3013              if (conn->A != NULL)
3014                {
3015                  SH_FREE(conn->A);
3016                  conn->A = NULL;
3017                }
3018              conn->A = SH_ALLOC(3*KEY_LEN+1);
3019              sl_strlcpy (conn->A, conn->K, KEY_LEN+1); 
3020              sl_strlcat(conn->A, conn->buf, /* truncate */
3021                         2*KEY_LEN+1);
3022              sl_strlcat(conn->A, conn->client_entry->session_key, 
3023                         3*KEY_LEN+1);
3024              sl_strlcpy (conn->K, sh_tiger_hash(conn->A,TIGER_DATA,3*KEY_LEN,
3025                                                 hashbuf, sizeof(hashbuf)),
3026                          KEY_LEN+1);
3027              SH_FREE(conn->A); 
3028              conn->A = NULL;
3029
3030
3031#ifdef SH_ENCRYPT
3032              if ((conn->client_entry->encf_flag != 0) &&
3033                  ((conn->head[0] & SH_PROTO_ENC) == 0)) 
3034                {
3035                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
3036                                  _("file download"),
3037#ifdef SH_ENCRYPT_2
3038                                  _("version2"),
3039#else
3040                                  _("version1"),
3041#endif
3042                                  _("none"));
3043                  if (sl_strlen(conn->buf) > (KEY_LEN + 5)) {
3044                    if (sh_tools_hash_vfy(conn->K, conn->buf, KEY_LEN+5)) {
3045                      if (conn->buf[KEY_LEN+4] == conn->head[0]) {
3046                        /* conn->client_entry->encf_flag = 0 */ ; /* FIXME */
3047                      }
3048                    }
3049                  }
3050                }
3051              else if ((conn->client_entry->encf_flag != 0) &&
3052                       ((conn->head[0] & SH_MASK_ENC) != 
3053                        conn->client_entry->encf_flag))
3054                {
3055                  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
3056                                  MSG_TCP_MISENC,
3057                                  _("file download"),
3058#ifdef SH_ENCRYPT_2
3059                                  _("version2"),
3060#else
3061                                  _("version1"),
3062#endif
3063                                  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1")
3064                                  );
3065                  conn->client_entry->encf_flag = 
3066                    (conn->head[0] & SH_MASK_ENC);
3067                }
3068#else
3069              if ((conn->head[0] & SH_PROTO_ENC) != 0) 
3070                {
3071                  sh_error_handle((-1), FIL__, __LINE__, 0, 
3072                                  MSG_TCP_MISENC,
3073                                  _("file download"),
3074                                  _("none"), 
3075                                  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
3076                }
3077#endif
3078
3079
3080              /* ---- K = H(NSRV, NCLT, session_key) -------
3081               */ 
3082
3083              if (conn->FileName != NULL)
3084                {
3085                  SH_FREE(conn->FileName);
3086                  conn->FileName = NULL;
3087                }
3088
3089              if (0 == sl_strncmp (_("CONF"), &(conn->buf[KEY_LEN]), 4))
3090                {
3091                  strcpy(conn->FileType, _("CONF"));     /* known to fit  */
3092                  conn->FileName = get_client_conf_file(conn->peer, 
3093                                                        &(conn->FileLength));
3094                  conn->FileSent = 0;
3095                }
3096              else  if (0 == sl_strncmp (_("DATA"), &(conn->buf[KEY_LEN]), 4))
3097                {
3098                  strcpy(conn->FileType, _("DATA"));     /* known to fit  */
3099                  conn->FileName = get_client_data_file(conn->peer, 
3100                                                        &(conn->FileLength));
3101                  conn->FileSent = 0;
3102                }
3103              else
3104                {
3105                  ptok = sh_util_safe_name(&(conn->buf[KEY_LEN]));
3106                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FFILE,
3107                                  conn->peer, 
3108                                  ptok);
3109                  SH_FREE(ptok);
3110                  status_update (conn->client_entry, CLT_FAILED);
3111                  sh_forward_do_free (conn);
3112                }
3113
3114              bytes = -1;
3115
3116              if (conn != NULL && conn->FileName != NULL)
3117                {
3118                  sfd = sl_open_read(FIL__, __LINE__, 
3119                                     conn->FileName, SL_YESPRIV);
3120                  if (!SL_ISERROR(sfd))
3121                    {
3122                      read_buf = SH_ALLOC(TRANS_BYTES);
3123                      bytes = sl_read (sfd, read_buf, TRANS_BYTES);
3124                      sl_close(sfd);
3125                    }
3126
3127                  else
3128                    {
3129                      sh_error_handle((-1), FIL__, __LINE__, sfd, 
3130                                      MSG_E_ACCESS,
3131                                      (long) geteuid(),
3132                                      conn->FileName);
3133                    }
3134                  if (bytes >= 0)
3135                    {
3136#ifdef SH_ENCRYPT
3137                      /* need to send N * B_SIZ bytes
3138                       */ 
3139                      blkfac = bytes / B_SIZ;
3140                      rem    = bytes - (blkfac * B_SIZ);
3141                      if (rem != 0)
3142                        {
3143                          memset(&read_buf[bytes], '\n', (B_SIZ-rem));
3144                          ++blkfac;
3145                          send_bytes = blkfac * B_SIZ;
3146                        }
3147                      else
3148                        send_bytes = bytes;
3149
3150                      send_buf = hash_me(conn->K, read_buf, 
3151                                         send_bytes);
3152
3153                      sh_forward_prep_send_crypt (conn, send_buf, 
3154                                                  send_bytes+KEY_LEN, 
3155                                                  _("FILE"), 
3156                                                  SH_PROTO_BIG|conn->client_entry->encf_flag);
3157#else
3158                      send_buf = hash_me(conn->K, read_buf, bytes);
3159                      sh_forward_prep_send_crypt (conn, send_buf, 
3160                                                  bytes+KEY_LEN, 
3161                                                  _("FILE"),  SH_PROTO_BIG);
3162#endif
3163                      conn->FileSent += bytes;
3164                      if (send_buf != NULL) 
3165                        {
3166                          SH_FREE(send_buf);
3167                        }
3168                      SH_FREE(read_buf);
3169                    }
3170                }
3171
3172              if (conn == NULL    || conn->FileName == NULL || 
3173                  SL_ISERROR(sfd) || bytes < 0)
3174                {
3175                  sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_TCP_NFILE,
3176                                  conn->peer, 
3177                                  (conn->FileName == NULL) ? 
3178                                  _("(NULL)") : conn->FileName);
3179                  status_update (conn->client_entry, CLT_FAILED);
3180                  sh_forward_do_free (conn);
3181                }
3182
3183            }
3184         
3185         else if (0 == check_request_nerr((char *)&(conn->head[3]), 
3186                                          _("RECV"))                    &&
3187                   conn->client_entry != NULL                           &&
3188                   conn->K != NULL                                      &&
3189                   conn->FileName != NULL)
3190            {
3191
3192              TPT(( 0, FIL__, __LINE__, 
3193                    _("msg=<File transfer - RCVT (5+).>\n")));
3194
3195              if (conn->FileSent == conn->FileLength)
3196                {
3197                  send_buf = hash_me(conn->K, conn->peer, 
3198                                     sl_strlen(conn->peer));
3199#ifdef SH_ENCRYPT
3200                  sh_forward_prep_send_crypt (conn, send_buf, 
3201                                              sl_strlen(conn->peer)+KEY_LEN, 
3202                                              _("EEOT"), 
3203                                              SH_PROTO_BIG|conn->client_entry->encf_flag);
3204#else
3205                  sh_forward_prep_send_crypt (conn, send_buf, 
3206                                              sl_strlen(conn->peer)+KEY_LEN, 
3207                                              _("EEOT"), 
3208                                              SH_PROTO_BIG);
3209#endif
3210                  SH_FREE(send_buf);
3211                }
3212              else
3213                {
3214                  bytes = -1;
3215                  sfd = sl_open_read(FIL__, __LINE__, 
3216                                     conn->FileName, SL_YESPRIV);
3217                  if (!SL_ISERROR(sfd))
3218                    {
3219                      read_buf = SH_ALLOC(TRANS_BYTES);
3220                      sl_seek (sfd, (off_t) conn->FileSent);
3221                      bytes = sl_read (sfd, read_buf, TRANS_BYTES);
3222                      sl_close(sfd);
3223                    }
3224                  else
3225                    {
3226                      sh_error_handle((-1), FIL__, __LINE__, sfd, 
3227                                      MSG_E_ACCESS,
3228                                      (long) geteuid(),
3229                                      conn->FileName);
3230                    }
3231                  if (bytes >= 0)
3232                    {
3233#ifdef SH_ENCRYPT
3234                      /* need to send N * B_SIZ bytes
3235                       */ 
3236                      blkfac = bytes / B_SIZ;
3237                      rem    = bytes - (blkfac * B_SIZ);
3238                      if (rem != 0)
3239                        {
3240                          memset(&read_buf[bytes], '\n', (B_SIZ-rem));
3241                          ++blkfac;
3242                          send_bytes = blkfac * B_SIZ;
3243                        }
3244                      else
3245                        send_bytes = bytes;
3246
3247                      send_buf = hash_me(conn->K, read_buf, 
3248                                         send_bytes);
3249
3250                      sh_forward_prep_send_crypt (conn, send_buf, 
3251                                                  send_bytes+KEY_LEN, 
3252                                                  _("FILE"), 
3253                                                  SH_PROTO_BIG|conn->client_entry->encf_flag);
3254#else
3255
3256                      send_buf = hash_me(conn->K, read_buf, bytes);
3257                      sh_forward_prep_send_crypt (conn, send_buf, 
3258                                                  bytes+KEY_LEN, 
3259                                                  _("FILE"), 
3260                                                  SH_PROTO_BIG);
3261#endif
3262
3263                      conn->FileSent += bytes;
3264                      SH_FREE(send_buf);
3265                      SH_FREE(read_buf);
3266                    }
3267                  else
3268                    {
3269                      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NFILE,
3270                                      conn->peer,
3271                                      (conn->FileName == NULL) ? 
3272                                      _("(NULL)") : conn->FileName);
3273                      status_update (conn->client_entry, CLT_FAILED);
3274                      sh_forward_do_free (conn);
3275                    }
3276                }
3277            }
3278
3279
3280          else if (0 == check_request_nerr((char *)&(conn->head[3]), 
3281                                           _("EOTE")) &&
3282                   conn->client_entry != NULL)
3283            {
3284
3285              TPT(( 0, FIL__, __LINE__, 
3286                    _("msg=<File transfer - EOTE (7).>\n")));
3287
3288              if (flag_err_info == SL_TRUE)
3289                sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKFILE,
3290                                conn->peer);
3291
3292              if ((conn->client_entry->status_now != CLT_SUSPEND) &&
3293                  (conn->client_entry->status_now != CLT_TOOLONG))
3294                { status_update (conn->client_entry, CLT_FILE); }
3295              else
3296                { conn->client_entry->session_key[0]    = '\0'; }
3297              conn->client_entry->last_connect = time (NULL);
3298              sh_forward_do_free (conn);
3299            }
3300           
3301
3302          /* client does something unexpected
3303           */
3304          else  /* ---- ??? ----- */
3305            {
3306              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
3307                              1, conn->pass, conn->peer, 
3308                              '\\', conn->head[3], '\\',conn->head[4],
3309                              '\\', conn->head[5], '\\',conn->head[6]);
3310              status_update (conn->client_entry, CLT_FAILED);
3311              sh_forward_do_free (conn);
3312            }
3313        }
3314
3315      else if (state == SH_DO_WRITE)  /* finished writing */
3316        {
3317          TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - (wait).>\n")));
3318
3319          /* challenge is sent, now wait for message from client
3320           */
3321          conn->headcount     = 0;
3322          conn->bytecount     = 0;
3323          conn->bytes_to_send = 0;
3324          conn->bytes_to_get  = 0;
3325          if (conn->buf != NULL) 
3326            {
3327              SH_FREE(conn->buf);
3328              conn->buf           = NULL;
3329            }
3330          conn->state     = CONN_READING;
3331        }
3332      SL_RET0(_("check_protocol"));
3333    }
3334
3335  /* ---------  message exchange  -----------
3336   */
3337  if ((conn->head[0] & SH_PROTO_SRP) == 0  && 
3338      (conn->head[0] & SH_PROTO_MSG) != 0  /* is set */ )
3339    {
3340
3341      if (state == SH_DO_READ)        /* finished reading */
3342        {
3343
3344          TPT(( 0, FIL__, __LINE__, _("msg=<Message transfer - entry.>\n")));
3345
3346          /* client requests challenge
3347           */
3348         if (0 == check_request_nerr ((char *)&(conn->head[3]), _("HELO")))
3349            {
3350
3351              TPT(( 0, FIL__, __LINE__, 
3352                    _("msg=<Message transfer - HELO (1).>\n")));
3353
3354              if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN )
3355                {
3356                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
3357                  sh_forward_do_free (conn);
3358                  SL_RET0(_("check_protocol"));
3359                } 
3360
3361              TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
3362
3363              /* ----  search the register  -----
3364               */
3365              this_client = search_register (conn, KEY_LEN);
3366              if (NULL == this_client)
3367                SL_RET0(_("check_protocol"));
3368
3369              /* ---- force authentication -----
3370               */
3371              if ( (this_client->session_key[0] == '\0') || 
3372                   ((time(NULL)-this_client->session_key_timer) 
3373                    > (time_t) TIMEOUT_KEY)
3374                   )
3375                {
3376
3377                  /* fake an auth request and jump there
3378                   */
3379                  conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
3380                  conn->head[3]  = 'S';
3381                  conn->head[4]  = 'A';
3382                  conn->head[5]  = 'L';
3383                  conn->head[6]  = 'T';
3384                  if (flag_err_info == SL_TRUE)
3385                    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
3386                                    &(conn->buf[KEY_LEN]));
3387                  len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
3388                  /* &(conn->buf[KEY_LEN]) is hostname         */
3389                  /* may overlap, thus only memmove is correct */
3390                  memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
3391                  this_client->session_key[0]    = '\0';
3392                  this_client->session_key_timer = (time_t) 1;
3393
3394                  goto servInit;
3395                }
3396             
3397              /* check whether hostname is properly signed
3398               */ 
3399              if (conn->K != NULL)
3400                { 
3401                  SH_FREE(conn->K);
3402                  conn->K = NULL;
3403                }
3404              /* FIXME len = sl_strlen(&(conn->buf[KEY_LEN])) + KEY_LEN + 1; */
3405              conn->K = SH_ALLOC(KEY_LEN + 1);
3406
3407              sl_strlcpy (conn->K, 
3408                          sh_util_siggen(this_client->session_key,
3409                                         &(conn->buf[KEY_LEN]),
3410                                         sl_strlen(&(conn->buf[KEY_LEN])),
3411                                         sigbuf, sizeof(sigbuf)),
3412                          KEY_LEN+1);
3413              TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"), 
3414                   &(conn->buf[KEY_LEN])));
3415              TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"), 
3416                   this_client->session_key));
3417              TPT((0, FIL__, __LINE__, _("msg=<sign %s>\n"), conn->K));
3418
3419              if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
3420                {
3421                  TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s>\n"), conn->buf));
3422                  TPT(( 0, FIL__, __LINE__, _("msg=<Want %s>\n"), conn->K));
3423                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
3424                                  _("Signature mismatch"), 
3425                                  &(conn->buf[KEY_LEN]));
3426
3427                  this_client->session_key_timer = 
3428                    time(NULL) - (2*TIMEOUT_KEY);
3429
3430                  sh_forward_do_free (conn);
3431                  SL_RET0(_("check_protocol"));
3432                }
3433              SH_FREE(conn->K); 
3434              conn->K = NULL;
3435
3436              /* -- create a nonce and send it --
3437               */
3438
3439              conn->client_entry = this_client;
3440              sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
3441
3442              ticks = (UINT32) taus_get ();
3443
3444              test = (char *) &ticks;
3445              sh_util_cpylong (conn->challenge, test, 4);
3446              conn->challenge[4] = '\0';
3447              for (i = 0; i < 4; ++i)
3448                if (conn->challenge[i] == '\0')
3449                  conn->challenge[i] = 0x01;
3450
3451              sh_forward_prep_send (conn, conn->challenge, 5, _("TALK"), 
3452                                    SH_PROTO_MSG);
3453              TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s.>\n"), 
3454                    hu_trans(conn->challenge)));
3455            }
3456
3457          /* Client has send a message. Check whether we are in proper
3458           * state, and verify message.
3459           */
3460          else if (0 == 
3461                   check_request_nerr((char *)&(conn->head[3]), _("MESG")) &&
3462                   conn->client_entry != NULL                           &&
3463                   conn->client_entry->session_key[0] != '\0'           &&
3464                   (len = sl_strlen(conn->buf) - KEY_LEN) > 0           &&
3465                   sl_strlen(conn->challenge) == 4)
3466            {
3467              TPT(( 0, FIL__, __LINE__, 
3468                    _("msg=<Message transfer - MESG (3).>\n")));
3469
3470#ifdef SH_ENCRYPT
3471              if (conn->client_entry->encf_flag == 0) {
3472                conn->client_entry->ency_flag = 0;
3473              }
3474              if ((conn->client_entry->ency_flag != 0) && 
3475                  ((conn->head[0] & SH_PROTO_ENC) == 0)) 
3476                {
3477                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
3478                                  _("message transfer"), 
3479#ifdef SH_ENCRYPT_2
3480                                  _("version2"),
3481#else
3482                                  _("version1"),
3483#endif
3484                                  _("none"));
3485                  /* conn->client_entry->ency_flag = 0; */
3486                }
3487              else if ((conn->client_entry->ency_flag != 0) &&
3488                       ((conn->head[0] & SH_MASK_ENC) != 
3489                        conn->client_entry->ency_flag))
3490                {
3491                  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
3492                                  MSG_TCP_MISENC,
3493                                  _("message transfer"), 
3494#ifdef SH_ENCRYPT_2
3495                                  _("version2"),
3496#else
3497                                  _("version1"),
3498#endif
3499                                  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
3500                  conn->client_entry->ency_flag = 
3501                    (conn->head[0] & SH_MASK_ENC); 
3502                }
3503#else
3504              if ((conn->head[0] & SH_PROTO_ENC) != 0) 
3505                {
3506                  sh_error_handle((-1), FIL__, __LINE__, 0, 
3507                                  MSG_TCP_MISENC,
3508                                  _("message transfer"), 
3509                                  _("none"), 
3510                                  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
3511                }
3512#endif
3513
3514              TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
3515              /* get hash from message end, truncate message
3516               */
3517              sl_strlcpy(hash, &(conn->buf[len]), KEY_LEN+1);
3518              conn->buf[len] = '\0';
3519             
3520              /* verify hash
3521               */
3522              buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL);
3523              i =  sl_strncmp(hash, 
3524                              sh_util_siggen(conn->client_entry->session_key,
3525                                             buffer,
3526                                             sl_strlen(buffer),
3527                                             sigbuf, sizeof(sigbuf)),
3528                              KEY_LEN);
3529              TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
3530                   sh_util_siggen(conn->client_entry->session_key,
3531                                  buffer,
3532                                  sl_strlen(buffer),
3533                                  sigbuf, sizeof(sigbuf))));
3534
3535
3536              if (0 != i)
3537                {
3538                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3539                  status_update (conn->client_entry, CLT_FAILED);
3540                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
3541                                  _("Msg signature mismatch"), conn->peer);
3542                  conn->client_entry->session_key_timer = 
3543                    time(NULL) - (2*TIMEOUT_KEY);
3544                  sh_forward_do_free (conn);
3545                  SL_RET0(_("check_protocol"));
3546                }
3547              else
3548                {
3549                  conn->client_entry->last_connect = time (NULL);
3550
3551                  if (NULL != sl_strstr(conn->buf,      _("EXIT")))
3552                    {
3553                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3554                      conn->client_entry->exit_flag = 1;
3555                      status_update (conn->client_entry, CLT_EXITED);
3556                    }
3557                  else if (NULL != sl_strstr(conn->buf, _("PANIC")))
3558                    {
3559                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3560                      status_update (conn->client_entry, CLT_PANIC);
3561                    }
3562                  else if (NULL != sl_strstr(conn->buf, _("SUSPEND")))
3563                    {
3564                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3565                      status_update (conn->client_entry, CLT_SUSPEND);
3566                    }
3567                  else if (NULL != sl_strstr(conn->buf, _("POLICY")))
3568                    {
3569                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3570                      status_update (conn->client_entry, CLT_POLICY);
3571                    }
3572                  else if (NULL != sl_strstr(conn->buf, 
3573                                             _("File check completed")))
3574                    {
3575                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3576                      status_update (conn->client_entry, CLT_CHECK);
3577                    }
3578                  else if (NULL != sl_strstr(conn->buf, _("START")))
3579                    {
3580                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3581                      sh_socket_add2reload (conn->client_entry->hostname);
3582                      if (conn->client_entry->status_now == CLT_SUSPEND) {
3583                        status_update (conn->client_entry, CLT_ILLEGAL);
3584                        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
3585                                        conn->peer);
3586                      }
3587                      else
3588                        status_update (conn->client_entry, CLT_STARTED);
3589                    }
3590                  else
3591                    {
3592                      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
3593                      if (NULL != sl_strstr(conn->buf, 
3594                                            _("Runtime configuration reloaded")))
3595                        {
3596                          sh_socket_add2reload (conn->client_entry->hostname);
3597                        }
3598                      status_update (conn->client_entry, CLT_MSG);
3599                    }
3600
3601                  TPT((0, FIL__, __LINE__, _("msg=<status updated>\n")));
3602                  clt_sev   = atoi(conn->buf);
3603                  clt_class = (-1);
3604                  ptok    = strchr(conn->buf, '?');
3605                  if (ptok != NULL)
3606                    {
3607                      ++ptok;
3608                      if (ptok != NULL && sh.flag.client_class == S_TRUE) 
3609                        clt_class = atoi(ptok);  /* is a global */
3610                      ptok = strchr(ptok, '?');
3611                      if (ptok != NULL) 
3612                        ++ptok;
3613                    }
3614                  if (sh.flag.client_severity == S_FALSE)
3615                    clt_sev = (-1);
3616
3617                  /* here we expect an xml formatted message, thus we don't
3618                     escape xml special chars (flag == 0) */
3619                  ptok = 
3620                    sh_tools_safe_name ((ptok!=NULL) ? ptok : conn->buf, 0);
3621
3622                  /* push client name to error routine
3623                   */
3624#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
3625                  {
3626                    char peer_ip[SH_IP_BUF];
3627                    sh_ipvx_ntoa(peer_ip, sizeof(peer_ip), &(conn->addr_peer)); 
3628                    sh_error_set_peer_ip( peer_ip );
3629                  }                       
3630#endif
3631                  sh_error_set_peer(sh_strip_domain (conn->peer));
3632                  sh_error_handle(clt_sev, FIL__, __LINE__, 0, MSG_TCP_MSG,
3633                                  sh_strip_domain (conn->peer), 
3634                                  ptok);
3635                  sh_error_set_peer(NULL);
3636#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
3637                  sh_error_set_peer_ip(NULL);
3638#endif
3639                 
3640                  TPT((0, FIL__, __LINE__, _("msg=<%s>\n"), ptok));
3641                  SH_FREE(ptok);
3642                  clt_class = (-1);
3643                }
3644              memset(buffer, '\0', sl_strlen(buffer));
3645              SH_FREE(buffer);
3646
3647              /* SERVER CONF SEND
3648               */
3649              buffer = sh_util_strconcat(conn->buf,
3650                                         conn->challenge,
3651                                         NULL);
3652              sl_strlcpy(hash, 
3653                         sh_util_siggen ( conn->client_entry->session_key,
3654                                          buffer,
3655                                          sl_strlen(buffer),
3656                                          sigbuf, sizeof(sigbuf)),
3657                         KEY_LEN+1);
3658             
3659              /* --- SERVER CMD --- */
3660              cmd = sh_socket_check (conn->peer);
3661
3662              if (cmd != NULL)
3663                {
3664                  /* max cmd size is SH_MAXMSGLEN bytes
3665                   */
3666                  sl_strlcpy(&hash[KEY_LEN], cmd, SH_MAXMSGLEN);
3667                  sl_strlcat(&hash[KEY_LEN],
3668                             sh_util_siggen ( conn->client_entry->session_key,
3669                                              &hash[KEY_LEN],
3670                                              sl_strlen(&hash[KEY_LEN]),
3671                                              sigbuf, sizeof(sigbuf)),
3672                             SH_MAXMSGLEN+KEY_LEN+1);
3673                 
3674                  TPT((0, FIL__, __LINE__, _("CONF SEND <0> <%s>\n"), 
3675                          &hash[KEY_LEN]));
3676                 
3677                } else {
3678                 
3679                  TPT((0, FIL__, __LINE__, _("CONF SEND <0> <[NULL]>\n")));
3680                 
3681                }
3682              /* --- SERVER CMD END --- */
3683
3684              TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
3685                   sh_util_siggen(conn->client_entry->session_key,
3686                                  buffer,
3687                                  sl_strlen(buffer),
3688                                  sigbuf, sizeof(sigbuf))));
3689         
3690#ifdef SH_ENCRYPT
3691              sh_forward_prep_send_crypt (conn, hash, 
3692                                          sl_strlen(hash) /* KEY_LEN */, 
3693                                          _("CONF"), 
3694                                          SH_PROTO_MSG|SH_PROTO_END|conn->client_entry->ency_flag);
3695#else
3696              sh_forward_prep_send_crypt (conn, hash, 
3697                                          sl_strlen(hash) /* KEY_LEN */, 
3698                                          _("CONF"), 
3699                                          SH_PROTO_MSG|SH_PROTO_END);
3700#endif
3701
3702              memset(buffer, '\0', sl_strlen(buffer));
3703              SH_FREE(buffer);
3704             
3705              /* sh_forward_do_free (conn); */
3706            }
3707         
3708          /* client does something unexpected
3709           */
3710          else  /* ---- ??? ----- */
3711            {
3712              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
3713                              2, conn->pass, conn->peer, 
3714                              '\\', conn->head[3], '\\',conn->head[4],
3715                              '\\', conn->head[5], '\\',conn->head[6]);
3716              status_update (conn->client_entry, CLT_FAILED);
3717              conn->client_entry->session_key_timer = 
3718                time(NULL) - (2*TIMEOUT_KEY);
3719              sh_forward_do_free (conn);
3720            }
3721        }
3722      else if (state == SH_DO_WRITE)  /* finished writing */
3723        {
3724          if (0 != (conn->head[0] & SH_PROTO_END))
3725            {
3726              if (flag_err_debug == SL_TRUE)
3727                sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKMSG,
3728                                sh_strip_domain (conn->peer));
3729              sh_forward_do_free (conn);
3730              SL_RET0(_("check_protocol"));
3731            }
3732
3733          TPT(( 0, FIL__, __LINE__, _("msg=<Msg transfer - (wait).>\n")));
3734
3735          /* challenge is sent, now wait for message from client
3736           */
3737          conn->headcount     = 0;
3738          conn->bytecount     = 0;
3739          conn->bytes_to_send = 0;
3740          conn->bytes_to_get  = 0;
3741          if (conn->buf != NULL) 
3742            {
3743              SH_FREE(conn->buf);
3744              conn->buf           = NULL;
3745            }
3746          conn->state     = CONN_READING;
3747        }
3748      TPT((0, FIL__, __LINE__, _("msg=<return>\n") ));
3749      SL_RET0(_("check_protocol"));
3750    }
3751
3752  /* ---------  authentication  -----------
3753   */
3754
3755  /* entry point for jump from message forward if session key must
3756   * be re-initialized
3757   */   
3758 servInit:
3759
3760  if ( (conn->head[0] & SH_PROTO_SRP) != 0   /* is set */ )
3761    {
3762
3763#ifndef USE_SRP_PROTOCOL
3764
3765      if (state == SH_DO_READ)        /* finished reading */
3766        {
3767          TPT((0, FIL__, __LINE__, _("msg=<Authentication - entry.>\n")));
3768
3769          /* first pass -- client request salt 
3770           */
3771          if (conn->pass    == 1) 
3772            {
3773
3774              TPT((0, FIL__, __LINE__, 
3775                   _("msg=<Authentication - SALT (1).>\n")));
3776
3777              if (conn->buf == NULL || sl_strlen(conn->buf) == 0)
3778                {
3779                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
3780                  sh_forward_do_free (conn);
3781                  SL_RET0(_("check_protocol"));
3782                } 
3783                 
3784
3785              /* search the register
3786               */
3787
3788              this_client = search_register (conn, 0);
3789              if (NULL == this_client)
3790                SL_RET0(_("check_protocol"));
3791
3792
3793              conn->client_entry = this_client;
3794              sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
3795
3796              if (0 != check_request_s((char *)&(conn->head[3]), 
3797                                       _("SALT"),conn->peer))
3798                {
3799                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
3800                                  _("No salt requested"), conn->peer);
3801                  status_update (conn->client_entry, CLT_FAILED);
3802                  conn->client_entry->session_key_timer = 
3803                    time(NULL) - (2*TIMEOUT_KEY);
3804                  sh_forward_do_free (conn);
3805                  SL_RET0(_("check_protocol"));
3806                } 
3807
3808               
3809              /* -- create server nounce v --
3810               */
3811              ticks = (UINT32) taus_get ();
3812             
3813              if (conn->A != NULL)
3814                {
3815                  SH_FREE(conn->A);
3816                  conn->A = NULL;
3817                }
3818              conn->A = SH_ALLOC(KEY_LEN+1);
3819
3820              sl_strlcpy(conn->A, 
3821                         sh_tiger_hash((char *) &ticks, 
3822                                       TIGER_DATA, sizeof(UINT32), 
3823                                       hashbuf, sizeof(hashbuf)),
3824                         KEY_LEN+1);
3825              u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
3826
3827              if (conn->M1 != NULL)
3828                {
3829                  SH_FREE(conn->M1);
3830                  conn->M1 = NULL;
3831                }
3832              conn->M1 = SH_ALLOC(2*KEY_LEN+1);
3833
3834              /* compute hash key H(v(server), P)v(server)
3835               */
3836              sh_passwd (conn->A, conn->client_entry->verifier, 
3837                         NULL, conn->M1);
3838
3839              sl_strlcat(conn->M1, conn->A, 2*KEY_LEN+1);
3840
3841
3842              /* --- send H(v(server), P)v(server) ----
3843               */
3844              sh_forward_prep_send (conn, 
3845                                    conn->M1, 
3846                                    sl_strlen(conn->M1), 
3847                                    u, 
3848                                    (conn->head[0]|SH_PROTO_SRP));
3849
3850              SH_FREE(conn->M1); 
3851              conn->M1 = NULL;
3852            }
3853
3854          /* client -- third pass
3855           * Message is H(H(u,v),P)u
3856           *
3857           * A := v, verifier := H(password),
3858           */
3859          else if (conn->pass    == 3                   && 
3860                   conn->client_entry != NULL)
3861            {
3862
3863              TPT((0, FIL__, __LINE__, 
3864                   _("msg=<Authentication - PASS (3).>\n")));
3865                                 
3866              if (0 != check_request_s((char *) &(conn->head[3]), _("PASS"), 
3867                                       conn->peer)                    ||
3868                  sl_strlen(conn->buf) <= KEY_LEN                        ||
3869                  conn->A == NULL)
3870                {
3871                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
3872                                  _("Invalid client request"), conn->peer);
3873                  status_update (conn->client_entry, CLT_FAILED);
3874                  conn->client_entry->session_key_timer = 
3875                    time(NULL) - (2*TIMEOUT_KEY);
3876                  sh_forward_do_free (conn);
3877                  SL_RET0(_("check_protocol"));
3878                } 
3879
3880              /* store random nonce u from client
3881               */
3882              if (conn->K != NULL)
3883                {
3884                  SH_FREE(conn->K);
3885                  conn->K = NULL;
3886                }
3887              conn->K = SH_ALLOC(KEY_LEN+1);
3888              sl_strlcpy(conn->K, &(conn->buf[KEY_LEN]), KEY_LEN+1);
3889
3890              /* verify random nonce u from client
3891               */
3892              if (conn->M1 != NULL)
3893                {
3894                  SH_FREE(conn->M1);
3895                  conn->M1 = NULL;
3896                }
3897              conn->M1 = sh_util_strconcat(conn->K, conn->A, NULL);
3898
3899              TPT((0, FIL__, __LINE__, _("msg=<c/r: K = %s>\n"), conn->K));
3900              TPT((0, FIL__, __LINE__, _("msg=<c/r: A = %s>\n"), conn->A));
3901              TPT((0, FIL__, __LINE__, _("msg=<c/r: M = %s>\n"), conn->M1));
3902
3903              sl_strlcpy(hash, sh_tiger_hash (conn->M1, 
3904                                              TIGER_DATA, 
3905                                              sl_strlen(conn->M1),
3906                                              hashbuf, sizeof(hashbuf)), 
3907                         KEY_LEN+1); 
3908              sh_passwd (hash, conn->client_entry->verifier, NULL, conn->M1);
3909
3910              TPT((0, FIL__, __LINE__, _("msg=<c/r: H = %s>\n"), hash));
3911              TPT((0, FIL__, __LINE__, _("msg=<c/r: P = %s>\n"), conn->M1));
3912
3913              if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN))
3914                {
3915                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
3916                                  _("Session key mismatch"), conn->peer);
3917                  status_update (conn->client_entry, CLT_FAILED);
3918                  conn->client_entry->session_key_timer = 
3919                    time(NULL) - (2*TIMEOUT_KEY);
3920                  sh_forward_do_free (conn);
3921                  SL_RET0(_("check_protocol"));
3922                } 
3923                 
3924
3925              /* ---- compute hash key H(v, P, u) ----
3926               */
3927             
3928              sh_passwd (conn->A, conn->client_entry->verifier, conn->K,
3929                         conn->M1);
3930
3931              sl_strlcpy(conn->client_entry->session_key, 
3932                         conn->M1, KEY_LEN+1);
3933              TPT((0, FIL__, __LINE__, _("msg=<c/r: Key = %s>\n"), 
3934                   conn->client_entry->session_key));
3935
3936#ifdef SH_ENCRYPT
3937               err_num = makeKey(&(conn->client_entry->keyInstE), 
3938                                 DIR_ENCRYPT, 192, 
3939                                 conn->client_entry->session_key);
3940               if (err_num < 0)
3941                 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
3942                                 errorExplain(err_num, expbuf, sizeof(expbuf)), 
3943                                 _("check_protocol: makeKey"));
3944               err_num = makeKey(&(conn->client_entry->keyInstD), 
3945                                 DIR_DECRYPT, 192, 
3946                                 conn->client_entry->session_key);
3947               if (err_num < 0)
3948                 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
3949                                 errorExplain(err_num, expbuf, sizeof(expbuf)), 
3950                                 _("check_protocol: makeKey"));
3951#endif
3952
3953              if (conn->!= NULL) SH_FREE (conn->K);
3954              conn->= NULL;
3955              if (conn->!= NULL) SH_FREE (conn->A);
3956              conn->= NULL;
3957              if (conn->M1 != NULL) SH_FREE (conn->M1);
3958              conn->M1 = NULL;
3959
3960              /* if (conn->client_entry->status_now == CLT_STARTED */
3961              if (((conn->client_entry->status_now != CLT_INACTIVE) &&
3962                   (conn->client_entry->status_now != CLT_EXITED)   &&
3963                   (conn->client_entry->status_now != CLT_SUSPEND))
3964                  && conn->client_entry->session_key_timer > (time_t) 1)
3965                {
3966                  status_update (conn->client_entry, CLT_ILLEGAL);
3967                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
3968                                  conn->peer);
3969                }
3970              else if (conn->client_entry->session_key_timer == (time_t) 0)
3971                {
3972                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW,
3973                                  conn->peer);
3974                  if (conn->client_entry->status_now != CLT_SUSPEND)
3975                    status_update (conn->client_entry, CLT_STARTED);
3976                }
3977
3978              conn->client_entry->session_key_timer = time (NULL);
3979              conn->client_entry->last_connect = time (NULL);
3980
3981              /* put in read state
3982               */
3983              sh_forward_prep_send (conn, 
3984                                    _("AUTH"),
3985                                    5, 
3986                                    _("AUTH"), 
3987                                    (conn->head[0]|SH_PROTO_SRP));
3988
3989            }
3990          else
3991            {
3992              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
3993                              3, conn->pass, conn->peer, 
3994                              '\\', conn->head[3], '\\', conn->head[4],
3995                              '\\', conn->head[5], '\\', conn->head[6]);
3996              sh_forward_do_free (conn);
3997            }
3998        }
3999
4000#else
4001      /* use SRP                    */
4002
4003
4004      if (state == SH_DO_READ)        /* finished reading */
4005        {
4006
4007          TPT((0, FIL__, __LINE__, _("msg=<Authentication - entry.>\n")));
4008
4009          /* first pass -- client request salt 
4010           */
4011          if (conn->pass    == 1)
4012            {
4013              TPT((0, FIL__, __LINE__, 
4014                   _("msg=<Authentication - SALT (1).>\n")));
4015
4016              if (conn->buf == NULL)
4017                {
4018                  sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
4019                  sh_forward_do_free (conn);
4020                  SL_RET0(_("check_protocol"));
4021                } 
4022
4023              /* search the register
4024               */
4025              this_client = search_register(conn, 0);
4026              if (NULL == this_client)
4027                SL_RET0(_("check_protocol"));
4028
4029              conn->client_entry = this_client;
4030              sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
4031
4032              if (0 != check_request_s((char *)&(conn->head[3]), _("SALT"),
4033                                       conn->peer))
4034                {
4035                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
4036                                  _("No salt requested"), conn->peer);
4037                  status_update (conn->client_entry, CLT_FAILED);
4038                  conn->client_entry->session_key_timer = 
4039                    time(NULL) - (2*TIMEOUT_KEY);
4040                  sh_forward_do_free (conn);
4041                  SL_RET0(_("check_protocol"));
4042                } 
4043                 
4044
4045              u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
4046             
4047              sh_forward_prep_send (conn, 
4048                                    conn->client_entry->salt, 
4049                                    sl_strlen(conn->client_entry->salt), 
4050                                    u, 
4051                                    (conn->head[0]|SH_PROTO_SRP));
4052            }
4053
4054          /* client has sent A -- third pass
4055           */
4056          else if (conn->pass == 3                    && 
4057                   conn->client_entry != NULL)
4058            {
4059
4060              TPT((0, FIL__, __LINE__, 
4061                   _("msg=<Authentication - PC01 (3).>\n")));
4062
4063              if (0 != check_request_s((char *)&(conn->head[3]),_("PC01"),conn->peer)||
4064                  conn->buf == NULL
4065                  )
4066                {
4067                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
4068                                  _("Invalid client request"), conn->peer);
4069                  status_update (conn->client_entry, CLT_FAILED);
4070                  conn->client_entry->session_key_timer = 
4071                    time(NULL) - (2*TIMEOUT_KEY);
4072                  sh_forward_do_free (conn);
4073                  SL_RET0(_("check_protocol"));
4074                } 
4075
4076              if (0 != sh_srp_init())
4077                {
4078                  status_update (conn->client_entry, CLT_FAILED);
4079                  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
4080                                  MSG_TCP_EBGN);
4081                  sh_forward_do_free (conn);
4082                  SL_RET0(_("check_protocol"));
4083                }
4084                 
4085
4086              /* check A, only send B if correct
4087               */
4088              if ( sl_strlen(conn->buf) < SH_BUFSIZE && 
4089                   0 == sh_srp_check_zero (conn->buf) )
4090                {
4091                  len = sl_strlen(conn->buf)+1;
4092
4093                  if (conn->A != NULL)
4094                    {
4095                      SH_FREE(conn->A);
4096                      conn->A = NULL;
4097                    }
4098                  conn->A = SH_ALLOC(len);
4099                  sl_strlcpy (conn->A, conn->buf, len);
4100                 
4101                  /*
4102                   * compute B
4103                   */
4104                  if (0 != sh_srp_make_a ())     /* b        random number */
4105                    {
4106                      status_update (conn->client_entry, CLT_FAILED);
4107                     
4108                      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
4109                                      MSG_TCP_EBGN);
4110                      sh_srp_exit();
4111                      sh_forward_do_free (conn);
4112                      SL_RET0(_("check_protocol"));
4113                    }
4114             
4115                  foo_B = sh_srp_B               /* B = v + g^b            */
4116                    (conn->client_entry->verifier);
4117
4118                  if (foo_B == NULL)
4119                    {
4120                      status_update (conn->client_entry, CLT_FAILED);
4121                     
4122                      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
4123                                      MSG_TCP_EBGN);
4124                      sh_srp_exit();
4125                      sh_forward_do_free (conn);
4126                      SL_RET0(_("check_protocol"));
4127                    }
4128
4129                  TPT((0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), conn->A));
4130                  TPT((0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), foo_B));
4131
4132                  /*
4133                   * create nonce u
4134                   */
4135                  ticks = (UINT32) taus_get ();
4136
4137                  test = (char *) &ticks;
4138                  sh_util_cpylong (u, test, 4);  /* u        nounce        */
4139                  u[4] = '\0';
4140                  sl_strlcpy(conn->challenge, 
4141                             sh_tiger_hash(u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)),
4142                             SH_CHALLENGE_SIZE);
4143
4144                  TPT((0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), u[0], u[1], u[2], u[3]));
4145                  TPT((0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
4146                       conn->challenge));
4147
4148                  /*
4149                   * compute the session key K and M1 = Hash(A,B,K)
4150                   */
4151                  foo_Ss = sh_srp_S_s (conn->challenge, 
4152                                       conn->A, 
4153                                       conn->client_entry->verifier);
4154
4155                  if (foo_Ss == NULL || 0 != sh_srp_check_zero (foo_Ss))
4156                    {
4157                      status_update (conn->client_entry, CLT_FAILED);
4158                     
4159                      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
4160                                      MSG_TCP_EBGN);
4161                      sh_srp_exit();
4162                      sh_forward_do_free (conn);
4163                      SL_RET0(_("check_protocol"));
4164                    }
4165
4166                  if (conn->K != NULL)
4167                    {
4168                      SH_FREE(conn->K);
4169                      conn->K = NULL;
4170                    }
4171                  conn->K = SH_ALLOC(KEY_LEN+1);
4172                  sl_strlcpy(conn->K, 
4173                             sh_tiger_hash(foo_Ss, TIGER_DATA, 
4174                                           sl_strlen(foo_Ss), 
4175                                           hashbuf, sizeof(hashbuf)),
4176                             KEY_LEN+1);
4177
4178                  if (conn->M1 != NULL)
4179                    {
4180                      SH_FREE(conn->M1);
4181                      conn->M1 = NULL;
4182                    }
4183                  conn->M1 = SH_ALLOC(KEY_LEN+1);
4184                  sh_srp_M (conn->A, foo_B, conn->K, conn->M1, KEY_LEN+1);
4185
4186                  TPT((0, FIL__, __LINE__, _("msg=<srp:Ss = %s>\n"), foo_Ss));
4187                  TPT((0, FIL__, __LINE__, _("msg=<srp: K = %s>\n"), conn->K));
4188                  TPT((0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"),conn->M1));
4189
4190                  /*
4191                   * send B
4192                   */
4193                  sh_forward_prep_send (conn, 
4194                                        foo_B,
4195                                        sl_strlen(foo_B)+1,
4196                                        u,
4197                                        (conn->head[0]|SH_PROTO_SRP));
4198                  if (foo_Ss != NULL)
4199                    {
4200                      SH_FREE(foo_Ss);
4201                      foo_Ss = NULL;
4202                    }
4203                  if (foo_B  != NULL)
4204                    {
4205                      SH_FREE(foo_B);
4206                      foo_B = NULL;
4207                    }
4208                }
4209              else
4210                {
4211                  status_update (conn->client_entry, CLT_FAILED);
4212
4213                  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
4214                                  MSG_TCP_EZERO);
4215                  sh_forward_do_free (conn);
4216                }
4217
4218              sh_srp_exit();
4219            }
4220                 
4221          /* client has sent M1 -- fifth pass
4222           */
4223          else if (conn->pass    == 5           && 
4224                   conn->client_entry != NULL) 
4225            {
4226              TPT((0, FIL__, __LINE__, 
4227                   _("msg=<Authentication - PC02 (5).>\n")));
4228
4229              /* check that the state is valid
4230               */
4231              if (0 != check_request_s((char *)&(conn->head[3]), _("PC02"),
4232                                       conn->peer)                   ||
4233                  conn->A == NULL || conn->K == NULL || conn->M1 == NULL)
4234                {
4235                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
4236                                  _("Invalid client request"), conn->peer);
4237                  status_update (conn->client_entry, CLT_FAILED);
4238                  conn->client_entry->session_key_timer = 
4239                    time(NULL) - (2*TIMEOUT_KEY);
4240                  sh_forward_do_free (conn);
4241                  SL_RET0(_("check_protocol"));
4242                } 
4243
4244              /* ------ verify M1 = H(A,  B, K) -------
4245               * -----    send M2 = H(A, M1, K) -------
4246               */
4247              if (conn->buf != NULL && 
4248                  sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
4249                {
4250                  /*
4251                   * send M2
4252                   */
4253                  char M_buf[KEY_LEN+1];
4254                  sh_forward_prep_send (conn, 
4255                                        sh_srp_M (conn->A, conn->M1, conn->K,
4256                                                  M_buf, sizeof(M_buf)),
4257                                        KEY_LEN+1,
4258                                        _("PARP"),
4259                                        (conn->head[0]|SH_PROTO_SRP));
4260
4261                  if (conn->!= NULL) SH_FREE(conn->A);  conn->= NULL;
4262                  if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL;
4263                  sl_strlcpy(conn->client_entry->session_key, 
4264                             conn->K, KEY_LEN+1);
4265                  TPT((0, FIL__, __LINE__, _("msg=<key %s>\n"), 
4266                       conn->client_entry->session_key));
4267
4268#ifdef SH_ENCRYPT
4269                  err_num = makeKey(&(conn->client_entry->keyInstE), 
4270                                    DIR_ENCRYPT, 192, 
4271                                    conn->client_entry->session_key);
4272                  if (err_num < 0)
4273                    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
4274                                    errorExplain(err_num, expbuf, sizeof(expbuf)), 
4275                                    _("sh_forward_prep_send_int: makeKey"));
4276                  err_num = makeKey(&(conn->client_entry->keyInstD), 
4277                                    DIR_DECRYPT, 192, 
4278                                    conn->client_entry->session_key);
4279                  if (err_num < 0)
4280                    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
4281                                    errorExplain(err_num, expbuf, sizeof(expbuf)), 
4282                                    _("sh_forward_prep_send_int: makeKey"));
4283#endif
4284
4285                  if (conn->!= NULL) SH_FREE(conn->K);  conn->= NULL;
4286
4287                  conn->client_entry->last_connect = time (NULL);
4288                 
4289                  if (((conn->client_entry->status_now != CLT_INACTIVE) &&
4290                       (conn->client_entry->status_now != CLT_EXITED)   &&
4291                       (conn->client_entry->status_now != CLT_SUSPEND))
4292                      && conn->client_entry->session_key_timer > (time_t) 1)
4293                    {
4294                      status_update (conn->client_entry, CLT_ILLEGAL);
4295
4296                      sh_error_handle((-1), FIL__, __LINE__, 0, 
4297                                      MSG_TCP_ILL,
4298                                      conn->peer);
4299                    }
4300                  else if (conn->client_entry->session_key_timer == (time_t) 0)
4301                    {
4302                      sh_error_handle((-1), FIL__, __LINE__, 0, 
4303                                      MSG_TCP_NEW,
4304                                      conn->peer);
4305                      if (conn->client_entry->status_now != CLT_SUSPEND)
4306                        status_update (conn->client_entry, CLT_STARTED);
4307                    }
4308                  conn->client_entry->session_key_timer = time (NULL);
4309
4310                }
4311              else
4312                {
4313                  status_update (conn->client_entry, CLT_FAILED);
4314                  conn->client_entry->session_key_timer = 
4315                    time(NULL) - (2*TIMEOUT_KEY);
4316
4317                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
4318                                  _("Session key mismatch"), conn->peer);
4319                  sh_forward_do_free (conn);
4320                } 
4321            }
4322
4323          else
4324            {
4325              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
4326                              4, conn->pass, conn->peer, 
4327                              '\\', conn->head[3], '\\', conn->head[4],
4328                              '\\', conn->head[5], '\\', conn->head[6]);
4329              sh_forward_do_free (conn);
4330            }
4331        }
4332
4333#endif
4334
4335      else if (state == SH_DO_WRITE)  /* finished writing */
4336        {
4337          TPT((0, FIL__, __LINE__, _("msg=<Authentication -- (wait).>\n")));
4338
4339          conn->headcount     = 0;
4340          conn->bytecount     = 0;
4341          conn->bytes_to_send = 0;
4342          conn->bytes_to_get  = 0;
4343          if (conn->buf != NULL) 
4344            {
4345              SH_FREE(conn->buf);
4346              conn->buf           = NULL;
4347            }
4348          conn->state     = CONN_READING;
4349        }
4350    }
4351  SL_RET0(_("check_protocol"));
4352}
4353
4354
4355/***********************************************************
4356 *
4357 *    SERVER RECEIVE FUNCTION
4358 *
4359 ***********************************************************
4360 */
4361int sh_forward_do_read (sh_conn_t * conn)
4362{
4363  unsigned long   byteread;     /* bytes read         */
4364
4365#ifdef SH_ENCRYPT
4366
4367  unsigned long           blkfac = 0;
4368  /* unsigned long           length2; */
4369  char                  * p = NULL, * q = NULL;
4370  RIJ_BYTE                    inBlock[B_SIZ]; 
4371  RIJ_BYTE                    outBlock[B_SIZ];
4372  unsigned int            j;
4373  cipherInstance          cipherInst;
4374  int                     err_num;
4375  char expbuf[SH_ERRBUF_SIZE];
4376#endif
4377
4378  SL_ENTER(_("sh_forward_do_read"));
4379
4380  if (conn->state == CONN_SENDING)
4381    {
4382      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
4383                      conn->peer);
4384      SL_RETURN( (-1), _("sh_forward_do_read"));
4385    }
4386
4387  if (conn->headcount < SH_HEADER_SIZE) 
4388    {
4389      conn->bytes_to_get = SH_HEADER_SIZE - conn->headcount;
4390      byteread           = read (conn->fd, &(conn->head[conn->headcount]),
4391                                    conn->bytes_to_get);
4392      if (byteread > 0 || errno == EINTR) 
4393        {
4394          if (byteread > 0) 
4395            conn->headcount += byteread;
4396          if (conn->headcount == SH_HEADER_SIZE)
4397            {
4398                conn->bytes_to_get = 
4399                  (256 * (unsigned int)conn->head[1] + 
4400                   (unsigned int)conn->head[2]);
4401                SH_SHOWPROT(conn->head, '<');
4402                conn->bytecount = 0;
4403            }
4404        }
4405      else
4406        {
4407          goto conn_reset;
4408        }
4409      SL_RETURN( (0), _("sh_forward_do_read"));
4410    }
4411
4412
4413  /* limit message size
4414   */
4415  /*
4416  conn->bytes_to_get =
4417    (conn->bytes_to_get > (16*SH_BUFSIZE - 1)) ?
4418    (16*SH_BUFSIZE - 1) : conn->bytes_to_get;
4419  */
4420  conn->bytes_to_get = (conn->bytes_to_get > TRANS_BYTES) ? 
4421    TRANS_BYTES : conn->bytes_to_get;
4422
4423  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get > 0)
4424    {
4425      if ((conn->bytecount > 0) && (conn->bytes_to_get > conn->bytecount))
4426        {
4427          /* do nothing */;
4428        }
4429      else
4430        {
4431          if (conn->buf != NULL)
4432            SH_FREE (conn->buf);
4433          conn->buf = SH_ALLOC(conn->bytes_to_get + 1); /* <= TRANS_BYTES+1 */
4434          conn->bytecount = 0;
4435        }
4436
4437      byteread           = read (conn->fd, &(conn->buf[conn->bytecount]),
4438                                 conn->bytes_to_get - conn->bytecount);
4439      if (byteread > 0 || errno == EINTR) 
4440        {
4441          if (byteread > 0) 
4442            conn->bytecount    += byteread;
4443          if (conn->bytecount == conn->bytes_to_get) 
4444            {
4445              ++conn->pass;
4446              /* always terminate with NULL - we might use sl_strcmp()
4447               */
4448              conn->buf[conn->bytecount] = '\0';
4449              conn->state                = CONN_PAUSE;
4450
4451#ifdef SH_ENCRYPT
4452              if      ((conn->head[0] & SH_PROTO_EN2) != 0) /* if encrypted */
4453                {
4454                  conn->buf = 
4455                    sh_tools_revertPack (conn->head, conn->buf,
4456                                         &(conn->client_entry->keyInstD),
4457                                         conn->bytecount);
4458                }
4459              else if ((conn->head[0] & SH_PROTO_ENC) != 0) /* if encrypted */
4460                {
4461                  /* Decrypt only complete blocks.
4462                   * If there is an incomplete block,
4463                   * something is wrong anyway.
4464                   * Decrypt in place.
4465                   */
4466                  blkfac  = conn->bytecount / B_SIZ;
4467                  /* length2 = (B_SIZ * blkfac); */
4468                  p       = conn->buf;
4469                  q       = conn->buf;
4470     
4471                  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
4472                  if (err_num < 0)
4473                    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
4474                                    errorExplain(err_num, expbuf, sizeof(expbuf)), 
4475                                    _("sh_forward_do_read: cipherInit"));
4476
4477                  for (j = 0; j < blkfac; ++j)
4478                    {
4479                      memcpy(inBlock, p, B_SIZ);
4480                      err_num = blockDecrypt(&cipherInst, 
4481                                             &(conn->client_entry->keyInstD), 
4482                                             inBlock, 128 * BNUM, outBlock);
4483                      if (err_num < 0)
4484                        sh_error_handle((-1), FIL__, __LINE__, -1, 
4485                                        MSG_E_SUBGEN,
4486                                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
4487                                        _("sh_forward_do_read: blockDecrypt"));
4488                      memcpy(q, outBlock, B_SIZ);
4489                      p += 16;
4490                      q += 16;
4491                    }
4492                }
4493#endif
4494
4495              /* ------  HERE CALL check_protocol(conn) -------  */
4496              check_protocol(conn, SH_DO_READ);
4497            }
4498        }
4499      else
4500        {
4501          goto conn_reset;
4502        }
4503    }
4504
4505  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get == 0)
4506    {
4507      if (conn->buf != NULL)
4508        SH_FREE (conn->buf);
4509      conn->buf       = NULL;
4510      conn->bytecount = 0;
4511      ++conn->pass;
4512      conn->state     = CONN_PAUSE;
4513      /* fprintf(stderr, "\n**** FIXME null read ****\n\n"); */
4514      /* ------  HERE CALL check_protocol(conn) -------  */
4515      check_protocol(conn, SH_DO_READ);
4516    }
4517     
4518  SL_RETURN( (0), _("sh_forward_do_read"));
4519
4520 conn_reset:
4521  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
4522                  conn->peer);
4523  sh_forward_do_free ( conn );
4524  SL_RETURN( (-1), _("sh_forward_do_read"));
4525}
4526
4527#if !defined(O_NONBLOCK)
4528#if defined(O_NDELAY)
4529#define O_NONBLOCK  O_NDELAY
4530#else
4531#define O_NONBLOCK  0
4532#endif
4533#endif
4534
4535/* send to the client
4536 */
4537int sh_forward_do_write (sh_conn_t * conn)
4538{
4539  int    flags;
4540  long   arg = 0;
4541  long   bytesent;     /* bytes read         */
4542
4543  SL_ENTER(_("sh_forward_do_write"));
4544
4545  /* ---- consistency check ------
4546   */
4547  if (conn->state == CONN_READING)
4548    {
4549      sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
4550                      conn->peer);
4551      SL_RETURN( (-1), _("sh_forward_do_write"));
4552    }
4553     
4554 
4555  flags = retry_fcntl (FIL__, __LINE__, conn->fd, F_GETFL, arg);
4556  retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags|O_NONBLOCK);
4557
4558  /* ---- send the header ------
4559   */
4560  if (conn->headcount < SH_HEADER_SIZE) 
4561    {
4562      conn->bytes_to_send = SH_HEADER_SIZE - conn->headcount;
4563      bytesent            = write (conn->fd, 
4564                                   &(conn->head[conn->headcount]), 
4565                                   conn->bytes_to_send);
4566      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
4567        {
4568          if (bytesent > 0) 
4569            conn->headcount += bytesent;
4570          if (conn->headcount == SH_HEADER_SIZE) 
4571            {
4572              conn->bytes_to_send = 
4573                (256 * (int)conn->head[1] + (int)conn->head[2]);
4574            }
4575        }
4576      else 
4577        {
4578          goto conn_reset_w;
4579        }
4580      if (conn->fd >= 0)
4581        retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
4582      SL_RETURN( (0), _("sh_forward_do_write"));
4583    }
4584
4585
4586  /* ---- send the body ------
4587   */
4588
4589  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send > 0 &&
4590      conn->buf != NULL)
4591    {
4592      bytesent           = write (conn->fd, &(conn->buf[conn->bytecount]), 
4593                                     conn->bytes_to_send - conn->bytecount);
4594      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
4595        {
4596          if (bytesent > 0) 
4597            conn->bytecount    += bytesent;
4598          if (conn->bytecount == conn->bytes_to_send) 
4599            {
4600              ++conn->pass;
4601              conn->state         = CONN_PAUSE;
4602              /* ------  HERE CALL check_protocol(conn) -------  */
4603              check_protocol(conn, SH_DO_WRITE);
4604            }
4605        }
4606      else
4607        {
4608          goto conn_reset_w;
4609        }
4610    }
4611     
4612  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send == 0)
4613    {
4614      ++conn->pass;
4615      conn->state     = CONN_PAUSE;
4616      /* fprintf(stderr, "\n**** FIXME null write ****\n\n"); */
4617      /* ------  HERE CALL check_protocol(conn) -------  */
4618      check_protocol(conn, SH_DO_WRITE);
4619    }
4620
4621  if (conn->fd >= 0)
4622    retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
4623  SL_RETURN( (0), _("sh_forward_do_write"));
4624
4625 conn_reset_w:
4626  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
4627                  conn->peer);
4628  sh_forward_do_free ( conn );
4629  SL_RETURN( (-1), _("sh_forward_do_write"));
4630}
4631
4632/* accept a connection from a client
4633 */ 
4634#include <syslog.h>
4635#ifdef SH_USE_LIBWRAP
4636#include <tcpd.h>
4637
4638#ifndef ALLOW_SEVERITY
4639#define ALLOW_SEVERITY LOG_INFO
4640#define DENY_SEVERITY  LOG_WARNING
4641#endif
4642
4643int allow_severity;
4644int deny_severity;
4645#endif
4646
4647int sh_forward_accept (int sock, sh_conn_t * newconn)
4648{
4649  int                errflag;
4650  int                rc;
4651  struct sh_sockaddr addr;
4652#ifdef SH_USE_LIBWRAP
4653  struct request_info request;
4654  char                errbuf[128];
4655  char                daemon[128];
4656#endif
4657 
4658  /* handle AIX (size_t addrlen) in wrapper
4659   */
4660  int                addrlen = sizeof(addr);
4661
4662  SL_ENTER(_("sh_forward_accept"));
4663
4664  rc = retry_accept(FIL__, __LINE__, sock, &addr, &addrlen);
4665
4666  if (rc >= 0)
4667    {
4668
4669      if (addrlen == 0)
4670        {
4671          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
4672                          _("Connecting entity unknown"), _("accept"));
4673          newconn->fd    = -1;
4674          newconn->state = CONN_FREE;
4675          sl_close_fd(FIL__, __LINE__, rc);
4676          SL_RETURN( (-1), _("sh_forward_accept"));
4677        }
4678
4679#ifdef SH_USE_LIBWRAP
4680      sl_strlcpy(daemon, SH_INSTALL_NAME, sizeof(daemon));
4681      request_init(&request, RQ_DAEMON, daemon, RQ_FILE, rc, 0);
4682      fromhost(&request);
4683      if (!hosts_access(&request)) 
4684        {
4685          sl_strlcpy(errbuf, _("Refused connection from "), sizeof(errbuf));
4686          sl_strlcat(errbuf,   eval_client(&request), sizeof(errbuf));
4687
4688          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
4689                          errbuf, _("libwrap"));
4690          newconn->fd    = -1;
4691          newconn->state = CONN_FREE;
4692          sl_close_fd(FIL__, __LINE__, rc);
4693          SL_RETURN( (-1), _("sh_forward_accept"));
4694        }
4695#endif
4696
4697      memcpy (&(newconn->addr_peer), &addr, sizeof(struct sh_sockaddr));
4698
4699      /* prepare for usage of connection
4700       */
4701      (void) retry_fcntl( FIL__, __LINE__, rc, F_SETFD, 1 );
4702      newconn->fd           = rc;
4703      newconn->state        = CONN_READING;
4704      newconn->timer        = (unsigned long) time (NULL);
4705
4706      if (flag_err_info == SL_TRUE)
4707        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CNEW, newconn->fd);
4708
4709      SL_RETURN( (0), _("sh_forward_accept"));
4710    }
4711  else
4712    {
4713      char err_buf[SH_ERRBUF_SIZE];
4714      errflag = errno;
4715      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
4716                      sh_error_message(errflag,err_buf, sizeof(err_buf)), _("accept"));
4717      newconn->fd    = -1;
4718      newconn->state = CONN_FREE;
4719      SL_RETURN( (-1), _("sh_forward_accept"));
4720    }
4721}
4722
4723extern char sh_sig_msg[64];  /* defined in sh_unix.c */
4724
4725/* ------------  port and interface -------
4726 */
4727static unsigned int server_port = SH_DEFAULT_PORT;
4728
4729int sh_forward_set_port (const char * str)
4730{
4731  int retval = 0;
4732  unsigned long   i;
4733  char * endptr;
4734 
4735  SL_ENTER(_("sh_forward_set_port"));
4736  i = strtoul (str, &endptr, 0);
4737  if (endptr == str) {
4738    retval = -1;
4739  } else if (i > 65535) {
4740    retval = -1;
4741  } else {
4742    server_port = i;
4743  }
4744  SL_RETURN( (retval), _("sh_forward_set_port"));
4745}
4746
4747static struct sh_sockaddr server_interface;
4748static int            use_server_interface = 0;
4749
4750int sh_forward_set_interface (const char * str)
4751{
4752  if (0 == strcmp(str, _("INADDR_ANY")))
4753    {
4754      use_server_interface = 0;
4755      return 0;
4756    }
4757
4758  if (0 == sh_ipvx_aton(str, &server_interface)) 
4759    {
4760      use_server_interface = 0;
4761      return -1;
4762    }
4763
4764  use_server_interface = 1;
4765  return 0;
4766}
4767
4768/* ------------  print error --------------
4769 */
4770struct sock_err_st {
4771  char msg[128];
4772  int  errnum;
4773  int  port;
4774  int  line;
4775  int  euid;
4776};
4777
4778static struct sock_err_st sock_err[2];
4779
4780void sh_forward_printerr(char * str, int errnum, unsigned int port, int line)
4781{
4782  int slot = 0;
4783
4784  if (port != server_port)
4785    slot = 1;
4786  if (str == NULL)
4787    sock_err[slot].msg[0] = '\0';
4788  else
4789    sl_strlcpy(sock_err[slot].msg, str, 128);
4790  sock_err[slot].errnum = errnum;
4791  sock_err[slot].port   = port;
4792  sock_err[slot].line   = line;
4793  sock_err[slot].euid   = (int) geteuid();
4794}
4795
4796int sh_forward_printerr_final(int slot)
4797{
4798  char errbuf[SH_ERRBUF_SIZE];
4799
4800  SL_ENTER(_("sh_forward_printerr_final"));
4801  if (sock_err[slot].msg[0] != '\0')
4802    {
4803      dlog(1, FIL__, __LINE__, 
4804           _("Could not set up the listening socket for the server because of the\nfollowing error: %s\nPossible reasons include:\n - insufficient privilege for UID %d, or\n - the port %d is already used by another program.\n"),
4805           sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), 
4806           sock_err[slot].euid, 
4807           sock_err[slot].port);
4808      sh_error_handle((-1), FIL__, sock_err[slot].line, 
4809                      sock_err[slot].errnum, MSG_EXIT_ABORTS,
4810                      sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)),
4811                      sh.prg_name,
4812                      sock_err[slot].msg);
4813      SL_RETURN((-1), _("sh_forward_printerr_final"));
4814    }
4815  SL_RETURN(0, _("sh_forward_printerr_final"));
4816}
4817
4818#define  TIME_OUT_DEF 900
4819static   unsigned long  time_out_val = TIME_OUT_DEF;
4820
4821int sh_forward_set_timeout (const char * c)
4822{
4823  long val;
4824
4825  SL_ENTER(_("sh_forward_set_time_out"));
4826
4827  val = strtol (c, (char **)NULL, 10);
4828
4829  if (val == 0)
4830    {
4831      val = TIME_OUT_DEF;
4832    }
4833  else if (val < 0)
4834    {
4835      time_out_val = TIME_OUT_DEF;
4836      SL_RETURN( (-1), _("sh_forward_set_time_out"));
4837    }
4838
4839  time_out_val = (unsigned long) val;
4840  SL_RETURN( (0), _("sh_forward_set_time_out"));
4841}
4842
4843
4844static   sh_conn_t        * conns = NULL;
4845static   int  maxconn = 0;  /* maximum number of simultaneous connections */
4846
4847
4848#ifdef INET_SYSLOG
4849#define INET_SUSPEND_TIME 180           /* equal to 3 minutes */
4850#define SH_MINSOCK_DEFAULT 3
4851int create_syslog_socket (int flag);
4852static int recv_syslog_socket   (int fd);
4853static int syslog_sock[SH_SOCKMAX] = { -1 };
4854static int syslog_sock_n = 0;
4855#else
4856#define SH_MINSOCK_DEFAULT 2
4857#endif
4858
4859static int SH_MINSOCK = SH_MINSOCK_DEFAULT;
4860extern int pf_unix_fd;
4861
4862/* the tcp socket, and the function to establish it
4863 */
4864static int sh_tcp_sock[SH_SOCKMAX] = { -1 };
4865static int sh_tcp_sock_n = 0;
4866
4867static int do_socket(int domain, int type, int protocol,
4868                     struct sockaddr * sa, int salen)
4869{
4870  int sock = -1;
4871  int errnum = 0;
4872  int flag   = 1; /* non-zero to enable an option */
4873
4874  /* fprintf(stderr, "FIXME IPVX: bind addr %s (%d) :%d\n",
4875          sh_ipvx_print_sockaddr (sa, domain), salen,
4876          sh_ipvx_get_port(sa, domain)); */
4877
4878  /* create the socket, bind() it and listen()
4879   */
4880  if ((sock = socket(domain, type, protocol)) < 0 )
4881    {
4882      errnum = errno; 
4883      sh_forward_printerr (_("socket"), errnum, server_port, __LINE__);
4884      return -1;
4885    }
4886  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
4887 
4888  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
4889                  (void *) &flag, sizeof(flag)) < 0 )
4890    {
4891      errnum = errno;
4892      sh_forward_printerr (_("setsockopt"), errnum, server_port, __LINE__);
4893      sl_close_fd (FIL__, __LINE__, sock);
4894      return -1;
4895    }
4896 
4897  if ( bind(sock, (struct sockaddr *) sa, salen) < 0) 
4898    {
4899      if (errno != EADDRINUSE)
4900        {
4901          errnum = errno;
4902          sh_forward_printerr (_("bind"), errnum, server_port, __LINE__);
4903          sl_close_fd (FIL__, __LINE__, sock);
4904          return -1;
4905        }
4906      else
4907        {
4908          sl_close_fd (FIL__, __LINE__, sock);
4909          return -2;
4910        }
4911    }
4912 
4913  if ( retry_fcntl( FIL__, __LINE__, sock, F_SETFL, O_NONBLOCK ) < 0 )
4914    {
4915      errnum = errno;
4916      sh_forward_printerr (_("fcntl"), errnum, server_port, __LINE__);
4917      sl_close_fd (FIL__, __LINE__, sock);
4918      return -1;
4919    }
4920 
4921  if ( listen(sock, 64) < 0)
4922    {
4923      errnum = errno;
4924      sh_forward_printerr (_("listen"), errnum, server_port, __LINE__);
4925      sl_close_fd (FIL__, __LINE__, sock);
4926      return -1;
4927    }
4928
4929  return sock;
4930}
4931
4932int sh_create_tcp_socket (void)
4933{
4934#if defined(USE_IPVX)
4935  struct addrinfo *ai;
4936  struct addrinfo *p;
4937  struct addrinfo hints;
4938  char            port[32];
4939#else
4940  struct sockaddr_in addr;
4941  int addrlen      = sizeof(addr);
4942#endif
4943
4944  int sock   = -1;
4945
4946  SL_ENTER(_("sh_create_tcp_socket"));
4947
4948  sh_forward_printerr (NULL, 0, server_port, __LINE__);
4949
4950#if defined(USE_IPVX)
4951  if (use_server_interface == 0)
4952    {
4953      memset (&hints, '\0', sizeof (hints));
4954      hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
4955      hints.ai_socktype = SOCK_STREAM;
4956      hints.ai_family   = AF_UNSPEC;
4957      sl_snprintf(port, sizeof(port), "%d", server_port);
4958
4959      if (getaddrinfo (NULL, port, &hints, &ai) != 0)
4960        {
4961          int errnum = errno;
4962          sh_forward_printerr (_("getaddrinfo"), errnum, server_port, __LINE__);
4963          sl_close_fd (FIL__, __LINE__, sock);
4964          SL_RETURN((-1), _("sl_create_tcp_socket"));
4965        }
4966     
4967      p = ai;
4968     
4969      while (p != NULL && sh_tcp_sock_n < SH_SOCKMAX)
4970        {
4971          sock = do_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
4972                           p->ai_addr, p->ai_addrlen);
4973         
4974          if (sock >= 0) {
4975            if (sh_tcp_sock_n < SH_SOCKMAX) {
4976              sh_tcp_sock[sh_tcp_sock_n] = sock;
4977              ++sh_tcp_sock_n;
4978            }
4979            else {
4980              sl_close_fd (FIL__, __LINE__, sock);
4981            }   
4982          } else if (sock == -1) {
4983            freeaddrinfo (ai);
4984            goto end;
4985          }
4986          p = p->ai_next;
4987        }
4988     
4989      freeaddrinfo (ai);
4990    }
4991  else
4992    {
4993      sh_ipvx_set_port(&server_interface, server_port);
4994
4995      sock = do_socket(server_interface.ss_family, SOCK_STREAM, 0, 
4996                       sh_ipvx_sockaddr_cast(&server_interface), 
4997                       SH_SS_LEN(server_interface));
4998     
4999      if (sock >= 0) {
5000        sh_tcp_sock[0] = sock;
5001        sh_tcp_sock_n  = 1;
5002      }
5003    }         
5004#else
5005  if (use_server_interface == 0)
5006    addr.sin_addr.s_addr = INADDR_ANY;
5007  else
5008    memcpy(&addr, sh_ipvx_sockaddr_cast(&server_interface), addrlen);
5009  addr.sin_family      = AF_INET;
5010  addr.sin_port        = htons(server_port);
5011 
5012  sock = do_socket(AF_INET, SOCK_STREAM, 0, (struct sockaddr *) &addr, addrlen);
5013
5014  if (sock >= 0) {
5015      sh_tcp_sock[0] = sock;
5016      sh_tcp_sock_n  = 1;
5017  }
5018
5019#endif
5020
5021#if defined(USE_IPVX)
5022 end:
5023#endif
5024  if (sh_tcp_sock_n > 1)
5025    SH_MINSOCK += (sh_tcp_sock_n - 1);
5026
5027  SL_RETURN((sh_tcp_sock_n), _("sl_create_tcp_socket"));
5028}
5029
5030/*****************************************
5031 *
5032 * This is the server main loop.
5033 *
5034 * The server is set up for listening, and
5035 * and starts a select() loop.
5036 *
5037 *****************************************/
5038
5039void sh_receive()
5040{
5041#ifdef SH_USE_XML
5042  extern int  sh_log_file    (char * message, char * inet_peer);
5043#endif
5044
5045  /* Use volatile to circumvent a gcc4 problem on RH/CentOS 4.8 (?) */
5046  volatile int       sock = -1;
5047  sh_conn_t        * cx;
5048  fd_set             readset;
5049  fd_set             writeset;
5050  struct timeval     tv;
5051  int                num_sel;
5052  int                errnum;
5053  int                nowconn;
5054  int                status;
5055  int                high_fd = -1;
5056  register int       i;
5057  long               dummy = 0;
5058  unsigned long      time_now;
5059  unsigned long      time_last = 0;
5060  unsigned long      time_out = time_out_val; 
5061 
5062  time_t told;
5063  time_t tcurrent;
5064
5065  unsigned long tchkold;
5066
5067  int setsize_fd;
5068
5069  int sock_tcp[2];
5070  int sock_unix;
5071#ifdef INET_SYSLOG
5072  int sock_log[2];
5073#endif
5074 
5075  SL_ENTER(_("sh_receive"));
5076
5077  if ( sh_forward_printerr_final(0) < 0)
5078    {
5079      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
5080    }
5081
5082  sock = sh_tcp_sock[0];
5083
5084  /* ****************************************************************
5085   *
5086   * This is a non-forking server. We use select() on the listen()
5087   * socket to watch for new connections. For new connections, accept()
5088   * will return a new socket that is put in the read/write filesets.
5089   * Data about active connections are kept in the 'conns' table.
5090   *
5091   ******************************************************************/
5092 
5093  /* The table to hold info on sockets.
5094   * We reserve 6 file descriptors for misc. use.
5095   * The POSIX lower limit on open files seems to be eight.
5096   */
5097  maxconn    = get_open_max() - 6;
5098
5099  /* ugly fix for FreeBSD compiler warning; casting FD_SETSIZE in the
5100   * conditional expression does not suppress the warning... */
5101  setsize_fd = (int)FD_SETSIZE;
5102  maxconn = (setsize_fd < maxconn) ? setsize_fd : maxconn;
5103
5104  if (maxconn < 0 || !sl_ok_muls(maxconn, sizeof(sh_conn_t)))
5105    {
5106      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
5107                      0, sock);
5108      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
5109    }
5110  conns   = SH_ALLOC (sizeof(sh_conn_t) * maxconn);
5111
5112  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
5113                  (maxconn-1), sock);
5114
5115  /* timer
5116   */
5117  tcurrent                   = (unsigned long) time (NULL);
5118  told                       = tcurrent;
5119
5120  tchkold                    = tcurrent;
5121 
5122  for (i = SH_MINSOCK; i < maxconn; ++i)
5123    {
5124      conns[i].buf         = NULL;
5125      conns[i].K           = NULL;
5126      conns[i].A           = NULL;
5127      conns[i].M1          = NULL;
5128      conns[i].FileName    = NULL;
5129      conns[i].fd          = -1;
5130      sh_forward_do_free ( &conns[i]);
5131    }
5132 
5133  /* status init
5134   */
5135  server_status.conn_open  = 0;
5136  server_status.conn_total = 0;
5137  server_status.conn_max   = maxconn-1;
5138  server_status.start      = time (NULL);
5139  server_status.last       = (time_t) 0;
5140
5141  nowconn    = 1;
5142  tv.tv_sec  = 5;
5143  tv.tv_usec = 0;
5144 
5145  /* conns[0] is the listen() socket. Always in read mode.
5146   */
5147  sock = 0;
5148
5149  sock_tcp[0] = 0;
5150  while (sock < sh_tcp_sock_n)
5151    {
5152      conns[sock].fd    = sh_tcp_sock[sock];
5153      conns[sock].state = CONN_READING;
5154      /* high_fd = (sh_tcp_sock[sock] > high_fd) ? sh_tcp_sock[sock] : high_fd; */
5155      ++sock;
5156    }
5157  sock_tcp[1] = sock;
5158 
5159  conns[sock].fd    = pf_unix_fd;
5160  conns[sock].state = CONN_READING;
5161  /* high_fd = (pf_unix_fd > high_fd) ? pf_unix_fd : high_fd; */
5162
5163  sock_unix = sock;
5164
5165  ++sock;
5166
5167#ifdef INET_SYSLOG
5168  conns[sock].fd = -1;
5169
5170  if ( sh_forward_printerr_final(1) < 0)
5171    {
5172      SH_FREE(conns);
5173      conns = NULL;
5174      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
5175    }
5176
5177  sock_log[0] = sock;
5178  sock_log[1] = sock;
5179
5180  if (syslog_sock_n > 0)
5181    {
5182      int s2;
5183      for (s2 = 0; s2 < syslog_sock_n; ++s2)
5184        {
5185          conns[sock].fd    = syslog_sock[s2];
5186          conns[sock].state = CONN_READING;
5187          /* high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; */
5188          ++sock;
5189        }
5190      sock_log[1] = sock;
5191
5192    }
5193#endif
5194 
5195  sh_html_write(all_clients);
5196 
5197  /* This is the select() loop.
5198   */
5199  while (1 == 1)
5200    {
5201
5202    if (sig_raised > 0)
5203      {
5204        TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
5205
5206        if (sig_termfast == 1)  /* SIGTERM */
5207          {
5208            TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
5209            strncpy (sh_sig_msg, _("SIGTERM"), 20);
5210            --sig_raised; --sig_urgent;
5211            aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
5212          }
5213         
5214        if (sig_config_read_again == 1)
5215          {
5216            TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
5217            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
5218
5219
5220            /* -- Delete the name server cache. --
5221             */
5222
5223            delete_cache();
5224#if defined(WITH_EXTERNAL)
5225            /* -- Delete list of external tasks. --
5226             */
5227            (void) sh_ext_cleanup();
5228#endif
5229#if defined(SH_WITH_MAIL)
5230              sh_nmail_free();
5231#endif
5232            /* - mark all clients dead
5233             * - read configuration file
5234             * - remove clients still dead
5235             */
5236            sh_forward_mark_dead ();
5237
5238            reset_count_dev_console();
5239            reset_count_dev_time();
5240            sl_trust_purge_user();
5241
5242            (void) sh_readconf_read ();
5243
5244            for (i = SH_MINSOCK; i < maxconn; ++i)
5245              if (conns[i].state != CONN_FREE   && 
5246                  conns[i].client_entry != NULL &&
5247                  conns[i].client_entry->dead_flag == 1)
5248                sh_forward_do_free ( &conns[i]);
5249            sh_forward_clean_tree ();
5250
5251            sig_config_read_again = 0;
5252            --sig_raised;
5253          }
5254
5255        if (sig_fresh_trail == 1) /* SIGIOT */
5256          {
5257            /* Logfile access
5258             */
5259#ifdef SH_USE_XML
5260            sh_log_file (NULL, NULL);
5261#endif
5262            TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
5263            sh_error_only_stderr (S_TRUE);
5264            sh_unix_rm_lock_file(sh.srvlog.name);
5265            retry_msleep(3, 0);
5266            sh.flag.log_start = S_TRUE;
5267            sh_error_only_stderr (S_FALSE);
5268            sig_fresh_trail       = 0;
5269            --sig_raised;
5270          }
5271       
5272         
5273        if (sig_terminate == 1 && nowconn < 2)  /* SIGQUIT */
5274          {
5275            TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
5276            strncpy (sh_sig_msg, _("SIGQUIT"), 20);
5277            --sig_raised; --sig_urgent;
5278            aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
5279          }
5280       
5281         
5282        if (sig_debug_switch == 1)  /* SIGUSR1 */
5283          {
5284            TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
5285            sh_error_dbg_switch();
5286            sig_debug_switch = 0;
5287            --sig_raised;
5288          }
5289       
5290        if (sig_suspend_switch > 0)  /* SIGUSR2 */
5291          {
5292            TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
5293            if (sh_global_suspend_flag == 1) {
5294              sh_global_suspend_flag = 0;
5295            } else {
5296              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
5297                              sh.prg_name);
5298              sh_global_suspend_flag = 1;
5299            }
5300            --sig_suspend_switch;
5301            --sig_raised; --sig_urgent;
5302          }
5303
5304        sig_raised = (sig_raised < 0) ? 0 : sig_raised;
5305        sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
5306        TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
5307      }
5308     
5309      if (sh_global_suspend_flag == 1)
5310        {
5311          (void) retry_msleep (1, 0);
5312          continue;
5313        }
5314
5315      /* Recompute the descriptor set. select() modifies it,
5316       * thus we update it using the info from the connection table.
5317       * Also recompute the number of open connections.
5318       */
5319      FD_ZERO( &readset );
5320      FD_ZERO( &writeset );
5321      high_fd = conns[0].fd;
5322
5323      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
5324        {
5325          FD_SET(conns[sock].fd, &readset );
5326          high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
5327        }
5328
5329      if (conns[sock_unix].fd > -1)
5330        {
5331          FD_SET(conns[sock_unix].fd, &readset );
5332          high_fd   = (high_fd > conns[sock_unix].fd) ? high_fd : conns[sock_unix].fd;
5333        }
5334
5335#ifdef INET_SYSLOG
5336      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
5337        {
5338          if (conns[sock].fd > -1)
5339            {
5340              FD_SET(conns[sock].fd, &readset );
5341              high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
5342            }
5343        }
5344#endif
5345
5346      time_now  = (unsigned long) time (NULL);
5347      nowconn   = 1;
5348     
5349      for (i = SH_MINSOCK; i < maxconn; ++i)
5350        {
5351          /* eliminate timed out connections
5352           */
5353          if (conns[i].state != CONN_FREE) 
5354            {
5355              if (time_now-conns[i].timer > time_out)
5356                {
5357                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMOUT,
5358                                  conns[i].peer);
5359                  sh_forward_do_free ( &conns[i]);
5360                }
5361              else
5362                ++nowconn;
5363            }
5364         
5365         
5366          if       (conns[i].state   == CONN_READING)
5367            { 
5368              FD_SET(conns[i].fd, &readset);
5369              high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
5370            }
5371          else if  (conns[i].state   == CONN_SENDING)
5372            {
5373              FD_SET(conns[i].fd, &writeset);
5374              high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
5375            }
5376        }
5377
5378      /* -- Exponentially reduce timeout limit if more than 1/2 full. --
5379       */
5380      /* Eliminate this, will cause problems when too much clients are
5381       * starting up. */
5382#if 0
5383      if (nowconn > (maxconn/2))
5384        time_out = ( (time_out/2) > 1) ? (time_out/2) : 1;
5385      else
5386        time_out = time_out_val;
5387#endif
5388     
5389     
5390      /* -- Do the select(). --
5391       */
5392      num_sel = select(high_fd+1, &readset, &writeset, NULL, &tv);
5393      errnum  = errno;
5394     
5395      /* reset timeout - modified by select() on some systems
5396       */
5397      tv.tv_sec  = 5;
5398      tv.tv_usec = 0;
5399     
5400
5401      if ( (time_now - time_last) > 2L)
5402        {
5403          time_last = time_now;
5404          if (sh_html_write(all_clients) < 0)
5405            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
5406        }
5407     
5408     
5409      /* Error handling.
5410       */
5411      if ( num_sel < 0 )        /* some error             */
5412        {
5413          char errbuf[SH_ERRBUF_SIZE];
5414
5415          if (sig_raised == 1)
5416            {
5417              sig_raised = 2;
5418              continue;
5419            }
5420
5421          if ( errnum == EINTR)
5422            continue;     /* try again              */
5423
5424          if ( errnum == EBADF)
5425            {
5426              /* seek and destroy the bad fd
5427               */
5428              for (i = SH_MINSOCK; i < high_fd; ++i)
5429                {
5430                  if ((conns[i].state == CONN_READING) ||
5431                      (conns[i].state == CONN_SENDING))
5432                    {
5433                      if (-1 == retry_fcntl(FIL__, __LINE__, 
5434                                            conns[i].fd, F_GETFL, dummy))
5435                        sh_forward_do_free ( &conns[i]);
5436                    }
5437                }
5438              continue;
5439            }
5440
5441          sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_EXIT_ABORTS,
5442                          sh_error_message(errnum, errbuf, sizeof(errbuf)), 
5443                          sh.prg_name,
5444                          _("select"));
5445          aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
5446        }
5447     
5448
5449      /* log the timestamp
5450       */
5451      if ((tcurrent - told) > sh.looptime )
5452        {
5453          told = tcurrent;
5454#ifdef MEM_DEBUG
5455          sh_mem_check();
5456          sh_unix_count_mlock();
5457#else
5458          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
5459#endif
5460        }
5461
5462#if defined(SH_WITH_MAIL)
5463      /*
5464       * flush the mail queue
5465       */
5466      if (tcurrent - sh.mailTime.alarm_last > sh.mailTime.alarm_interval) 
5467        {
5468          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
5469          (void) sh_nmail_flush ();
5470          sh.mailTime.alarm_last = tcurrent;
5471        }
5472#endif
5473#ifdef MEM_DEBUG
5474      sh_mem_dump();
5475#endif
5476
5477      tcurrent = (unsigned long) time (NULL);
5478
5479      /* check for time limit exceeded
5480       */
5481      if ((tcurrent - tchkold) > (unsigned int) 3 )
5482        {
5483          tchkold = tcurrent;
5484          client_time_check(/* all_clients */);
5485          /* reset cache */
5486          sh_userid_destroy();
5487        }
5488     
5489      /* seed / re-seed the PRNG if required
5490       */
5491      (void) taus_seed();
5492
5493      /* select() timeout handling.
5494       */
5495      if ( num_sel == 0 )       /* timeout - no connection */ 
5496        {
5497          if (sh_html_write(all_clients) < 0)
5498            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
5499          continue;
5500        }
5501
5502      /* New connection.
5503       */
5504      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
5505        {
5506          if ( FD_ISSET(conns[sock].fd , &readset )) /* a new connection   */
5507            {
5508              --num_sel;
5509              status = 0;
5510              if (nowconn < maxconn && sig_terminate == 0 && sig_termfast == 0)
5511                {
5512                  /* Find a free slot to accept the connection
5513                   */
5514                  i = SH_MINSOCK;
5515                  while (i < maxconn)
5516                    {
5517                      if (conns[i].state == CONN_FREE)
5518                        {
5519                          /* Here we run the accept() and copy the peer to
5520                           * the free slot.
5521                           */
5522                          status = sh_forward_accept(conns[sock].fd, &conns[i]);
5523                         
5524                          if (status == 0)
5525                            {
5526                              high_fd = 
5527                                (high_fd > conns[i].fd ? high_fd : conns[i].fd);
5528                              ++server_status.conn_open;
5529                              ++server_status.conn_total;
5530                              server_status.last = time (NULL);
5531                            }
5532                          break;
5533                        }
5534                      ++i;
5535                    }
5536                }
5537              /* This re-runs select to accept data on the new
5538               * connection, rather than first dealing with old
5539               * connections.
5540               */
5541              if (status == 0) 
5542                continue;
5543            }
5544        }
5545     
5546      /* check for commands on the socket
5547       */
5548      if (conns[sock_unix].fd > (-1) && FD_ISSET(conns[sock_unix].fd , &readset ))
5549        {
5550          sh_socket_poll();
5551        }
5552
5553#ifdef INET_SYSLOG
5554      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
5555        {
5556          if (conns[sock].fd > (-1) && FD_ISSET(conns[sock].fd , &readset ))
5557            {
5558              recv_syslog_socket (conns[sock].fd);
5559            }
5560        }
5561#endif
5562
5563      /* Check for pending read/write on the rest of the sockets.
5564       */
5565      for ( i = SH_MINSOCK; num_sel > 0 && i < maxconn; ++i )
5566        {
5567          if (sig_termfast == 1)
5568            break;
5569
5570          cx = &conns[i];
5571          if ( cx->state == CONN_READING &&
5572               FD_ISSET( cx->fd, &readset ) )
5573            {
5574              --num_sel;
5575              sh_forward_do_read ( cx );
5576            }
5577          else if ( cx->state == CONN_SENDING &&
5578                    FD_ISSET( cx->fd, &writeset ) )
5579            {
5580              --num_sel;
5581              sh_forward_do_write ( cx );
5582            }
5583        }
5584      /* continue */
5585    }
5586  /* notreached */
5587}
5588
5589void  free_client_tree (void)
5590{
5591  SL_ENTER(_("free_client_tree"));
5592  zAVLFreeTree (all_clients, free_client);
5593  SL_RET0(_("free_client_tree"));
5594}
5595
5596void sh_forward_free_all ()
5597{
5598  register int i;
5599 
5600  SL_ENTER(_("sh_forward_free_all"));
5601
5602  if (conns != NULL)
5603    for (i = SH_MINSOCK; i < maxconn; ++i)
5604      {
5605        sh_forward_do_free ( &conns[i]);
5606      }
5607
5608
5609  free_client_tree ();
5610
5611  if (conns != NULL)
5612    SH_FREE (conns);
5613
5614  SL_RET0(_("sh_forward_free_all"));
5615}
5616
5617#ifdef INET_SYSLOG
5618
5619/* Unlike Linux / FreeBSD, most systems don't define the stuff below
5620 * in syslog.h
5621 */
5622
5623#ifndef LOG_FAC
5624#define LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
5625#endif
5626
5627#ifndef LOG_PRI
5628#define LOG_PRI(p)      ((p) & LOG_PRIMASK)
5629#endif
5630
5631typedef struct sh_code {
5632        char    *c_name;
5633        int     c_val;
5634} SH_CODE;
5635
5636SH_CODE sh_facilitynames[] =
5637{
5638#ifdef LOG_AUTH
5639  { N_("auth"), LOG_AUTH },
5640#endif
5641#ifdef LOG_AUTHPRIV
5642  { N_("authpriv"), LOG_AUTHPRIV },
5643#endif
5644#ifdef LOG_CRON
5645  { N_("cron"), LOG_CRON },
5646#endif
5647#ifdef LOG_DAEMON
5648  { N_("daemon"), LOG_DAEMON },
5649#endif
5650#ifdef LOG_FTP
5651  { N_("ftp"), LOG_FTP },
5652#endif
5653#ifdef LOG_KERN
5654  { N_("kern"), LOG_KERN },
5655#endif
5656#ifdef LOG_LPR
5657  { N_("lpr"), LOG_LPR },
5658#endif
5659#ifdef LOG_MAIL
5660  { N_("mail"), LOG_MAIL },
5661#endif
5662#ifdef INTERNAL_MARK
5663  { N_("mark"), INTERNAL_MARK },          /* INTERNAL */
5664#endif
5665#ifdef LOG_NEWS
5666  { N_("news"), LOG_NEWS },
5667#endif
5668#ifdef LOG_AUTH
5669  { N_("security"), LOG_AUTH },           /* DEPRECATED */
5670#endif
5671#ifdef LOG_SYSLOG
5672  { N_("syslog"), LOG_SYSLOG },
5673#endif
5674#ifdef LOG_USER
5675  { N_("user"), LOG_USER },
5676#endif
5677#ifdef LOG_UUCP
5678  { N_("uucp"), LOG_UUCP },
5679#endif
5680#ifdef LOG_LOCAL0
5681  { N_("local0"), LOG_LOCAL0 },
5682#endif
5683#ifdef LOG_LOCAL1
5684  { N_("local1"), LOG_LOCAL1 },
5685#endif
5686#ifdef LOG_LOCAL2
5687  { N_("local2"), LOG_LOCAL2 },
5688#endif
5689#ifdef LOG_LOCAL3
5690  { N_("local3"), LOG_LOCAL3 },
5691#endif
5692#ifdef LOG_LOCAL4
5693  { N_("local4"), LOG_LOCAL4 },
5694#endif
5695#ifdef LOG_LOCAL5
5696  { N_("local5"), LOG_LOCAL5 },
5697#endif
5698#ifdef LOG_LOCAL6
5699  { N_("local6"), LOG_LOCAL6 },
5700#endif
5701#ifdef LOG_LOCAL7
5702  { N_("local7"), LOG_LOCAL7 },
5703#endif
5704  { NULL, -1 }
5705};
5706 
5707
5708SH_CODE sh_prioritynames[] =
5709{ 
5710#ifdef LOG_ALERT
5711  { N_("alert"), LOG_ALERT },
5712#endif
5713#ifdef LOG_CRIT
5714  { N_("crit"), LOG_CRIT },
5715#endif
5716#ifdef LOG_DEBUG
5717  { N_("debug"), LOG_DEBUG },
5718#endif
5719#ifdef LOG_EMERG
5720  { N_("emerg"), LOG_EMERG },
5721#endif
5722#ifdef LOG_ERR
5723  { N_("err"), LOG_ERR },
5724#endif
5725#ifdef LOG_ERR
5726  { N_("error"), LOG_ERR },               /* DEPRECATED */
5727#endif
5728#ifdef LOG_INFO
5729  { N_("info"), LOG_INFO },
5730#endif
5731#ifdef INTERNAL_NOPRI
5732  { N_("none"), INTERNAL_NOPRI },         /* INTERNAL */
5733#endif
5734#ifdef LOG_NOTICE
5735  { N_("notice"), LOG_NOTICE },
5736#endif
5737#ifdef LOG_EMERG
5738  { N_("panic"), LOG_EMERG },             /* DEPRECATED */
5739#endif
5740#ifdef LOG_WARNING
5741  { N_("warn"), LOG_WARNING },            /* DEPRECATED */
5742#endif
5743#ifdef LOG_WARNING
5744  { N_("warning"), LOG_WARNING },
5745#endif
5746  { NULL, -1 }
5747};
5748
5749static int enable_syslog_socket = S_FALSE;
5750
5751static int recv_syslog_socket (int fd)
5752{
5753  static time_t      return_next = 0;
5754  int                priority = 0;
5755  int                fac, pri;
5756  int                i;
5757  char             * cfac = NULL;
5758  char             * cpri = NULL;
5759  int                res;
5760  char             * tmp;
5761  char             * bptr;
5762  char             * ptr = NULL;
5763  char               buf[1048];
5764  struct sockaddr_in from;
5765  char errbuf[SH_ERRBUF_SIZE];
5766
5767  struct sh_sockaddr ss;
5768  struct sockaddr * sa = (struct sockaddr *) &from;
5769  char   namebuf[SH_BUFSIZE];
5770
5771  /* The 6th argument in recvfrom is *socklen_t in Linux and *BSD,
5772   * but *int everywhere else. Because socklen_t is unsigned int, there
5773   * should be no problem as long as  sizeof(struct sockaddr_in) < INT_MAX ...
5774   */
5775  unsigned int fromlen = sizeof(from);
5776
5777  if (enable_syslog_socket == S_FALSE)
5778    return 0;
5779
5780  SL_ENTER(_("recv_syslog_socket"));
5781
5782  if (return_next > 0)
5783    {
5784      if ( (time(NULL) - return_next) < 2)
5785        SL_RETURN( 0, _("recv_syslog_socket"));
5786      else
5787        return_next = 0;
5788    }
5789
5790  res = recvfrom(fd,  buf,  1047, 0, (struct sockaddr *) &from, &fromlen);
5791
5792  sh_ipvx_save(&ss, sa->sa_family, (struct sockaddr *) &from);
5793  sh_ipvx_ntoa(namebuf, sizeof(namebuf), &ss);
5794
5795  if (res > 0)
5796    {
5797      res = (res < 1047) ? res : 1047; 
5798      buf[res] = '\0';
5799      if (res > 1 && buf[res-1] == '\n')
5800        buf[res-1] = '\0';
5801
5802      /* here we expect an xml formatted message, thus we don't
5803         escape xml special chars (flag == 0) */
5804      /* commented out to not escape twice    */
5805      /* bptr = sh_tools_safe_name(buf, 0);   */
5806      bptr = buf;
5807
5808      if (!bptr || !(*bptr))
5809        {
5810          res = errno;
5811          TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
5812          sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
5813                          sh_error_message(res, errbuf, sizeof(errbuf)), 
5814                          namebuf);
5815          SL_RETURN( (-1), _("recv_syslog_socket"));
5816        }     
5817
5818      TPT(( 0, FIL__, __LINE__, _("msg=<UDP message from %s>\n"), namebuf ));
5819
5820      ptr = bptr;
5821      i = 0;
5822      if (*ptr == '<') 
5823        {
5824          ++ptr; ++i;
5825          while (i < res &&
5826                 (unsigned char) *ptr > 47 && (unsigned char) *ptr < 58)
5827            {
5828              priority = 10 * priority + (*ptr - '0');
5829              ++ptr;
5830              ++i;
5831            }
5832          if (*ptr == '>')
5833            ++ptr;
5834        }
5835      fac = LOG_FAC(priority);
5836      i = 0; 
5837      while (sh_facilitynames[i].c_name != NULL)
5838        {
5839          if (sh_facilitynames[i].c_val == (fac<<3))
5840            { cfac = sh_util_strdup(_(sh_facilitynames[i].c_name)); break; }
5841          ++i;
5842        }
5843      pri = LOG_PRI(priority);
5844      i = 0; 
5845      while (sh_prioritynames[i].c_name != NULL)
5846        {
5847          if (sh_prioritynames[i].c_val == pri)
5848            { cpri = sh_util_strdup(_(sh_prioritynames[i].c_name)); break; }
5849          ++i;
5850        }
5851
5852      /* here we do not expect an xml formatted message, thus we escape
5853         xml special chars (flag == 1) */
5854      tmp = sh_tools_safe_name (ptr, 1);
5855      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_INET_SYSLOG,
5856                      namebuf, 
5857                      (cfac == NULL) ? _("none") : cfac, 
5858                      (cpri == NULL) ? _("none") : cpri, 
5859                      (tmp  == NULL) ? _("none") : tmp);
5860      if (cfac != NULL)
5861        SH_FREE(cfac);
5862      if (cpri != NULL)
5863        SH_FREE(cpri);
5864      SH_FREE(tmp);
5865      /* SH_FREE(bptr); */
5866    }
5867
5868  else if (res < 0 && errno != EINTR)
5869    {
5870      res = errno;
5871      TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
5872      sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
5873                      sh_error_message(res, errbuf, sizeof(errbuf)), 
5874                      namebuf);
5875
5876      /* don't accept anything the next 2 seconds
5877       */
5878      return_next = time(NULL);
5879      SL_RETURN( (-1), _("recv_syslog_socket"));
5880    }     
5881  SL_RETURN( (0), _("recv_syslog_socket"));
5882}
5883
5884int set_syslog_active(const char * c)
5885{
5886  return sh_util_flagval(c, &enable_syslog_socket);
5887}
5888
5889static int do_syslog_socket(int domain, int type, int protocol,
5890                            struct sockaddr * sa, int salen)
5891{
5892  int                flag = 1;  /* non-zero to enable an option */
5893  int sock;
5894  int errnum;
5895  int res;
5896
5897  /* create the socket, bind() it and listen()
5898   */
5899  sock = socket(domain, type, protocol);
5900
5901  if (sock < 0)
5902    {
5903      errnum = errno; 
5904      sh_forward_printerr (_("syslog socket"), errnum, 514, __LINE__);
5905      return -1;
5906    }
5907  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
5908 
5909  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
5910                  (void *) &flag, sizeof(flag)) < 0 )
5911    {
5912      errnum = errno;
5913      sh_forward_printerr (_("syslog setsockopt SO_REUSEADDR"), 
5914                           errnum, 514, __LINE__);
5915      return -1;
5916    }
5917
5918#if defined(SO_BSDCOMPAT)
5919  if ( setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
5920                  (void *) &flag, sizeof(flag)) < 0 )
5921    {
5922      errnum = errno;
5923      sh_forward_printerr (_("syslog setsockopt SO_BSDCOMPAT"), 
5924                           errnum, 514, __LINE__);
5925      return -1;
5926    }
5927#endif
5928 
5929  res = bind(sock, sa, salen);
5930
5931  if ( res < 0) 
5932    {
5933      errnum = errno;
5934      sh_forward_printerr (_("syslog bind"), errnum, 514, __LINE__);
5935      sl_close_fd(FIL__, __LINE__, sock);
5936      return -1;
5937    }
5938  return sock;
5939}
5940
5941/* callerFlag == S_TRUE means override the enable_syslog_socket flag
5942 */
5943int create_syslog_socket (int callerFlag)
5944{
5945  int sock;
5946
5947#if defined(USE_IPVX)
5948  struct addrinfo *ai;
5949  struct addrinfo *p;
5950  struct addrinfo hints;
5951#else
5952  struct sockaddr_in addr;
5953  int addrlen      = sizeof(addr);
5954#endif
5955
5956  SL_ENTER(_("create_syslog_socket"));
5957
5958  if (callerFlag == S_FALSE)
5959    {
5960      if (enable_syslog_socket == S_FALSE && syslog_sock_n > 0)
5961        {
5962          /* user does n