source: trunk/src/sh_portcheck.c@ 533

Last change on this file since 533 was 530, checked in by katerina, 7 years ago

Fix for ticket #428 (compiler warnings).

  • Property svn:executable set to *
File size: 68.1 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2006 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/***************************************************************************
21 *
22 * This file provides a module for samhain to check for open ports
23 * on the local machine.
24 *
25 */
26
27
28/* #define TEST_ONLY */
29#ifndef TEST_ONLY
30#include "config_xor.h"
31#endif
32
33#include <stdio.h>
34#include <string.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#ifdef HAVE_IFADDRS_H
41#include <ifaddrs.h>
42#include <netdb.h>
43#endif
44#include <errno.h>
45#include <unistd.h>
46#include <fcntl.h>
47
48#define PORTCHK_VERSION "1.1"
49
50#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
51
52
53#define PORTMAP
54#ifdef HAVE_RPC_RPC_H
55#include <rpc/rpc.h>
56#ifdef HAVE_RPC_RPCENT_H
57#include <rpc/rpcent.h>
58#endif
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61#endif
62#include <netdb.h>
63
64/*
65 * struct pmaplist {
66 * struct pmap pml_map;
67 * struct pmaplist *pml_next;
68 * };
69 */
70
71/* struct pmap {
72 * long unsigned pm_prog;
73 * long unsigned pm_vers;
74 * long unsigned pm_prot;
75 * long unsigned pm_port;
76 * };
77 */
78
79/* TIME_WAIT ? 60-240 seconds */
80
81#if !defined(TEST_ONLY)
82
83#define FIL__ _("sh_portcheck.c")
84#include "samhain.h"
85#include "sh_error.h"
86#include "sh_mem.h"
87#include "sh_calls.h"
88#include "sh_utils.h"
89#include "sh_modules.h"
90#define SH_NEED_GETHOSTBYXXX
91#include "sh_static.h"
92#include "sh_pthread.h"
93#include "sh_ipvx.h"
94
95/* the size of an interface string
96 */
97#define SH_INTERFACE_SIZE SH_IP_BUF
98
99#define SH_PORT_NOT 0
100#define SH_PORT_REQ 1
101#define SH_PORT_OPT 2
102#define SH_PORT_IGN 3
103#define SH_PORT_BLACKLIST 4
104
105static char * sh_port_type2str (int type)
106{
107 if (type == 0) return _("not");
108 if (type == 1) return _("req");
109 if (type == 2) return _("opt");
110 if (type == 3) return _("ign");
111 if (type == 4) return _("blc");
112 return _("???");
113}
114
115#define SH_PORT_MISS 0
116#define SH_PORT_ISOK 1
117#define SH_PORT_UNKN 2
118
119#define SH_PORT_NOREPT 0
120#define SH_PORT_REPORT 1
121
122#define SH_PROTO_TCP 0
123#define SH_PROTO_UDP 1
124#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
125
126struct sh_portentry {
127 int port;
128 char interface[SH_INTERFACE_SIZE];
129 char * service;
130 char * error;
131 int flag; /* required or not */
132 int status; /* missing or not */
133 struct sh_portentry * next;
134};
135
136static struct sh_portentry * portlist_tcp = NULL;
137static struct sh_portentry * portlist_udp = NULL;
138
139
140#define SH_PORTCHK_INTERVAL 300
141
142static int sh_portchk_check_udp = 1;
143static int sh_portchk_active = 1;
144static int sh_portchk_same_ports = 1;
145static int sh_portchk_transients = 1;
146static int sh_portchk_interval = SH_PORTCHK_INTERVAL;
147
148static int sh_portchk_minport = -1;
149static int sh_portchk_maxport = -1;
150
151struct sh_port {
152 int port;
153 struct sh_sockaddr * paddr;
154 struct sh_port * next;
155};
156
157static struct sh_port * blacklist_tcp = NULL;
158static struct sh_port * blacklist_udp = NULL;
159
160static struct sh_port * transient_tcp = NULL;
161static struct sh_port * transient_udp = NULL;
162
163SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
164
165static int sh_portchk_severity = SH_ERR_SEVERE;
166
167extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
168 unsigned long * pid, char * user, size_t userlen);
169extern int sh_port2proc_prepare();
170extern void sh_port2proc_finish();
171
172#endif
173
174/* Exported interface to add ignoreable ports as 'iface:portlist'
175 */
176static int sh_portchk_add_ignore (const char * str);
177
178/* Exported interface to add required ports as 'iface:portlist'
179 */
180static int sh_portchk_add_required (const char * str);
181
182/* Exported interface to add optional ports as 'iface:portlist'
183 */
184static int sh_portchk_add_optional (const char * str);
185
186/* Exported interface to add blacklisted ports as 'iface:portlist'
187 */
188static int sh_portchk_add_blacklist (const char * str);
189
190/* Exported interface to add an ethernet interface
191 */
192static int sh_portchk_add_interface (const char * str);
193
194#if defined(HAVE_IFADDRS_H)
195/* Exported interface to add an ethernet device
196 */
197static int sh_portchk_add_device (const char * str);
198#endif
199
200/* verify whether port/interface is blacklisted (do not check)
201 */
202static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
203
204/* verify whether port/interface is transient (used as source port hence no check required)
205 */
206static int sh_portchk_is_transient(int port, struct sh_sockaddr * haddr, int proto);
207static int sh_portchk_transient(int port, struct sh_sockaddr * haddr, int proto);
208
209#ifndef TEST_ONLY
210
211static int sh_portchk_set_interval (const char * c)
212{
213 int retval = 0;
214 long val;
215
216 SL_ENTER(_("sh_portchk_set_interval"));
217 val = strtol (c, (char **)NULL, 10);
218 if (val <= 0)
219 {
220 SH_MUTEX_LOCK(mutex_thread_nolog);
221 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
222 _("port check interval"), c);
223 SH_MUTEX_UNLOCK(mutex_thread_nolog);
224 retval = -1;
225 }
226 else
227 {
228 sh_portchk_interval = (time_t) val;
229 }
230 SL_RETURN(retval, _("sh_portchk_set_interval"));
231}
232
233static int sh_portchk_set_port_minmax (const char * c, int * setthis)
234{
235 int retval = 0;
236 long val;
237
238 SL_ENTER(_("sh_portchk_set_port_minmax"));
239 val = strtol (c, (char **)NULL, 10);
240 if (val < 0 || val > 65535)
241 {
242 SH_MUTEX_LOCK(mutex_thread_nolog);
243 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
244 _("port check port minmax"), c);
245 SH_MUTEX_UNLOCK(mutex_thread_nolog);
246 retval = -1;
247 }
248 else
249 {
250 *setthis = (int) val;
251 }
252 SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
253}
254
255
256static int sh_portchk_set_minport (const char * str)
257{
258 return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
259}
260
261static int sh_portchk_set_maxport (const char * str)
262{
263 return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
264}
265
266static int sh_portchk_set_active (const char * str)
267{
268 return sh_util_flagval(str, &sh_portchk_active);
269}
270
271static int sh_portchk_set_udp (const char * str)
272{
273 return sh_util_flagval(str, &sh_portchk_check_udp);
274}
275#if defined(SH_ALLOW_RESTORE)
276static int sh_portchk_set_transients (const char * str)
277{
278 return sh_util_flagval(str, &sh_portchk_transients);
279}
280
281static int sh_portchk_set_same_ports (const char * str)
282{
283 return sh_util_flagval(str, &sh_portchk_same_ports);
284}
285#endif
286static int sh_portchk_set_severity (const char * str)
287{
288 char tmp[32];
289 tmp[0] = '='; tmp[1] = '\0';
290 sl_strlcat (tmp, str, 32);
291 return sh_error_set_level (tmp, &sh_portchk_severity);
292}
293
294sh_rconf sh_portchk_table[] = {
295 {
296 N_("severityportcheck"),
297 sh_portchk_set_severity,
298 },
299 {
300 N_("portcheckrequired"),
301 sh_portchk_add_required,
302 },
303 {
304 N_("portcheckoptional"),
305 sh_portchk_add_optional,
306 },
307 {
308 N_("portcheckignore"),
309 sh_portchk_add_ignore,
310 },
311 {
312 N_("portcheckskip"),
313 sh_portchk_add_blacklist,
314 },
315 {
316 N_("portcheckactive"),
317 sh_portchk_set_active,
318 },
319#if defined(HAVE_IFADDRS_H)
320 {
321 N_("portcheckdevice"),
322 sh_portchk_add_device,
323 },
324#endif
325 {
326 N_("portcheckinterface"),
327 sh_portchk_add_interface,
328 },
329 {
330 N_("portcheckinterval"),
331 sh_portchk_set_interval,
332 },
333 {
334 N_("portcheckminport"),
335 sh_portchk_set_minport,
336 },
337 {
338 N_("portcheckmaxport"),
339 sh_portchk_set_maxport,
340 },
341 {
342 N_("portcheckudp"),
343 sh_portchk_set_udp,
344 },
345#if defined(SH_ALLOW_RESTORE)
346 {
347 N_("portchecktransients"),
348 sh_portchk_set_transients,
349 },
350 {
351 N_("portchecksameports"),
352 sh_portchk_set_same_ports,
353 },
354#endif
355 {
356 NULL,
357 NULL
358 }
359};
360
361#endif
362
363/* Interface to initialize port check
364 */
365int sh_portchk_init (struct mod_type * arg);
366
367/* Interface to reset port check
368 */
369int sh_portchk_reset (void);
370
371/* Interface to run port check
372 */
373int sh_portchk_check (void);
374
375
376static char * check_services (int port, int proto);
377
378#ifdef TEST_ONLY
379
380static int portchk_debug = 0;
381#define SH_ALLOC malloc
382#define SH_FREE free
383#define sh_util_strdup strdup
384#define sl_strlcpy strncpy
385#define _(a) a
386
387#else
388
389static int portchk_debug = 0;
390
391#endif
392
393#ifdef HAVE_RPC_RPC_H
394static char * sh_getrpcbynumber (int number, char * buf, size_t len)
395{
396 FILE * fp;
397
398 if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
399 {
400 sh_string * s = sh_string_new(0);
401 while (0 < sh_string_read(s, fp, 1024))
402 {
403 char * p = sh_string_str(s);
404 while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
405 if (*p == '\0' || *p == '#')
406 continue; /* skip comment */
407 else
408 {
409 size_t lengths[3];
410 unsigned int fields = 3;
411 char * q = sh_string_str(s);
412 char ** splits = split_array_ws(q, &fields, lengths);
413
414 if (fields >= 2)
415 {
416 int n = atoi(splits[1]);
417 if (n == number)
418 {
419 sl_strlcpy(buf, splits[0], len);
420 SH_FREE(splits);
421 sh_string_destroy(&s);
422 sl_fclose(FIL__, __LINE__, fp);
423 return buf;
424 }
425 }
426 SH_FREE(splits);
427 }
428 }
429 sh_string_destroy(&s);
430 sl_fclose(FIL__, __LINE__, fp);
431 }
432 return NULL;
433}
434#endif
435
436static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
437{
438 FILE * fp;
439 char proto[8];
440
441 sl_strlcpy(proto, proto_in, sizeof(proto));
442
443 if (NULL != (fp = fopen(_("/etc/services"), "r")))
444 {
445 sh_string * s = sh_string_new(0);
446 while (0 < sh_string_read(s, fp, 1024))
447 {
448 char * p = sh_string_str(s);
449 while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
450 if (*p == '\0' || *p == '#')
451 continue; /* skip comment */
452 else
453 {
454 size_t lengths[3];
455 unsigned int fields = 3;
456 char * q = sh_string_str(s);
457 char ** splits = split_array_ws(q, &fields, lengths);
458
459 if (fields >= 2)
460 {
461 char * end;
462 long n = strtol(splits[1], &end, 10);
463 if (n == port && end && (*end == '/' || *end == ','))
464 {
465 ++end;
466 if (0 == strcmp(end, proto))
467 {
468 sl_strlcpy(buf, splits[0], len);
469 SH_FREE(splits);
470 sh_string_destroy(&s);
471 sl_fclose(FIL__, __LINE__, fp);
472 return buf;
473 }
474 }
475 }
476 SH_FREE(splits);
477 }
478 }
479 sh_string_destroy(&s);
480 sl_fclose(FIL__, __LINE__, fp);
481 }
482 return NULL;
483}
484
485static void sh_portchk_add_to_list (int proto,
486 int port, struct sh_sockaddr * paddr,
487 char * service,
488 int flag, int status)
489{
490 struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
491
492 new->port = port;
493 sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
494 new->status = status;
495 new->flag = flag;
496
497 new->error = NULL;
498
499 if (portchk_debug)
500 fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"),
501 port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"),
502 new->interface);
503
504 if (service)
505 new->service = sh_util_strdup (service);
506 else
507 new->service = NULL;
508 if (proto == IPPROTO_TCP)
509 {
510 new->next = portlist_tcp;
511 portlist_tcp = new;
512 }
513 else
514 {
515 new->next = portlist_udp;
516 portlist_udp = new;
517 }
518 return;
519}
520
521/* Reset the list by setting all entries to UNKN.
522 * In the next cycle we will check, and set found ports to ISOK.
523 * Thereafter, we check for entries that are still UNKN.
524 */
525static void sh_portchk_reset_lists (void)
526{
527 struct sh_portentry * portlist;
528
529 portlist = portlist_tcp;
530 while (portlist)
531 {
532 if (portlist->status != SH_PORT_MISS)
533 portlist->status = SH_PORT_UNKN;
534 portlist = portlist->next;
535 }
536 portlist = portlist_udp;
537 while (portlist)
538 {
539 if (portlist->status != SH_PORT_MISS)
540 portlist->status = SH_PORT_UNKN;
541 portlist = portlist->next;
542 }
543 return;
544}
545
546static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
547{
548 if (head)
549 {
550 if (head->next)
551 sh_portchk_kill_list (head->next);
552
553 if (head->service)
554 SH_FREE(head->service);
555 SH_FREE(head);
556 }
557 return NULL;
558}
559
560static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
561{
562 if (head)
563 {
564 if (head->next)
565 sh_portchk_kill_blacklist (head->next);
566
567 SH_FREE(head->paddr);
568 SH_FREE(head);
569 }
570 return NULL;
571}
572
573static struct sh_port * sh_portchk_kill_transient (struct sh_port * head)
574{
575 if (head)
576 {
577 if (head->next)
578 sh_portchk_kill_transient (head->next);
579
580 SH_FREE(head->paddr);
581 SH_FREE(head);
582 }
583 return NULL;
584}
585
586/* These variables are not used anywhere. They only exist
587 * to assign &pre, &ptr to them, which keeps gcc from
588 * putting it into a register, and avoids the 'clobbered
589 * by longjmp' warning. And no, 'volatile' proved insufficient.
590 */
591void * sh_dummy_531_pre = NULL;
592void * sh_dummy_532_ptr = NULL;
593
594/* check the list of open ports for any that are marked as UNKN
595 */
596static void sh_portchk_check_list (struct sh_portentry ** head,
597 int proto, int report)
598{
599 struct sh_portentry * ptr = *head;
600 struct sh_portentry * pre = *head;
601 char errbuf[256];
602
603 /* Take the address to keep gcc from putting them into registers.
604 * Avoids the 'clobbered by longjmp' warning.
605 */
606 sh_dummy_531_pre = (void*) &pre;
607 sh_dummy_532_ptr = (void*) &ptr;
608
609 while (ptr)
610 {
611 if (portchk_debug && report)
612 fprintf(stderr, _("check list: port %d/%s %d %d\n"),
613 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
614
615 if (ptr->status == SH_PORT_UNKN)
616 {
617 /* Don't report missing ports that are marked as optional
618 */
619 if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
620 {
621 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
622 ptr->interface, ptr->port, SH_PROTO_STR(proto),
623 ptr->service ? ptr->service : check_services(ptr->port, proto));
624#ifdef TEST_ONLY
625 if (report == SH_PORT_REPORT)
626 fprintf(stderr, _("%s\n"), errbuf);
627#else
628 if (report == SH_PORT_REPORT)
629 {
630 SH_MUTEX_LOCK(mutex_thread_nolog);
631 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
632 MSG_PORT_MISS, errbuf);
633 SH_MUTEX_UNLOCK(mutex_thread_nolog);
634 }
635#endif
636 }
637
638 ptr->status = SH_PORT_MISS;
639
640 if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
641 {
642 if (portchk_debug && report)
643 fprintf(stderr, _("removing: port %d/%s %d %d\n"),
644 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
645
646 if (ptr == *head)
647 {
648 *head = ptr->next;
649 if (ptr->service)
650 SH_FREE(ptr->service);
651 SH_FREE(ptr);
652 ptr = *head;
653 pre = *head;
654 continue;
655 }
656 else if (ptr->next == NULL)
657 {
658 pre->next = NULL;
659 if (ptr->service)
660 SH_FREE(ptr->service);
661 SH_FREE(ptr);
662 return;
663 }
664 else
665 {
666 pre->next = ptr->next;
667 if (ptr->service)
668 SH_FREE(ptr->service);
669 SH_FREE(ptr);
670 ptr = pre->next;
671 continue;
672 }
673 }
674 }
675 pre = ptr;
676 ptr = ptr->next;
677 }
678
679 sh_dummy_532_ptr = NULL;
680 sh_dummy_531_pre = NULL;
681
682 return;
683}
684
685
686static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
687 struct sh_sockaddr * paddr, char * service)
688{
689 struct sh_portentry * portlist;
690 char str_addr[SH_IP_BUF];
691
692
693 if (proto == IPPROTO_TCP)
694 portlist = portlist_tcp;
695 else
696 portlist = portlist_udp;
697
698 sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
699
700 if (service)
701 {
702 while (portlist)
703 {
704 if (portlist->service &&
705 0 == strcmp(service, portlist->service) &&
706 ( 0 == strcmp(portlist->interface, str_addr) ||
707 sh_ipvx_isany(paddr) ))
708 return portlist;
709 portlist = portlist->next;
710 }
711 }
712 else
713 {
714 while (portlist)
715 {
716 if (port == portlist->port &&
717 (0 == strcmp(portlist->interface, str_addr) ||
718 sh_ipvx_isany(paddr) ))
719 return portlist;
720 portlist = portlist->next;
721 }
722 }
723 return NULL;
724}
725
726
727static void sh_portchk_cmp_to_list (int proto, int port,
728 struct sh_sockaddr * paddr, char * service)
729{
730 struct sh_portentry * portent;
731 char errbuf[256];
732
733
734 portent = sh_portchk_get_from_list (proto, port, paddr, service);
735
736 if (service)
737 {
738 if (!portent)
739 {
740 char * path;
741 unsigned long qpid;
742 char user[USER_MAX];
743 char saddr[SH_IP_BUF];
744
745 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
746
747 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
748 saddr, port, SH_PROTO_STR(proto), service);
749
750 if (portchk_debug)
751 fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"),
752 saddr, port, SH_PROTO_STR(proto), service);
753
754#ifndef TEST_ONLY
755 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
756 SH_MUTEX_LOCK(mutex_thread_nolog);
757 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
758 MSG_PORT_NEW, errbuf, path, qpid, user);
759 SH_MUTEX_UNLOCK(mutex_thread_nolog);
760 SH_FREE(path);
761#endif
762 /*
763 * was not there, thus it is not in 'required' or 'optional' list
764 */
765 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
766 }
767 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
768 {
769 char * path;
770 unsigned long qpid;
771 char user[USER_MAX];
772 char saddr[SH_IP_BUF];
773
774 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
775
776 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
777 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
778#ifdef TEST_ONLY
779 fprintf(stderr, _("service: %s\n"), errbuf);
780#else
781 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
782 SH_MUTEX_LOCK(mutex_thread_nolog);
783 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
784 MSG_PORT_RESTART, errbuf, path, qpid, user);
785 SH_MUTEX_UNLOCK(mutex_thread_nolog);
786 SH_FREE(path);
787#endif
788
789 portent->status = SH_PORT_ISOK;
790 }
791 else if (port != portent->port && (-1) != portent->port)
792 {
793 char * path;
794 unsigned long qpid;
795 char user[USER_MAX];
796 char saddr[SH_IP_BUF];
797
798 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
799
800 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
801 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
802#ifdef TEST_ONLY
803 fprintf(stderr, _("service: %s\n"), errbuf);
804#else
805 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
806 SH_MUTEX_LOCK(mutex_thread_nolog);
807 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
808 MSG_PORT_NEWPORT, errbuf, path, qpid, user);
809 SH_MUTEX_UNLOCK(mutex_thread_nolog);
810 SH_FREE(path);
811#endif
812 portent->port = port;
813 portent->status = SH_PORT_ISOK;
814 }
815 else
816 {
817 portent->status = SH_PORT_ISOK;
818 }
819 }
820 else
821 {
822 if (!portent)
823 {
824 char * path;
825 unsigned long qpid;
826 char user[USER_MAX];
827 char saddr[SH_IP_BUF];
828
829 if (portchk_debug)
830 fprintf(stderr, _("call to sh_ipvx_ntoa (port %d)\n"), port);
831
832 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
833
834 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
835 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
836
837 if (portchk_debug)
838 fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"),
839 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
840
841#ifndef TEST_ONLY
842 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
843 SH_MUTEX_LOCK(mutex_thread_nolog);
844 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
845 MSG_PORT_NEW, errbuf, path, qpid, user);
846 SH_MUTEX_UNLOCK(mutex_thread_nolog);
847 SH_FREE(path);
848#endif
849
850 /* was not there, thus it is not in 'required' or 'optional' list
851 */
852 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
853 }
854 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
855 {
856 char * path;
857 unsigned long qpid;
858 char user[USER_MAX];
859 char saddr[SH_IP_BUF];
860
861 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
862
863 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
864 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
865#ifdef TEST_ONLY
866 fprintf(stderr, _("port : %s\n"), errbuf);
867#else
868 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
869 SH_MUTEX_LOCK(mutex_thread_nolog);
870 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
871 MSG_PORT_RESTART, errbuf, path, qpid, user);
872 SH_MUTEX_UNLOCK(mutex_thread_nolog);
873 SH_FREE(path);
874#endif
875
876 portent->status = SH_PORT_ISOK;
877 }
878 else
879 {
880 portent->status = SH_PORT_ISOK;
881 }
882 }
883
884 return;
885}
886
887
888/* Returns a static buffer containing the name of the service
889 * running on port <port> (from /etc/services)
890 * Returns NULL on failure
891 */
892static char * check_services (int port, int proto)
893{
894 static char buf[256];
895 char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
896
897 if (!service)
898 {
899 snprintf (buf, sizeof(buf), "%s",_("unknown"));
900 }
901 return buf;
902}
903
904/* Returns a static buffer containing the name of the service
905 * running on port <port> at <address> (from portmap daemon)
906 * Returns NULL on failure
907 */
908static char * check_rpc_list (int port, struct sockaddr_in * address,
909 unsigned long prot)
910{
911#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
912 struct pmaplist * head;
913 char *r;
914 static char buf[256];
915
916 head = pmap_getmaps(address);
917
918 if (head)
919 {
920 do /* while (head != NULL) */
921 {
922 if ((head->pml_map.pm_prot == prot) &&
923 (port == (int)head->pml_map.pm_port))
924 {
925 r = sh_getrpcbynumber((int)head->pml_map.pm_prog,
926 buf, sizeof(buf));
927 if (r)
928 {
929 return buf;
930 }
931 else
932 {
933 snprintf (buf, sizeof(buf), "RPC_%lu",
934 (unsigned long)head->pml_map.pm_prog);
935 return buf;
936 }
937 }
938 head = head->pml_next;
939 }
940 while (head != NULL);
941 }
942#else
943 (void) port;
944 (void) address;
945 (void) prot;
946#endif
947 return NULL;
948}
949
950void * sh_dummy_950_p = NULL;
951void * sh_dummy_951_p = NULL;
952
953static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
954{
955 int retval;
956 char * p = NULL;
957 char buf[8];
958#ifndef TEST_ONLY
959 char errmsg[256];
960 volatile int nerr;
961#endif
962 char errbuf[SH_ERRBUF_SIZE];
963 char ipbuf[SH_IP_BUF];
964
965 struct sh_sockaddr saddr;
966 socklen_t slen = 0;
967 volatile int sport = 0;
968
969 sh_dummy_950_p = (void*) &p;
970
971 sh_ipvx_set_port(paddr, port);
972
973 do {
974 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
975 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
976
977 if (retval == -1)
978 {
979#ifdef TEST_ONLY
980 if (portchk_debug)
981 perror(_("connect"));
982#else
983 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
984
985 nerr = errno;
986 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
987 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
988 SH_MUTEX_LOCK(mutex_thread_nolog);
989 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
990 errmsg, _("connect"));
991 SH_MUTEX_UNLOCK(mutex_thread_nolog);
992#endif
993 }
994 else
995 {
996 /* Register the used source port as transient. This will avoid
997 * the issue of lingering source ports being reported as a spurious
998 * service. The lingering source port is effectvely a race condition.
999 *
1000 * Also use this code to obtain the source port. Sometimes Samhain
1001 * reports on a port where it connects back to itself. In that case
1002 * source and destination port are the same.
1003 *
1004 * AGH, 23 Apr 2017 (www.2024sight.com).
1005 */
1006
1007#if defined(USE_IPVX)
1008 if (paddr->ss_family == AF_INET)
1009 {
1010 saddr.ss_family = AF_INET;
1011 slen = sizeof( struct sockaddr_in );
1012 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1013 }
1014 else
1015 {
1016 saddr.ss_family = AF_INET6;
1017 slen = sizeof( struct sockaddr_in6 );
1018 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1019 }
1020#else
1021 saddr.ss_family = AF_INET;
1022 slen = sizeof( struct sockaddr_in );
1023 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1024#endif
1025
1026 if ( retval == 0 )
1027 {
1028 sport = sh_ipvx_get_port(&saddr);
1029 sh_portchk_transient(sport, &saddr, IPPROTO_UDP);
1030 }
1031 else
1032 {
1033#ifdef TEST_ONLY
1034 if (portchk_debug)
1035 perror(_("getsockname"));
1036#else
1037 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1038 nerr = errno;
1039 sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/udp: %s"),
1040 ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1041 SH_MUTEX_LOCK(mutex_thread_nolog);
1042 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("getsockname"));
1043 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1044#endif
1045 }
1046
1047 if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1048 {
1049 do {
1050 retval = send (fd, buf, 0, 0);
1051 } while (retval < 0 && errno == EINTR);
1052
1053 if (retval == -1 && errno == ECONNREFUSED)
1054 {
1055 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1056 if (portchk_debug)
1057 fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
1058 port, ipbuf);
1059 }
1060 else
1061 {
1062 /* Only the second send() may catch the error
1063 */
1064 do {
1065 retval = send (fd, buf, 0, 0);
1066 } while (retval < 0 && errno == EINTR);
1067
1068 if (retval == -1 && errno == ECONNREFUSED)
1069 {
1070 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1071 if (portchk_debug)
1072 fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
1073 port, ipbuf);
1074 }
1075 else if (retval != -1)
1076 {
1077 /* Try to get service name from portmap
1078 */
1079 if (paddr->ss_family == AF_INET)
1080 {
1081 p = check_rpc_list (port,
1082 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
1083 IPPROTO_UDP);
1084 }
1085
1086 sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
1087
1088 /* If not an RPC service, try to get name from /etc/services
1089 */
1090 if (!p)
1091 p = check_services(port, IPPROTO_UDP);
1092
1093 if (portchk_debug)
1094 {
1095 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1096 fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"),
1097 port, ipbuf, p);
1098 }
1099
1100 }
1101 else
1102 {
1103 if (portchk_debug)
1104 {
1105 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1106 fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"),
1107 port, ipbuf, errno);
1108 }
1109 }
1110 }
1111 }
1112 else
1113 {
1114 if (portchk_debug)
1115 {
1116 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1117 fprintf(stderr, _("check port_udp: %5d/udp on %15s same source and destination port\n"),
1118 port, ipbuf);
1119 }
1120 }
1121 }
1122 sl_close_fd (FIL__, __LINE__, fd);
1123 sh_dummy_950_p = NULL;
1124 return 0;
1125}
1126
1127static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
1128{
1129 volatile int retval;
1130 int flags;
1131 char * p = NULL;
1132#ifndef TEST_ONLY
1133 char errmsg[256];
1134 volatile int nerr;
1135#endif
1136 char errbuf[SH_ERRBUF_SIZE];
1137 char ipbuf[SH_IP_BUF];
1138
1139 struct sh_sockaddr saddr;
1140 socklen_t slen = 0;
1141 volatile int sport = 0;
1142
1143 sh_dummy_951_p = (void*) &p;
1144
1145 sh_ipvx_set_port(paddr, port);
1146
1147 do {
1148 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
1149 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
1150
1151 if (retval == -1 && errno == ECONNREFUSED)
1152 {
1153 if (portchk_debug)
1154 {
1155 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1156 fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
1157 port, ipbuf);
1158 }
1159 }
1160 else if (retval == -1)
1161 {
1162#ifdef TEST_ONLY
1163 if (portchk_debug)
1164 perror(_("connect"));
1165#else
1166 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1167 nerr = errno;
1168 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
1169 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
1170 SH_MUTEX_LOCK(mutex_thread_nolog);
1171 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1172 errmsg, _("connect"));
1173 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1174#endif
1175 }
1176 else
1177 {
1178 /* Register the used source port as transient. This will avoid
1179 * the issue of lingering source ports being reported as a spurious
1180 * service. The lingering source port is effectively a race condition.
1181 *
1182 * Also use this code to obtain the source port. Sometimes Samhain
1183 * reports on a port where it connects back to itself. In that case
1184 * source and destination port are the same.
1185 *
1186 * AGH, 23 Apr 2017 (www.2024sight.com).
1187 */
1188
1189#if defined(USE_IPVX)
1190 if (paddr->ss_family == AF_INET)
1191 {
1192 saddr.ss_family = AF_INET;
1193 slen = sizeof( struct sockaddr_in );
1194 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1195 }
1196 else
1197 {
1198 saddr.ss_family = AF_INET6;
1199 slen = sizeof( struct sockaddr_in6 );
1200 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1201 }
1202#else
1203 saddr.ss_family = AF_INET;
1204 slen = sizeof( struct sockaddr_in );
1205 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1206#endif
1207
1208 if ( retval == 0 )
1209 {
1210 sport = sh_ipvx_get_port(&saddr);
1211 sh_portchk_transient(sport, &saddr, IPPROTO_TCP);
1212 }
1213 else
1214 {
1215#ifdef TEST_ONLY
1216 if (portchk_debug)
1217 perror(_("getsockname"));
1218#else
1219 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1220 nerr = errno;
1221 sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/tcp: %s"),
1222 ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1223 SH_MUTEX_LOCK(mutex_thread_nolog);
1224 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1225 errmsg, _("getsockname"));
1226 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1227#endif
1228 }
1229
1230 if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1231 {
1232 /* Try to get service name from portmap
1233 */
1234 if (paddr->ss_family == AF_INET)
1235 {
1236 p = check_rpc_list (port,
1237 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
1238 IPPROTO_TCP);
1239 }
1240
1241 sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
1242
1243 /* If not an RPC service, try to get name from /etc/services
1244 */
1245 if (!p)
1246 p = check_services(port, IPPROTO_TCP);
1247
1248 if (portchk_debug)
1249 {
1250 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1251 fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"),
1252 port, ipbuf, p);
1253 }
1254 }
1255 else
1256 {
1257 if (portchk_debug)
1258 {
1259 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1260 fprintf(stderr, _("check port_udp: %5d/tcp on %15s same source and destination port\n"),
1261 port, ipbuf);
1262 }
1263 }
1264
1265#if !defined(O_NONBLOCK)
1266#if defined(O_NDELAY)
1267#define O_NONBLOCK O_NDELAY
1268#else
1269#define O_NONBLOCK 0
1270#endif
1271#endif
1272
1273 /* prepare to close connection gracefully
1274 */
1275 if (port == 22) /* ssh */
1276 {
1277 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1278 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1279 retval = write (fd, _("SSH-2.0-Foobar"), 14);
1280 if (retval > 0) retval = write (fd, "\r\n", 2);
1281 }
1282 else if (port == 25) /* smtp */
1283 {
1284 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1285 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1286 retval = write (fd, _("QUIT"), 4);
1287 if (retval > 0) retval = write (fd, "\r\n", 2);
1288 }
1289 else if (port == 79) /* finger */
1290 {
1291 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1292 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1293 retval = write (fd, "\r\n", 2);
1294 }
1295 else if (port == 110) /* pop3 */
1296 {
1297 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1298 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1299 retval = write (fd, _("QUIT"), 4);
1300 if (retval > 0) retval = write (fd, "\r\n", 2);
1301 }
1302 else if (port == 143) /* imap */
1303 {
1304 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1305 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1306 retval = write (fd, _("A01 LOGOUT"), 10);
1307 if (retval > 0) retval = write (fd, "\r\n", 2);
1308 }
1309
1310 if (portchk_debug && retval < 0)
1311 fprintf(stderr, _("check port: error writing to port %5d\n"),
1312 port);
1313 }
1314 sl_close_fd (FIL__, __LINE__, fd);
1315 sh_dummy_951_p = NULL;
1316 return 0;
1317}
1318
1319/* typedef uint32_t in_addr_t;
1320 * struct in_addr
1321 * {
1322 * in_addr_t s_addr;
1323 * };
1324 */
1325
1326#define SH_IFACE_MAX 64
1327#define SH_IFACE_ADDR 0
1328#define SH_IFACE_DEV 1
1329
1330struct portchk_interfaces {
1331 struct sh_sockaddr iface;
1332 int type;
1333};
1334
1335static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1336static int iface_list_used = 0;
1337static int iface_initialized = 0;
1338
1339#ifdef TEST_ONLY
1340static char * portchk_hostname = NULL;
1341#else
1342static char * portchk_hostname = sh.host.name;
1343#endif
1344
1345static int sh_portchk_init_internal (void)
1346{
1347 volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1348 char errbuf[256];
1349#if defined(USE_IPVX)
1350 struct addrinfo hints;
1351 struct addrinfo *res;
1352#else
1353 struct hostent * hent;
1354#endif
1355 char ipbuf[SH_IP_BUF];
1356
1357 if (portchk_debug)
1358 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
1359
1360 if (!portchk_hostname)
1361 return -1;
1362
1363 if (sh_portchk_active == S_FALSE)
1364 return -1;
1365
1366 SH_MUTEX_LOCK(mutex_port_check);
1367 if (iface_initialized == 0)
1368 {
1369 iface_list_used = 0;
1370 iface_initialized = 1;
1371 }
1372
1373#if !defined(USE_IPVX)
1374 SH_MUTEX_LOCK(mutex_resolv);
1375 hent = sh_gethostbyname(portchk_hostname);
1376 i = 0;
1377 while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
1378 {
1379 struct sockaddr_in sin;
1380 struct sh_sockaddr iface_tmp;
1381
1382 memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
1383 sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1384
1385 for (j = 0; j < iface_list_used; ++j)
1386 {
1387 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1388 {
1389 goto next_iface;
1390 }
1391 }
1392
1393 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1394 AF_INET, (struct sockaddr *)&sin);
1395 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1396
1397 if (portchk_debug)
1398 {
1399 char buf[256];
1400 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1401 fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
1402 }
1403 ++iface_list_used;
1404
1405 next_iface:
1406 ++i;
1407 }
1408 SH_MUTEX_UNLOCK(mutex_resolv);
1409#else
1410 memset(&hints, '\0', sizeof(hints));
1411 hints.ai_family = PF_UNSPEC;
1412 hints.ai_flags = AI_ADDRCONFIG;
1413
1414 if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1415 {
1416 struct addrinfo *p = res;
1417 struct sh_sockaddr iface_tmp;
1418
1419 while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
1420 {
1421 sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1422
1423 for (j = 0; j < iface_list_used; ++j)
1424 {
1425 if (portchk_debug)
1426 {
1427 char buf1[256], buf2[256];
1428 sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
1429 sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1430 fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
1431 }
1432 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1433 {
1434 if (portchk_debug)
1435 fprintf(stderr, _("skipping interface[%d]\n"), j);
1436 goto next_iface;
1437 }
1438 }
1439 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1440 p->ai_family, p->ai_addr);
1441 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1442 if (portchk_debug)
1443 {
1444 char buf[256];
1445 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1446 fprintf(stderr, _("added interface[%d]: %s\n"), iface_list_used, buf);
1447 }
1448
1449 ++iface_list_used;
1450
1451 next_iface:
1452 p = p->ai_next;
1453 }
1454 freeaddrinfo(res);
1455 }
1456#endif
1457
1458 for (i = 0; i < iface_list_used; ++i)
1459 {
1460 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
1461 sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
1462
1463 SH_MUTEX_LOCK(mutex_thread_nolog);
1464 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1465 errbuf, _("sh_portchk_init"));
1466 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1467 }
1468 SH_MUTEX_UNLOCK(mutex_port_check);
1469
1470 return 0;
1471}
1472
1473int sh_portchk_init (struct mod_type * arg)
1474{
1475#ifndef HAVE_PTHREAD
1476 (void) arg;
1477#endif
1478
1479 if (sh_portchk_active == S_FALSE)
1480 return SH_MOD_FAILED;
1481 if (!portchk_hostname)
1482 return SH_MOD_FAILED;
1483
1484#ifdef HAVE_PTHREAD
1485 if (arg != NULL && arg->initval < 0 &&
1486 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1487 {
1488 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1489 return SH_MOD_THREAD;
1490 else
1491 return SH_MOD_FAILED;
1492 }
1493 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1494 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1495 {
1496 (void) sh_portchk_init_internal();
1497 return SH_MOD_THREAD;
1498 }
1499#endif
1500 return sh_portchk_init_internal();
1501}
1502
1503static void dev_list_kill();
1504
1505#if !defined(TEST_ONLY)
1506int sh_portchk_reconf (void)
1507{
1508 SH_MUTEX_LOCK(mutex_port_check);
1509 iface_initialized = 0;
1510 sh_portchk_active = 1;
1511 sh_portchk_check_udp = 1;
1512 sh_portchk_interval = SH_PORTCHK_INTERVAL;
1513
1514 sh_portchk_minport = -1;
1515 sh_portchk_maxport = -1;
1516
1517 dev_list_kill();
1518
1519 portlist_udp = sh_portchk_kill_list (portlist_udp);
1520 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1521
1522 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1523 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
1524 sh_port2proc_finish();
1525
1526 SH_MUTEX_UNLOCK(mutex_port_check);
1527 return 0;
1528}
1529
1530int sh_portchk_cleanup (void)
1531{
1532 return sh_portchk_reconf ();
1533}
1534
1535int sh_portchk_timer (time_t tcurrent)
1536{
1537 static time_t lastcheck = 0;
1538
1539 SL_ENTER(_("sh_portchk_timer"));
1540 if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
1541 {
1542 lastcheck = tcurrent;
1543 SL_RETURN((-1), _("sh_portchk_timer"));
1544 }
1545 SL_RETURN(0, _("sh_portchk_timer"));
1546}
1547#endif
1548
1549static int check_port_generic (int port, int domain, int type, int protocol)
1550{
1551 volatile int i = 0;
1552 int sock = -1;
1553 int flag = 1; /* non-zero to enable an option */
1554 struct sh_sockaddr paddr;
1555 char errbuf[SH_ERRBUF_SIZE];
1556
1557 /* Check all interfaces for this host
1558 */
1559 while (i < iface_list_used)
1560 {
1561 memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
1562
1563 if (paddr.ss_family != domain)
1564 {
1565 ++i;
1566 continue;
1567 }
1568
1569 if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
1570 {
1571 ++i;
1572 continue;
1573 }
1574
1575 if (0 != sh_portchk_is_transient(port, &paddr, protocol))
1576 {
1577 ++i;
1578 continue;
1579 }
1580
1581 if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1582 {
1583 ++i;
1584#ifdef TEST_ONLY
1585 if (portchk_debug)
1586 perror(_("socket"));
1587#else
1588
1589#ifndef EPROTONOSUPPORT
1590#define EPROTONOSUPPORT 0
1591#endif
1592#ifndef EAFNOSUPPORT
1593#define EAFNOSUPPORT 0
1594#endif
1595 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1596 {
1597 SH_MUTEX_LOCK(mutex_thread_nolog);
1598 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1599 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1600 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1601 }
1602#endif
1603 continue;
1604 }
1605 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1606 (void *) &flag, sizeof(flag)) < 0 )
1607 {
1608 ++i;
1609#ifdef TEST_ONLY
1610 if (portchk_debug)
1611 perror(_("setsockopt"));
1612#else
1613 SH_MUTEX_LOCK(mutex_thread_nolog);
1614 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1615 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1616 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1617#endif
1618 continue;
1619 }
1620
1621
1622 if (protocol == IPPROTO_TCP)
1623 check_port_tcp_internal(sock, port, &paddr);
1624 else
1625 check_port_udp_internal(sock, port, &paddr);
1626
1627 ++i;
1628 }
1629
1630 return 0;
1631}
1632
1633
1634
1635static int check_port_udp (int port, int domain)
1636{
1637 return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
1638}
1639
1640static int check_port_tcp (int port, int domain)
1641{
1642 return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
1643}
1644
1645
1646static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
1647 int domain, int type, int protocol)
1648{
1649 /*
1650 int min_port = 1024;
1651 int max_port = 65535;
1652 */
1653
1654 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1655 volatile int max_port = max_port_arg;
1656 int retval;
1657 int sock = -1;
1658#if 0
1659 int flag = 1; /* non-zero to enable an option */
1660#endif
1661 struct sockaddr_in addr4;
1662 struct sockaddr_in6 addr6;
1663
1664 int addrlen4 = sizeof(addr4);
1665 int addrlen6 = sizeof(addr6);
1666
1667 struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
1668
1669 char errbuf[SH_ERRBUF_SIZE];
1670
1671 if (min_port == -1)
1672 min_port = 0;
1673 if (max_port == -1)
1674 max_port = 65535;
1675
1676 if (portchk_debug)
1677 fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"),
1678 min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"),
1679 (protocol == IPPROTO_TCP) ? _("tcp") : _("udp"));
1680
1681 for (port = min_port; port <= max_port; ++port)
1682 {
1683 if ((sock = socket(domain, type, protocol)) < 0 )
1684 {
1685#ifdef TEST_ONLY
1686 if (portchk_debug)
1687 perror(_("socket"));
1688#else
1689#ifndef EPROTONOSUPPORT
1690#define EPROTONOSUPPORT 0
1691#endif
1692#ifndef EAFNOSUPPORT
1693#define EAFNOSUPPORT 0
1694#endif
1695 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1696 {
1697 SH_MUTEX_LOCK(mutex_thread_nolog);
1698 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1699 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1700 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1701 }
1702#endif
1703 continue;
1704 }
1705
1706#if 0
1707 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1708 (void *) &flag, sizeof(flag)) < 0 )
1709 {
1710#ifdef TEST_ONLY
1711 if (portchk_debug)
1712 perror(_("setsockopt"));
1713#else
1714 SH_MUTEX_LOCK(mutex_thread_nolog);
1715 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1716 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1717 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1718#endif
1719 continue;
1720 }
1721#endif
1722
1723 if (domain == AF_INET)
1724 {
1725 addr4.sin_family = AF_INET;
1726 addr4.sin_port = htons(port);
1727 addr4.sin_addr.s_addr = INADDR_ANY;
1728 retval = bind (sock, (struct sockaddr *) &addr4, addrlen4);
1729 }
1730 else
1731 {
1732 addr6.sin6_family = AF_INET6;
1733 addr6.sin6_port = htons(port);
1734 memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr));
1735 retval = bind (sock, (struct sockaddr *) &addr6, addrlen6);
1736 }
1737
1738 if (retval == 0)
1739 {
1740 /* we can bind the port, thus it is unused
1741 */
1742 sl_close_fd (FIL__, __LINE__, sock);
1743 }
1744 else
1745 {
1746 if (errno == EINVAL || errno == EADDRINUSE)
1747 {
1748 /* try to connect to the port
1749 */
1750 if (protocol == IPPROTO_TCP)
1751 check_port_tcp(port, domain);
1752 else
1753 check_port_udp(port, domain);
1754 }
1755 else
1756 {
1757#ifdef TEST_ONLY
1758 if (portchk_debug)
1759 perror(_("bind"));
1760#else
1761 SH_MUTEX_LOCK(mutex_thread_nolog);
1762 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1763 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1764 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1765#endif
1766 }
1767 sl_close_fd (FIL__, __LINE__, sock);
1768 }
1769 }
1770
1771 if (protocol == IPPROTO_TCP)
1772 transient_tcp=sh_portchk_kill_transient(transient_tcp);
1773 else
1774 transient_udp=sh_portchk_kill_transient(transient_udp);
1775
1776 return 0;
1777}
1778
1779static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1780{
1781#if defined(USE_IPVX)
1782 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1783 SOCK_STREAM, IPPROTO_TCP);
1784#endif
1785 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1786 SOCK_STREAM, IPPROTO_TCP);
1787}
1788
1789static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1790{
1791#if defined(USE_IPVX)
1792 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1793 SOCK_DGRAM, IPPROTO_UDP);
1794#endif
1795 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1796 SOCK_DGRAM, IPPROTO_UDP);
1797}
1798
1799/* Subroutine to add an interface
1800 */
1801void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
1802
1803static int sh_portchk_add_interface_int (const char * str, int type)
1804{
1805 struct sh_sockaddr saddr;
1806 char errbuf[256];
1807 char buf[64];
1808
1809 sh_dummy_1564_str = (void*) &str;
1810
1811 if (iface_initialized == 0)
1812 {
1813 iface_list_used = 0;
1814 iface_initialized = 1;
1815 }
1816
1817 do {
1818
1819 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1820
1821 if (*str)
1822 {
1823 char ipbuf[SH_IP_BUF];
1824 unsigned int i = 0;
1825 while (*str && i < (sizeof(buf)-1) &&
1826 *str != ',' && *str != ' ' && *str != '\t')
1827 {
1828 buf[i] = *str; ++str; ++i;
1829 }
1830 buf[i] = '\0';
1831
1832 if (0 == sh_ipvx_aton(buf, &saddr))
1833 return -1;
1834
1835 if (iface_list_used == SH_IFACE_MAX)
1836 return -1;
1837
1838 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1839 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
1840 SH_MUTEX_LOCK(mutex_thread_nolog);
1841 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1842 errbuf, _("sh_portchk_add_interface"));
1843 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1844
1845 memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1846 iface_list[iface_list_used].type = type;
1847 ++iface_list_used;
1848 }
1849 } while (*str);
1850
1851 sh_dummy_1564_str = NULL;
1852 return 0;
1853}
1854
1855static int sh_portchk_add_interface (const char * str)
1856{
1857 return sh_portchk_add_interface_int (str, SH_IFACE_ADDR);
1858}
1859
1860#if defined(HAVE_IFADDRS_H)
1861/*
1862 * subroutines to add a device
1863 */
1864void * sh_dummy_1651_ifa = NULL; /* fix clobbered by.. warning */
1865
1866static int portchk_add_device_int (const char * buf)
1867{
1868 struct ifaddrs *ifaddr, *ifa;
1869 int family;
1870#ifndef NI_MAXHOST
1871#define NI_MAXHOST 1025
1872#endif
1873 char host[NI_MAXHOST];
1874
1875 sh_dummy_1651_ifa = (void*) &ifa;
1876
1877 if (getifaddrs(&ifaddr) == -1)
1878 {
1879 volatile int nerr = errno;
1880 char errbuf[SH_ERRBUF_SIZE];
1881 sh_error_message(errno, errbuf, sizeof(errbuf));
1882 SH_MUTEX_LOCK(mutex_thread_nolog);
1883 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1884 errbuf, _("getifaddrs"));
1885 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1886 return -1;
1887 }
1888
1889 for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1890 {
1891 if (ifa->ifa_addr == NULL)
1892 continue;
1893
1894 if (strcmp(ifa->ifa_name, buf) == 0)
1895 {
1896 volatile int s = 0;
1897 family = ifa->ifa_addr->sa_family;
1898
1899 if (family == AF_INET)
1900 {
1901 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in),
1902 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1903
1904 if (s == 0)
1905 {
1906 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1907 {
1908 freeifaddrs(ifaddr);
1909 return -1;
1910 }
1911 }
1912 }
1913
1914#if defined(USE_IPVX)
1915 if (family == AF_INET6)
1916 {
1917 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in6),
1918 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1919
1920 if (s == 0)
1921 {
1922 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1923 {
1924 freeifaddrs(ifaddr);
1925 return -1;
1926 }
1927 }
1928 }
1929#endif
1930
1931 if (s != 0)
1932 {
1933 char errbuf[SH_ERRBUF_SIZE];
1934 sl_strlcpy(errbuf, buf, sizeof(errbuf));
1935 sl_strlcat(errbuf, ": ", sizeof(errbuf));
1936 sl_strlcat(errbuf, gai_strerror(s), sizeof(errbuf));
1937 SH_MUTEX_LOCK(mutex_thread_nolog);
1938 sh_error_handle((-1), FIL__, __LINE__, s, MSG_E_SUBGEN,
1939 errbuf, _("getnameinfo"));
1940 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1941 }
1942
1943 }
1944 }
1945
1946 freeifaddrs(ifaddr);
1947 return 0;
1948}
1949
1950struct added_dev {
1951 char dev[64];
1952 struct added_dev * next;
1953};
1954
1955static struct added_dev * dev_list = NULL;
1956
1957static void dev_list_add (char * buf)
1958{
1959 struct added_dev * new = SH_ALLOC(sizeof(struct added_dev));
1960 sl_strlcpy(new->dev, buf, 64);
1961 new->next = dev_list;
1962 dev_list = new;
1963 return;
1964}
1965
1966static void dev_list_kill ()
1967{
1968 struct added_dev * old;
1969 struct added_dev * new = dev_list;
1970 dev_list = NULL;
1971
1972 while (new)
1973 {
1974 old = new;
1975 new = new->next;
1976 SH_FREE(old);
1977 }
1978 return;
1979}
1980
1981static int sh_portchk_add_device (const char * str)
1982{
1983 char buf[64];
1984
1985 do {
1986
1987 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1988
1989 if (*str)
1990 {
1991 unsigned int i = 0;
1992 while (*str && i < (sizeof(buf)-1) &&
1993 *str != ',' && *str != ' ' && *str != '\t') {
1994 buf[i] = *str; ++str; ++i;
1995 }
1996 buf[i] = '\0';
1997
1998 if (portchk_add_device_int (buf) < 0)
1999 return -1;
2000
2001 dev_list_add(buf);
2002 }
2003 } while (*str);
2004
2005 return 0;
2006}
2007
2008static int iface_comp (const void *a, const void *b)
2009{
2010 const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
2011 const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
2012 return (aa->type - bb->type);
2013}
2014
2015static void iface_qsort()
2016{
2017 qsort(&iface_list[0], iface_list_used, sizeof(struct portchk_interfaces),
2018 iface_comp);
2019 return;
2020}
2021
2022static void recheck_devices()
2023{
2024 if (dev_list)
2025 {
2026 struct added_dev * dev = dev_list;
2027 int i, j;
2028
2029 if (portchk_debug)
2030 {
2031 for (j = 0; j < iface_list_used; ++j)
2032 {
2033 char buf[SH_IP_BUF];
2034 struct portchk_interfaces * aa = &(iface_list[j]);
2035 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2036 fprintf(stderr, _("presort: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2037 }
2038 }
2039
2040 iface_qsort();
2041
2042 if (portchk_debug)
2043 {
2044 for (j = 0; j < iface_list_used; ++j)
2045 {
2046 char buf[SH_IP_BUF];
2047 struct portchk_interfaces * aa = &(iface_list[j]);
2048 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2049 fprintf(stderr, _("postsor: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2050 }
2051 }
2052
2053 i = 0;
2054 for (j = 0; j < iface_list_used; ++j)
2055 if (iface_list[j].type == SH_IFACE_DEV) ++i;
2056 iface_list_used -= i;
2057
2058 if (portchk_debug)
2059 {
2060 for (j = 0; j < iface_list_used; ++j)
2061 {
2062 char buf[SH_IP_BUF];
2063 struct portchk_interfaces * aa = &(iface_list[j]);
2064 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2065 fprintf(stderr, _("postdel: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2066 }
2067 }
2068
2069 while (dev)
2070 {
2071 portchk_add_device_int (dev->dev);
2072 dev = dev->next;
2073 }
2074 }
2075 return;
2076}
2077#endif
2078
2079/* verify whether port/interface is blacklisted (do not check)
2080 */
2081static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
2082 int proto)
2083{
2084 struct sh_port * head;
2085
2086 if (proto == IPPROTO_TCP)
2087 head = blacklist_tcp;
2088 else
2089 head = blacklist_udp;
2090
2091 while (head)
2092 {
2093 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2094 return 1;
2095 head = head->next;
2096 }
2097 return 0;
2098}
2099
2100
2101static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
2102{
2103 struct sh_port * black;
2104 struct sh_port * head;
2105
2106 if (proto == IPPROTO_TCP)
2107 head = blacklist_tcp;
2108 else
2109 head = blacklist_udp;
2110
2111 black = head;
2112
2113 while (black)
2114 {
2115 if (black->port == port &&
2116 0 == sh_ipvx_cmp(head->paddr, saddr))
2117 return -1;
2118 black = black->next;
2119 }
2120
2121 black = SH_ALLOC (sizeof(struct sh_port));
2122 black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2123 black->port = port;
2124 memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
2125 black->next = head;
2126
2127 if (proto == IPPROTO_TCP)
2128 blacklist_tcp = black;
2129 else
2130 blacklist_udp = black;
2131
2132 if (portchk_debug)
2133 {
2134 int checkit = sh_portchk_is_blacklisted(port, saddr, proto);
2135 fprintf(stderr, _("port blacklisted: %d %s\n"), port,
2136 (checkit == 1) ? _("ok") : _("fail"));
2137 }
2138 return 0;
2139}
2140
2141
2142/* verify whether port/interface is transient (used as source port
2143 *hence no check required)
2144 */
2145static int sh_portchk_is_transient(int port, struct sh_sockaddr * saddr,
2146 int proto)
2147{
2148 struct sh_port * head;
2149
2150 if (proto == IPPROTO_TCP)
2151 head = transient_tcp;
2152 else
2153 head = transient_udp;
2154
2155 while (head)
2156 {
2157 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2158 return 1;
2159 head = head->next;
2160 }
2161 return 0;
2162}
2163
2164
2165static int sh_portchk_transient(int port, struct sh_sockaddr * saddr, int proto)
2166{
2167 struct sh_port * transient;
2168 struct sh_port * head;
2169
2170 if (sh_portchk_transients == S_FALSE)
2171 return 0;
2172
2173 if (proto == IPPROTO_TCP)
2174 head = transient_tcp;
2175 else
2176 head = transient_udp;
2177
2178 transient = head;
2179
2180 while (transient)
2181 {
2182 if (transient->port == port &&
2183 0 == sh_ipvx_cmp(head->paddr, saddr))
2184 return -1;
2185 transient = transient->next;
2186 }
2187
2188 transient = SH_ALLOC (sizeof(struct sh_port));
2189 transient->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2190 transient->port = port;
2191 memcpy(transient->paddr, saddr, sizeof(struct sh_sockaddr));
2192 transient->next = head;
2193
2194 if (proto == IPPROTO_TCP)
2195 transient_tcp = transient;
2196 else
2197 transient_udp = transient;
2198
2199 if (portchk_debug)
2200 {
2201 int checkit = sh_portchk_is_transient(port, saddr, proto);
2202 fprintf(stderr, _("port transient: %d %s\n"), port,
2203 (checkit == 1) ? _("ok") : _("fail"));
2204 }
2205 return 0;
2206}
2207
2208
2209/* Subroutine to add a required or optional port/service
2210 */
2211static int sh_portchk_add_required_port_generic (char * service,
2212 char * interface, int type)
2213{
2214 char buf[256] = { '\0' };
2215 int proto;
2216 char * p;
2217 char * endptr;
2218 unsigned long int port;
2219 struct sh_sockaddr saddr;
2220 struct sh_portentry * portent;
2221
2222 if (0 == sh_ipvx_aton(interface, &saddr))
2223 return -1;
2224
2225 sl_strlcpy (buf, service, sizeof(buf));
2226
2227 p = strchr(buf, '/');
2228 if (!p)
2229 return -1;
2230 if (0 == strcasecmp(p, _("/tcp")))
2231 proto = IPPROTO_TCP;
2232 else if (0 == strcasecmp(p, _("/udp")))
2233 proto = IPPROTO_UDP;
2234 else
2235 return -1;
2236
2237 *p = '\0';
2238 port = strtoul(buf, &endptr, 0);
2239
2240 if (portchk_debug)
2241 {
2242 char buf[SH_IP_BUF];
2243 sh_ipvx_ntoa(buf, sizeof(buf), &saddr);
2244 fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"),
2245 interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"),
2246 sh_port_type2str(type));
2247 }
2248
2249 /* Blacklisted ports
2250 */
2251 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
2252 return (sh_portchk_blacklist(port, &saddr, proto));
2253
2254 if (*endptr != '\0')
2255 {
2256 portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
2257 if (!portent)
2258 {
2259 if (portchk_debug)
2260 fprintf(stderr, _("add_required_port %d\n"), (int) port);
2261 sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN);
2262 }
2263 else
2264 {
2265#ifdef TEST_ONLY
2266 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
2267#else
2268 SH_MUTEX_LOCK(mutex_thread_nolog);
2269 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2270 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2271 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2272#endif
2273 return -1;
2274 }
2275 }
2276 else if (port <= 65535)
2277 {
2278 portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
2279 if (!portent)
2280 {
2281 if (portchk_debug)
2282 fprintf(stderr, _("add_required_port: open port: %d/%s\n"),
2283 (int) port, SH_PROTO_STR(proto));
2284 sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN);
2285 }
2286 else
2287 {
2288#ifdef TEST_ONLY
2289 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
2290#else
2291 SH_MUTEX_LOCK(mutex_thread_nolog);
2292 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2293 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2294 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2295#endif
2296 return -1;
2297 }
2298 }
2299 else
2300 return -1;
2301
2302 return 0;
2303}
2304
2305/* Internal interface to add required or optional ports as 'iface:portlist'
2306 */
2307static int sh_portchk_add_required_generic (const char * str, int type)
2308{
2309 size_t ll = 0;
2310 int status;
2311
2312 char * interface = NULL;
2313 char * list;
2314 char * p;
2315#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2316 char * saveptr;
2317#endif
2318
2319 if (!str)
2320 return -1;
2321
2322 if (strchr(str, ':'))
2323 {
2324 char *last = strrchr(str, ':');
2325 if (last != NULL)
2326 {
2327 size_t tolast = (last - str);
2328 interface = SH_ALLOC(tolast+1);
2329 sl_strlcpy(interface, str, tolast+1);
2330 interface[tolast] = '\0';
2331
2332 ll = tolast;
2333
2334 while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
2335 ++ll;
2336 }
2337 }
2338 else
2339 {
2340 interface = SH_ALLOC(8);
2341 sl_strlcpy(interface, _("0.0.0.0"), 8);
2342 interface[7] = '\0';
2343 while (str[ll] == ' ' || str[ll] == '\t')
2344 ++ll;
2345 }
2346
2347 if (!interface)
2348 return -1;
2349
2350 if (str[ll] == '\0')
2351 {
2352 SH_FREE(interface);
2353 return -1;
2354 }
2355
2356 if (portchk_debug)
2357 fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
2358
2359 list = sh_util_strdup(&str[ll]);
2360#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2361 p = strtok_r (list, " ,\t", &saveptr);
2362#else
2363 p = strtok (list, " ,\t");
2364#endif
2365 if (!p)
2366 {
2367 SH_FREE(interface);
2368 SH_FREE(list);
2369 return -1;
2370 }
2371 while (p)
2372 {
2373 status = sh_portchk_add_required_port_generic (p, interface, type);
2374
2375 if (-1 == status)
2376 {
2377 SH_FREE(interface);
2378 SH_FREE(list);
2379 return -1;
2380 }
2381#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2382 p = strtok_r (NULL, " ,\t", &saveptr);
2383#else
2384 p = strtok (NULL, " ,\t");
2385#endif
2386 }
2387 SH_FREE(interface);
2388 SH_FREE(list);
2389 return 0;
2390}
2391
2392/* User interface to add required ports as 'iface:portlist'
2393 */
2394static int sh_portchk_add_required (const char * str)
2395{
2396 return sh_portchk_add_required_generic (str, SH_PORT_REQ);
2397}
2398
2399/* User interface to add optional ports as 'iface:portlist'
2400 */
2401static int sh_portchk_add_optional (const char * str)
2402{
2403 return sh_portchk_add_required_generic (str, SH_PORT_OPT);
2404}
2405
2406/* User interface to add ignoreable ports as 'iface:portlist'
2407 */
2408static int sh_portchk_add_ignore (const char * str)
2409{
2410 return sh_portchk_add_required_generic (str, SH_PORT_IGN);
2411}
2412
2413/* User interface to add ports that should not be checked as 'iface:portlist'
2414 */
2415static int sh_portchk_add_blacklist (const char * str)
2416{
2417 return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST);
2418}
2419
2420/* Interface to run port check
2421 */
2422int sh_portchk_check ()
2423{
2424 volatile int min_port;
2425 static int noprivports = 0;
2426
2427 SH_MUTEX_LOCK(mutex_port_check);
2428
2429 min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
2430
2431 if (sh_portchk_active != S_FALSE)
2432 {
2433 SH_MUTEX_LOCK(mutex_thread_nolog);
2434 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2435 _("Checking for open ports"),
2436 _("sh_portchk_check"));
2437 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2438
2439 sh_portchk_reset_lists();
2440
2441#if defined(HAVE_IFADDRS_H)
2442 recheck_devices();
2443#endif
2444
2445 if ((0 != geteuid()) && (min_port < 1024))
2446 {
2447 min_port = 1024;
2448 if (noprivports == 0)
2449 {
2450#ifdef TEST_ONLY
2451 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
2452#else
2453 SH_MUTEX_LOCK(mutex_thread_nolog);
2454 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2455 _("not scanning ports below 1024"),
2456 _("sh_portchk_check"));
2457 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2458#endif
2459 noprivports = 1;
2460 }
2461 }
2462
2463 sh_port2proc_prepare();
2464
2465 if (sh_portchk_check_udp == 1)
2466 sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2467 sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
2468
2469
2470 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
2471 if (sh_portchk_check_udp == 1)
2472 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
2473
2474 }
2475 SH_MUTEX_UNLOCK(mutex_port_check);
2476 return 0;
2477}
2478#endif
2479
2480#ifdef SH_CUTEST
2481#include "CuTest.h"
2482
2483void Test_portcheck_lists (CuTest *tc)
2484{
2485#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
2486 struct sh_sockaddr haddr_local;
2487 struct sh_portentry * portent;
2488 char buf[256];
2489 char * p;
2490
2491#ifdef HAVE_RPC_RPC_H
2492 p = sh_getrpcbynumber(0, buf, sizeof(buf));
2493 CuAssertTrue(tc, p == NULL);
2494
2495 p = sh_getrpcbynumber(100000, buf, sizeof(buf));
2496 CuAssertPtrNotNull(tc, p);
2497 CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
2498 CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
2499
2500 p = sh_getrpcbynumber(100007, buf, sizeof(buf));
2501 CuAssertPtrNotNull(tc, p);
2502 CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
2503 CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
2504#endif
2505
2506 p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2507 CuAssertTrue(tc, p == NULL);
2508
2509#if !defined(HOST_IS_CYGWIN)
2510 p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
2511 CuAssertPtrNotNull(tc, p);
2512 CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
2513 CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
2514#endif
2515
2516 p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2517 CuAssertPtrNotNull(tc, p);
2518 CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
2519 CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
2520
2521 CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
2522
2523 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2524
2525 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2526 CuAssertPtrNotNull(tc, portent);
2527
2528 CuAssertTrue(tc, portent->port == 8000);
2529 CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
2530 CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
2531 CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
2532
2533 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2534
2535 CuAssertTrue(tc, NULL == portlist_tcp);
2536
2537 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2538 sh_portchk_add_to_list (IPPROTO_TCP, 8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2539 sh_portchk_add_to_list (IPPROTO_TCP, 8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2540 sh_portchk_add_to_list (IPPROTO_TCP, 8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2541 sh_portchk_add_to_list (IPPROTO_TCP, 8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
2542 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
2543 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
2544 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
2545 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
2546 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
2547
2548 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2549
2550 CuAssertPtrNotNull(tc, portlist_tcp);
2551
2552 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2553 CuAssertPtrNotNull(tc, portent);
2554
2555 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL);
2556 CuAssertTrue(tc, NULL == portent);
2557
2558 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL);
2559 CuAssertPtrNotNull(tc, portent);
2560
2561 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL);
2562 CuAssertTrue(tc, NULL == portent);
2563
2564 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL);
2565 CuAssertPtrNotNull(tc, portent);
2566
2567 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1");
2568 CuAssertTrue(tc, NULL == portent);
2569
2570 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2");
2571 CuAssertPtrNotNull(tc, portent);
2572 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2573
2574 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3");
2575 CuAssertTrue(tc, NULL == portent);
2576
2577 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4");
2578 CuAssertPtrNotNull(tc, portent);
2579 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
2580
2581 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5");
2582 CuAssertPtrNotNull(tc, portent);
2583 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
2584
2585 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2586 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2587 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP));
2588 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP));
2589 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2590 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2591 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP));
2592 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP));
2593
2594 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP));
2595 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP));
2596 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP));
2597 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP));
2598
2599 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP));
2600 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP));
2601 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP));
2602 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP));
2603#else
2604 (void) tc; /* fix compiler warning */
2605#endif
2606 return;
2607}
2608#endif
2609
2610#ifdef TEST_ONLY
2611
2612void usage (char * pname)
2613{
2614 printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
2615 printf (" Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
2616 printf (" Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
2617 printf (" Portlist: List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
2618 printf (" required -> must be open\n");
2619 printf (" optional -> may be open or closed\n");
2620 printf (" RPC services must be specified with service **name**, others with **port number**\n\n");
2621 printf (" Example:\n");
2622 printf (" %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
2623 return;
2624}
2625
2626int main(int argc, char *argv[])
2627{
2628 char * pname = argv[0];
2629
2630
2631 /*
2632 test_lists();
2633
2634 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
2635 portlist_udp = sh_portchk_kill_list (portlist_udp);
2636 */
2637
2638 /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
2639
2640 while (argc > 1 && argv[1][0] == '-')
2641 {
2642 if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
2643 {
2644 usage(pname);
2645 exit (0);
2646 }
2647 else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
2648 {
2649 if (argc < 3)
2650 {
2651 usage(pname);
2652 exit (1);
2653 }
2654 sh_portchk_add_required (argv[2]);
2655 --argc; ++argv;
2656 }
2657 else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
2658 {
2659 if (argc < 3)
2660 {
2661 usage(pname);
2662 exit (1);
2663 }
2664 sh_portchk_add_optional (argv[2]);
2665 --argc; ++argv;
2666 }
2667 else if (0 == strcmp(argv[1], "--no-udp"))
2668 {
2669 sh_portchk_check_udp = 0;
2670 }
2671 else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
2672 {
2673 portchk_debug = 1;
2674 }
2675 else
2676 {
2677 usage(pname);
2678 exit (1);
2679 }
2680 --argc; ++argv;
2681 }
2682
2683 if (argc < 2)
2684 {
2685 usage(pname);
2686 exit (1);
2687 }
2688
2689 portchk_hostname = argv[1];
2690
2691 if (0 != sh_portchk_init ())
2692 {
2693 usage(pname);
2694 exit (1);
2695 }
2696
2697 sh_portchk_check();
2698
2699 return 0;
2700}
2701#endif
Note: See TracBrowser for help on using the repository browser.