source: trunk/src/sh_portcheck.c@ 577

Last change on this file since 577 was 560, checked in by katerina, 4 years ago

Fix for ticket #449 (gcc 10 compile issues).

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