source: trunk/src/sh_xfer_server.c@ 487

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

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 93.1 KB
RevLine 
[481]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->K != NULL) SH_FREE (conn->K);
2128 conn->K = NULL;
2129 if (conn->A != NULL) SH_FREE (conn->A);
2130 conn->A = 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->A != NULL) SH_FREE(conn->A); conn->A = 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->K != NULL) SH_FREE(conn->K); conn->K = 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) < 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.