source: trunk/src/sh_portcheck.c@ 528

Last change on this file since 528 was 526, checked in by katerina, 7 years ago

Fix for ticket #421 (spurious port detections) and ticket #422 (PortCheckSkip bug).

  • Property svn:executable set to *
File size: 67.9 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
950static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
951{
952 int retval;
953 char * p = NULL;
954 char buf[8];
955#ifndef TEST_ONLY
956 char errmsg[256];
957 volatile int nerr;
958#endif
959 char errbuf[SH_ERRBUF_SIZE];
960 char ipbuf[SH_IP_BUF];
961
962 struct sh_sockaddr saddr;
963 socklen_t slen = 0;
964 volatile int sport = 0;
965
966 sh_ipvx_set_port(paddr, port);
967
968 do {
969 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
970 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
971
972 if (retval == -1)
973 {
974#ifdef TEST_ONLY
975 if (portchk_debug)
976 perror(_("connect"));
977#else
978 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
979
980 nerr = errno;
981 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
982 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
983 SH_MUTEX_LOCK(mutex_thread_nolog);
984 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
985 errmsg, _("connect"));
986 SH_MUTEX_UNLOCK(mutex_thread_nolog);
987#endif
988 }
989 else
990 {
991 /* Register the used source port as transient. This will avoid
992 * the issue of lingering source ports being reported as a spurious
993 * service. The lingering source port is effectvely a race condition.
994 *
995 * Also use this code to obtain the source port. Sometimes Samhain
996 * reports on a port where it connects back to itself. In that case
997 * source and destination port are the same.
998 *
999 * AGH, 23 Apr 2017 (www.2024sight.com).
1000 */
1001
1002#if defined(USE_IPVX)
1003 if (paddr->ss_family == AF_INET)
1004 {
1005 saddr.ss_family = AF_INET;
1006 slen = sizeof( struct sockaddr_in );
1007 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1008 }
1009 else
1010 {
1011 saddr.ss_family = AF_INET6;
1012 slen = sizeof( struct sockaddr_in6 );
1013 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1014 }
1015#else
1016 saddr.ss_family = AF_INET;
1017 slen = sizeof( struct sockaddr_in );
1018 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1019#endif
1020
1021 if ( retval == 0 )
1022 {
1023 sport = sh_ipvx_get_port(&saddr);
1024 sh_portchk_transient(sport, &saddr, IPPROTO_UDP);
1025 }
1026 else
1027 {
1028#ifdef TEST_ONLY
1029 if (portchk_debug)
1030 perror(_("getsockname"));
1031#else
1032 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1033 nerr = errno;
1034 sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/udp: %s"),
1035 ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1036 SH_MUTEX_LOCK(mutex_thread_nolog);
1037 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("getsockname"));
1038 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1039#endif
1040 }
1041
1042 if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1043 {
1044 do {
1045 retval = send (fd, buf, 0, 0);
1046 } while (retval < 0 && errno == EINTR);
1047
1048 if (retval == -1 && errno == ECONNREFUSED)
1049 {
1050 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1051 if (portchk_debug)
1052 fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
1053 port, ipbuf);
1054 }
1055 else
1056 {
1057 /* Only the second send() may catch the error
1058 */
1059 do {
1060 retval = send (fd, buf, 0, 0);
1061 } while (retval < 0 && errno == EINTR);
1062
1063 if (retval == -1 && errno == ECONNREFUSED)
1064 {
1065 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1066 if (portchk_debug)
1067 fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
1068 port, ipbuf);
1069 }
1070 else if (retval != -1)
1071 {
1072 /* Try to get service name from portmap
1073 */
1074 if (paddr->ss_family == AF_INET)
1075 {
1076 p = check_rpc_list (port,
1077 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
1078 IPPROTO_UDP);
1079 }
1080
1081 sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
1082
1083 /* If not an RPC service, try to get name from /etc/services
1084 */
1085 if (!p)
1086 p = check_services(port, IPPROTO_UDP);
1087
1088 if (portchk_debug)
1089 {
1090 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1091 fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"),
1092 port, ipbuf, p);
1093 }
1094
1095 }
1096 else
1097 {
1098 if (portchk_debug)
1099 {
1100 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1101 fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"),
1102 port, ipbuf, errno);
1103 }
1104 }
1105 }
1106 }
1107 else
1108 {
1109 if (portchk_debug)
1110 {
1111 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1112 fprintf(stderr, _("check port_udp: %5d/udp on %15s same source and destination port\n"),
1113 port, ipbuf);
1114 }
1115 }
1116 }
1117 sl_close_fd (FIL__, __LINE__, fd);
1118 return 0;
1119}
1120
1121static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
1122{
1123 volatile int retval;
1124 int flags;
1125 char * p = NULL;
1126#ifndef TEST_ONLY
1127 char errmsg[256];
1128 volatile int nerr;
1129#endif
1130 char errbuf[SH_ERRBUF_SIZE];
1131 char ipbuf[SH_IP_BUF];
1132
1133 struct sh_sockaddr saddr;
1134 socklen_t slen = 0;
1135 volatile int sport = 0;
1136
1137 sh_ipvx_set_port(paddr, port);
1138
1139 do {
1140 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
1141 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
1142
1143 if (retval == -1 && errno == ECONNREFUSED)
1144 {
1145 if (portchk_debug)
1146 {
1147 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1148 fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
1149 port, ipbuf);
1150 }
1151 }
1152 else if (retval == -1)
1153 {
1154#ifdef TEST_ONLY
1155 if (portchk_debug)
1156 perror(_("connect"));
1157#else
1158 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1159 nerr = errno;
1160 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
1161 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
1162 SH_MUTEX_LOCK(mutex_thread_nolog);
1163 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1164 errmsg, _("connect"));
1165 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1166#endif
1167 }
1168 else
1169 {
1170 /* Register the used source port as transient. This will avoid
1171 * the issue of lingering source ports being reported as a spurious
1172 * service. The lingering source port is effectively a race condition.
1173 *
1174 * Also use this code to obtain the source port. Sometimes Samhain
1175 * reports on a port where it connects back to itself. In that case
1176 * source and destination port are the same.
1177 *
1178 * AGH, 23 Apr 2017 (www.2024sight.com).
1179 */
1180
1181#if defined(USE_IPVX)
1182 if (paddr->ss_family == AF_INET)
1183 {
1184 saddr.ss_family = AF_INET;
1185 slen = sizeof( struct sockaddr_in );
1186 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1187 }
1188 else
1189 {
1190 saddr.ss_family = AF_INET6;
1191 slen = sizeof( struct sockaddr_in6 );
1192 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1193 }
1194#else
1195 saddr.ss_family = AF_INET;
1196 slen = sizeof( struct sockaddr_in );
1197 retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1198#endif
1199
1200 if ( retval == 0 )
1201 {
1202 sport = sh_ipvx_get_port(&saddr);
1203 sh_portchk_transient(sport, &saddr, IPPROTO_TCP);
1204 }
1205 else
1206 {
1207#ifdef TEST_ONLY
1208 if (portchk_debug)
1209 perror(_("getsockname"));
1210#else
1211 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1212 nerr = errno;
1213 sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/tcp: %s"),
1214 ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1215 SH_MUTEX_LOCK(mutex_thread_nolog);
1216 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1217 errmsg, _("getsockname"));
1218 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1219#endif
1220 }
1221
1222 if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1223 {
1224 /* Try to get service name from portmap
1225 */
1226 if (paddr->ss_family == AF_INET)
1227 {
1228 p = check_rpc_list (port,
1229 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
1230 IPPROTO_TCP);
1231 }
1232
1233 sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
1234
1235 /* If not an RPC service, try to get name from /etc/services
1236 */
1237 if (!p)
1238 p = check_services(port, IPPROTO_TCP);
1239
1240 if (portchk_debug)
1241 {
1242 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1243 fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"),
1244 port, ipbuf, p);
1245 }
1246 }
1247 else
1248 {
1249 if (portchk_debug)
1250 {
1251 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1252 fprintf(stderr, _("check port_udp: %5d/tcp on %15s same source and destination port\n"),
1253 port, ipbuf);
1254 }
1255 }
1256
1257#if !defined(O_NONBLOCK)
1258#if defined(O_NDELAY)
1259#define O_NONBLOCK O_NDELAY
1260#else
1261#define O_NONBLOCK 0
1262#endif
1263#endif
1264
1265 /* prepare to close connection gracefully
1266 */
1267 if (port == 22) /* ssh */
1268 {
1269 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1270 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1271 retval = write (fd, _("SSH-2.0-Foobar"), 14);
1272 if (retval > 0) retval = write (fd, "\r\n", 2);
1273 }
1274 else if (port == 25) /* smtp */
1275 {
1276 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1277 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1278 retval = write (fd, _("QUIT"), 4);
1279 if (retval > 0) retval = write (fd, "\r\n", 2);
1280 }
1281 else if (port == 79) /* finger */
1282 {
1283 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1284 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1285 retval = write (fd, "\r\n", 2);
1286 }
1287 else if (port == 110) /* pop3 */
1288 {
1289 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1290 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1291 retval = write (fd, _("QUIT"), 4);
1292 if (retval > 0) retval = write (fd, "\r\n", 2);
1293 }
1294 else if (port == 143) /* imap */
1295 {
1296 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1297 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1298 retval = write (fd, _("A01 LOGOUT"), 10);
1299 if (retval > 0) retval = write (fd, "\r\n", 2);
1300 }
1301
1302 if (portchk_debug && retval < 0)
1303 fprintf(stderr, _("check port: error writing to port %5d\n"),
1304 port);
1305 }
1306 sl_close_fd (FIL__, __LINE__, fd);
1307 return 0;
1308}
1309
1310/* typedef uint32_t in_addr_t;
1311 * struct in_addr
1312 * {
1313 * in_addr_t s_addr;
1314 * };
1315 */
1316
1317#define SH_IFACE_MAX 64
1318#define SH_IFACE_ADDR 0
1319#define SH_IFACE_DEV 1
1320
1321struct portchk_interfaces {
1322 struct sh_sockaddr iface;
1323 int type;
1324};
1325
1326static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1327static int iface_list_used = 0;
1328static int iface_initialized = 0;
1329
1330#ifdef TEST_ONLY
1331static char * portchk_hostname = NULL;
1332#else
1333static char * portchk_hostname = sh.host.name;
1334#endif
1335
1336static int sh_portchk_init_internal (void)
1337{
1338 volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1339 char errbuf[256];
1340#if defined(USE_IPVX)
1341 struct addrinfo hints;
1342 struct addrinfo *res;
1343#else
1344 struct hostent * hent;
1345#endif
1346 char ipbuf[SH_IP_BUF];
1347
1348 if (portchk_debug)
1349 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
1350
1351 if (!portchk_hostname)
1352 return -1;
1353
1354 if (sh_portchk_active == S_FALSE)
1355 return -1;
1356
1357 SH_MUTEX_LOCK(mutex_port_check);
1358 if (iface_initialized == 0)
1359 {
1360 iface_list_used = 0;
1361 iface_initialized = 1;
1362 }
1363
1364#if !defined(USE_IPVX)
1365 SH_MUTEX_LOCK(mutex_resolv);
1366 hent = sh_gethostbyname(portchk_hostname);
1367 i = 0;
1368 while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
1369 {
1370 struct sockaddr_in sin;
1371 struct sh_sockaddr iface_tmp;
1372
1373 memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
1374 sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1375
1376 for (j = 0; j < iface_list_used; ++j)
1377 {
1378 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1379 {
1380 goto next_iface;
1381 }
1382 }
1383
1384 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1385 AF_INET, (struct sockaddr *)&sin);
1386 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1387
1388 if (portchk_debug)
1389 {
1390 char buf[256];
1391 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1392 fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
1393 }
1394 ++iface_list_used;
1395
1396 next_iface:
1397 ++i;
1398 }
1399 SH_MUTEX_UNLOCK(mutex_resolv);
1400#else
1401 memset(&hints, '\0', sizeof(hints));
1402 hints.ai_family = PF_UNSPEC;
1403 hints.ai_flags = AI_ADDRCONFIG;
1404
1405 if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1406 {
1407 struct addrinfo *p = res;
1408 struct sh_sockaddr iface_tmp;
1409
1410 while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
1411 {
1412 sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1413
1414 for (j = 0; j < iface_list_used; ++j)
1415 {
1416 if (portchk_debug)
1417 {
1418 char buf1[256], buf2[256];
1419 sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
1420 sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1421 fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
1422 }
1423 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1424 {
1425 if (portchk_debug)
1426 fprintf(stderr, _("skipping interface[%d]\n"), j);
1427 goto next_iface;
1428 }
1429 }
1430 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1431 p->ai_family, p->ai_addr);
1432 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1433 if (portchk_debug)
1434 {
1435 char buf[256];
1436 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1437 fprintf(stderr, _("added interface[%d]: %s\n"), iface_list_used, buf);
1438 }
1439
1440 ++iface_list_used;
1441
1442 next_iface:
1443 p = p->ai_next;
1444 }
1445 freeaddrinfo(res);
1446 }
1447#endif
1448
1449 for (i = 0; i < iface_list_used; ++i)
1450 {
1451 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
1452 sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
1453
1454 SH_MUTEX_LOCK(mutex_thread_nolog);
1455 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1456 errbuf, _("sh_portchk_init"));
1457 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1458 }
1459 SH_MUTEX_UNLOCK(mutex_port_check);
1460
1461 return 0;
1462}
1463
1464int sh_portchk_init (struct mod_type * arg)
1465{
1466#ifndef HAVE_PTHREAD
1467 (void) arg;
1468#endif
1469
1470 if (sh_portchk_active == S_FALSE)
1471 return SH_MOD_FAILED;
1472 if (!portchk_hostname)
1473 return SH_MOD_FAILED;
1474
1475#ifdef HAVE_PTHREAD
1476 if (arg != NULL && arg->initval < 0 &&
1477 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1478 {
1479 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1480 return SH_MOD_THREAD;
1481 else
1482 return SH_MOD_FAILED;
1483 }
1484 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1485 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1486 {
1487 (void) sh_portchk_init_internal();
1488 return SH_MOD_THREAD;
1489 }
1490#endif
1491 return sh_portchk_init_internal();
1492}
1493
1494static void dev_list_kill();
1495
1496#if !defined(TEST_ONLY)
1497int sh_portchk_reconf (void)
1498{
1499 SH_MUTEX_LOCK(mutex_port_check);
1500 iface_initialized = 0;
1501 sh_portchk_active = 1;
1502 sh_portchk_check_udp = 1;
1503 sh_portchk_interval = SH_PORTCHK_INTERVAL;
1504
1505 sh_portchk_minport = -1;
1506 sh_portchk_maxport = -1;
1507
1508 dev_list_kill();
1509
1510 portlist_udp = sh_portchk_kill_list (portlist_udp);
1511 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1512
1513 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1514 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
1515 sh_port2proc_finish();
1516
1517 SH_MUTEX_UNLOCK(mutex_port_check);
1518 return 0;
1519}
1520
1521int sh_portchk_cleanup (void)
1522{
1523 return sh_portchk_reconf ();
1524}
1525
1526int sh_portchk_timer (time_t tcurrent)
1527{
1528 static time_t lastcheck = 0;
1529
1530 SL_ENTER(_("sh_portchk_timer"));
1531 if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
1532 {
1533 lastcheck = tcurrent;
1534 SL_RETURN((-1), _("sh_portchk_timer"));
1535 }
1536 SL_RETURN(0, _("sh_portchk_timer"));
1537}
1538#endif
1539
1540static int check_port_generic (int port, int domain, int type, int protocol)
1541{
1542 volatile int i = 0;
1543 int sock = -1;
1544 int flag = 1; /* non-zero to enable an option */
1545 struct sh_sockaddr paddr;
1546 char errbuf[SH_ERRBUF_SIZE];
1547
1548 /* Check all interfaces for this host
1549 */
1550 while (i < iface_list_used)
1551 {
1552 memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
1553
1554 if (paddr.ss_family != domain)
1555 {
1556 ++i;
1557 continue;
1558 }
1559
1560 if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
1561 {
1562 ++i;
1563 continue;
1564 }
1565
1566 if (0 != sh_portchk_is_transient(port, &paddr, protocol))
1567 {
1568 ++i;
1569 continue;
1570 }
1571
1572 if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1573 {
1574 ++i;
1575#ifdef TEST_ONLY
1576 if (portchk_debug)
1577 perror(_("socket"));
1578#else
1579
1580#ifndef EPROTONOSUPPORT
1581#define EPROTONOSUPPORT 0
1582#endif
1583#ifndef EAFNOSUPPORT
1584#define EAFNOSUPPORT 0
1585#endif
1586 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1587 {
1588 SH_MUTEX_LOCK(mutex_thread_nolog);
1589 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1590 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1591 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1592 }
1593#endif
1594 continue;
1595 }
1596 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1597 (void *) &flag, sizeof(flag)) < 0 )
1598 {
1599 ++i;
1600#ifdef TEST_ONLY
1601 if (portchk_debug)
1602 perror(_("setsockopt"));
1603#else
1604 SH_MUTEX_LOCK(mutex_thread_nolog);
1605 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1606 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1607 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1608#endif
1609 continue;
1610 }
1611
1612
1613 if (protocol == IPPROTO_TCP)
1614 check_port_tcp_internal(sock, port, &paddr);
1615 else
1616 check_port_udp_internal(sock, port, &paddr);
1617
1618 ++i;
1619 }
1620
1621 return 0;
1622}
1623
1624
1625
1626static int check_port_udp (int port, int domain)
1627{
1628 return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
1629}
1630
1631static int check_port_tcp (int port, int domain)
1632{
1633 return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
1634}
1635
1636
1637static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
1638 int domain, int type, int protocol)
1639{
1640 /*
1641 int min_port = 1024;
1642 int max_port = 65535;
1643 */
1644
1645 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1646 volatile int max_port = max_port_arg;
1647 int retval;
1648 int sock = -1;
1649#if 0
1650 int flag = 1; /* non-zero to enable an option */
1651#endif
1652 struct sockaddr_in addr4;
1653 struct sockaddr_in6 addr6;
1654
1655 int addrlen4 = sizeof(addr4);
1656 int addrlen6 = sizeof(addr6);
1657
1658 struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
1659
1660 char errbuf[SH_ERRBUF_SIZE];
1661
1662 if (min_port == -1)
1663 min_port = 0;
1664 if (max_port == -1)
1665 max_port = 65535;
1666
1667 if (portchk_debug)
1668 fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"),
1669 min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"),
1670 (protocol == IPPROTO_TCP) ? _("tcp") : _("udp"));
1671
1672 for (port = min_port; port <= max_port; ++port)
1673 {
1674 if ((sock = socket(domain, type, protocol)) < 0 )
1675 {
1676#ifdef TEST_ONLY
1677 if (portchk_debug)
1678 perror(_("socket"));
1679#else
1680#ifndef EPROTONOSUPPORT
1681#define EPROTONOSUPPORT 0
1682#endif
1683#ifndef EAFNOSUPPORT
1684#define EAFNOSUPPORT 0
1685#endif
1686 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1687 {
1688 SH_MUTEX_LOCK(mutex_thread_nolog);
1689 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1690 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1691 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1692 }
1693#endif
1694 continue;
1695 }
1696
1697#if 0
1698 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1699 (void *) &flag, sizeof(flag)) < 0 )
1700 {
1701#ifdef TEST_ONLY
1702 if (portchk_debug)
1703 perror(_("setsockopt"));
1704#else
1705 SH_MUTEX_LOCK(mutex_thread_nolog);
1706 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1707 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1708 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1709#endif
1710 continue;
1711 }
1712#endif
1713
1714 if (domain == AF_INET)
1715 {
1716 addr4.sin_family = AF_INET;
1717 addr4.sin_port = htons(port);
1718 addr4.sin_addr.s_addr = INADDR_ANY;
1719 retval = bind (sock, (struct sockaddr *) &addr4, addrlen4);
1720 }
1721 else
1722 {
1723 addr6.sin6_family = AF_INET6;
1724 addr6.sin6_port = htons(port);
1725 memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr));
1726 retval = bind (sock, (struct sockaddr *) &addr6, addrlen6);
1727 }
1728
1729 if (retval == 0)
1730 {
1731 /* we can bind the port, thus it is unused
1732 */
1733 sl_close_fd (FIL__, __LINE__, sock);
1734 }
1735 else
1736 {
1737 if (errno == EINVAL || errno == EADDRINUSE)
1738 {
1739 /* try to connect to the port
1740 */
1741 if (protocol == IPPROTO_TCP)
1742 check_port_tcp(port, domain);
1743 else
1744 check_port_udp(port, domain);
1745 }
1746 else
1747 {
1748#ifdef TEST_ONLY
1749 if (portchk_debug)
1750 perror(_("bind"));
1751#else
1752 SH_MUTEX_LOCK(mutex_thread_nolog);
1753 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1754 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1755 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1756#endif
1757 }
1758 sl_close_fd (FIL__, __LINE__, sock);
1759 }
1760 }
1761
1762 if (protocol == IPPROTO_TCP)
1763 transient_tcp=sh_portchk_kill_transient(transient_tcp);
1764 else
1765 transient_udp=sh_portchk_kill_transient(transient_udp);
1766
1767 return 0;
1768}
1769
1770static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1771{
1772#if defined(USE_IPVX)
1773 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1774 SOCK_STREAM, IPPROTO_TCP);
1775#endif
1776 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1777 SOCK_STREAM, IPPROTO_TCP);
1778}
1779
1780static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1781{
1782#if defined(USE_IPVX)
1783 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1784 SOCK_DGRAM, IPPROTO_UDP);
1785#endif
1786 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1787 SOCK_DGRAM, IPPROTO_UDP);
1788}
1789
1790/* Subroutine to add an interface
1791 */
1792void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
1793
1794static int sh_portchk_add_interface_int (const char * str, int type)
1795{
1796 struct sh_sockaddr saddr;
1797 char errbuf[256];
1798 char buf[64];
1799
1800 sh_dummy_1564_str = (void*) &str;
1801
1802 if (iface_initialized == 0)
1803 {
1804 iface_list_used = 0;
1805 iface_initialized = 1;
1806 }
1807
1808 do {
1809
1810 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1811
1812 if (*str)
1813 {
1814 char ipbuf[SH_IP_BUF];
1815 unsigned int i = 0;
1816 while (*str && i < (sizeof(buf)-1) &&
1817 *str != ',' && *str != ' ' && *str != '\t')
1818 {
1819 buf[i] = *str; ++str; ++i;
1820 }
1821 buf[i] = '\0';
1822
1823 if (0 == sh_ipvx_aton(buf, &saddr))
1824 return -1;
1825
1826 if (iface_list_used == SH_IFACE_MAX)
1827 return -1;
1828
1829 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1830 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
1831 SH_MUTEX_LOCK(mutex_thread_nolog);
1832 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1833 errbuf, _("sh_portchk_add_interface"));
1834 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1835
1836 memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1837 iface_list[iface_list_used].type = type;
1838 ++iface_list_used;
1839 }
1840 } while (*str);
1841
1842 sh_dummy_1564_str = NULL;
1843 return 0;
1844}
1845
1846static int sh_portchk_add_interface (const char * str)
1847{
1848 return sh_portchk_add_interface_int (str, SH_IFACE_ADDR);
1849}
1850
1851#if defined(HAVE_IFADDRS_H)
1852/*
1853 * subroutines to add a device
1854 */
1855void * sh_dummy_1651_ifa = NULL; /* fix clobbered by.. warning */
1856
1857static int portchk_add_device_int (const char * buf)
1858{
1859 struct ifaddrs *ifaddr, *ifa;
1860 int family;
1861#ifndef NI_MAXHOST
1862#define NI_MAXHOST 1025
1863#endif
1864 char host[NI_MAXHOST];
1865
1866 sh_dummy_1651_ifa = (void*) &ifa;
1867
1868 if (getifaddrs(&ifaddr) == -1)
1869 {
1870 volatile int nerr = errno;
1871 char errbuf[SH_ERRBUF_SIZE];
1872 sh_error_message(errno, errbuf, sizeof(errbuf));
1873 SH_MUTEX_LOCK(mutex_thread_nolog);
1874 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1875 errbuf, _("getifaddrs"));
1876 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1877 return -1;
1878 }
1879
1880 for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1881 {
1882 if (ifa->ifa_addr == NULL)
1883 continue;
1884
1885 if (strcmp(ifa->ifa_name, buf) == 0)
1886 {
1887 volatile int s = 0;
1888 family = ifa->ifa_addr->sa_family;
1889
1890 if (family == AF_INET)
1891 {
1892 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in),
1893 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1894
1895 if (s == 0)
1896 {
1897 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1898 {
1899 freeifaddrs(ifaddr);
1900 return -1;
1901 }
1902 }
1903 }
1904
1905#if defined(USE_IPVX)
1906 if (family == AF_INET6)
1907 {
1908 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in6),
1909 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1910
1911 if (s == 0)
1912 {
1913 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1914 {
1915 freeifaddrs(ifaddr);
1916 return -1;
1917 }
1918 }
1919 }
1920#endif
1921
1922 if (s != 0)
1923 {
1924 char errbuf[SH_ERRBUF_SIZE];
1925 sl_strlcpy(errbuf, buf, sizeof(errbuf));
1926 sl_strlcat(errbuf, ": ", sizeof(errbuf));
1927 sl_strlcat(errbuf, gai_strerror(s), sizeof(errbuf));
1928 SH_MUTEX_LOCK(mutex_thread_nolog);
1929 sh_error_handle((-1), FIL__, __LINE__, s, MSG_E_SUBGEN,
1930 errbuf, _("getnameinfo"));
1931 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1932 }
1933
1934 }
1935 }
1936
1937 freeifaddrs(ifaddr);
1938 return 0;
1939}
1940
1941struct added_dev {
1942 char dev[64];
1943 struct added_dev * next;
1944};
1945
1946static struct added_dev * dev_list = NULL;
1947
1948static void dev_list_add (char * buf)
1949{
1950 struct added_dev * new = SH_ALLOC(sizeof(struct added_dev));
1951 sl_strlcpy(new->dev, buf, 64);
1952 new->next = dev_list;
1953 dev_list = new;
1954 return;
1955}
1956
1957static void dev_list_kill ()
1958{
1959 struct added_dev * old;
1960 struct added_dev * new = dev_list;
1961 dev_list = NULL;
1962
1963 while (new)
1964 {
1965 old = new;
1966 new = new->next;
1967 SH_FREE(old);
1968 }
1969 return;
1970}
1971
1972static int sh_portchk_add_device (const char * str)
1973{
1974 char buf[64];
1975
1976 do {
1977
1978 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1979
1980 if (*str)
1981 {
1982 unsigned int i = 0;
1983 while (*str && i < (sizeof(buf)-1) &&
1984 *str != ',' && *str != ' ' && *str != '\t') {
1985 buf[i] = *str; ++str; ++i;
1986 }
1987 buf[i] = '\0';
1988
1989 if (portchk_add_device_int (buf) < 0)
1990 return -1;
1991
1992 dev_list_add(buf);
1993 }
1994 } while (*str);
1995
1996 return 0;
1997}
1998
1999static int iface_comp (const void *a, const void *b)
2000{
2001 const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
2002 const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
2003 return (aa->type - bb->type);
2004}
2005
2006static void iface_qsort()
2007{
2008 qsort(&iface_list[0], iface_list_used, sizeof(struct portchk_interfaces),
2009 iface_comp);
2010 return;
2011}
2012
2013static void recheck_devices()
2014{
2015 if (dev_list)
2016 {
2017 struct added_dev * dev = dev_list;
2018 int i, j;
2019
2020 if (portchk_debug)
2021 {
2022 for (j = 0; j < iface_list_used; ++j)
2023 {
2024 char buf[SH_IP_BUF];
2025 struct portchk_interfaces * aa = &(iface_list[j]);
2026 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2027 fprintf(stderr, _("presort: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2028 }
2029 }
2030
2031 iface_qsort();
2032
2033 if (portchk_debug)
2034 {
2035 for (j = 0; j < iface_list_used; ++j)
2036 {
2037 char buf[SH_IP_BUF];
2038 struct portchk_interfaces * aa = &(iface_list[j]);
2039 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2040 fprintf(stderr, _("postsor: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2041 }
2042 }
2043
2044 i = 0;
2045 for (j = 0; j < iface_list_used; ++j)
2046 if (iface_list[j].type == SH_IFACE_DEV) ++i;
2047 iface_list_used -= i;
2048
2049 if (portchk_debug)
2050 {
2051 for (j = 0; j < iface_list_used; ++j)
2052 {
2053 char buf[SH_IP_BUF];
2054 struct portchk_interfaces * aa = &(iface_list[j]);
2055 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2056 fprintf(stderr, _("postdel: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2057 }
2058 }
2059
2060 while (dev)
2061 {
2062 portchk_add_device_int (dev->dev);
2063 dev = dev->next;
2064 }
2065 }
2066 return;
2067}
2068#endif
2069
2070/* verify whether port/interface is blacklisted (do not check)
2071 */
2072static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
2073 int proto)
2074{
2075 struct sh_port * head;
2076
2077 if (proto == IPPROTO_TCP)
2078 head = blacklist_tcp;
2079 else
2080 head = blacklist_udp;
2081
2082 while (head)
2083 {
2084 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2085 return 1;
2086 head = head->next;
2087 }
2088 return 0;
2089}
2090
2091
2092static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
2093{
2094 struct sh_port * black;
2095 struct sh_port * head;
2096
2097 if (proto == IPPROTO_TCP)
2098 head = blacklist_tcp;
2099 else
2100 head = blacklist_udp;
2101
2102 black = head;
2103
2104 while (black)
2105 {
2106 if (black->port == port &&
2107 0 == sh_ipvx_cmp(head->paddr, saddr))
2108 return -1;
2109 black = black->next;
2110 }
2111
2112 black = SH_ALLOC (sizeof(struct sh_port));
2113 black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2114 black->port = port;
2115 memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
2116 black->next = head;
2117
2118 if (proto == IPPROTO_TCP)
2119 blacklist_tcp = black;
2120 else
2121 blacklist_udp = black;
2122
2123 if (portchk_debug)
2124 {
2125 int checkit = sh_portchk_is_blacklisted(port, saddr, proto);
2126 fprintf(stderr, _("port blacklisted: %d %s\n"), port,
2127 (checkit == 1) ? _("ok") : _("fail"));
2128 }
2129 return 0;
2130}
2131
2132
2133/* verify whether port/interface is transient (used as source port
2134 *hence no check required)
2135 */
2136static int sh_portchk_is_transient(int port, struct sh_sockaddr * saddr,
2137 int proto)
2138{
2139 struct sh_port * head;
2140
2141 if (proto == IPPROTO_TCP)
2142 head = transient_tcp;
2143 else
2144 head = transient_udp;
2145
2146 while (head)
2147 {
2148 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2149 return 1;
2150 head = head->next;
2151 }
2152 return 0;
2153}
2154
2155
2156static int sh_portchk_transient(int port, struct sh_sockaddr * saddr, int proto)
2157{
2158 struct sh_port * transient;
2159 struct sh_port * head;
2160
2161 if (sh_portchk_transients == S_FALSE)
2162 return 0;
2163
2164 if (proto == IPPROTO_TCP)
2165 head = transient_tcp;
2166 else
2167 head = transient_udp;
2168
2169 transient = head;
2170
2171 while (transient)
2172 {
2173 if (transient->port == port &&
2174 0 == sh_ipvx_cmp(head->paddr, saddr))
2175 return -1;
2176 transient = transient->next;
2177 }
2178
2179 transient = SH_ALLOC (sizeof(struct sh_port));
2180 transient->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2181 transient->port = port;
2182 memcpy(transient->paddr, saddr, sizeof(struct sh_sockaddr));
2183 transient->next = head;
2184
2185 if (proto == IPPROTO_TCP)
2186 transient_tcp = transient;
2187 else
2188 transient_udp = transient;
2189
2190 if (portchk_debug)
2191 {
2192 int checkit = sh_portchk_is_transient(port, saddr, proto);
2193 fprintf(stderr, _("port transient: %d %s\n"), port,
2194 (checkit == 1) ? _("ok") : _("fail"));
2195 }
2196 return 0;
2197}
2198
2199
2200/* Subroutine to add a required or optional port/service
2201 */
2202static int sh_portchk_add_required_port_generic (char * service,
2203 char * interface, int type)
2204{
2205 char buf[256] = { '\0' };
2206 int proto;
2207 char * p;
2208 char * endptr;
2209 unsigned long int port;
2210 struct sh_sockaddr saddr;
2211 struct sh_portentry * portent;
2212
2213 if (0 == sh_ipvx_aton(interface, &saddr))
2214 return -1;
2215
2216 sl_strlcpy (buf, service, sizeof(buf));
2217
2218 p = strchr(buf, '/');
2219 if (!p)
2220 return -1;
2221 if (0 == strcasecmp(p, _("/tcp")))
2222 proto = IPPROTO_TCP;
2223 else if (0 == strcasecmp(p, _("/udp")))
2224 proto = IPPROTO_UDP;
2225 else
2226 return -1;
2227
2228 *p = '\0';
2229 port = strtoul(buf, &endptr, 0);
2230
2231 if (portchk_debug)
2232 {
2233 char buf[SH_IP_BUF];
2234 sh_ipvx_ntoa(buf, sizeof(buf), &saddr);
2235 fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"),
2236 interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"),
2237 sh_port_type2str(type));
2238 }
2239
2240 /* Blacklisted ports
2241 */
2242 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
2243 return (sh_portchk_blacklist(port, &saddr, proto));
2244
2245 if (*endptr != '\0')
2246 {
2247 portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
2248 if (!portent)
2249 {
2250 if (portchk_debug)
2251 fprintf(stderr, _("add_required_port %d\n"), (int) port);
2252 sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN);
2253 }
2254 else
2255 {
2256#ifdef TEST_ONLY
2257 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
2258#else
2259 SH_MUTEX_LOCK(mutex_thread_nolog);
2260 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2261 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2262 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2263#endif
2264 return -1;
2265 }
2266 }
2267 else if (port <= 65535)
2268 {
2269 portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
2270 if (!portent)
2271 {
2272 if (portchk_debug)
2273 fprintf(stderr, _("add_required_port: open port: %d/%s\n"),
2274 (int) port, SH_PROTO_STR(proto));
2275 sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN);
2276 }
2277 else
2278 {
2279#ifdef TEST_ONLY
2280 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
2281#else
2282 SH_MUTEX_LOCK(mutex_thread_nolog);
2283 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2284 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2285 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2286#endif
2287 return -1;
2288 }
2289 }
2290 else
2291 return -1;
2292
2293 return 0;
2294}
2295
2296/* Internal interface to add required or optional ports as 'iface:portlist'
2297 */
2298static int sh_portchk_add_required_generic (const char * str, int type)
2299{
2300 size_t ll = 0;
2301 int status;
2302
2303 char * interface = NULL;
2304 char * list;
2305 char * p;
2306#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2307 char * saveptr;
2308#endif
2309
2310 if (!str)
2311 return -1;
2312
2313 if (strchr(str, ':'))
2314 {
2315 char *last = strrchr(str, ':');
2316 if (last != NULL)
2317 {
2318 size_t tolast = (last - str);
2319 interface = SH_ALLOC(tolast+1);
2320 sl_strlcpy(interface, str, tolast+1);
2321 interface[tolast] = '\0';
2322
2323 ll = tolast;
2324
2325 while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
2326 ++ll;
2327 }
2328 }
2329 else
2330 {
2331 interface = SH_ALLOC(8);
2332 sl_strlcpy(interface, _("0.0.0.0"), 8);
2333 interface[7] = '\0';
2334 while (str[ll] == ' ' || str[ll] == '\t')
2335 ++ll;
2336 }
2337
2338 if (!interface)
2339 return -1;
2340
2341 if (str[ll] == '\0')
2342 {
2343 SH_FREE(interface);
2344 return -1;
2345 }
2346
2347 if (portchk_debug)
2348 fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
2349
2350 list = sh_util_strdup(&str[ll]);
2351#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2352 p = strtok_r (list, " ,\t", &saveptr);
2353#else
2354 p = strtok (list, " ,\t");
2355#endif
2356 if (!p)
2357 {
2358 SH_FREE(interface);
2359 SH_FREE(list);
2360 return -1;
2361 }
2362 while (p)
2363 {
2364 status = sh_portchk_add_required_port_generic (p, interface, type);
2365
2366 if (-1 == status)
2367 {
2368 SH_FREE(interface);
2369 SH_FREE(list);
2370 return -1;
2371 }
2372#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2373 p = strtok_r (NULL, " ,\t", &saveptr);
2374#else
2375 p = strtok (NULL, " ,\t");
2376#endif
2377 }
2378 SH_FREE(interface);
2379 SH_FREE(list);
2380 return 0;
2381}
2382
2383/* User interface to add required ports as 'iface:portlist'
2384 */
2385static int sh_portchk_add_required (const char * str)
2386{
2387 return sh_portchk_add_required_generic (str, SH_PORT_REQ);
2388}
2389
2390/* User interface to add optional ports as 'iface:portlist'
2391 */
2392static int sh_portchk_add_optional (const char * str)
2393{
2394 return sh_portchk_add_required_generic (str, SH_PORT_OPT);
2395}
2396
2397/* User interface to add ignoreable ports as 'iface:portlist'
2398 */
2399static int sh_portchk_add_ignore (const char * str)
2400{
2401 return sh_portchk_add_required_generic (str, SH_PORT_IGN);
2402}
2403
2404/* User interface to add ports that should not be checked as 'iface:portlist'
2405 */
2406static int sh_portchk_add_blacklist (const char * str)
2407{
2408 return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST);
2409}
2410
2411/* Interface to run port check
2412 */
2413int sh_portchk_check ()
2414{
2415 volatile int min_port;
2416 static int noprivports = 0;
2417
2418 SH_MUTEX_LOCK(mutex_port_check);
2419
2420 min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
2421
2422 if (sh_portchk_active != S_FALSE)
2423 {
2424 SH_MUTEX_LOCK(mutex_thread_nolog);
2425 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2426 _("Checking for open ports"),
2427 _("sh_portchk_check"));
2428 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2429
2430 sh_portchk_reset_lists();
2431
2432#if defined(HAVE_IFADDRS_H)
2433 recheck_devices();
2434#endif
2435
2436 if ((0 != geteuid()) && (min_port < 1024))
2437 {
2438 min_port = 1024;
2439 if (noprivports == 0)
2440 {
2441#ifdef TEST_ONLY
2442 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
2443#else
2444 SH_MUTEX_LOCK(mutex_thread_nolog);
2445 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2446 _("not scanning ports below 1024"),
2447 _("sh_portchk_check"));
2448 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2449#endif
2450 noprivports = 1;
2451 }
2452 }
2453
2454 sh_port2proc_prepare();
2455
2456 if (sh_portchk_check_udp == 1)
2457 sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2458 sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
2459
2460
2461 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
2462 if (sh_portchk_check_udp == 1)
2463 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
2464
2465 }
2466 SH_MUTEX_UNLOCK(mutex_port_check);
2467 return 0;
2468}
2469#endif
2470
2471#ifdef SH_CUTEST
2472#include "CuTest.h"
2473
2474void Test_portcheck_lists (CuTest *tc)
2475{
2476#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
2477 struct sh_sockaddr haddr_local;
2478 struct sh_portentry * portent;
2479 char buf[256];
2480 char * p;
2481
2482#ifdef HAVE_RPC_RPC_H
2483 p = sh_getrpcbynumber(0, buf, sizeof(buf));
2484 CuAssertTrue(tc, p == NULL);
2485
2486 p = sh_getrpcbynumber(100000, buf, sizeof(buf));
2487 CuAssertPtrNotNull(tc, p);
2488 CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
2489 CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
2490
2491 p = sh_getrpcbynumber(100007, buf, sizeof(buf));
2492 CuAssertPtrNotNull(tc, p);
2493 CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
2494 CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
2495#endif
2496
2497 p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2498 CuAssertTrue(tc, p == NULL);
2499
2500#if !defined(HOST_IS_CYGWIN)
2501 p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
2502 CuAssertPtrNotNull(tc, p);
2503 CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
2504 CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
2505#endif
2506
2507 p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2508 CuAssertPtrNotNull(tc, p);
2509 CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
2510 CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
2511
2512 CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
2513
2514 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2515
2516 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2517 CuAssertPtrNotNull(tc, portent);
2518
2519 CuAssertTrue(tc, portent->port == 8000);
2520 CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
2521 CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
2522 CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
2523
2524 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2525
2526 CuAssertTrue(tc, NULL == portlist_tcp);
2527
2528 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2529 sh_portchk_add_to_list (IPPROTO_TCP, 8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2530 sh_portchk_add_to_list (IPPROTO_TCP, 8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2531 sh_portchk_add_to_list (IPPROTO_TCP, 8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2532 sh_portchk_add_to_list (IPPROTO_TCP, 8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
2533 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
2534 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
2535 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
2536 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
2537 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
2538
2539 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2540
2541 CuAssertPtrNotNull(tc, portlist_tcp);
2542
2543 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2544 CuAssertPtrNotNull(tc, portent);
2545
2546 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL);
2547 CuAssertTrue(tc, NULL == portent);
2548
2549 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL);
2550 CuAssertPtrNotNull(tc, portent);
2551
2552 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL);
2553 CuAssertTrue(tc, NULL == portent);
2554
2555 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL);
2556 CuAssertPtrNotNull(tc, portent);
2557
2558 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1");
2559 CuAssertTrue(tc, NULL == portent);
2560
2561 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2");
2562 CuAssertPtrNotNull(tc, portent);
2563 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2564
2565 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3");
2566 CuAssertTrue(tc, NULL == portent);
2567
2568 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4");
2569 CuAssertPtrNotNull(tc, portent);
2570 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
2571
2572 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5");
2573 CuAssertPtrNotNull(tc, portent);
2574 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
2575
2576 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2577 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2578 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP));
2579 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP));
2580 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2581 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2582 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP));
2583 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP));
2584
2585 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP));
2586 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP));
2587 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP));
2588 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP));
2589
2590 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP));
2591 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP));
2592 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP));
2593 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP));
2594#else
2595 (void) tc; /* fix compiler warning */
2596#endif
2597 return;
2598}
2599#endif
2600
2601#ifdef TEST_ONLY
2602
2603void usage (char * pname)
2604{
2605 printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
2606 printf (" Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
2607 printf (" Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
2608 printf (" Portlist: List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
2609 printf (" required -> must be open\n");
2610 printf (" optional -> may be open or closed\n");
2611 printf (" RPC services must be specified with service **name**, others with **port number**\n\n");
2612 printf (" Example:\n");
2613 printf (" %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
2614 return;
2615}
2616
2617int main(int argc, char *argv[])
2618{
2619 char * pname = argv[0];
2620
2621
2622 /*
2623 test_lists();
2624
2625 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
2626 portlist_udp = sh_portchk_kill_list (portlist_udp);
2627 */
2628
2629 /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
2630
2631 while (argc > 1 && argv[1][0] == '-')
2632 {
2633 if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
2634 {
2635 usage(pname);
2636 exit (0);
2637 }
2638 else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
2639 {
2640 if (argc < 3)
2641 {
2642 usage(pname);
2643 exit (1);
2644 }
2645 sh_portchk_add_required (argv[2]);
2646 --argc; ++argv;
2647 }
2648 else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
2649 {
2650 if (argc < 3)
2651 {
2652 usage(pname);
2653 exit (1);
2654 }
2655 sh_portchk_add_optional (argv[2]);
2656 --argc; ++argv;
2657 }
2658 else if (0 == strcmp(argv[1], "--no-udp"))
2659 {
2660 sh_portchk_check_udp = 0;
2661 }
2662 else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
2663 {
2664 portchk_debug = 1;
2665 }
2666 else
2667 {
2668 usage(pname);
2669 exit (1);
2670 }
2671 --argc; ++argv;
2672 }
2673
2674 if (argc < 2)
2675 {
2676 usage(pname);
2677 exit (1);
2678 }
2679
2680 portchk_hostname = argv[1];
2681
2682 if (0 != sh_portchk_init ())
2683 {
2684 usage(pname);
2685 exit (1);
2686 }
2687
2688 sh_portchk_check();
2689
2690 return 0;
2691}
2692#endif
Note: See TracBrowser for help on using the repository browser.