source: trunk/src/sh_xfer_server.c @ 491

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

Fix for ticket #389 (libwrap) and #390 (update on FreeBSD).

File size: 93.1 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22#include <string.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <ctype.h>
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
41#define TRANS_BYTES 65120
42#else
43#define TRANS_BYTES 65280
44#endif
45
46/* timeout for session key
47 */
48#define TIMEOUT_KEY 7200
49
50/* max time between connection attempts
51 */
52#define TIMEOUT_CON 2048
53
54/* #undef  SRP_DEBUG */
55/* #define SRP_DEBUG */
56
57#ifdef HAVE_MEMORY_H
58#include <memory.h>
59#endif
60
61#if TIME_WITH_SYS_TIME
62#include <sys/time.h>
63#include <time.h>
64#else
65#if HAVE_SYS_TIME_H
66#include <sys/time.h>
67#else
68#include <time.h>
69#endif
70#endif
71
72/*
73#ifdef TM_IN_SYS_TIME
74#include <sys/time.h>
75#else
76#include <time.h>
77#endif
78*/
79
80#ifdef HAVE_SYS_SELECT_H
81#include <sys/select.h>
82#endif
83
84#ifdef  HAVE_UNISTD_H
85#include <errno.h>
86#include <signal.h>
87#include <setjmp.h>
88#include <pwd.h>
89#include <grp.h>
90#include <sys/stat.h>
91#include <sys/resource.h>
92#include <fcntl.h>
93#include <sys/wait.h>
94#include <unistd.h>
95#endif
96
97#ifndef FD_SET
98#define NFDBITS         32
99#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
100#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
101#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
102#endif /* !FD_SET */
103#ifndef FD_SETSIZE
104#define FD_SETSIZE      32
105#endif
106#ifndef FD_ZERO
107#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
108#endif
109
110#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
111#include <sys/mman.h>
112#endif
113
114
115#include <netdb.h> 
116#include <sys/types.h> 
117#include <netinet/in.h> 
118#include <sys/socket.h> 
119#ifndef S_SPLINT_S
120#include <arpa/inet.h>
121#endif
122
123#include "sh_ipvx.h"
124#include "samhain.h"
125#include "sh_tiger.h"
126#include "sh_utils.h"
127#include "sh_unix.h"
128#include "sh_xfer.h"
129#include "sh_srp.h"
130#include "sh_fifo.h"
131#include "sh_tools.h"
132#include "sh_entropy.h"
133#include "sh_html.h"
134#include "sh_nmail.h"
135#include "sh_socket.h"
136#define SH_NEED_GETHOSTBYXXX
137#include "sh_static.h"
138#include "sh_guid.h"
139
140#ifdef SH_ENCRYPT
141#include "rijndael-api-fst.h"
142char * sh_tools_makePack (unsigned char * header, int flag,
143                          char * payload, unsigned long payload_size,
144                          keyInstance * keyInstE);
145char * sh_tools_revertPack (unsigned char * header, int flag, char * message,
146                            keyInstance * keyInstE, 
147                            unsigned long message_size);
148#endif
149
150/* define this if you want to debug the client/server communication */
151/* #define SH_DBG_PROT 1 */
152
153#ifdef  SH_DBG_PROT
154#define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d))
155#else
156#define SH_SHOWPROT(c,d)
157#endif
158
159/* the port client will be connecting to
160 */
161#ifndef SH_DEFAULT_PORT
162#define SH_DEFAULT_PORT 49777   
163#endif
164
165#ifndef SH_SELECT_REPEAT
166#define SH_SELECT_REPEAT 60
167#endif
168
169#ifndef SH_HEADER_SIZE
170#define SH_HEADER_SIZE 7
171#endif
172
173#ifndef SH_CHALLENGE_SIZE
174#define SH_CHALLENGE_SIZE 9
175#endif
176
177#undef  FIL__
178#define FIL__  _("sh_xfer_server.c")
179
180int     clt_class = (-1);
181
182extern int flag_err_debug;
183extern int flag_err_info;
184
185
186#if defined (SH_WITH_SERVER)
187
188#if defined(WITH_TRACE) || defined(WITH_TPT)
189extern char * hu_trans(const char * ihu);
190#endif
191extern unsigned int ServerPort;
192#if !defined(USE_SRP_PROTOCOL)
193extern void sh_passwd (char * salt, char * password, char * nounce, char *hash);
194#endif
195
196static int StripDomain = S_TRUE;
197
198int sh_xfer_set_strip (const char * str)
199{
200  static int fromcl = 0;
201
202  if (fromcl == 1)
203    return 0;
204  else
205    return (sh_util_flagval(str, &StripDomain));
206}
207
208static char * sh_strip_domain (char *name)
209{
210  char * out = NULL;
211
212  SL_ENTER(_("sh_strip_domain"));
213
214  if (StripDomain == S_FALSE || strchr(name, '.') == NULL) 
215    {
216      out = sh_util_strdup(name);
217      SL_RETURN( out, _("sh_strip_domain"));
218    }
219  else
220    {
221      /* check whether it is in dotted number format
222       * --> last part must be kept
223       */
224      if (0 != sh_ipvx_is_numeric(name))
225        {
226          out = sh_util_strdup(name);
227          SL_RETURN( out, _("sh_strip_domain"));
228        }
229      else
230        {
231          char * p;
232          out = sh_util_strdup(name);
233          p   = strchr(out, '.');
234          if (p) *p = '\0';
235          SL_RETURN( out, _("sh_strip_domain"));
236        }
237    }
238
239  SL_RETURN( out, _("sh_strip_domain"));
240}
241
242#ifndef USE_SRP_PROTOCOL
243
244int sh_xfer_make_client (const char * str)
245{
246  /* char *          safer; */
247  char            key[KEY_LEN+1];
248  unsigned char   in[PW_LEN+1];
249  int    i = 0, j, k, l = 0;
250  char hashbuf[KEYBUF_SIZE];
251 
252  if (sl_strlen(str) != (PW_LEN * 2)) 
253    {
254      fprintf(stderr, 
255              _("Input must be a %d digit hexadecimal number"\
256                " (only 0-9, a-f, A-F allowed in input)\n"),
257              (PW_LEN * 2));
258      _exit(EXIT_FAILURE);
259    }
260 
261  while (i < (PW_LEN * 2))
262    {
263      k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
264      if (k != -1 && j != -1) 
265        {
266          in[l] = (k * 16 + j);
267          ++l; i+= 2;
268        }
269      else
270        {
271          fprintf(stderr, _("Invalid char %c\n"), str[i]);
272          _exit(EXIT_FAILURE);
273        }
274    }
275  in[PW_LEN] = '\0';
276
277  sl_strlcpy ((char *)key, 
278              sh_tiger_hash ((char*)in, TIGER_DATA, PW_LEN, 
279                             hashbuf, sizeof(hashbuf)), 
280              KEY_LEN+1);
281  key[KEY_LEN] = '\0';
282 
283  fprintf(stdout, _("Client entry: Client=HOSTNAME@00000000@%s\n"), 
284          key);
285  fflush(stdout);
286
287  _exit(EXIT_SUCCESS);
288  return 0;
289}
290
291#else
292
293int sh_xfer_make_client (const char * str)
294{
295  char * foo_v;
296
297  char   salt[17];
298  char   key[KEY_LEN+1];
299  char   in[PW_LEN];
300  int    i = 0, j, k, l = 0;
301  char hashbuf[KEYBUF_SIZE];
302 
303  if (sl_strlen(str) != (PW_LEN*2)) 
304    {
305      fprintf(stderr, 
306              _("Input must be a %d digit hexadecimal number"\
307                " (only 0-9, a-f, A-F allowed in input)\n"),
308              (PW_LEN*2));
309      _exit(EXIT_FAILURE);
310    }
311
312    while (i < (PW_LEN*2))
313      {
314        k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
315        if (k != -1 && j != -1) 
316          {
317            in[l] = (k * 16 + j);
318            ++l; i+= 2;
319          }
320        else
321          {
322            fprintf(stderr, _("Invalid char %c\n"), str[i]);
323            _exit(EXIT_FAILURE);
324          }
325      }
326   
327 
328    if (0 == sh_srp_init())
329      {
330        sh_util_keyinit(key, KEY_LEN);
331        sl_strlcpy(salt, sh_tiger_hash(key, TIGER_DATA, KEY_LEN, 
332                                       hashbuf, sizeof(hashbuf)), 
333                   17); 
334        sh_srp_x (salt, in);
335        foo_v  = sh_srp_verifier ();
336        fprintf(stdout, _("Client=HOSTNAME@%s@%s\n"), 
337                salt, foo_v);
338        fflush(stdout);
339        SH_FREE(foo_v);
340        sh_srp_exit();
341        _exit(EXIT_SUCCESS);
342      }
343    fprintf(stdout, "%s",_("ERROR initializing BigNum library.\n"));
344    fflush (stdout);
345    _exit(EXIT_FAILURE);
346    return -1;
347}
348#endif
349
350
351int sh_xfer_create_password (const char * dummy)
352{
353  UINT32   val[2]; 
354  char     output[KEY_LEN+1];
355  char hashbuf[KEYBUF_SIZE];
356
357  val[0] = taus_get ();
358  val[1] = taus_get ();
359
360  sl_strlcpy (output, 
361              sh_tiger_hash((char *)(&val[0]), TIGER_DATA, 2*sizeof(UINT32),
362                            hashbuf, sizeof(hashbuf)),
363              KEY_LEN);
364
365  output[16] = '\0';
366
367  fprintf(stdout, _("%s\n"), output);
368  fflush (stdout);
369
370  if (dummy)
371    _exit(EXIT_SUCCESS);
372  else
373    _exit(EXIT_SUCCESS); 
374  return (0);  /* avoid compiler warning */
375}
376
377/* #if defined (SH_WITH_SERVER) */
378#endif
379
380/**************************************************
381 *
382 *
383 *  S E R V E R   
384 *
385 *
386 ***************************************************/
387
388#ifdef SH_WITH_SERVER
389
390#include "sh_readconf.h"
391
392
393#define CONN_FREE    0
394#define CONN_READING 1
395#define CONN_SENDING 2
396#define CONN_PAUSE   3
397#define CONN_BUSY    4
398
399char * clt_stat[] = {
400  N_("Inactive"),
401  N_("Started"),
402  N_("ILLEGAL"),
403  N_("FAILED"),
404  N_("Exited"),
405  N_("PANIC"),
406  N_("POLICY"),
407  N_("File_transfer"),
408  N_("Message"),
409  N_("TIMEOUT_EXCEEDED"),
410  N_("Suspended"),
411  N_("Filecheck"),
412};
413
414#include <time.h>
415
416/* in sh_html.h:
417 *  typedef struct client_entry {
418 *  } client_t;
419 */
420
421#include "zAVLTree.h"
422
423static char * sh_tolower (char * s)
424{
425  char * ret = s;
426  if (s)
427    {
428      for (; *s; ++s)
429        { 
430          *s = tolower((unsigned char) *s);
431        }
432    }
433  return ret;
434}
435
436/* Function to return the key for indexing
437 * the argument
438 */
439zAVLKey sh_avl_key (void const * arg)
440{
441  const client_t * sa = (const client_t *) arg;
442  return (zAVLKey) sa->hostname;
443}
444
445zAVLTree * all_clients = NULL;
446
447void sh_xfer_html_write()
448{
449  SL_ENTER(_("sh_xfer_html_write"));
450  sh_html_write(all_clients);
451  SL_RET0(_("sh_xfer_html_write"));
452}
453
454
455int sh_xfer_use_clt_class (const char * c)
456{
457  int i;
458  SL_ENTER(_("sh_xfer_use_clt_class"));
459  i = sh_util_flagval(c, &(sh.flag.client_class));
460  SL_RETURN(i, _("sh_xfer_use_clt_class"));
461}
462
463int sh_xfer_use_clt_sev (const char * c)
464{
465  int i;
466  SL_ENTER(_("sh_xfer_use_clt_sev"));
467  i = sh_util_flagval(c, &(sh.flag.client_severity));
468  SL_RETURN(i, _("sh_xfer_use_clt_sev")); 
469}
470
471
472/* the destructor
473 */
474void free_client(void * inptr)
475{
476  client_t * here;
477
478  SL_ENTER(_("free_client"));
479  if (inptr == NULL)
480    SL_RET0(_("free_client"));
481  else
482    here = (client_t *) inptr;
483
484  if (here->hostname != NULL)
485    SH_FREE(here->hostname);
486  if (here->salt != NULL)
487    SH_FREE(here->salt);
488  if (here->verifier != NULL)
489    SH_FREE(here->verifier);
490  SH_FREE(here);
491  SL_RET0(_("free_client"));
492}
493
494
495int sh_xfer_register_client (const char * str)
496{
497  client_t   * newclt;
498  client_t   * testclt;
499
500  const char * ptr;
501  int          sepnum = 0;
502  int          sep[2];
503  register int i = 0;
504  int          siz_str = 0;
505
506  SL_ENTER(_("sh_xfer_register_client"));
507
508  ptr = str; 
509  while (*ptr) {
510    if (*ptr == '@' && sepnum < 2 ) 
511      { 
512        sep[sepnum] = i;
513        ++sepnum;
514      } 
515    ++ptr; ++i; 
516  }
517
518  if (all_clients == NULL)
519    {
520      all_clients = zAVLAllocTree (sh_avl_key, zAVL_KEY_STRING);
521      if (all_clients == NULL) 
522        {
523          (void) safe_logger (0, 0, NULL);
524          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
525        }
526    }
527 
528  if ((sepnum == 2) && (sep[0] > 0) && (sep[1] > sep[0]))
529    {
530      newclt = SH_ALLOC (sizeof(client_t));
531      newclt->hostname = SH_ALLOC (sep[0]+1);
532      newclt->salt     = SH_ALLOC (sep[1]-sep[0]);
533      newclt->verifier = SH_ALLOC (sl_strlen(str)-sep[1]+1);
534      newclt->exit_flag         = 0;
535      newclt->dead_flag         = 0;
536#ifdef SH_ENCRYPT
537      newclt->encf_flag         = SH_PROTO_ENC;
538      newclt->ency_flag         = SH_PROTO_ENC;
539#else
540      newclt->encf_flag         = 0;
541      newclt->ency_flag         = 0;
542#endif
543      newclt->ivst_flag         = 0;
544      newclt->session_key[0]    = '\0';
545      newclt->last_connect      = (time_t) 0;
546      newclt->session_key_timer = (time_t) 0;
547      newclt->status_now        = CLT_INACTIVE;
548      for (i = 0; i < CLT_MAX; ++i) 
549        newclt->status_arr[i] = CLT_INACTIVE;
550      (void) sh_unix_time(0, newclt->timestamp[CLT_INACTIVE], TIM_MAX);
551
552      /* truncate */
553      sl_strlcpy(newclt->hostname,  &str[0],        sep[0]+1);
554      sh_tolower(newclt->hostname);
555
556      /* truncate */
557      sl_strlcpy(newclt->salt,      &str[sep[0]+1], sep[1]-sep[0]);
558      sl_strlcpy(newclt->verifier,  &str[sep[1]+1], sl_strlen(str)-sep[1]+1);
559
560      testclt = (client_t *) zAVLSearch (all_clients, newclt->hostname);
561
562      if (testclt != NULL)
563        {
564          SH_FREE(testclt->verifier);
565          siz_str = strlen (newclt->verifier) + 1;
566          testclt->verifier = SH_ALLOC (siz_str);
567          sl_strlcpy(testclt->verifier, newclt->verifier, siz_str);
568
569          SH_FREE(testclt->salt);
570          siz_str = strlen (newclt->salt) + 1;
571          testclt->salt = SH_ALLOC (siz_str);
572          sl_strlcpy(testclt->salt, newclt->salt, siz_str);
573
574          testclt->dead_flag = 0;
575             
576          free_client(newclt);
577          SL_RETURN( 0, _("sh_xfer_register_client"));
578        }
579      else
580        {
581          if (0 == zAVLInsert (all_clients, newclt))
582            {
583              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CREG,
584                              newclt->hostname, 
585                              newclt->salt, newclt->verifier);
586              SL_RETURN( 0, _("sh_xfer_register_client"));
587            }
588        }
589    }
590  SL_RETURN (-1, _("sh_xfer_register_client"));
591}
592
593typedef struct {
594  int             state;
595  int             fd;
596  char          * buf;
597  unsigned char   head[SH_HEADER_SIZE];
598  char            challenge[SH_CHALLENGE_SIZE];
599  char            peer[SH_MINIBUF+1];
600  client_t      * client_entry;
601  char          * K;
602  char          * M1;
603  char          * A;
604  int             headcount;
605  unsigned long   bytecount;
606  unsigned long   bytes_to_send;
607  unsigned long   bytes_to_get;
608  int             pass;
609  unsigned long   timer;
610
611  char          * FileName;
612  unsigned long   FileLength;
613  unsigned long   FileSent;
614  char            FileType[5];
615
616  struct sh_sockaddr addr_peer;
617} sh_conn_t;
618
619
620static char zap_challenge[SH_CHALLENGE_SIZE] = { 0 };
621 
622void sh_xfer_do_free (sh_conn_t * conn)
623{
624  SL_ENTER(_("sh_xfer_do_free"));
625
626  if (conn->K != NULL) 
627    {
628      SH_FREE(conn->K);
629      conn->K           = NULL;
630    }
631  if (conn->A != NULL) 
632    {
633      SH_FREE(conn->A);
634      conn->A           = NULL;
635    }
636  if (conn->M1 != NULL) 
637    {
638      SH_FREE(conn->M1);
639      conn->M1           = NULL;
640    }
641  if (conn->buf != NULL) 
642    {
643      SH_FREE(conn->buf);
644      conn->buf          = NULL;
645    }
646  if (conn->fd != (-1))
647    {
648      sl_close_fd (FIL__, __LINE__, conn->fd);
649      conn->fd            = -1;
650    }
651  memcpy(conn->challenge, zap_challenge, SH_CHALLENGE_SIZE);
652  conn->state         = CONN_FREE;
653  conn->headcount     = 0;
654  conn->bytecount     = 0;
655  conn->bytes_to_send = 0;
656  conn->bytes_to_get  = 0;
657  conn->pass          = 0;
658  conn->timer         = 0;
659  conn->client_entry  = NULL;
660
661  if (conn->FileName != NULL) 
662    {
663      SH_FREE(conn->FileName);
664      conn->FileName     = NULL;
665    }
666  conn->FileLength     = 0;
667  conn->FileSent       = 0;
668  conn->FileType[0] = '\0';
669  conn->FileType[1] = '\0';
670  conn->FileType[2] = '\0';
671  conn->FileType[3] = '\0';
672  conn->FileType[4] = '\0';
673
674  --server_status.conn_open;
675 
676  SL_RET0(_("sh_xfer_do_free"));
677}
678
679/****************************************
680 *
681 *   -- Reconfiguration. --
682 *
683 *   (1) Mark all clients as 'dead'.
684 *   (2) Reload configuration - clients
685 *       in config are non-dead now.
686 *   (3) Remove all clients still
687 *       marked as 'dead'.
688 */
689
690/* -- Mark all clients as dead.
691 */
692void sh_xfer_mark_dead (void)
693{
694  zAVLCursor avlcursor;
695  client_t * item;
696
697  SL_ENTER(_("sh_xfer_mark_dead"));
698
699  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
700       item = (client_t *) zAVLNext(&avlcursor))
701    {
702      item->dead_flag = 1;
703    }
704  SL_RET0(_("sh_xfer_mark_dead"));
705}
706
707
708/* -- Clean tree from dead clients.
709 */
710void sh_xfer_clean_tree (void)
711{
712  zAVLCursor avlcursor;
713  client_t * item;
714
715  SL_ENTER(_("sh_xfer_clean_tree"));
716
717 repeat_search:
718
719  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
720       item = (client_t *) zAVLNext(&avlcursor))
721    {
722      if (item->dead_flag == 1)
723        {
724          zAVLDelete (all_clients, item->hostname);
725          free_client (item);
726          goto repeat_search;
727        }
728    }
729  SL_RET0(_("sh_xfer_clean_tree"));
730}
731
732/*
733 *
734 **********************************************/
735
736
737
738/* -- SERVER SEND FUNCTION. --
739 */
740void sh_xfer_prep_send_int (sh_conn_t * conn, 
741                            char * msg, unsigned long length,
742                            char * u, char protocol,
743                            int docrypt)
744{
745  /* register unsigned long i; */
746  unsigned long           length2;
747
748#if !defined(SH_ENCRYPT)
749  (void) docrypt;
750#endif
751
752  SL_ENTER(_("sh_xfer_prep_send_int"));
753
754  TPT((0, FIL__, __LINE__, _("msg=<%s>, docrypt=<%d>\n"), msg, docrypt ));
755
756  length2 = length;
757
758  conn->headcount     = 0;
759  conn->bytecount     = 0;
760  conn->bytes_to_send = 0;
761  conn->bytes_to_get  = 0;
762
763  if (conn->buf != NULL) 
764    {
765      SH_FREE(conn->buf);
766      conn->buf           = NULL;
767    }
768
769  put_header (conn->head, protocol, &length2, u);
770  SH_SHOWPROT(conn->head,'>');
771
772  TPT((0, FIL__, __LINE__, _("msg=<put_header done>\n") ));
773
774  if (msg == NULL) 
775    length2 = 0;
776 
777#ifdef SH_ENCRYPT
778  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0))
779    {
780      TPT((0, FIL__, __LINE__, _("encrypting (version 2)\n")));
781     
782      conn->buf = sh_tools_makePack (conn->head, conn->client_entry->ivst_flag,
783                                     msg, length2,
784                                     &(conn->client_entry->keyInstE));
785    }
786  else if (msg == NULL)
787    {
788      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
789                      _("msg is NULL"), 
790                      _("sh_xfer_prep_send_int: cipherInit"));
791    }
792  else
793    {
794      if ((length2 + 1) < length2) --length2;
795      conn->buf       = SH_ALLOC(length2 + 1);
796
797      memcpy(conn->buf, msg, length2);
798      conn->buf[length2] = '\0';
799      TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
800    }
801#else
802  if ((length2 + 1) < length2) --length2;
803  conn->buf       = SH_ALLOC(length2 + 1);
804
805  memcpy(conn->buf, msg, length2);
806  conn->buf[length2] = '\0';
807  TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
808#endif
809
810  conn->state     = CONN_SENDING;
811  SL_RET0(_("sh_xfer_prep_send_int"));
812}
813
814/* -- Send/Receive. --
815 */
816void sh_xfer_prep_send (sh_conn_t * conn, 
817                           char * msg, unsigned long length,
818                           char * u, char protocol)
819{
820  SL_ENTER(_("sh_xfer_prep_send"));
821  sh_xfer_prep_send_int (conn,  msg, length, u, protocol, S_FALSE);
822  SL_RET0(_("sh_xfer_prep_send"));
823} 
824
825void sh_xfer_send_crypt (sh_conn_t * conn, 
826                                 char * msg, unsigned long length,
827                                 char * u, char protocol)
828{
829  SL_ENTER(_("sh_xfer_send_crypt"));
830  sh_xfer_prep_send_int (conn,  msg, length, u, protocol, S_TRUE);
831  SL_RET0(_("sh_xfer_send_crypt"));
832} 
833
834/* #include <sys/times.h> */
835
836#if defined(WITH_EXTERNAL)
837#include "sh_extern.h"
838#endif
839
840/* -- Update the client status. --
841 *
842 * Update the status array for the client,
843 * and eventually call external program.
844 */
845static void status_update (client_t * conn, int status)
846{ 
847#if defined(WITH_EXTERNAL)
848  char msg[2 * SH_MINIBUF + TIM_MAX + 3];
849#endif
850
851  SL_ENTER(_("status_update"));
852
853  if (conn == NULL || 
854      status < 0   || status >= CLT_MAX)
855    SL_RET0(_("status_update"));
856
857  conn->status_now = status;
858  conn->status_arr[status] = status;
859  (void) sh_unix_time(0, conn->timestamp[status], TIM_MAX);
860
861#if defined(WITH_EXTERNAL)
862  sl_snprintf(msg, sizeof(msg), _("%s %s %s"),
863              conn->hostname, conn->timestamp[status], _(clt_stat[status]));
864  sh_ext_execute('s', 'r', 'v', msg, 0);
865#endif
866
867  SL_RET0(_("status_update"));
868}
869
870static time_t time_client_limit = 86400;
871
872int sh_xfer_set_time_limit (const char * c)
873{
874  long val;
875
876  SL_ENTER(_("sh_xfer_set_time_limit"));
877
878  val = strtol (c, (char **)NULL, 10);
879  if (val <= 0)
880    SL_RETURN( (-1), _("sh_xfer_set_time_limit"));
881
882  time_client_limit = (time_t) val;
883  SL_RETURN( (0), _("sh_xfer_set_time_limit"));
884}
885
886
887/* -- Check for time limit exceeded. --
888 */
889static int client_time_check(void)
890{
891  zAVLCursor avlcursor;
892  client_t * item;
893
894  SL_ENTER(_("client_time_check"));
895
896  if (time_client_limit == (time_t) 0)
897    SL_RETURN( 0, _("client_time_check"));
898
899  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
900       item = (client_t *) zAVLNext(&avlcursor))
901    {
902      if (item->exit_flag == 0 && item->last_connect != (time_t) 0)
903        {
904          if ( (time(NULL) - item->last_connect) > time_client_limit)
905            {
906              if (item->status_now != CLT_TOOLONG)
907                {
908                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMEXC,
909                                  item->hostname);
910                  status_update (item, CLT_TOOLONG);
911                }
912            }
913        }
914    }
915  SL_RETURN( 0, _("client_time_check"));
916}
917
918static int lookup_err = SH_ERR_SEVERE;
919
920int sh_xfer_lookup_level (const char * c)
921{
922  int ci =  sh_error_convert_level (c);
923
924  SL_ENTER(_("sh_xfer_lookup_level"));
925
926  if (ci >= 0)
927    {
928      lookup_err = ci;
929      SL_RETURN( 0, _("sh_xfer_lookup_level"));
930    }
931  else
932    SL_RETURN( (-1), _("sh_xfer_lookup_level"));
933}
934
935#ifndef MAXHOSTNAMELEN
936#define MAXHOSTNAMELEN  127
937#endif
938
939int check_addr (const char * claim, struct sh_sockaddr * addr_peer)
940{
941  char               h_name[MAXHOSTNAMELEN + 1];
942  char               h_peer[MAXHOSTNAMELEN + 1];
943  char               h_peer_IP[SH_IP_BUF];
944  char               tmp_peer_IP[SH_IP_BUF];
945  char             * canonical;
946  char               numeric[SH_IP_BUF];
947
948  SL_ENTER(_("check_addr"));
949
950  if (claim == NULL)
951    {
952      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
953                      _("NULL input"), _("check_addr"));
954      SL_RETURN ((-1), _("check_addr"));
955    }
956
957  /* Make sure we have the canonical name for the client
958   */
959  canonical = sh_ipvx_canonical(claim, numeric, sizeof(numeric));
960
961  /* copy canonical name into h_name
962   */
963  if (canonical != NULL)
964    {
965      sl_strlcpy(h_name, canonical, MAXHOSTNAMELEN + 1);
966      SH_FREE(canonical);
967    }
968  else
969    {
970      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESCLT,
971                      claim);
972      SL_RETURN ((0), _("check_addr"));
973    }
974
975
976  /* get canonical name of socket peer
977   */
978  canonical = sh_ipvx_addrtoname(addr_peer);
979
980  if (canonical)
981    {
982      if (0 == sl_strcmp(canonical, _("localhost")))
983        sl_strlcpy(h_peer, sh.host.name, MAXHOSTNAMELEN + 1);
984      else
985        sl_strlcpy(h_peer, canonical, MAXHOSTNAMELEN + 1);
986      SH_FREE(canonical);
987    }
988  else
989    {
990      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
991      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESPEER,
992                      claim, tmp_peer_IP);
993      SL_RETURN ((0), _("check_addr"));
994    }
995
996  sh_ipvx_ntoa (h_peer_IP, sizeof(h_peer_IP), addr_peer);
997
998  /* reverse lookup
999   */
1000  if (0 == sh_ipvx_reverse_check_ok (h_peer, ServerPort, addr_peer))
1001    {
1002      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
1003
1004      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKERS,
1005                      claim, h_peer, tmp_peer_IP);
1006      SL_RETURN ((0), _("check_addr"));
1007    }
1008
1009  /* Check whether claim and peer are identical
1010   */
1011  sh_tolower(h_peer); /* Canonical name of what the peer is     */
1012  sh_tolower(h_name); /* Canonical name of what the peer claims */
1013
1014  if ((0 == sl_strcmp(h_peer, h_name)) || (0 == sl_strcmp(h_peer_IP, h_name)))
1015    {
1016      SL_RETURN ((0), _("check_addr"));
1017    }
1018#if !defined(USE_IPVX)
1019  else
1020    {
1021      struct hostent   * he = sh_gethostbyname(h_peer);
1022      int                i = 0;
1023      int                flag = 0;
1024
1025      while (he->h_aliases[i] != NULL)
1026        {
1027          if (0 == sl_strcmp(sh_tolower(he->h_aliases[i]), h_name))
1028            {
1029              flag = 1;
1030              break;
1031            }
1032          ++i;
1033        }
1034      if (flag == 0) 
1035        sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKUP,
1036                        claim, h_peer);
1037    }
1038#endif
1039
1040  SL_RETURN ((0), _("check_addr"));
1041}
1042
1043static int UseSocketPeer = S_FALSE;
1044
1045int set_socket_peer (const char * c)
1046{
1047  return sh_util_flagval(c, &UseSocketPeer);
1048}
1049
1050
1051/* -- Search register. --
1052 */
1053client_t * search_register(sh_conn_t * conn, int pos)
1054{
1055  client_t * this_client;
1056  char       peer_ip[SH_IP_BUF];
1057  char       numerical[SH_IP_BUF];
1058  char       peer_name[MAXHOSTNAMELEN+1];
1059  char     * search_string;
1060
1061  struct sh_sockaddr peer_addr;
1062  char             * canonical;
1063
1064  SL_ENTER(_("search_register"));
1065
1066  if (UseSocketPeer == S_TRUE)
1067    {
1068      memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr));
1069      sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr);
1070
1071      /* get canonical name of socket peer
1072       */
1073      canonical = sh_ipvx_canonical(peer_ip, numerical, sizeof(numerical));
1074
1075      if (canonical != NULL)
1076        {
1077          if (0 == sl_strcmp(canonical, _("localhost")))
1078            sl_strlcpy(peer_name, sh.host.name, MAXHOSTNAMELEN + 1);
1079          else
1080            sl_strlcpy(peer_name, canonical,    MAXHOSTNAMELEN + 1);
1081          SH_FREE(canonical);
1082        }
1083
1084      if (0 == sh_ipvx_reverse_check_ok (peer_name, ServerPort, &peer_addr))
1085        {
1086          sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
1087        }
1088
1089      search_string = peer_name;
1090    }
1091  else
1092    {
1093      search_string = &(conn->buf[pos]);
1094
1095      if (0 != check_addr (search_string, &(conn->addr_peer)))
1096        {
1097          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
1098                          _("Reverse lookup failed"), search_string);
1099          sh_xfer_do_free (conn);
1100          SL_RETURN( NULL, _("search_register"));
1101        } 
1102    }
1103
1104  sh_tolower(search_string);
1105
1106  /* ----  search the register  -----
1107   */
1108  this_client = zAVLSearch(all_clients, search_string);
1109
1110  if (this_client == NULL)
1111    {
1112      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
1113                      _("Not in client list"), search_string);
1114      sh_xfer_do_free (conn);
1115      SL_RETURN( NULL, _("search_register"));
1116    } 
1117  if (this_client->exit_flag == 1)
1118    {
1119      TPT((0, FIL__, __LINE__, _("msg=<this_client->exit_flag == 1>\n")));
1120      this_client->session_key_timer = (time_t) 0;
1121      this_client->session_key[0]    = '\0';
1122      this_client->exit_flag         = 0;   
1123    }
1124  TPT((0, FIL__, __LINE__, _("msg=<search_register: client %s>\n"), 
1125       this_client->hostname));
1126  TPT((0, FIL__, __LINE__, _("msg=<search_register: key %s>\n"), 
1127       this_client->session_key));
1128  SL_RETURN( this_client, _("search_register"));
1129} 
1130
1131client_t * do_check_client(sh_conn_t * conn, int * retval)
1132{
1133  client_t * this_client = NULL; 
1134  char sigbuf[KEYBUF_SIZE];
1135 
1136  *retval = 0;
1137
1138  TPT(( 0, FIL__, __LINE__, _("msg=<Client connect - HELO (1).>\n")));
1139         
1140  if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN)
1141    {
1142      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
1143      sh_xfer_do_free (conn);
1144      return NULL;
1145    } 
1146         
1147  /* ----  search the register  -----
1148   */
1149 
1150  this_client = search_register (conn, KEY_LEN);
1151  if (this_client == NULL)
1152    return NULL;
1153 
1154  /* ---- force authentication -----
1155   */
1156 
1157  if (this_client->session_key[0] == '\0' ||
1158      (time(NULL) - this_client->session_key_timer) 
1159      > (time_t) TIMEOUT_KEY )
1160    {
1161      size_t len;
1162
1163      /* fake an auth request and jump there
1164       */
1165      conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
1166      conn->head[3]  = 'S';
1167      conn->head[4]  = 'A';
1168      conn->head[5]  = 'L';
1169      conn->head[6]  = 'T';
1170      if (flag_err_info == S_TRUE)
1171        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
1172                        &(conn->buf[KEY_LEN]));
1173      len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
1174      /* may overlap, thus only memmove is correct */
1175      memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
1176      this_client->session_key[0]    = '\0';
1177      this_client->session_key_timer = (time_t) 1;
1178      *retval = -1;
1179      return NULL;
1180    }
1181
1182  /* --- check whether hostname is properly signed ---
1183   */ 
1184  if (conn->K != NULL) 
1185    {
1186      SH_FREE(conn->K);
1187      conn->K = NULL;
1188    }
1189 
1190  conn->K = SH_ALLOC(KEY_LEN+1);
1191 
1192  sl_strlcpy (conn->K, 
1193              sh_util_siggen(this_client->session_key,
1194                             &(conn->buf[KEY_LEN]),
1195                             sl_strlen(&(conn->buf[KEY_LEN])),
1196                             sigbuf, sizeof(sigbuf)),
1197              KEY_LEN+1);
1198 
1199  if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
1200    {
1201      TPT((0, FIL__, __LINE__, _("msg=<clt %s>\n"), conn->buf));
1202      TPT((0, FIL__, __LINE__, _("msg=<srv %s>\n"), conn->K));
1203      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
1204                      _("Signature mismatch"), 
1205                      &(conn->buf[KEY_LEN]));
1206     
1207      this_client->session_key_timer =
1208        time(NULL) - (2*TIMEOUT_KEY);
1209     
1210      sh_xfer_do_free (conn);
1211      return NULL;
1212    }
1213  SH_FREE(conn->K); 
1214  conn->K = NULL;
1215
1216  return this_client;
1217}
1218
1219/* ------------------------------------------------------
1220 *
1221 *  FILE TRANSFER
1222 *
1223 * ------------------------------------------------------ */
1224
1225static void do_file_send_data(sh_conn_t * conn)
1226{
1227  char     * read_buf = 0;
1228  char     * send_buf;
1229  int        bytes;
1230  SL_TICKET  sfd = -1;
1231#ifdef SH_ENCRYPT
1232  int        blkfac;
1233  int        rem;
1234  int        send_bytes;
1235#endif
1236
1237  if (conn == NULL    || conn->FileName == NULL)
1238    {
1239      sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_TCP_NFILE,
1240                      conn->peer, 
1241                      (conn->FileName == NULL) ? 
1242                      _("(NULL)") : conn->FileName);
1243      status_update (conn->client_entry, CLT_FAILED);
1244      sh_xfer_do_free (conn);
1245      return;
1246    }
1247
1248  if (conn->FileSent == conn->FileLength)
1249    {
1250      send_buf = hash_me(conn->K, conn->peer, sl_strlen(conn->peer));
1251#ifdef SH_ENCRYPT
1252      sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, 
1253                                  _("EEOT"), SH_PROTO_BIG|conn->client_entry->encf_flag);
1254#else
1255      sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, 
1256                                  _("EEOT"), SH_PROTO_BIG);
1257#endif
1258      SH_FREE(send_buf);
1259    }
1260  else
1261    {
1262      bytes = -1;
1263
1264      sfd = sl_open_read(FIL__, __LINE__, conn->FileName, SL_YESPRIV);
1265
1266      if (!SL_ISERROR(sfd))
1267        {
1268          read_buf = SH_ALLOC(TRANS_BYTES);
1269          if (conn->FileSent > 0)
1270            sl_seek (sfd, (off_t) conn->FileSent);
1271          bytes = sl_read (sfd, read_buf, TRANS_BYTES);
1272          sl_close(sfd);
1273        }
1274      else
1275        {
1276          sh_error_handle((-1), FIL__, __LINE__, sfd, 
1277                          MSG_E_ACCESS, (long) geteuid(), conn->FileName);
1278        }
1279
1280      if (bytes >= 0)
1281        {
1282#ifdef SH_ENCRYPT
1283          /* need to send N * B_SIZ bytes
1284           */ 
1285          blkfac = bytes / B_SIZ;
1286          rem    = bytes - (blkfac * B_SIZ);
1287          if (rem != 0)
1288            {
1289              memset(&read_buf[bytes], '\n', (B_SIZ-rem));
1290              ++blkfac;
1291              send_bytes = blkfac * B_SIZ;
1292            }
1293          else
1294            send_bytes = bytes;
1295         
1296          send_buf = hash_me(conn->K, read_buf,  send_bytes);
1297         
1298          sh_xfer_send_crypt (conn, send_buf, send_bytes+KEY_LEN, _("FILE"), 
1299                                      SH_PROTO_BIG|conn->client_entry->encf_flag);
1300#else
1301          send_buf = hash_me(conn->K, read_buf, bytes);
1302          sh_xfer_send_crypt (conn, send_buf, bytes+KEY_LEN, _("FILE"), 
1303                                      SH_PROTO_BIG);
1304#endif
1305          conn->FileSent += bytes;
1306          if (send_buf) /* hash_me() *may* return NULL */
1307            SH_FREE(send_buf);
1308          SH_FREE(read_buf);
1309        }
1310      else
1311        {
1312          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NFILE, conn->peer,
1313                          (conn->FileName == NULL) ? _("(NULL)") : conn->FileName);
1314          status_update (conn->client_entry, CLT_FAILED);
1315          sh_xfer_do_free (conn);
1316        }
1317    }
1318  return;
1319}
1320
1321static void do_file_initial(sh_conn_t * conn)
1322{
1323  char     * ptok;
1324  char       hashbuf[KEYBUF_SIZE];
1325
1326  /* --- get client nonce and compute hash ---
1327   *
1328   *  K = H(NSRV, NCLT, session_key)
1329   */ 
1330  if (conn->A != NULL)
1331    {
1332      SH_FREE(conn->A);
1333      conn->A = NULL;
1334    }
1335  conn->A = SH_ALLOC(3*KEY_LEN+1);
1336  sl_strlcpy (conn->A, conn->K, KEY_LEN+1); 
1337  sl_strlcat(conn->A, conn->buf, /* truncate */
1338             2*KEY_LEN+1);
1339  sl_strlcat(conn->A, conn->client_entry->session_key, 
1340             3*KEY_LEN+1);
1341  sl_strlcpy (conn->K, sh_tiger_hash(conn->A,TIGER_DATA,3*KEY_LEN,
1342                                     hashbuf, sizeof(hashbuf)),
1343              KEY_LEN+1);
1344  SH_FREE(conn->A); 
1345  conn->A = NULL;
1346 
1347
1348  /* Warn about encryption mismatch
1349   */
1350#ifdef SH_ENCRYPT
1351  if ((conn->client_entry->encf_flag != 0) &&  /* server */
1352      ((conn->head[0] & SH_PROTO_ENC) == 0))   /* client */
1353    {
1354      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
1355                      _("file download"), _("version2"), _("none"));
1356    }
1357
1358  else if ((conn->client_entry->encf_flag != 0) && /* server */
1359           ((conn->head[0] & SH_MASK_ENC) !=       /* client */
1360            conn->client_entry->encf_flag))
1361    {
1362      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
1363                      _("file download"), _("version2"),
1364                      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? 
1365                      _("version2") : _("invalid"));
1366      conn->client_entry->encf_flag = (conn->head[0] & SH_MASK_ENC);
1367    }
1368#else
1369  if ((conn->head[0] & SH_PROTO_ENC) != 0) 
1370    {
1371      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
1372                      _("file download"), _("none"), 
1373                      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? 
1374                      _("version2") : _("invalid"));
1375    }
1376#endif
1377 
1378 
1379  if (conn->FileName != NULL)
1380    {
1381      SH_FREE(conn->FileName);
1382      conn->FileName = NULL;
1383    }
1384
1385  /* Determine what to send
1386   */
1387  if (0 == sl_strncmp (_("CONF"), &(conn->buf[KEY_LEN]), 4))
1388    {
1389      strcpy(conn->FileType, _("CONF"));     /* known to fit  */
1390      conn->FileName = get_client_conf_file(conn->peer, &(conn->FileLength));
1391      conn->FileSent = 0;
1392    }
1393  else  if (0 == sl_strncmp (_("DATA"), &(conn->buf[KEY_LEN]), 4))
1394    {
1395      strcpy(conn->FileType, _("DATA"));     /* known to fit  */
1396      conn->FileName = get_client_data_file(conn->peer, &(conn->FileLength));
1397      conn->FileSent = 0;
1398    }
1399  else  if (0 == sh_uuid_check(&(conn->buf[KEY_LEN])))
1400    {
1401      char * uuid = &(conn->buf[KEY_LEN]);
1402      strcpy(conn->FileType, _("UUID"));     /* known to fit  */
1403      conn->FileName = get_client_uuid_file(conn->peer, &(conn->FileLength), uuid);
1404      conn->FileSent = 0;
1405    }
1406  else
1407    {
1408      ptok = sh_util_safe_name(&(conn->buf[KEY_LEN]));
1409      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FFILE,
1410                      conn->peer, 
1411                      ptok);
1412      SH_FREE(ptok);
1413      status_update (conn->client_entry, CLT_FAILED);
1414      sh_xfer_do_free (conn);
1415    }
1416
1417  return;
1418}
1419
1420
1421static int do_file_transfer(sh_conn_t * conn, int state)
1422{
1423  client_t * this_client; 
1424  UINT32     ticks;
1425  char       hashbuf[KEYBUF_SIZE];
1426
1427  SL_ENTER(_("do_file_transfer"));
1428
1429  if (state == SH_DO_READ)        /* finished reading */
1430    {
1431      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
1432     
1433      /* -- Client requests challenge. --
1434       */
1435      if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
1436        {
1437          int client_state;
1438
1439          this_client = do_check_client(conn, &client_state);
1440          if (!this_client)
1441            SL_RETURN(client_state, _("do_file_transfer"));
1442
1443          /* --- create and send a nonce ---
1444           */
1445         
1446          conn->client_entry = this_client;
1447          sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
1448         
1449          ticks = (UINT32) taus_get ();
1450         
1451          if (conn->K != NULL) 
1452            {
1453              SH_FREE(conn->K);
1454              conn->K = NULL;
1455            }
1456          conn->K = SH_ALLOC(KEY_LEN+1);
1457          sl_strlcpy (conn->K, 
1458                      sh_tiger_hash ((char *) &ticks, 
1459                                     TIGER_DATA, sizeof(UINT32), 
1460                                     hashbuf, sizeof(hashbuf)), 
1461                      KEY_LEN+1);
1462         
1463          TPT((0, FIL__, __LINE__, _("msg=<send nonce>\n")));
1464          sh_xfer_prep_send (conn, conn->K, KEY_LEN+1, _("NSRV"), 
1465                                SH_PROTO_BIG);
1466        }
1467
1468      /* --- Client has send a message. Check state and message. ---
1469       */
1470      else if (0 == check_request_nerr((char *)&(conn->head[3]), _("NCLT")) &&
1471               conn->client_entry != NULL                           &&
1472               sl_strlen(conn->buf) > KEY_LEN                       &&
1473               conn->K != NULL)
1474        {
1475         
1476          TPT(( 0, FIL__, __LINE__, 
1477                _("msg=<File transfer - NCLT (3).>\n")));
1478         
1479          do_file_initial(conn);
1480          do_file_send_data(conn);
1481        }
1482     
1483      else if (0 == check_request_nerr((char *)&(conn->head[3]), 
1484                                       _("RECV"))                    &&
1485               conn->client_entry != NULL                           &&
1486               conn->K != NULL                                      &&
1487               conn->FileName != NULL)
1488        {
1489         
1490          TPT(( 0, FIL__, __LINE__, 
1491                _("msg=<File transfer - RCVT (5+).>\n")));
1492         
1493          do_file_send_data(conn);
1494        }
1495     
1496     
1497      else if (0 == check_request_nerr((char *)&(conn->head[3]), 
1498                                       _("EOTE")) &&
1499               conn->client_entry != NULL)
1500        {
1501         
1502          TPT(( 0, FIL__, __LINE__, 
1503                _("msg=<File transfer - EOTE (7).>\n")));
1504         
1505          if (flag_err_info == S_TRUE)
1506            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKFILE,
1507                            conn->peer);
1508         
1509          if ((conn->client_entry->status_now != CLT_SUSPEND) &&
1510              (conn->client_entry->status_now != CLT_TOOLONG))
1511            { status_update (conn->client_entry, CLT_FILE); }
1512          else
1513            { conn->client_entry->session_key[0]    = '\0'; }
1514          conn->client_entry->last_connect = time (NULL);
1515          sh_xfer_do_free (conn);
1516        }
1517     
1518     
1519      /* client does something unexpected
1520       */
1521      else  /* ---- ??? ----- */
1522        {
1523          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
1524                          1, conn->pass, conn->peer, 
1525                          '\\', conn->head[3], '\\',conn->head[4],
1526                          '\\', conn->head[5], '\\',conn->head[6]);
1527          status_update (conn->client_entry, CLT_FAILED);
1528          sh_xfer_do_free (conn);
1529        }
1530    }
1531 
1532  else if (state == SH_DO_WRITE)  /* finished writing */
1533    {
1534      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - (wait).>\n")));
1535     
1536      /* challenge is sent, now wait for message from client
1537       */
1538      conn->headcount     = 0;
1539      conn->bytecount     = 0;
1540      conn->bytes_to_send = 0;
1541      conn->bytes_to_get  = 0;
1542      if (conn->buf != NULL) 
1543        {
1544          SH_FREE(conn->buf);
1545          conn->buf           = NULL;
1546        }
1547      conn->state     = CONN_READING;
1548    }
1549  SL_RETURN(0, _("do_file_transfer"));
1550}
1551
1552/* ------------------------------------------------------
1553 *
1554 *  MESSAGE TRANSFER
1555 *
1556 * ------------------------------------------------------ */
1557static int do_message_transfer(sh_conn_t * conn, int state)
1558{
1559  client_t * this_client; 
1560  char     * cmd;
1561  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
1562  char     * buffer;
1563  int        clt_sev;
1564  char     * ptok;
1565  UINT32     ticks;
1566  size_t     len;
1567  int        i;
1568  char     * test;
1569  char       sigbuf[KEYBUF_SIZE];
1570
1571  SL_ENTER(_("do_message_transfer"));
1572
1573  if (state == SH_DO_READ)        /* finished reading */
1574    {
1575      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
1576     
1577      /* -- Client requests challenge. --
1578       */
1579      if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
1580        {
1581          int client_state;
1582         
1583          this_client = do_check_client(conn, &client_state);
1584          if (!this_client)
1585            SL_RETURN(client_state, _("do_message_transfer"));
1586         
1587         
1588          /* -- create a nonce and send it --
1589           */
1590          conn->client_entry = this_client;
1591          sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
1592         
1593          ticks = (UINT32) taus_get ();
1594         
1595          test = (char *) &ticks;
1596          sh_util_cpylong (conn->challenge, test, 4);
1597          conn->challenge[4] = '\0';
1598          for (i = 0; i < 4; ++i)
1599            if (conn->challenge[i] == '\0')
1600              conn->challenge[i] = 0x01;
1601     
1602          sh_xfer_prep_send (conn, conn->challenge, 5, _("TALK"), 
1603                                SH_PROTO_MSG);
1604          TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s.>\n"), 
1605                hu_trans(conn->challenge)));
1606        }
1607     
1608      /* Client has send a message. Check whether we are in proper
1609       * state, and verify message.
1610       */
1611      else if (0 == 
1612               check_request_nerr((char *)&(conn->head[3]), _("MESG")) &&
1613               conn->client_entry != NULL                           &&
1614               conn->client_entry->session_key[0] != '\0'           &&
1615               (len = sl_strlen(conn->buf) - KEY_LEN) > 0           &&
1616               sl_strlen(conn->challenge) == 4)
1617        {
1618          TPT(( 0, FIL__, __LINE__, 
1619                _("msg=<Message transfer - MESG (3).>\n")));
1620         
1621#ifdef SH_ENCRYPT
1622          if (conn->client_entry->encf_flag == 0) {
1623            conn->client_entry->ency_flag = 0;
1624          }
1625          if ((conn->client_entry->ency_flag != 0) && 
1626              ((conn->head[0] & SH_PROTO_ENC) == 0)) 
1627            {
1628              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
1629                              _("message transfer"), 
1630                              _("version2"),
1631                              _("none"));
1632            }
1633          else if ((conn->client_entry->ency_flag != 0) &&
1634                   ((conn->head[0] & SH_MASK_ENC) != 
1635                    conn->client_entry->ency_flag))
1636            {
1637              sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
1638                              MSG_TCP_MISENC,
1639                              _("message transfer"), 
1640                              _("version2"),
1641                              ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid"));
1642              conn->client_entry->ency_flag = 
1643                (conn->head[0] & SH_MASK_ENC); 
1644            }
1645#else
1646          if ((conn->head[0] & SH_PROTO_ENC) != 0) 
1647            {
1648              sh_error_handle((-1), FIL__, __LINE__, 0, 
1649                              MSG_TCP_MISENC,
1650                              _("message transfer"), 
1651                              _("none"), 
1652                              ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid"));
1653            }
1654#endif
1655         
1656          TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
1657          /* get hash from message end, truncate message
1658           */
1659          sl_strlcpy(hash, &(conn->buf[len]), KEY_LEN+1);
1660          conn->buf[len] = '\0';
1661         
1662          /* verify hash
1663           */
1664          buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL);
1665          i =  sl_strncmp(hash, 
1666                          sh_util_siggen(conn->client_entry->session_key,
1667                                         buffer,
1668                                         sl_strlen(buffer),
1669                                         sigbuf, sizeof(sigbuf)),
1670                          KEY_LEN);
1671          TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
1672               sh_util_siggen(conn->client_entry->session_key,
1673                              buffer,
1674                              sl_strlen(buffer),
1675                              sigbuf, sizeof(sigbuf))));
1676         
1677         
1678          if (0 != i)
1679            {
1680              TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1681              status_update (conn->client_entry, CLT_FAILED);
1682              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
1683                              _("Msg signature mismatch"), conn->peer);
1684              conn->client_entry->session_key_timer = 
1685                time(NULL) - (2*TIMEOUT_KEY);
1686              sh_xfer_do_free (conn);
1687              SL_RETURN(0, _("do_message_transfer"));
1688            }
1689          else
1690            {
1691              conn->client_entry->last_connect = time (NULL);
1692             
1693              if (NULL != sl_strstr(conn->buf,      _("EXIT")))
1694                {
1695                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1696                  conn->client_entry->exit_flag = 1;
1697                  status_update (conn->client_entry, CLT_EXITED);
1698                }
1699              else if (NULL != sl_strstr(conn->buf, _("PANIC")))
1700                {
1701                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1702                  status_update (conn->client_entry, CLT_PANIC);
1703                }
1704              else if (NULL != sl_strstr(conn->buf, _("SUSPEND")))
1705                {
1706                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1707                  status_update (conn->client_entry, CLT_SUSPEND);
1708                }
1709              else if (NULL != sl_strstr(conn->buf, _("POLICY")))
1710                {
1711                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1712                  status_update (conn->client_entry, CLT_POLICY);
1713                }
1714              else if (NULL != sl_strstr(conn->buf, 
1715                                         _("File check completed")))
1716                {
1717                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1718                  status_update (conn->client_entry, CLT_CHECK);
1719                }
1720              else if (NULL != sl_strstr(conn->buf, _("START")))
1721                {
1722                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1723                  sh_socket_add2reload (conn->client_entry->hostname);
1724                  if (conn->client_entry->status_now == CLT_SUSPEND) {
1725                    status_update (conn->client_entry, CLT_ILLEGAL);
1726                    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
1727                                    conn->peer);
1728                  }
1729                  else
1730                    status_update (conn->client_entry, CLT_STARTED);
1731                }
1732              else
1733                {
1734                  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
1735                  if (NULL != sl_strstr(conn->buf, 
1736                                        _("Runtime configuration reloaded")))
1737                    {
1738                      sh_socket_add2reload (conn->client_entry->hostname);
1739                    }
1740                  status_update (conn->client_entry, CLT_MSG);
1741                }
1742             
1743              TPT((0, FIL__, __LINE__, _("msg=<status updated>\n")));
1744              clt_sev   = atoi(conn->buf);
1745              clt_class = (-1);
1746              ptok    = strchr(conn->buf, '?');
1747              if (ptok != NULL)
1748                {
1749                  ++ptok;
1750                  if (ptok != NULL && sh.flag.client_class == S_TRUE) 
1751                    clt_class = atoi(ptok);  /* is a global */
1752                  ptok = strchr(ptok, '?');
1753                  if (ptok != NULL) 
1754                    ++ptok;
1755                }
1756              if (sh.flag.client_severity == S_FALSE)
1757                clt_sev = (-1);
1758             
1759              /* here we expect an xml formatted message, thus we don't
1760                 escape xml special chars (flag == 0) */
1761              ptok = 
1762                sh_tools_safe_name ((ptok!=NULL) ? ptok : conn->buf, 0);
1763             
1764              /* push client name to error routine
1765               */
1766#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
1767              {
1768                char peer_ip[SH_IP_BUF];
1769                sh_ipvx_ntoa(peer_ip, sizeof(peer_ip), &(conn->addr_peer)); 
1770                sh_error_set_peer_ip( peer_ip );
1771              }                       
1772#endif
1773              {
1774                char * pstrip = sh_strip_domain (conn->peer);
1775                sh_error_set_peer(pstrip);
1776                sh_error_handle(clt_sev, FIL__, __LINE__, 0, MSG_TCP_MSG,
1777                                pstrip, 
1778                                ptok);
1779                SH_FREE(pstrip);
1780                sh_error_set_peer(NULL);
1781              }
1782#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
1783              sh_error_set_peer_ip(NULL);
1784#endif
1785             
1786              TPT((0, FIL__, __LINE__, _("msg=<%s>\n"), ptok));
1787              SH_FREE(ptok);
1788              clt_class = (-1);
1789            }
1790          memset(buffer, '\0', sl_strlen(buffer));
1791          SH_FREE(buffer);
1792         
1793          /* SERVER CONF SEND
1794           */
1795          buffer = sh_util_strconcat(conn->buf,
1796                                     conn->challenge,
1797                                     NULL);
1798          sl_strlcpy(hash, 
1799                     sh_util_siggen ( conn->client_entry->session_key,
1800                                      buffer,
1801                                      sl_strlen(buffer),
1802                                      sigbuf, sizeof(sigbuf)),
1803                     KEY_LEN+1);
1804         
1805          /* --- SERVER CMD --- */
1806          cmd = sh_socket_check (conn->peer);
1807         
1808          if (cmd != NULL)
1809            {
1810              /* max cmd size is SH_MAXMSGLEN bytes
1811               */
1812              sl_strlcpy(&hash[KEY_LEN], cmd, SH_MAXMSGLEN);
1813              sl_strlcat(&hash[KEY_LEN],
1814                         sh_util_siggen ( conn->client_entry->session_key,
1815                                          &hash[KEY_LEN],
1816                                          sl_strlen(&hash[KEY_LEN]),
1817                                          sigbuf, sizeof(sigbuf)),
1818                         SH_MAXMSGLEN+KEY_LEN+1);
1819             
1820              TPT((0, FIL__, __LINE__, _("CONF SEND <0> <%s>\n"), 
1821                   &hash[KEY_LEN]));
1822             
1823            } else {
1824           
1825            TPT((0, FIL__, __LINE__, _("CONF SEND <0> <[NULL]>\n")));
1826           
1827          }
1828          /* --- SERVER CMD END --- */
1829         
1830          TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
1831               sh_util_siggen(conn->client_entry->session_key,
1832                              buffer,
1833                              sl_strlen(buffer),
1834                              sigbuf, sizeof(sigbuf))));
1835         
1836#ifdef SH_ENCRYPT
1837          sh_xfer_send_crypt (conn, hash, 
1838                              sl_strlen(hash) /* KEY_LEN */, 
1839                              _("CONF"), 
1840                              SH_PROTO_MSG|SH_PROTO_END|conn->client_entry->ency_flag);
1841#else
1842          sh_xfer_send_crypt (conn, hash, 
1843                              sl_strlen(hash) /* KEY_LEN */, 
1844                              _("CONF"), 
1845                              SH_PROTO_MSG|SH_PROTO_END);
1846#endif
1847         
1848          memset(buffer, '\0', sl_strlen(buffer));
1849          SH_FREE(buffer);
1850         
1851          /* sh_xfer_do_free (conn); */
1852        }
1853     
1854      /* client does something unexpected
1855       */
1856      else  /* ---- ??? ----- */
1857        {
1858          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
1859                          2, conn->pass, conn->peer, 
1860                          '\\', conn->head[3], '\\',conn->head[4],
1861                          '\\', conn->head[5], '\\',conn->head[6]);
1862          status_update (conn->client_entry, CLT_FAILED);
1863          conn->client_entry->session_key_timer = 
1864            time(NULL) - (2*TIMEOUT_KEY);
1865          sh_xfer_do_free (conn);
1866        }
1867    }
1868
1869  else if (state == SH_DO_WRITE)  /* finished writing */
1870    {
1871      if (0 != (conn->head[0] & SH_PROTO_END))
1872        {
1873          if (flag_err_debug == S_TRUE)
1874            {
1875              char * pstrip = sh_strip_domain (conn->peer);
1876              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKMSG,
1877                              pstrip);
1878              SH_FREE(pstrip);
1879            }
1880          sh_xfer_do_free (conn);
1881          SL_RETURN(0, _("do_message_transfer"));
1882        }
1883     
1884      TPT(( 0, FIL__, __LINE__, _("msg=<Msg transfer - (wait).>\n")));
1885     
1886      /* challenge is sent, now wait for message from client
1887       */
1888      conn->headcount     = 0;
1889      conn->bytecount     = 0;
1890      conn->bytes_to_send = 0;
1891      conn->bytes_to_get  = 0;
1892      if (conn->buf != NULL) 
1893        {
1894          SH_FREE(conn->buf);
1895          conn->buf           = NULL;
1896        }
1897      conn->state     = CONN_READING;
1898    }
1899  TPT((0, FIL__, __LINE__, _("msg=<return>\n") ));
1900  SL_RETURN(0, _("do_message_transfer"));
1901}
1902
1903/* ------------------------------------------------------
1904 *
1905 *  AUTHENTICATION
1906 *
1907 * ------------------------------------------------------ */
1908
1909static void check_probe(sh_conn_t * conn)
1910{
1911  if (conn && conn->client_entry)
1912    {
1913      /* If client has sent probe, change ivst_flag and clear probe in head[0].
1914       */
1915      conn->head[0] = sh_tools_probe_store(conn->head[0], 
1916                                           &(conn->client_entry->ivst_flag));
1917    }
1918}
1919
1920client_t * do_auth_start(sh_conn_t * conn)
1921{
1922  client_t * this_client;
1923
1924  TPT((0, FIL__, __LINE__, 
1925       _("msg=<Authentication - SALT (1).>\n")));
1926 
1927  if (conn->buf == NULL || sl_strlen(conn->buf) == 0)
1928    {
1929      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
1930      sh_xfer_do_free (conn);
1931      return NULL;
1932    } 
1933                 
1934  /* search the register
1935   */
1936 
1937  this_client = search_register (conn, 0);
1938  if (NULL == this_client)
1939    return NULL;
1940   
1941  conn->client_entry = this_client;
1942  sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
1943 
1944  if (0 != check_request_s((char *)&(conn->head[3]), 
1945                           _("SALT"),conn->peer))
1946    {
1947      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
1948                      _("No salt requested"), conn->peer);
1949      status_update (conn->client_entry, CLT_FAILED);
1950      conn->client_entry->session_key_timer = 
1951        time(NULL) - (2*TIMEOUT_KEY);
1952      sh_xfer_do_free (conn);
1953      return NULL;
1954    }
1955
1956  check_probe(conn);
1957  return this_client;
1958}
1959
1960#if !defined(USE_SRP_PROTOCOL)
1961
1962int do_auth(sh_conn_t * conn)
1963{
1964  client_t * this_client; 
1965  UINT32     ticks;
1966  char       u[5] = "OOOO";
1967#ifdef SH_ENCRYPT
1968  int        err_num;
1969  char expbuf[SH_ERRBUF_SIZE];
1970#endif
1971  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
1972  char hashbuf[KEYBUF_SIZE];
1973
1974  /* first pass -- client request salt 
1975   */
1976  if (conn->pass    == 1) 
1977    {
1978      this_client = do_auth_start(conn);
1979
1980      if (!this_client)
1981        return -1;
1982
1983      /* -- create server nounce v --
1984       */
1985      ticks = (UINT32) taus_get ();
1986     
1987      if (conn->A != NULL)
1988        {
1989          SH_FREE(conn->A);
1990          conn->A = NULL;
1991        }
1992      conn->A = SH_ALLOC(KEY_LEN+1);
1993     
1994      sl_strlcpy(conn->A, 
1995                 sh_tiger_hash((char *) &ticks, 
1996                               TIGER_DATA, sizeof(UINT32), 
1997                               hashbuf, sizeof(hashbuf)),
1998                 KEY_LEN+1);
1999      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
2000     
2001      if (conn->M1 != NULL)
2002        {
2003          SH_FREE(conn->M1);
2004          conn->M1 = NULL;
2005        }
2006      conn->M1 = SH_ALLOC(2*KEY_LEN+1);
2007     
2008      /* compute hash key H(v(server), P)v(server)
2009       */
2010      sh_passwd (conn->A, conn->client_entry->verifier, 
2011                 NULL, conn->M1);
2012     
2013      sl_strlcat(conn->M1, conn->A, 2*KEY_LEN+1);
2014     
2015     
2016      /* --- send H(v(server), P)v(server) ----
2017       */
2018      sh_xfer_prep_send (conn, 
2019                            conn->M1, 
2020                            sl_strlen(conn->M1), 
2021                            u, 
2022                            (conn->head[0]|SH_PROTO_SRP));
2023     
2024      SH_FREE(conn->M1); 
2025      conn->M1 = NULL;
2026    }
2027 
2028  /* client -- third pass
2029   * Message is H(H(u,v),P)u
2030   *
2031   * A := v, verifier := H(password),
2032   */
2033  else if (conn->pass    == 3                   && 
2034           conn->client_entry != NULL)
2035    {
2036     
2037      TPT((0, FIL__, __LINE__, 
2038           _("msg=<Authentication - PASS (3).>\n")));
2039     
2040      if (0 != check_request_s((char *) &(conn->head[3]), _("PASS"), 
2041                               conn->peer)                    ||
2042          sl_strlen(conn->buf) <= KEY_LEN                        ||
2043          conn->A == NULL)
2044        {
2045          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2046                          _("Invalid client request"), conn->peer);
2047          status_update (conn->client_entry, CLT_FAILED);
2048          conn->client_entry->session_key_timer = 
2049            time(NULL) - (2*TIMEOUT_KEY);
2050          sh_xfer_do_free (conn);
2051          return -1;
2052        } 
2053
2054      check_probe(conn);
2055
2056      /* store random nonce u from client
2057       */
2058      if (conn->K != NULL)
2059        {
2060          SH_FREE(conn->K);
2061          conn->K = NULL;
2062        }
2063      conn->K = SH_ALLOC(KEY_LEN+1);
2064      sl_strlcpy(conn->K, &(conn->buf[KEY_LEN]), KEY_LEN+1);
2065     
2066      /* verify random nonce u from client
2067       */
2068      if (conn->M1 != NULL)
2069        {
2070          SH_FREE(conn->M1);
2071          conn->M1 = NULL;
2072        }
2073      conn->M1 = sh_util_strconcat(conn->K, conn->A, NULL);
2074     
2075      TPT((0, FIL__, __LINE__, _("msg=<c/r: K = %s>\n"), conn->K));
2076      TPT((0, FIL__, __LINE__, _("msg=<c/r: A = %s>\n"), conn->A));
2077      TPT((0, FIL__, __LINE__, _("msg=<c/r: M = %s>\n"), conn->M1));
2078     
2079      sl_strlcpy(hash, sh_tiger_hash (conn->M1, 
2080                                      TIGER_DATA, 
2081                                      sl_strlen(conn->M1),
2082                                      hashbuf, sizeof(hashbuf)), 
2083                 KEY_LEN+1); 
2084      sh_passwd (hash, conn->client_entry->verifier, NULL, conn->M1);
2085     
2086      TPT((0, FIL__, __LINE__, _("msg=<c/r: H = %s>\n"), hash));
2087      TPT((0, FIL__, __LINE__, _("msg=<c/r: P = %s>\n"), conn->M1));
2088     
2089      if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN))
2090        {
2091          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2092                          _("Session key mismatch"), conn->peer);
2093          status_update (conn->client_entry, CLT_FAILED);
2094          conn->client_entry->session_key_timer = 
2095            time(NULL) - (2*TIMEOUT_KEY);
2096          sh_xfer_do_free (conn);
2097          return -1;
2098        } 
2099     
2100      /* ---- compute hash key H(v, P, u) ----
2101       */
2102      sh_passwd (conn->A, conn->client_entry->verifier, conn->K,
2103                 conn->M1);
2104     
2105      sl_strlcpy(conn->client_entry->session_key, 
2106                 conn->M1, KEY_LEN+1);
2107      TPT((0, FIL__, __LINE__, _("msg=<c/r: Key = %s>\n"), 
2108           conn->client_entry->session_key));
2109     
2110#ifdef SH_ENCRYPT
2111      err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), 
2112                                 DIR_ENCRYPT, 192, 
2113                                 conn->client_entry->session_key);
2114      if (err_num < 0)
2115        sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2116                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
2117                        _("check_protocol: makeKey"));
2118      err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), 
2119                                 DIR_DECRYPT, 192, 
2120                                 conn->client_entry->session_key);
2121      if (err_num < 0)
2122        sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2123                        errorExplain(err_num, expbuf, sizeof(expbuf)), 
2124                        _("check_protocol: makeKey"));
2125#endif
2126     
2127      if (conn->!= NULL) SH_FREE (conn->K);
2128      conn->= NULL;
2129      if (conn->!= NULL) SH_FREE (conn->A);
2130      conn->= NULL;
2131      if (conn->M1 != NULL) SH_FREE (conn->M1);
2132      conn->M1 = NULL;
2133     
2134      /* if (conn->client_entry->status_now == CLT_STARTED */
2135      if (((conn->client_entry->status_now != CLT_INACTIVE) &&
2136           (conn->client_entry->status_now != CLT_EXITED)   &&
2137           (conn->client_entry->status_now != CLT_SUSPEND))
2138          && conn->client_entry->session_key_timer > (time_t) 1)
2139        {
2140          status_update (conn->client_entry, CLT_ILLEGAL);
2141          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
2142                          conn->peer);
2143        }
2144      else if (conn->client_entry->session_key_timer == (time_t) 0)
2145        {
2146          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW,
2147                          conn->peer);
2148          if (conn->client_entry->status_now != CLT_SUSPEND)
2149            status_update (conn->client_entry, CLT_STARTED);
2150        }
2151     
2152      conn->client_entry->session_key_timer = time (NULL);
2153      conn->client_entry->last_connect = time (NULL);
2154     
2155      /* put in read state
2156       */
2157      sh_xfer_prep_send (conn, 
2158                            _("AUTH"),
2159                            5, 
2160                            _("AUTH"), 
2161                            (conn->head[0]|SH_PROTO_SRP));
2162     
2163    }
2164  else
2165    {
2166      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
2167                      3, conn->pass, conn->peer, 
2168                      '\\', conn->head[3], '\\', conn->head[4],
2169                      '\\', conn->head[5], '\\', conn->head[6]);
2170      sh_xfer_do_free (conn);
2171    }
2172  return 0;
2173}
2174
2175#else
2176
2177static void noise()
2178{
2179  UINT32 n = taus_get();
2180  retry_msleep(0, (n & 0x0000007F));
2181  return;
2182}
2183 
2184/* use SRP */
2185
2186int do_auth(sh_conn_t * conn)
2187{
2188  client_t * this_client; 
2189  UINT32     ticks;
2190  char       u[5] = "OOOO";
2191#ifdef SH_ENCRYPT
2192  int        err_num;
2193  char expbuf[SH_ERRBUF_SIZE];
2194#endif
2195  size_t     len;
2196  char     * test;
2197  char     * foo_B;
2198  char     * foo_Ss;
2199  char hashbuf[KEYBUF_SIZE];
2200
2201  /* use SRP                   
2202   */
2203  if (conn->pass == 1)
2204    {
2205      this_client = do_auth_start(conn);
2206      if (!this_client)
2207        return -1;
2208
2209      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
2210      sh_xfer_prep_send (conn, 
2211                            conn->client_entry->salt, 
2212                            sl_strlen(conn->client_entry->salt), 
2213                            u, 
2214                            (conn->head[0]|SH_PROTO_SRP));
2215    }
2216
2217  /* client has sent A -- third pass
2218   */
2219  else if (conn->pass == 3                    && 
2220           conn->client_entry != NULL)
2221    {
2222     
2223      TPT((0, FIL__, __LINE__, 
2224           _("msg=<Authentication - PC01 (3).>\n")));
2225     
2226      if (0 != check_request_s((char *)&(conn->head[3]),_("PC01"),conn->peer)||
2227          conn->buf == NULL
2228          )
2229        {
2230          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2231                          _("Invalid client request"), conn->peer);
2232          status_update (conn->client_entry, CLT_FAILED);
2233          conn->client_entry->session_key_timer = 
2234            time(NULL) - (2*TIMEOUT_KEY);
2235          sh_xfer_do_free (conn);
2236          return -1;
2237        } 
2238     
2239      check_probe(conn); noise();
2240
2241      if (0 != sh_srp_init())
2242        {
2243          status_update (conn->client_entry, CLT_FAILED);
2244          sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
2245                          MSG_TCP_EBGN);
2246          sh_xfer_do_free (conn);
2247          return -1;
2248        }
2249     
2250     
2251      /* check A, only send B if correct
2252       */
2253      if ( sl_strlen(conn->buf) < SH_BUFSIZE && 
2254           0 == sh_srp_check_zero (conn->buf) )
2255        {
2256          len = sl_strlen(conn->buf)+1;
2257         
2258          if (conn->A != NULL)
2259            {
2260              SH_FREE(conn->A);
2261              conn->A = NULL;
2262            }
2263          conn->A = SH_ALLOC(len);
2264          sl_strlcpy (conn->A, conn->buf, len);
2265         
2266          /*
2267           * compute B
2268           */
2269          if (0 != sh_srp_make_a ())     /* b        random number */
2270            {
2271              status_update (conn->client_entry, CLT_FAILED);
2272             
2273              sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
2274                              MSG_TCP_EBGN);
2275              sh_srp_exit();
2276              sh_xfer_do_free (conn);
2277              return -1;
2278            }
2279         
2280          foo_B = sh_srp_B               /* B = v + g^b            */
2281            (conn->client_entry->verifier);
2282         
2283          if (foo_B == NULL)
2284            {
2285              status_update (conn->client_entry, CLT_FAILED);
2286             
2287              sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
2288                              MSG_TCP_EBGN);
2289              sh_srp_exit();
2290              sh_xfer_do_free (conn);
2291              return -1;
2292            }
2293         
2294          TPT((0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), conn->A));
2295          TPT((0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), foo_B));
2296         
2297          /*
2298           * create nonce u
2299           */
2300          ticks = (UINT32) taus_get ();
2301         
2302          test = (char *) &ticks;
2303          sh_util_cpylong (u, test, 4);  /* u        nounce        */
2304          u[4] = '\0';
2305          sl_strlcpy(conn->challenge, 
2306                     sh_tiger_hash(u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)),
2307                     SH_CHALLENGE_SIZE);
2308         
2309          TPT((0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), u[0], u[1], u[2], u[3]));
2310          TPT((0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
2311               conn->challenge));
2312         
2313          /*
2314           * compute the session key K and M1 = Hash(A,B,K)
2315           */
2316          foo_Ss = sh_srp_S_s (conn->challenge, 
2317                               conn->A, 
2318                               conn->client_entry->verifier);
2319         
2320          if (foo_Ss == NULL || 0 != sh_srp_check_zero (foo_Ss))
2321            {
2322              status_update (conn->client_entry, CLT_FAILED);
2323             
2324              sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
2325                              MSG_TCP_EBGN);
2326              sh_srp_exit();
2327              sh_xfer_do_free (conn);
2328              return -1;
2329            }
2330         
2331          if (conn->K != NULL)
2332            {
2333              SH_FREE(conn->K);
2334              conn->K = NULL;
2335            }
2336          conn->K = SH_ALLOC(KEY_LEN+1);
2337          sl_strlcpy(conn->K, 
2338                     sh_tiger_hash(foo_Ss, TIGER_DATA, 
2339                                   sl_strlen(foo_Ss), 
2340                                   hashbuf, sizeof(hashbuf)),
2341                     KEY_LEN+1);
2342         
2343          if (conn->M1 != NULL)
2344            {
2345              SH_FREE(conn->M1);
2346              conn->M1 = NULL;
2347            }
2348          conn->M1 = SH_ALLOC(KEY_LEN+1);
2349          sh_srp_M (conn->A, foo_B, conn->K, conn->M1, KEY_LEN+1);
2350         
2351          TPT((0, FIL__, __LINE__, _("msg=<srp:Ss = %s>\n"), foo_Ss));
2352          TPT((0, FIL__, __LINE__, _("msg=<srp: K = %s>\n"), conn->K));
2353          TPT((0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"),conn->M1));
2354         
2355          /*
2356           * send B
2357           */
2358          sh_xfer_prep_send (conn, 
2359                                foo_B,
2360                                sl_strlen(foo_B)+1,
2361                                u,
2362                                (conn->head[0]|SH_PROTO_SRP));
2363          if (foo_Ss != NULL)
2364            {
2365              SH_FREE(foo_Ss);
2366              foo_Ss = NULL;
2367            }
2368          if (foo_B  != NULL)
2369            {
2370              SH_FREE(foo_B);
2371              foo_B = NULL;
2372            }
2373        }
2374      else
2375        {
2376          status_update (conn->client_entry, CLT_FAILED);
2377         
2378          sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
2379                          MSG_TCP_EZERO);
2380          sh_xfer_do_free (conn);
2381        }
2382     
2383      sh_srp_exit();
2384    }
2385 
2386  /* client has sent M1 -- fifth pass
2387   */
2388  else if (conn->pass    == 5           && 
2389           conn->client_entry != NULL) 
2390    {
2391      TPT((0, FIL__, __LINE__, 
2392           _("msg=<Authentication - PC02 (5).>\n")));
2393     
2394      /* check that the state is valid
2395       */
2396      if (0 != check_request_s((char *)&(conn->head[3]), _("PC02"),
2397                               conn->peer)                   ||
2398          conn->A == NULL || conn->K == NULL || conn->M1 == NULL)
2399        {
2400          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2401                          _("Invalid client request"), conn->peer);
2402          status_update (conn->client_entry, CLT_FAILED);
2403          conn->client_entry->session_key_timer = 
2404            time(NULL) - (2*TIMEOUT_KEY);
2405          sh_xfer_do_free (conn);
2406          return -1;
2407        } 
2408
2409      check_probe(conn); noise();
2410
2411      /* ------ verify M1 = H(A,  B, K) -------
2412       * -----    send M2 = H(A, M1, K) -------
2413       */
2414      if (conn->buf != NULL && 
2415          sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
2416        {
2417          /*
2418           * send M2
2419           */
2420          char M_buf[KEY_LEN+1];
2421          sh_xfer_prep_send (conn, 
2422                                sh_srp_M (conn->A, conn->M1, conn->K,
2423                                          M_buf, sizeof(M_buf)),
2424                                KEY_LEN+1,
2425                                _("PARP"),
2426                                (conn->head[0]|SH_PROTO_SRP));
2427         
2428          if (conn->!= NULL) SH_FREE(conn->A);  conn->= NULL;
2429          if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL;
2430          sl_strlcpy(conn->client_entry->session_key, 
2431                     conn->K, KEY_LEN+1);
2432          TPT((0, FIL__, __LINE__, _("msg=<key %s>\n"), 
2433               conn->client_entry->session_key));
2434         
2435#ifdef SH_ENCRYPT
2436          err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), 
2437                                     DIR_ENCRYPT, 192, 
2438                                     conn->client_entry->session_key);
2439          if (err_num < 0)
2440            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2441                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
2442                            _("sh_xfer_prep_send_int: makeKey"));
2443          err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), 
2444                                     DIR_DECRYPT, 192, 
2445                                     conn->client_entry->session_key);
2446          if (err_num < 0)
2447            sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
2448                            errorExplain(err_num, expbuf, sizeof(expbuf)), 
2449                            _("sh_xfer_prep_send_int: makeKey"));
2450#endif
2451         
2452          if (conn->!= NULL) SH_FREE(conn->K);  conn->= NULL;
2453         
2454          conn->client_entry->last_connect = time (NULL);
2455         
2456          if (((conn->client_entry->status_now != CLT_INACTIVE) &&
2457               (conn->client_entry->status_now != CLT_EXITED)   &&
2458               (conn->client_entry->status_now != CLT_SUSPEND))
2459              && conn->client_entry->session_key_timer > (time_t) 1)
2460            {
2461              status_update (conn->client_entry, CLT_ILLEGAL);
2462             
2463              sh_error_handle((-1), FIL__, __LINE__, 0, 
2464                              MSG_TCP_ILL,
2465                              conn->peer);
2466            }
2467          else if (conn->client_entry->session_key_timer == (time_t) 0)
2468            {
2469              sh_error_handle((-1), FIL__, __LINE__, 0, 
2470                              MSG_TCP_NEW,
2471                              conn->peer);
2472              if (conn->client_entry->status_now != CLT_SUSPEND)
2473                status_update (conn->client_entry, CLT_STARTED);
2474            }
2475          conn->client_entry->session_key_timer = time (NULL);
2476         
2477        }
2478      else
2479        {
2480          status_update (conn->client_entry, CLT_FAILED);
2481          conn->client_entry->session_key_timer = 
2482            time(NULL) - (2*TIMEOUT_KEY);
2483         
2484          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
2485                          _("Session key mismatch"), conn->peer);
2486          sh_xfer_do_free (conn);
2487        } 
2488    }
2489 
2490  else
2491    {
2492      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
2493                      4, conn->pass, conn->peer, 
2494                      '\\', conn->head[3], '\\', conn->head[4],
2495                      '\\', conn->head[5], '\\', conn->head[6]);
2496      sh_xfer_do_free (conn);
2497    }
2498  return 0;
2499}
2500#endif
2501
2502/************************************************************************
2503 *
2504 * Here we check the message received, and decide on the answer to send
2505 * (if any). The connection is in CONN_PAUSED state, thus we must:
2506 * (i)   define the proper reaction
2507 * (ii)  reset to CONN_READING or CONN_WRITING or CONN_FREE
2508 * (iii) eventually reset the connection entry
2509 *
2510 *************************************************************************/
2511static
2512void check_protocol(sh_conn_t * conn, int state)
2513{
2514  SL_ENTER(_("check_protocol"));
2515
2516  /* seed / re-seed the PRNG if required
2517   */
2518  (void) taus_seed();
2519
2520  /* protocols:
2521   * -- (iii)    file transfer
2522   * -- (ii)     authenticated message transfer
2523   * -- (i)      SRP key exchange
2524   */
2525
2526  /* --------- FILE TRANSFER  -----------
2527   */
2528  if ( (conn->head[0] & SH_PROTO_SRP) == 0  &&
2529       (conn->head[0] & SH_PROTO_BIG) != 0  /* is set */ )
2530    {
2531      /* nonzero means re-authentication is required
2532       */
2533      if (0 == do_file_transfer(conn, state))
2534        SL_RET0(_("check_protocol"));
2535    }
2536  /* --------- END FILE TRANSFER ----------- */
2537
2538
2539  /* ---------  message exchange  -----------
2540   */
2541  else if ((conn->head[0] & SH_PROTO_SRP) == 0  && 
2542           (conn->head[0] & SH_PROTO_MSG) != 0  /* is set */ )
2543    {
2544      /* nonzero means re-authentication is required
2545       */
2546      if (0 == do_message_transfer(conn, state))
2547        SL_RET0(_("check_protocol"));
2548    }
2549  /* ---------  END MESSAGE TRANSFER ------ */
2550
2551  /* ---------  authentication  -----------
2552   */
2553  if ( (conn->head[0] & SH_PROTO_SRP) != 0   /* is set */ )
2554    {
2555      if (state == SH_DO_READ)        /* finished reading */
2556        {
2557          do_auth(conn);
2558        }
2559
2560      else if (state == SH_DO_WRITE)  /* finished writing */
2561        {
2562          TPT((0, FIL__, __LINE__, _("msg=<Authentication -- (wait).>\n")));
2563
2564          conn->headcount     = 0;
2565          conn->bytecount     = 0;
2566          conn->bytes_to_send = 0;
2567          conn->bytes_to_get  = 0;
2568          if (conn->buf != NULL) 
2569            {
2570              SH_FREE(conn->buf);
2571              conn->buf           = NULL;
2572            }
2573          conn->state     = CONN_READING;
2574        }
2575    }
2576  SL_RET0(_("check_protocol"));
2577}
2578
2579
2580/***********************************************************
2581 *
2582 *    SERVER RECEIVE FUNCTION
2583 *
2584 ***********************************************************
2585 */
2586int sh_xfer_do_read (sh_conn_t * conn)
2587{
2588  unsigned long   byteread;     /* bytes read         */
2589
2590  SL_ENTER(_("sh_xfer_do_read"));
2591
2592  if (conn->state == CONN_SENDING)
2593    {
2594      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
2595                      conn->peer);
2596      SL_RETURN( (-1), _("sh_xfer_do_read"));
2597    }
2598
2599  if (conn->headcount < SH_HEADER_SIZE) 
2600    {
2601      conn->bytes_to_get = SH_HEADER_SIZE - conn->headcount;
2602      byteread = read (conn->fd, &(conn->head[conn->headcount]),
2603                       conn->bytes_to_get);
2604      if (byteread > 0 || errno == EINTR) 
2605        {
2606          if (byteread > 0) 
2607            conn->headcount += byteread;
2608          if (conn->headcount == SH_HEADER_SIZE)
2609            {
2610              conn->bytes_to_get = (256 * (unsigned int)conn->head[1] + 
2611                                    (unsigned int)conn->head[2]);
2612              SH_SHOWPROT(conn->head, '<');
2613              conn->bytecount = 0;
2614            }
2615        }
2616      else
2617        goto conn_reset;
2618      SL_RETURN( (0), _("sh_xfer_do_read"));
2619    }
2620
2621  /* limit message size
2622   */
2623  conn->bytes_to_get = (conn->bytes_to_get > TRANS_BYTES) ? 
2624    TRANS_BYTES : conn->bytes_to_get;
2625
2626  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get > 0)
2627    {
2628      if ( conn->bytecount == 0)
2629        {
2630          if (conn->buf != NULL)
2631            SH_FREE (conn->buf);
2632          conn->buf = SH_ALLOC(conn->bytes_to_get + 1); /* <= TRANS_BYTES+1 */
2633        }
2634
2635      byteread           = read (conn->fd, &(conn->buf[conn->bytecount]),
2636                                 conn->bytes_to_get - conn->bytecount);
2637      if (byteread > 0 || errno == EINTR) 
2638        {
2639          if (byteread > 0) 
2640            conn->bytecount    += byteread;
2641          if (conn->bytecount == conn->bytes_to_get) 
2642            {
2643              ++conn->pass;
2644              /* always terminate with NULL - we might use sl_strcmp() */
2645              conn->buf[conn->bytecount] = '\0';
2646              conn->state                = CONN_PAUSE;
2647
2648#ifdef SH_ENCRYPT
2649              if ((conn->head[0] & SH_PROTO_ENC) != 0) 
2650                {
2651                  conn->buf = sh_tools_revertPack (conn->head, 
2652                                                   conn->client_entry->ivst_flag,
2653                                                   conn->buf,
2654                                                   &(conn->client_entry->keyInstD),
2655                                                   conn->bytecount);
2656                }
2657#endif
2658              /* ------  HERE CALL check_protocol(conn) -------  */
2659              check_protocol(conn, SH_DO_READ);
2660            }
2661        }
2662      else
2663          goto conn_reset;
2664    }
2665
2666  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get == 0)
2667    {
2668      if (conn->buf != NULL)
2669        SH_FREE (conn->buf);
2670      conn->buf       = NULL;
2671      conn->bytecount = 0;
2672      ++conn->pass;
2673      conn->state     = CONN_PAUSE;
2674      /* ------  HERE CALL check_protocol(conn) -------  */
2675      check_protocol(conn, SH_DO_READ);
2676    }
2677     
2678  SL_RETURN( (0), _("sh_xfer_do_read"));
2679
2680 conn_reset:
2681  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
2682                  conn->peer);
2683  sh_xfer_do_free ( conn );
2684  SL_RETURN( (-1), _("sh_xfer_do_read"));
2685}
2686
2687#if !defined(O_NONBLOCK)
2688#if defined(O_NDELAY)
2689#define O_NONBLOCK  O_NDELAY
2690#else
2691#define O_NONBLOCK  0
2692#endif
2693#endif
2694
2695/* send to the client
2696 */
2697int sh_xfer_do_write (sh_conn_t * conn)
2698{
2699  int    flags;
2700  long   arg = 0;
2701  long   bytesent;     /* bytes read         */
2702
2703  SL_ENTER(_("sh_xfer_do_write"));
2704
2705  /* ---- consistency check ------
2706   */
2707  if (conn->state == CONN_READING)
2708    {
2709      sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
2710                      conn->peer);
2711      SL_RETURN( (-1), _("sh_xfer_do_write"));
2712    }
2713 
2714  flags = retry_fcntl (FIL__, __LINE__, conn->fd, F_GETFL, arg);
2715  retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags|O_NONBLOCK);
2716
2717  /* ---- send the header ------
2718   */
2719  if (conn->headcount < SH_HEADER_SIZE) 
2720    {
2721      conn->bytes_to_send = SH_HEADER_SIZE - conn->headcount;
2722      bytesent = write (conn->fd, &(conn->head[conn->headcount]), 
2723                        conn->bytes_to_send);
2724      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
2725        {
2726          if (bytesent > 0) 
2727            conn->headcount += bytesent;
2728          if (conn->headcount == SH_HEADER_SIZE) 
2729            conn->bytes_to_send = 
2730              (256 * (int)conn->head[1] + (int)conn->head[2]);
2731        }
2732      else 
2733        goto conn_reset_w;
2734
2735      if (conn->fd >= 0)
2736        retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
2737      SL_RETURN( (0), _("sh_xfer_do_write"));
2738    }
2739
2740  /* ---- send the body ------
2741   */
2742
2743  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send > 0 &&
2744      conn->buf != NULL)
2745    {
2746      bytesent = write (conn->fd, &(conn->buf[conn->bytecount]), 
2747                        conn->bytes_to_send - conn->bytecount);
2748      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
2749        {
2750          if (bytesent > 0) 
2751            conn->bytecount    += bytesent;
2752          if (conn->bytecount == conn->bytes_to_send) 
2753            {
2754              ++conn->pass;
2755              conn->state = CONN_PAUSE;
2756              /* ------  HERE CALL check_protocol(conn) -------  */
2757              check_protocol(conn, SH_DO_WRITE);
2758            }
2759        }
2760      else
2761        goto conn_reset_w;
2762    }
2763     
2764  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send == 0)
2765    {
2766      ++conn->pass;
2767      conn->state = CONN_PAUSE;
2768      /* ------  HERE CALL check_protocol(conn) -------  */
2769      check_protocol(conn, SH_DO_WRITE);
2770    }
2771
2772  if (conn->fd >= 0)
2773    retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
2774  SL_RETURN( (0), _("sh_xfer_do_write"));
2775
2776 conn_reset_w:
2777  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
2778                  conn->peer);
2779  sh_xfer_do_free ( conn );
2780  SL_RETURN( (-1), _("sh_xfer_do_write"));
2781}
2782
2783/* accept a connection from a client
2784 */ 
2785#include <syslog.h>
2786#ifdef SH_USE_LIBWRAP
2787#include <tcpd.h>
2788
2789#ifndef ALLOW_SEVERITY
2790#define ALLOW_SEVERITY LOG_INFO
2791#define DENY_SEVERITY  LOG_WARNING
2792#endif
2793
2794int allow_severity;
2795int deny_severity;
2796#endif
2797
2798#ifdef SH_USE_LIBWRAP
2799static int check_libwrap(int rc, sh_conn_t * newconn)
2800{
2801  struct request_info request;
2802  char                errbuf[128];
2803  char                daemon[128];
2804
2805  sl_strlcpy(daemon, SH_INSTALL_NAME, sizeof(daemon));
2806  request_init(&request, RQ_DAEMON, daemon, RQ_FILE, rc, 0);
2807  fromhost(&request);
2808  if (!hosts_access(&request)) 
2809    {
2810      sl_strlcpy(errbuf, _("Refused connection from "), sizeof(errbuf));
2811      sl_strlcat(errbuf,   eval_client(&request), sizeof(errbuf));
2812     
2813      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
2814                      errbuf, _("libwrap"));
2815      newconn->fd    = -1;
2816      newconn->state = CONN_FREE;
2817      sl_close_fd(FIL__, __LINE__, rc);
2818      return -1;
2819    }
2820  return 0;
2821}
2822#endif
2823
2824int sh_xfer_accept (int sock, sh_conn_t * newconn)
2825{
2826  int                errflag;
2827  int                rc;
2828  struct sh_sockaddr addr;
2829 
2830  /* handle AIX (size_t addrlen) in wrapper
2831   */
2832  int                addrlen = sizeof(addr);
2833
2834  SL_ENTER(_("sh_xfer_accept"));
2835
2836  rc = retry_accept(FIL__, __LINE__, sock, &addr, &addrlen);
2837
2838  if (rc < 0)
2839    {
2840      char err_buf[SH_ERRBUF_SIZE];
2841      errflag = errno;
2842      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
2843                      sh_error_message(errflag,err_buf, sizeof(err_buf)), _("accept"));
2844      newconn->fd    = -1;
2845      newconn->state = CONN_FREE;
2846      SL_RETURN( (-1), _("sh_xfer_accept"));
2847    }
2848
2849  if (addrlen == 0)
2850    {
2851      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
2852                      _("Connecting entity unknown"), _("accept"));
2853      newconn->fd    = -1;
2854      newconn->state = CONN_FREE;
2855      sl_close_fd(FIL__, __LINE__, rc);
2856      SL_RETURN( (-1), _("sh_xfer_accept"));
2857    }
2858
2859#ifdef SH_USE_LIBWRAP
2860  if (check_libwrap(rc, newconn) < 0)
2861    SL_RETURN( (-1), _("sh_xfer_accept"));
2862#endif
2863
2864  memcpy (&(newconn->addr_peer), &addr, sizeof(struct sh_sockaddr));
2865
2866  /* prepare for usage of connection
2867   */
2868  (void) retry_fcntl( FIL__, __LINE__, rc, F_SETFD, 1 );
2869  newconn->fd           = rc;
2870  newconn->state        = CONN_READING;
2871  newconn->timer        = (unsigned long) time (NULL);
2872 
2873  if (flag_err_info == S_TRUE)
2874    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CNEW, newconn->fd);
2875
2876  SL_RETURN( (0), _("sh_xfer_accept"));
2877}
2878
2879extern char sh_sig_msg[64];  /* defined in sh_unix.c */
2880
2881/* ------------  port and interface -------
2882 */
2883static unsigned int server_port = SH_DEFAULT_PORT;
2884
2885int sh_xfer_set_port (const char * str)
2886{
2887  int retval = 0;
2888  unsigned long   i;
2889  char * endptr;
2890 
2891  SL_ENTER(_("sh_xfer_set_port"));
2892  i = strtoul (str, &endptr, 0);
2893  if (endptr == str) {
2894    retval = -1;
2895  } else if (i > 65535) {
2896    retval = -1;
2897  } else {
2898    server_port = i;
2899  }
2900  SL_RETURN( (retval), _("sh_xfer_set_port"));
2901}
2902
2903static struct sh_sockaddr server_interface;
2904static int            use_server_interface = 0;
2905
2906int sh_xfer_set_interface (const char * str)
2907{
2908  if (0 == strcmp(str, _("INADDR_ANY")))
2909    {
2910      use_server_interface = 0;
2911      return 0;
2912    }
2913
2914  if (0 == sh_ipvx_aton(str, &server_interface)) 
2915    {
2916      use_server_interface = 0;
2917      return -1;
2918    }
2919
2920  use_server_interface = 1;
2921  return 0;
2922}
2923
2924/* ------------  print error --------------
2925 */
2926struct sock_err_st {
2927  char msg[128];
2928  int  errnum;
2929  int  port;
2930  int  line;
2931  int  euid;
2932};
2933
2934static struct sock_err_st sock_err[2];
2935
2936void sh_xfer_printerr(char * str, int errnum, unsigned int port, int line)
2937{
2938  int slot = 0;
2939
2940  if (port != server_port)
2941    slot = 1;
2942  if (str == NULL)
2943    sock_err[slot].msg[0] = '\0';
2944  else
2945    sl_strlcpy(sock_err[slot].msg, str, 128);
2946  sock_err[slot].errnum = errnum;
2947  sock_err[slot].port   = port;
2948  sock_err[slot].line   = line;
2949  sock_err[slot].euid   = (int) geteuid();
2950}
2951
2952int sh_xfer_printerr_final(int slot)
2953{
2954  char errbuf[SH_ERRBUF_SIZE];
2955
2956  SL_ENTER(_("sh_xfer_printerr_final"));
2957  if (sock_err[slot].msg[0] != '\0')
2958    {
2959      dlog(1, FIL__, __LINE__, 
2960           _("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"),
2961           sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), 
2962           sock_err[slot].euid, 
2963           sock_err[slot].port);
2964      sh_error_handle((-1), FIL__, sock_err[slot].line, 
2965                      sock_err[slot].errnum, MSG_EXIT_ABORTS,
2966                      sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)),
2967                      sh.prg_name,
2968                      sock_err[slot].msg);
2969      SL_RETURN((-1), _("sh_xfer_printerr_final"));
2970    }
2971  SL_RETURN(0, _("sh_xfer_printerr_final"));
2972}
2973
2974#define  TIME_OUT_DEF 900
2975static   unsigned long  time_out_val = TIME_OUT_DEF;
2976
2977int sh_xfer_set_timeout (const char * c)
2978{
2979  long val;
2980
2981  SL_ENTER(_("sh_xfer_set_time_out"));
2982
2983  val = strtol (c, (char **)NULL, 10);
2984
2985  if (val == 0)
2986    {
2987      val = TIME_OUT_DEF;
2988    }
2989  else if (val < 0)
2990    {
2991      time_out_val = TIME_OUT_DEF;
2992      SL_RETURN( (-1), _("sh_xfer_set_time_out"));
2993    }
2994
2995  time_out_val = (unsigned long) val;
2996  SL_RETURN( (0), _("sh_xfer_set_time_out"));
2997}
2998
2999
3000static   sh_conn_t        * conns = NULL;
3001static   int  maxconn = 0;  /* maximum number of simultaneous connections */
3002
3003
3004#ifdef INET_SYSLOG
3005#define INET_SUSPEND_TIME 180           /* equal to 3 minutes */
3006#define SH_MINSOCK_DEFAULT 3
3007int sh_xfer_syslog_sock[SH_SOCKMAX] = { -1 };
3008extern int sh_xfer_recv_syslog_socket   (int fd);
3009int sh_xfer_syslog_sock_n = 0;
3010#else
3011#define SH_MINSOCK_DEFAULT 2
3012#endif
3013
3014int SH_MINSOCK = SH_MINSOCK_DEFAULT;
3015
3016extern int pf_unix_fd;
3017
3018/* the tcp socket, and the function to establish it
3019 */
3020static int sh_tcp_sock[SH_SOCKMAX] = { -1 };
3021static int sh_tcp_sock_n = 0;
3022
3023static int do_socket(int domain, int type, int protocol,
3024                     struct sockaddr * sa, int salen)
3025{
3026  int sock = -1;
3027  int errnum = 0;
3028  int flag   = 1; /* non-zero to enable an option */
3029
3030  /* create the socket, bind() it and listen()
3031   */
3032  if ((sock = socket(domain, type, protocol)) < 0 )
3033    {
3034      errnum = errno; 
3035      sh_xfer_printerr (_("socket"), errnum, server_port, __LINE__);
3036      return -1;
3037    }
3038  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
3039 
3040  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
3041                  (void *) &flag, sizeof(flag)) < 0 )
3042    {
3043      errnum = errno;
3044      sh_xfer_printerr (_("setsockopt"), errnum, server_port, __LINE__);
3045      sl_close_fd (FIL__, __LINE__, sock);
3046      return -1;
3047    }
3048 
3049  if ( bind(sock, (struct sockaddr *) sa, salen) < 0) 
3050    {
3051      if (errno != EADDRINUSE)
3052        {
3053          errnum = errno;
3054          sh_xfer_printerr (_("bind"), errnum, server_port, __LINE__);
3055          sl_close_fd (FIL__, __LINE__, sock);
3056          return -1;
3057        }
3058      else
3059        {
3060          sl_close_fd (FIL__, __LINE__, sock);
3061          return -2;
3062        }
3063    }
3064 
3065  if ( retry_fcntl( FIL__, __LINE__, sock, F_SETFL, O_NONBLOCK ) < 0 )
3066    {
3067      errnum = errno;
3068      sh_xfer_printerr (_("fcntl"), errnum, server_port, __LINE__);
3069      sl_close_fd (FIL__, __LINE__, sock);
3070      return -1;
3071    }
3072 
3073  if ( listen(sock, 64) < 0)
3074    {
3075      errnum = errno;
3076      sh_xfer_printerr (_("listen"), errnum, server_port, __LINE__);
3077      sl_close_fd (FIL__, __LINE__, sock);
3078      return -1;
3079    }
3080
3081  return sock;
3082}
3083
3084int sh_create_tcp_socket (void)
3085{
3086#if defined(USE_IPVX)
3087  struct addrinfo *ai;
3088  struct addrinfo *p;
3089  struct addrinfo hints;
3090  char            port[32];
3091#else
3092  struct sockaddr_in addr;
3093  int addrlen      = sizeof(addr);
3094#endif
3095
3096  int sock   = -1;
3097
3098  SL_ENTER(_("sh_create_tcp_socket"));
3099
3100  sh_xfer_printerr (NULL, 0, server_port, __LINE__);
3101
3102#if defined(USE_IPVX)
3103  if (use_server_interface == 0) /* INADDR_ANY, listen on all interfaces */
3104    {
3105      memset (&hints, '\0', sizeof (hints));
3106      hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
3107      hints.ai_socktype = SOCK_STREAM;
3108      hints.ai_family   = AF_UNSPEC;
3109      sl_snprintf(port, sizeof(port), "%d", server_port);
3110
3111      if (getaddrinfo (NULL, port, &hints, &ai) != 0)
3112        {
3113          int errnum = errno;
3114          sh_xfer_printerr (_("getaddrinfo"), errnum, server_port, __LINE__);
3115          sl_close_fd (FIL__, __LINE__, sock);
3116          SL_RETURN((-1), _("sl_create_tcp_socket"));
3117        }
3118     
3119      p = ai;
3120     
3121      while (p != NULL && sh_tcp_sock_n < SH_SOCKMAX)
3122        {
3123          sock = do_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
3124                           p->ai_addr, p->ai_addrlen);
3125         
3126          if (sock >= 0) {
3127            if (sh_tcp_sock_n < SH_SOCKMAX) {
3128              sh_tcp_sock[sh_tcp_sock_n] = sock;
3129              ++sh_tcp_sock_n;
3130            }
3131            else {
3132              sl_close_fd (FIL__, __LINE__, sock);
3133            }   
3134          } else if (sock == -1) {
3135            freeaddrinfo (ai);
3136            goto end;
3137          }
3138          p = p->ai_next;
3139        }
3140     
3141      freeaddrinfo (ai);
3142    }
3143  else
3144    {
3145      sh_ipvx_set_port(&server_interface, server_port);
3146
3147      sock = do_socket(server_interface.ss_family, SOCK_STREAM, 0, 
3148                       sh_ipvx_sockaddr_cast(&server_interface), 
3149                       SH_SS_LEN(server_interface));
3150     
3151      if (sock >= 0) {
3152        sh_tcp_sock[0] = sock;
3153        sh_tcp_sock_n  = 1;
3154      }
3155    }         
3156#else
3157  if (use_server_interface == 0)
3158    addr.sin_addr.s_addr = INADDR_ANY;
3159  else
3160    memcpy(&addr, sh_ipvx_sockaddr_cast(&server_interface), addrlen);
3161  addr.sin_family      = AF_INET;
3162  addr.sin_port        = htons(server_port);
3163 
3164  sock = do_socket(AF_INET, SOCK_STREAM, 0, (struct sockaddr *) &addr, addrlen);
3165
3166  if (sock >= 0) {
3167      sh_tcp_sock[0] = sock;
3168      sh_tcp_sock_n  = 1;
3169  }
3170
3171#endif
3172
3173#if defined(USE_IPVX)
3174 end:
3175#endif
3176  if (sh_tcp_sock_n > 1)
3177    SH_MINSOCK += (sh_tcp_sock_n - 1);
3178
3179  SL_RETURN((sh_tcp_sock_n), _("sl_create_tcp_socket"));
3180}
3181
3182/*****************************************
3183 *
3184 * This is the server main loop.
3185 *
3186 * The server is set up for listening, and
3187 * and starts a select() loop.
3188 *
3189 *****************************************/
3190
3191void sh_xfer_start_server()
3192{
3193#ifdef SH_USE_XML
3194  extern int  sh_log_file    (char * message, char * inet_peer);
3195#endif
3196
3197  /* Use volatile to circumvent a gcc4 problem on RH/CentOS 4.8 (?) */
3198  volatile int       sock = -1;
3199  sh_conn_t        * cx;
3200  fd_set             readset;
3201  fd_set             writeset;
3202  struct timeval     tv;
3203  int                num_sel;
3204  int                errnum;
3205  int                nowconn;
3206  int                status;
3207  int                high_fd = -1;
3208  register int       i;
3209  long               dummy = 0;
3210  unsigned long      time_now;
3211  unsigned long      time_last = 0;
3212  unsigned long      time_out = time_out_val; 
3213 
3214  time_t told;
3215  time_t tcurrent;
3216
3217  unsigned long tchkold;
3218
3219  int setsize_fd;
3220
3221  int sock_tcp[2];
3222  int sock_unix;
3223#ifdef INET_SYSLOG
3224  int sock_log[2];
3225#endif
3226 
3227  SL_ENTER(_("sh_xfer_start_server"));
3228
3229  if ( sh_xfer_printerr_final(0) < 0)
3230    {
3231      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3232    }
3233
3234  sock = sh_tcp_sock[0];
3235
3236  /* ****************************************************************
3237   *
3238   * This is a non-forking server. We use select() on the listen()
3239   * socket to watch for new connections. For new connections, accept()
3240   * will return a new socket that is put in the read/write filesets.
3241   * Data about active connections are kept in the 'conns' table.
3242   *
3243   ******************************************************************/
3244 
3245  /* The table to hold info on sockets.
3246   * We reserve 6 file descriptors for misc. use.
3247   * The POSIX lower limit on open files seems to be eight.
3248   */
3249  maxconn    = get_open_max() - 6;
3250
3251  /* ugly fix for FreeBSD compiler warning; casting FD_SETSIZE in the
3252   * conditional expression does not suppress the warning... */
3253  setsize_fd = (int)FD_SETSIZE;
3254  maxconn = (setsize_fd < maxconn) ? setsize_fd : maxconn;
3255
3256  if (maxconn < 0 || !sl_ok_muls(maxconn, sizeof(sh_conn_t)))
3257    {
3258      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
3259                      0, sock);
3260      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
3261    }
3262  conns   = SH_ALLOC (sizeof(sh_conn_t) * maxconn);
3263
3264  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
3265                  (maxconn-1), sock);
3266
3267  /* timer
3268   */
3269  tcurrent                   = (unsigned long) time (NULL);
3270  told                       = tcurrent;
3271
3272  tchkold                    = tcurrent;
3273 
3274  for (i = SH_MINSOCK; i < maxconn; ++i)
3275    {
3276      conns[i].buf         = NULL;
3277      conns[i].K           = NULL;
3278      conns[i].A           = NULL;
3279      conns[i].M1          = NULL;
3280      conns[i].FileName    = NULL;
3281      conns[i].fd          = -1;
3282      sh_xfer_do_free ( &conns[i]);
3283    }
3284 
3285  /* status init
3286   */
3287  server_status.conn_open  = 0;
3288  server_status.conn_total = 0;
3289  server_status.conn_max   = maxconn-1;
3290  server_status.start      = time (NULL);
3291  server_status.last       = (time_t) 0;
3292
3293  nowconn    = 1;
3294  tv.tv_sec  = 5;
3295  tv.tv_usec = 0;
3296 
3297  /* conns[0] is the listen() socket. Always in read mode.
3298   */
3299  sock = 0;
3300
3301  sock_tcp[0] = 0;
3302  while (sock < sh_tcp_sock_n)
3303    {
3304      conns[sock].fd    = sh_tcp_sock[sock];
3305      conns[sock].state = CONN_READING;
3306      /* high_fd = (sh_tcp_sock[sock] > high_fd) ? sh_tcp_sock[sock] : high_fd; */
3307      ++sock;
3308    }
3309  sock_tcp[1] = sock;
3310 
3311  conns[sock].fd    = pf_unix_fd;
3312  conns[sock].state = CONN_READING;
3313  /* high_fd = (pf_unix_fd > high_fd) ? pf_unix_fd : high_fd; */
3314
3315  sock_unix = sock;
3316
3317  ++sock;
3318
3319#ifdef INET_SYSLOG
3320  conns[sock].fd = -1;
3321
3322  if ( sh_xfer_printerr_final(1) < 0)
3323    {
3324      SH_FREE(conns);
3325      conns = NULL;
3326      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3327    }
3328
3329  sock_log[0] = sock;
3330  sock_log[1] = sock;
3331
3332  if (sh_xfer_syslog_sock_n > 0)
3333    {
3334      int s2;
3335      for (s2 = 0; s2 < sh_xfer_syslog_sock_n; ++s2)
3336        {
3337          conns[sock].fd    = sh_xfer_syslog_sock[s2];
3338          conns[sock].state = CONN_READING;
3339          /* high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; */
3340          ++sock;
3341        }
3342      sock_log[1] = sock;
3343
3344    }
3345#endif
3346 
3347  sh_html_write(all_clients);
3348 
3349  /* This is the select() loop.
3350   */
3351  while (1 == 1)
3352    {
3353
3354    if (sig_raised > 0)
3355      {
3356        TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
3357
3358        if (sig_termfast == 1)  /* SIGTERM */
3359          {
3360            TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
3361            strncpy (sh_sig_msg, _("SIGTERM"), 20);
3362            --sig_raised; --sig_urgent;
3363            aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
3364          }
3365         
3366        if (sig_config_read_again == 1)
3367          {
3368            TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
3369            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
3370
3371
3372            /* -- Delete the name server cache. --
3373             */
3374
3375            delete_cache();
3376#if defined(WITH_EXTERNAL)
3377            /* -- Delete list of external tasks. --
3378             */
3379            (void) sh_ext_cleanup();
3380#endif
3381#if defined(SH_WITH_MAIL)
3382              sh_nmail_free();
3383#endif
3384            /* - mark all clients dead
3385             * - read configuration file
3386             * - remove clients still dead
3387             */
3388            sh_xfer_mark_dead ();
3389
3390            reset_count_dev_console();
3391            reset_count_dev_time();
3392            sl_trust_purge_user();
3393
3394            (void) sh_readconf_read ();
3395
3396            for (i = SH_MINSOCK; i < maxconn; ++i)
3397              if (conns[i].state != CONN_FREE   && 
3398                  conns[i].client_entry != NULL &&
3399                  conns[i].client_entry->dead_flag == 1)
3400                sh_xfer_do_free ( &conns[i]);
3401            sh_xfer_clean_tree ();
3402
3403            sig_config_read_again = 0;
3404            --sig_raised;
3405          }
3406
3407        if (sig_fresh_trail == 1) /* SIGIOT */
3408          {
3409            /* Logfile access
3410             */
3411#ifdef SH_USE_XML
3412            sh_log_file (NULL, NULL);
3413#endif
3414            TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
3415            sh_error_only_stderr (S_TRUE);
3416            sh_unix_rm_lock_file(sh.srvlog.name);
3417            retry_msleep(3, 0);
3418            sh.flag.log_start = S_TRUE;
3419            sh_error_only_stderr (S_FALSE);
3420            sig_fresh_trail       = 0;
3421            --sig_raised;
3422          }
3423       
3424         
3425        if (sig_terminate == 1 && nowconn < 2)  /* SIGQUIT */
3426          {
3427            TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
3428            strncpy (sh_sig_msg, _("SIGQUIT"), 20);
3429            --sig_raised; --sig_urgent;
3430            aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
3431          }
3432       
3433         
3434        if (sig_debug_switch == 1)  /* SIGUSR1 */
3435          {
3436            TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
3437            sh_error_dbg_switch();
3438            sig_debug_switch = 0;
3439            --sig_raised;
3440          }
3441       
3442        if (sig_suspend_switch > 0)  /* SIGUSR2 */
3443          {
3444            TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
3445            if (sh_global_suspend_flag == 1) {
3446              sh_global_suspend_flag = 0;
3447            } else {
3448              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
3449                              sh.prg_name);
3450              sh_global_suspend_flag = 1;
3451            }
3452            --sig_suspend_switch;
3453            --sig_raised; --sig_urgent;
3454          }
3455
3456        sig_raised = (sig_raised < 0) ? 0 : sig_raised;
3457        sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
3458        TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
3459      }
3460     
3461      if (sh_global_suspend_flag == 1)
3462        {
3463          (void) retry_msleep (1, 0);
3464          continue;
3465        }
3466
3467      /* Recompute the descriptor set. select() modifies it,
3468       * thus we update it using the info from the connection table.
3469       * Also recompute the number of open connections.
3470       */
3471      FD_ZERO( &readset );
3472      FD_ZERO( &writeset );
3473      high_fd = conns[0].fd;
3474
3475      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
3476        {
3477          FD_SET(conns[sock].fd, &readset );
3478          high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
3479        }
3480
3481      if (conns[sock_unix].fd > -1)
3482        {
3483          FD_SET(conns[sock_unix].fd, &readset );
3484          high_fd   = (high_fd > conns[sock_unix].fd) ? high_fd : conns[sock_unix].fd;
3485        }
3486
3487#ifdef INET_SYSLOG
3488      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
3489        {
3490          if (conns[sock].fd > -1)
3491            {
3492              FD_SET(conns[sock].fd, &readset );
3493              high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
3494            }
3495        }
3496#endif
3497
3498      time_now  = (unsigned long) time (NULL);
3499      nowconn   = 1;
3500     
3501      for (i = SH_MINSOCK; i < maxconn; ++i)
3502        {
3503          /* eliminate timed out connections
3504           */
3505          if (conns[i].state != CONN_FREE) 
3506            {
3507              if (time_now-conns[i].timer > time_out)
3508                {
3509                  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMOUT,
3510                                  conns[i].peer);
3511                  sh_xfer_do_free ( &conns[i]);
3512                }
3513              else
3514                ++nowconn;
3515            }
3516         
3517         
3518          if       (conns[i].state   == CONN_READING)
3519            { 
3520              FD_SET(conns[i].fd, &readset);
3521              high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
3522            }
3523          else if  (conns[i].state   == CONN_SENDING)
3524            {
3525              FD_SET(conns[i].fd, &writeset);
3526              high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
3527            }
3528        }
3529
3530      /* -- Exponentially reduce timeout limit if more than 1/2 full. --
3531       */
3532      /* Eliminate this, will cause problems when too much clients are
3533       * starting up. */
3534#if 0
3535      if (nowconn > (maxconn/2))
3536        time_out = ( (time_out/2) > 1) ? (time_out/2) : 1;
3537      else
3538        time_out = time_out_val;
3539#endif
3540     
3541     
3542      /* -- Do the select(). --
3543       */
3544      num_sel = select(high_fd+1, &readset, &writeset, NULL, &tv);
3545      errnum  = errno;
3546     
3547      /* reset timeout - modified by select() on some systems
3548       */
3549      tv.tv_sec  = 5;
3550      tv.tv_usec = 0;
3551     
3552
3553      if ( (time_now - time_last) > 2L)
3554        {
3555          time_last = time_now;
3556          if (sh_html_write(all_clients) < 0)
3557            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
3558        }
3559     
3560     
3561      /* Error handling.
3562       */
3563      if ( num_sel < 0 )        /* some error             */
3564        {
3565          char errbuf[SH_ERRBUF_SIZE];
3566
3567          if (sig_raised == 1)
3568            {
3569              sig_raised = 2;
3570              continue;
3571            }
3572
3573          if ( errnum == EINTR)
3574            continue;     /* try again              */
3575
3576          if ( errnum == EBADF)
3577            {
3578              /* seek and destroy the bad fd
3579               */
3580              for (i = SH_MINSOCK; i < high_fd; ++i)
3581                {
3582                  if ((conns[i].state == CONN_READING) ||
3583                      (conns[i].state == CONN_SENDING))
3584                    {
3585                      if (-1 == retry_fcntl(FIL__, __LINE__, 
3586                                            conns[i].fd, F_GETFL, dummy))
3587                        sh_xfer_do_free ( &conns[i]);
3588                    }
3589                }
3590              continue;
3591            }
3592
3593          sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_EXIT_ABORTS,
3594                          sh_error_message(errnum, errbuf, sizeof(errbuf)), 
3595                          sh.prg_name,
3596                          _("select"));
3597          aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
3598        }
3599     
3600
3601      /* log the timestamp
3602       */
3603      if ((tcurrent - told) > sh.looptime )
3604        {
3605          told = tcurrent;
3606#ifdef MEM_DEBUG
3607          sh_mem_check();
3608          sh_unix_count_mlock();
3609#else
3610          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
3611#endif
3612        }
3613
3614#if defined(SH_WITH_MAIL)
3615      /*
3616       * flush the mail queue
3617       */
3618      if (tcurrent - sh.mailTime.alarm_last > sh.mailTime.alarm_interval) 
3619        {
3620          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
3621          (void) sh_nmail_flush ();
3622          sh.mailTime.alarm_last = tcurrent;
3623        }
3624#endif
3625#ifdef MEM_DEBUG
3626      sh_mem_dump();
3627#endif
3628
3629      tcurrent = (unsigned long) time (NULL);
3630
3631      /* check for time limit exceeded
3632       */
3633      if ((tcurrent - tchkold) > (unsigned int) 3 )
3634        {
3635          tchkold = tcurrent;
3636          client_time_check(/* all_clients */);
3637          /* reset cache */
3638          sh_userid_destroy();
3639        }
3640     
3641      /* seed / re-seed the PRNG if required
3642       */
3643      (void) taus_seed();
3644
3645      /* select() timeout handling.
3646       */
3647      if ( num_sel == 0 )       /* timeout - no connection */ 
3648        {
3649          if (sh_html_write(all_clients) < 0)
3650            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
3651          continue;
3652        }
3653
3654      /* New connection.
3655       */
3656      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
3657        {
3658          if ( FD_ISSET(conns[sock].fd , &readset )) /* a new connection   */
3659            {
3660              --num_sel;
3661              status = 0;
3662              if (nowconn < maxconn && sig_terminate == 0 && sig_termfast == 0)
3663                {
3664                  /* Find a free slot to accept the connection
3665                   */
3666                  i = SH_MINSOCK;
3667                  while (i < maxconn)
3668                    {
3669                      if (conns[i].state == CONN_FREE)
3670                        {
3671                          /* Here we run the accept() and copy the peer to
3672                           * the free slot.
3673                           */
3674                          status = sh_xfer_accept(conns[sock].fd, &conns[i]);
3675                         
3676                          if (status == 0)
3677                            {
3678                              high_fd = 
3679                                (high_fd > conns[i].fd ? high_fd : conns[i].fd);
3680                              ++server_status.conn_open;
3681                              ++server_status.conn_total;
3682                              server_status.last = time (NULL);
3683                            }
3684                          break;
3685                        }
3686                      ++i;
3687                    }
3688                }
3689              /* This re-runs select to accept data on the new
3690               * connection, rather than first dealing with old
3691               * connections.
3692               */
3693              if (status == 0) 
3694                continue;
3695            }
3696        }
3697     
3698      /* check for commands on the socket
3699       */
3700      if (conns[sock_unix].fd > (-1) && FD_ISSET(conns[sock_unix].fd , &readset ))
3701        {
3702          sh_socket_poll();
3703        }
3704
3705#ifdef INET_SYSLOG
3706      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
3707        {
3708          if (conns[sock].fd > (-1) && FD_ISSET(conns[sock].fd , &readset ))
3709            {
3710              sh_xfer_recv_syslog_socket (conns[sock].fd);
3711            }
3712        }
3713#endif
3714
3715      /* Check for pending read/write on the rest of the sockets.
3716       */
3717      for ( i = SH_MINSOCK; num_sel > 0 && i < maxconn; ++i )
3718        {
3719          if (sig_termfast == 1)
3720            break;
3721
3722          cx = &conns[i];
3723          if ( cx->state == CONN_READING &&
3724               FD_ISSET( cx->fd, &readset ) )
3725            {
3726              --num_sel;
3727              sh_xfer_do_read ( cx );
3728            }
3729          else if ( cx->state == CONN_SENDING &&
3730                    FD_ISSET( cx->fd, &writeset ) )
3731            {
3732              --num_sel;
3733              sh_xfer_do_write ( cx );
3734            }
3735        }
3736      /* continue */
3737    }
3738  /* notreached */
3739}
3740
3741void  free_client_tree (void)
3742{
3743  SL_ENTER(_("free_client_tree"));
3744  zAVLFreeTree (all_clients, free_client);
3745  SL_RET0(_("free_client_tree"));
3746}
3747
3748void sh_xfer_free_all ()
3749{
3750  register int i;
3751 
3752  SL_ENTER(_("sh_xfer_free_all"));
3753
3754  if (conns != NULL)
3755    for (i = SH_MINSOCK; i < maxconn; ++i)
3756      {
3757        sh_xfer_do_free ( &conns[i]);
3758      }
3759
3760
3761  free_client_tree ();
3762
3763  if (conns != NULL)
3764    SH_FREE (conns);
3765
3766  SL_RET0(_("sh_xfer_free_all"));
3767}
3768
3769
3770
3771/* #ifdef SH_WITH_SERVER */
3772#endif
3773
3774
3775 
3776
3777
3778
Note: See TracBrowser for help on using the repository browser.