source: trunk/src/sh_forward.c @ 132

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

Make utility functions thread-safe.

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