source: trunk/src/sh_forward.c @ 133

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

Reentrant checksum/hash functions.

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