source: trunk/src/sh_portcheck.c@ 526

Last change on this file since 526 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
RevLine 
[67]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>
[511]35#include <stdlib.h>
[67]36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
[511]40#ifdef HAVE_IFADDRS_H
41#include <ifaddrs.h>
42#include <netdb.h>
43#endif
[67]44#include <errno.h>
45#include <unistd.h>
[109]46#include <fcntl.h>
[67]47
[526]48#define PORTCHK_VERSION "1.1"
[76]49
50#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
51
52
[67]53#define PORTMAP
[290]54#ifdef HAVE_RPC_RPC_H
[67]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>
[290]61#endif
[67]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
[295]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
[67]95/* the size of an interface string
96 */
[295]97#define SH_INTERFACE_SIZE SH_IP_BUF
[67]98
99#define SH_PORT_NOT 0
100#define SH_PORT_REQ 1
101#define SH_PORT_OPT 2
[127]102#define SH_PORT_IGN 3
[149]103#define SH_PORT_BLACKLIST 4
[67]104
[468]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
[67]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
[149]122#define SH_PROTO_TCP 0
123#define SH_PROTO_UDP 1
124#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
125
[67]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
[149]139
[67]140#define SH_PORTCHK_INTERVAL 300
141
[526]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;
[67]147
[328]148static int sh_portchk_minport = -1;
149static int sh_portchk_maxport = -1;
150
[295]151struct sh_port {
152 int port;
153 struct sh_sockaddr * paddr;
154 struct sh_port * next;
155};
[67]156
[295]157static struct sh_port * blacklist_tcp = NULL;
158static struct sh_port * blacklist_udp = NULL;
159
[526]160static struct sh_port * transient_tcp = NULL;
161static struct sh_port * transient_udp = NULL;
162
[149]163SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
164
[67]165static int sh_portchk_severity = SH_ERR_SEVERE;
[180]166
[295]167extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
[206]168 unsigned long * pid, char * user, size_t userlen);
[180]169extern int sh_port2proc_prepare();
[235]170extern void sh_port2proc_finish();
[180]171
[67]172#endif
173
[127]174/* Exported interface to add ignoreable ports as 'iface:portlist'
175 */
176static int sh_portchk_add_ignore (const char * str);
177
[67]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
[149]186/* Exported interface to add blacklisted ports as 'iface:portlist'
187 */
188static int sh_portchk_add_blacklist (const char * str);
189
[67]190/* Exported interface to add an ethernet interface
191 */
192static int sh_portchk_add_interface (const char * str);
193
[511]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
[149]200/* verify whether port/interface is blacklisted (do not check)
201 */
[295]202static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
[67]203
[526]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
[67]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 {
[149]220 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]221 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
222 _("port check interval"), c);
[149]223 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]224 retval = -1;
225 }
[362]226 else
227 {
228 sh_portchk_interval = (time_t) val;
229 }
230 SL_RETURN(retval, _("sh_portchk_set_interval"));
[67]231}
232
[328]233static int sh_portchk_set_port_minmax (const char * c, int * setthis)
234{
235 int retval = 0;
236 long val;
[67]237
[328]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 }
[362]248 else
249 {
250 *setthis = (int) val;
251 }
252 SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
[328]253}
254
255
[526]256static int sh_portchk_set_minport (const char * str)
[328]257{
258 return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
259}
260
[526]261static int sh_portchk_set_maxport (const char * str)
[328]262{
263 return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
264}
265
[526]266static int sh_portchk_set_active (const char * str)
[67]267{
268 return sh_util_flagval(str, &sh_portchk_active);
269}
270
[526]271static int sh_portchk_set_udp (const char * str)
[67]272{
273 return sh_util_flagval(str, &sh_portchk_check_udp);
274}
[526]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}
[67]280
[526]281static int sh_portchk_set_same_ports (const char * str)
[67]282{
[526]283 return sh_util_flagval(str, &sh_portchk_same_ports);
284}
285#endif
286static int sh_portchk_set_severity (const char * str)
287{
[67]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 {
[127]308 N_("portcheckignore"),
309 sh_portchk_add_ignore,
310 },
311 {
[149]312 N_("portcheckskip"),
313 sh_portchk_add_blacklist,
314 },
315 {
[67]316 N_("portcheckactive"),
317 sh_portchk_set_active,
318 },
[511]319#if defined(HAVE_IFADDRS_H)
[67]320 {
[511]321 N_("portcheckdevice"),
322 sh_portchk_add_device,
323 },
324#endif
325 {
[67]326 N_("portcheckinterface"),
327 sh_portchk_add_interface,
328 },
329 {
330 N_("portcheckinterval"),
331 sh_portchk_set_interval,
332 },
333 {
[328]334 N_("portcheckminport"),
335 sh_portchk_set_minport,
336 },
337 {
338 N_("portcheckmaxport"),
339 sh_portchk_set_maxport,
340 },
341 {
[67]342 N_("portcheckudp"),
343 sh_portchk_set_udp,
344 },
[526]345#if defined(SH_ALLOW_RESTORE)
[67]346 {
[526]347 N_("portchecktransients"),
348 sh_portchk_set_transients,
349 },
350 {
351 N_("portchecksameports"),
352 sh_portchk_set_same_ports,
353 },
354#endif
355 {
[67]356 NULL,
357 NULL
358 }
359};
360
361#endif
362
363/* Interface to initialize port check
364 */
[170]365int sh_portchk_init (struct mod_type * arg);
[67]366
367/* Interface to reset port check
368 */
[170]369int sh_portchk_reset (void);
[67]370
371/* Interface to run port check
372 */
[170]373int sh_portchk_check (void);
[67]374
375
[149]376static char * check_services (int port, int proto);
[67]377
378#ifdef TEST_ONLY
379
[380]380static int portchk_debug = 0;
[67]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
[290]393#ifdef HAVE_RPC_RPC_H
[218]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);
[252]422 sl_fclose(FIL__, __LINE__, fp);
[218]423 return buf;
424 }
425 }
426 SH_FREE(splits);
427 }
428 }
429 sh_string_destroy(&s);
[252]430 sl_fclose(FIL__, __LINE__, fp);
[218]431 }
432 return NULL;
433}
[290]434#endif
[218]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);
[252]471 sl_fclose(FIL__, __LINE__, fp);
[218]472 return buf;
473 }
474 }
475 }
476 SH_FREE(splits);
477 }
478 }
479 sh_string_destroy(&s);
[252]480 sl_fclose(FIL__, __LINE__, fp);
[218]481 }
482 return NULL;
483}
484
[149]485static void sh_portchk_add_to_list (int proto,
[295]486 int port, struct sh_sockaddr * paddr,
[218]487 char * service,
[67]488 int flag, int status)
489{
490 struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
491
492 new->port = port;
[295]493 sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
[67]494 new->status = status;
495 new->flag = flag;
496
497 new->error = NULL;
498
[380]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
[67]504 if (service)
505 new->service = sh_util_strdup (service);
506 else
507 new->service = NULL;
[149]508 if (proto == IPPROTO_TCP)
[67]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 */
[170]525static void sh_portchk_reset_lists (void)
[67]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
[149]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
[295]567 SH_FREE(head->paddr);
[149]568 SH_FREE(head);
569 }
570 return NULL;
571}
572
[526]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
[170]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 */
[481]591void * sh_dummy_531_pre = NULL;
592void * sh_dummy_532_ptr = NULL;
[170]593
[67]594/* check the list of open ports for any that are marked as UNKN
595 */
[481]596static void sh_portchk_check_list (struct sh_portentry ** head,
597 int proto, int report)
[67]598{
599 struct sh_portentry * ptr = *head;
600 struct sh_portentry * pre = *head;
601 char errbuf[256];
602
[170]603 /* Take the address to keep gcc from putting them into registers.
604 * Avoids the 'clobbered by longjmp' warning.
605 */
[481]606 sh_dummy_531_pre = (void*) &pre;
607 sh_dummy_532_ptr = (void*) &ptr;
[170]608
[67]609 while (ptr)
610 {
611 if (portchk_debug && report)
612 fprintf(stderr, _("check list: port %d/%s %d %d\n"),
[149]613 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]614
615 if (ptr->status == SH_PORT_UNKN)
616 {
617 /* Don't report missing ports that are marked as optional
618 */
[127]619 if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
[67]620 {
[169]621 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[149]622 ptr->interface, ptr->port, SH_PROTO_STR(proto),
[67]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)
[149]629 {
630 SH_MUTEX_LOCK(mutex_thread_nolog);
631 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[169]632 MSG_PORT_MISS, errbuf);
[149]633 SH_MUTEX_UNLOCK(mutex_thread_nolog);
634 }
[67]635#endif
636 }
637
638 ptr->status = SH_PORT_MISS;
639
[128]640 if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
[67]641 {
642 if (portchk_debug && report)
643 fprintf(stderr, _("removing: port %d/%s %d %d\n"),
[149]644 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]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 }
[383]678
[481]679 sh_dummy_532_ptr = NULL;
680 sh_dummy_531_pre = NULL;
[383]681
[67]682 return;
683}
684
685
[149]686static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
[295]687 struct sh_sockaddr * paddr, char * service)
[67]688{
689 struct sh_portentry * portlist;
[295]690 char str_addr[SH_IP_BUF];
[75]691
[526]692
[149]693 if (proto == IPPROTO_TCP)
[67]694 portlist = portlist_tcp;
695 else
696 portlist = portlist_udp;
697
[295]698 sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
699
[67]700 if (service)
701 {
702 while (portlist)
703 {
704 if (portlist->service &&
705 0 == strcmp(service, portlist->service) &&
[295]706 ( 0 == strcmp(portlist->interface, str_addr) ||
707 sh_ipvx_isany(paddr) ))
[67]708 return portlist;
709 portlist = portlist->next;
710 }
711 }
712 else
713 {
714 while (portlist)
715 {
716 if (port == portlist->port &&
[295]717 (0 == strcmp(portlist->interface, str_addr) ||
718 sh_ipvx_isany(paddr) ))
[67]719 return portlist;
720 portlist = portlist->next;
721 }
722 }
723 return NULL;
724}
725
726
[380]727static void sh_portchk_cmp_to_list (int proto, int port,
728 struct sh_sockaddr * paddr, char * service)
[67]729{
730 struct sh_portentry * portent;
731 char errbuf[256];
732
733
[295]734 portent = sh_portchk_get_from_list (proto, port, paddr, service);
[67]735
736 if (service)
737 {
738 if (!portent)
739 {
[180]740 char * path;
[206]741 unsigned long qpid;
[180]742 char user[USER_MAX];
[295]743 char saddr[SH_IP_BUF];
[180]744
[295]745 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
746
[169]747 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]748 saddr, port, SH_PROTO_STR(proto), service);
[380]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
[295]755 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]756 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]757 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]758 MSG_PORT_NEW, errbuf, path, qpid, user);
[149]759 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]760 SH_FREE(path);
[67]761#endif
762 /*
763 * was not there, thus it is not in 'required' or 'optional' list
764 */
[295]765 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]766 }
[127]767 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]768 {
[180]769 char * path;
[206]770 unsigned long qpid;
[180]771 char user[USER_MAX];
[295]772 char saddr[SH_IP_BUF];
[180]773
[295]774 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
775
[169]776 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
[295]777 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]778#ifdef TEST_ONLY
779 fprintf(stderr, _("service: %s\n"), errbuf);
780#else
[295]781 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]782 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]783 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]784 MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]785 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]786 SH_FREE(path);
[67]787#endif
788
789 portent->status = SH_PORT_ISOK;
790 }
791 else if (port != portent->port && (-1) != portent->port)
792 {
[180]793 char * path;
[206]794 unsigned long qpid;
[180]795 char user[USER_MAX];
[295]796 char saddr[SH_IP_BUF];
[180]797
[295]798 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
799
[169]800 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
[295]801 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]802#ifdef TEST_ONLY
803 fprintf(stderr, _("service: %s\n"), errbuf);
804#else
[295]805 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]806 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]807 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]808 MSG_PORT_NEWPORT, errbuf, path, qpid, user);
[149]809 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]810 SH_FREE(path);
[67]811#endif
[127]812 portent->port = port;
[67]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 {
[180]824 char * path;
[206]825 unsigned long qpid;
[180]826 char user[USER_MAX];
[295]827 char saddr[SH_IP_BUF];
[180]828
[468]829 if (portchk_debug)
830 fprintf(stderr, _("call to sh_ipvx_ntoa (port %d)\n"), port);
831
[295]832 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
833
[169]834 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]835 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[380]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
[295]842 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]843 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]844 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]845 MSG_PORT_NEW, errbuf, path, qpid, user);
[149]846 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]847 SH_FREE(path);
[67]848#endif
849
850 /* was not there, thus it is not in 'required' or 'optional' list
851 */
[295]852 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]853 }
[127]854 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]855 {
[180]856 char * path;
[206]857 unsigned long qpid;
[180]858 char user[USER_MAX];
[295]859 char saddr[SH_IP_BUF];
[180]860
[295]861 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
862
[169]863 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]864 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[67]865#ifdef TEST_ONLY
866 fprintf(stderr, _("port : %s\n"), errbuf);
867#else
[295]868 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]869 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]870 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]871 MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]872 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]873 SH_FREE(path);
[67]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 */
[149]892static char * check_services (int port, int proto)
[67]893{
894 static char buf[256];
[218]895 char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
[67]896
[218]897 if (!service)
[67]898 {
[210]899 snprintf (buf, sizeof(buf), "%s",_("unknown"));
[67]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{
[439]911#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
[67]912 struct pmaplist * head;
[218]913 char *r;
[67]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 {
[218]925 r = sh_getrpcbynumber((int)head->pml_map.pm_prog,
926 buf, sizeof(buf));
927 if (r)
[67]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 }
[290]942#else
943 (void) port;
944 (void) address;
945 (void) prot;
946#endif
[67]947 return NULL;
948}
949
[295]950static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]951{
952 int retval;
[295]953 char * p = NULL;
[67]954 char buf[8];
[78]955#ifndef TEST_ONLY
956 char errmsg[256];
[526]957 volatile int nerr;
[78]958#endif
[132]959 char errbuf[SH_ERRBUF_SIZE];
[295]960 char ipbuf[SH_IP_BUF];
[67]961
[526]962 struct sh_sockaddr saddr;
963 socklen_t slen = 0;
964 volatile int sport = 0;
965
[295]966 sh_ipvx_set_port(paddr, port);
[67]967
[78]968 do {
[295]969 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]970 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]971
[67]972 if (retval == -1)
973 {
974#ifdef TEST_ONLY
975 if (portchk_debug)
976 perror(_("connect"));
977#else
[295]978 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
979
[78]980 nerr = errno;
981 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
[295]982 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]983 SH_MUTEX_LOCK(mutex_thread_nolog);
[78]984 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
985 errmsg, _("connect"));
[149]986 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]987#endif
988 }
989 else
990 {
[526]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 */
[67]1001
[526]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 {
[78]1045 retval = send (fd, buf, 0, 0);
[526]1046 } while (retval < 0 && errno == EINTR);
[78]1047
[526]1048 if (retval == -1 && errno == ECONNREFUSED)
[67]1049 {
[295]1050 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[67]1051 if (portchk_debug)
[526]1052 fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
1053 port, ipbuf);
[67]1054 }
[526]1055 else
[67]1056 {
[526]1057 /* Only the second send() may catch the error
[67]1058 */
[526]1059 do {
1060 retval = send (fd, buf, 0, 0);
1061 } while (retval < 0 && errno == EINTR);
[380]1062
[526]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);
[67]1082
[526]1083 /* If not an RPC service, try to get name from /etc/services
1084 */
1085 if (!p)
1086 p = check_services(port, IPPROTO_UDP);
[67]1087
[526]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 }
[67]1094
[526]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 }
[67]1105 }
[526]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 }
[67]1116 }
[252]1117 sl_close_fd (FIL__, __LINE__, fd);
[67]1118 return 0;
1119}
1120
[295]1121static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]1122{
[526]1123 volatile int retval;
[109]1124 int flags;
[295]1125 char * p = NULL;
[78]1126#ifndef TEST_ONLY
1127 char errmsg[256];
[526]1128 volatile int nerr;
[78]1129#endif
[132]1130 char errbuf[SH_ERRBUF_SIZE];
[295]1131 char ipbuf[SH_IP_BUF];
[67]1132
[526]1133 struct sh_sockaddr saddr;
1134 socklen_t slen = 0;
1135 volatile int sport = 0;
1136
[295]1137 sh_ipvx_set_port(paddr, port);
[67]1138
[78]1139 do {
[295]1140 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]1141 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]1142
[67]1143 if (retval == -1 && errno == ECONNREFUSED)
1144 {
1145 if (portchk_debug)
[295]1146 {
1147 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[468]1148 fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
[295]1149 port, ipbuf);
1150 }
[67]1151 }
1152 else if (retval == -1)
1153 {
1154#ifdef TEST_ONLY
1155 if (portchk_debug)
1156 perror(_("connect"));
1157#else
[295]1158 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[78]1159 nerr = errno;
1160 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
[295]1161 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]1162 SH_MUTEX_LOCK(mutex_thread_nolog);
[78]1163 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1164 errmsg, _("connect"));
[149]1165 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1166#endif
1167 }
1168 else
1169 {
[526]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).
[67]1179 */
[526]1180
1181#if defined(USE_IPVX)
[295]1182 if (paddr->ss_family == AF_INET)
[526]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
[67]1199
[526]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 }
[67]1221
[526]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 }
[67]1232
[526]1233 sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
[109]1234
[526]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
[109]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);
[170]1271 retval = write (fd, _("SSH-2.0-Foobar"), 14);
1272 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1278 retval = write (fd, _("QUIT"), 4);
1279 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1285 retval = write (fd, "\r\n", 2);
[109]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);
[170]1291 retval = write (fd, _("QUIT"), 4);
1292 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1298 retval = write (fd, _("A01 LOGOUT"), 10);
1299 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]1300 }
[170]1301
1302 if (portchk_debug && retval < 0)
1303 fprintf(stderr, _("check port: error writing to port %5d\n"),
1304 port);
[67]1305 }
[252]1306 sl_close_fd (FIL__, __LINE__, fd);
[67]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
[511]1317#define SH_IFACE_MAX 64
1318#define SH_IFACE_ADDR 0
1319#define SH_IFACE_DEV 1
[67]1320
1321struct portchk_interfaces {
[511]1322 struct sh_sockaddr iface;
1323 int type;
[67]1324};
1325
[511]1326static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1327static int iface_list_used = 0;
[67]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
[149]1336static int sh_portchk_init_internal (void)
[67]1337{
[468]1338 volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
[67]1339 char errbuf[256];
[295]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];
[67]1347
1348 if (portchk_debug)
1349 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
[78]1350
[67]1351 if (!portchk_hostname)
1352 return -1;
1353
[78]1354 if (sh_portchk_active == S_FALSE)
1355 return -1;
1356
[149]1357 SH_MUTEX_LOCK(mutex_port_check);
[67]1358 if (iface_initialized == 0)
1359 {
[511]1360 iface_list_used = 0;
[67]1361 iface_initialized = 1;
1362 }
[295]1363
1364#if !defined(USE_IPVX)
[134]1365 SH_MUTEX_LOCK(mutex_resolv);
[162]1366 hent = sh_gethostbyname(portchk_hostname);
[170]1367 i = 0;
[511]1368 while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
[67]1369 {
[295]1370 struct sockaddr_in sin;
[468]1371 struct sh_sockaddr iface_tmp;
[295]1372
1373 memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
[468]1374 sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1375
[511]1376 for (j = 0; j < iface_list_used; ++j)
[468]1377 {
[511]1378 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
[468]1379 {
1380 goto next_iface;
1381 }
1382 }
1383
[511]1384 sh_ipvx_save(&(iface_list[iface_list_used].iface),
[295]1385 AF_INET, (struct sockaddr *)&sin);
[511]1386 iface_list[iface_list_used].type = SH_IFACE_ADDR;
[380]1387
1388 if (portchk_debug)
1389 {
1390 char buf[256];
[511]1391 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
[468]1392 fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
[380]1393 }
[511]1394 ++iface_list_used;
[468]1395
1396 next_iface:
[134]1397 ++i;
1398 }
1399 SH_MUTEX_UNLOCK(mutex_resolv);
[295]1400#else
1401 memset(&hints, '\0', sizeof(hints));
1402 hints.ai_family = PF_UNSPEC;
1403 hints.ai_flags = AI_ADDRCONFIG;
[134]1404
[295]1405 if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1406 {
1407 struct addrinfo *p = res;
[468]1408 struct sh_sockaddr iface_tmp;
[295]1409
[511]1410 while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
[295]1411 {
[468]1412 sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1413
[511]1414 for (j = 0; j < iface_list_used; ++j)
[468]1415 {
1416 if (portchk_debug)
1417 {
1418 char buf1[256], buf2[256];
[511]1419 sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
[468]1420 sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1421 fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
1422 }
[511]1423 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
[468]1424 {
1425 if (portchk_debug)
1426 fprintf(stderr, _("skipping interface[%d]\n"), j);
1427 goto next_iface;
1428 }
1429 }
[511]1430 sh_ipvx_save(&(iface_list[iface_list_used].iface),
[295]1431 p->ai_family, p->ai_addr);
[511]1432 iface_list[iface_list_used].type = SH_IFACE_ADDR;
[468]1433 if (portchk_debug)
1434 {
1435 char buf[256];
[511]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);
[468]1438 }
1439
[511]1440 ++iface_list_used;
[468]1441
1442 next_iface:
[295]1443 p = p->ai_next;
1444 }
1445 freeaddrinfo(res);
1446 }
1447#endif
1448
[511]1449 for (i = 0; i < iface_list_used; ++i)
[134]1450 {
[511]1451 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
[468]1452 sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
[295]1453
[149]1454 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1455 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1456 errbuf, _("sh_portchk_init"));
[149]1457 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1458 }
[149]1459 SH_MUTEX_UNLOCK(mutex_port_check);
[67]1460
1461 return 0;
1462}
1463
[149]1464int sh_portchk_init (struct mod_type * arg)
1465{
[210]1466#ifndef HAVE_PTHREAD
1467 (void) arg;
1468#endif
1469
[149]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 }
[335]1484 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1485 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1486 {
[511]1487 (void) sh_portchk_init_internal();
[335]1488 return SH_MOD_THREAD;
1489 }
[149]1490#endif
1491 return sh_portchk_init_internal();
1492}
1493
[511]1494static void dev_list_kill();
[149]1495
[67]1496#if !defined(TEST_ONLY)
[170]1497int sh_portchk_reconf (void)
[67]1498{
[149]1499 SH_MUTEX_LOCK(mutex_port_check);
[78]1500 iface_initialized = 0;
1501 sh_portchk_active = 1;
[80]1502 sh_portchk_check_udp = 1;
[149]1503 sh_portchk_interval = SH_PORTCHK_INTERVAL;
[78]1504
[328]1505 sh_portchk_minport = -1;
1506 sh_portchk_maxport = -1;
1507
[511]1508 dev_list_kill();
1509
[67]1510 portlist_udp = sh_portchk_kill_list (portlist_udp);
1511 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
[149]1512
1513 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1514 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
[235]1515 sh_port2proc_finish();
1516
[149]1517 SH_MUTEX_UNLOCK(mutex_port_check);
[67]1518 return 0;
1519}
1520
[170]1521int sh_portchk_cleanup (void)
[67]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
[295]1540static int check_port_generic (int port, int domain, int type, int protocol)
[67]1541{
[170]1542 volatile int i = 0;
[67]1543 int sock = -1;
1544 int flag = 1; /* non-zero to enable an option */
[295]1545 struct sh_sockaddr paddr;
[132]1546 char errbuf[SH_ERRBUF_SIZE];
1547
[67]1548 /* Check all interfaces for this host
1549 */
[511]1550 while (i < iface_list_used)
[67]1551 {
[511]1552 memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
[149]1553
[295]1554 if (paddr.ss_family != domain)
[149]1555 {
[295]1556 ++i;
1557 continue;
[149]1558 }
1559
[295]1560 if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
[67]1561 {
[295]1562 ++i;
1563 continue;
1564 }
1565
[526]1566 if (0 != sh_portchk_is_transient(port, &paddr, protocol))
1567 {
1568 ++i;
1569 continue;
1570 }
1571
[295]1572 if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1573 {
[170]1574 ++i;
[67]1575#ifdef TEST_ONLY
1576 if (portchk_debug)
1577 perror(_("socket"));
1578#else
[334]1579
1580#ifndef EPROTONOSUPPORT
1581#define EPROTONOSUPPORT 0
[170]1582#endif
[334]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
[149]1594 continue;
[67]1595 }
1596 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1597 (void *) &flag, sizeof(flag)) < 0 )
1598 {
[170]1599 ++i;
[67]1600#ifdef TEST_ONLY
1601 if (portchk_debug)
1602 perror(_("setsockopt"));
1603#else
[149]1604 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1605 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1606 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1607 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1608#endif
[149]1609 continue;
[67]1610 }
1611
1612
1613 if (protocol == IPPROTO_TCP)
[295]1614 check_port_tcp_internal(sock, port, &paddr);
[67]1615 else
[295]1616 check_port_udp_internal(sock, port, &paddr);
[67]1617
1618 ++i;
1619 }
1620
1621 return 0;
1622}
1623
1624
1625
[295]1626static int check_port_udp (int port, int domain)
[67]1627{
[295]1628 return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
[67]1629}
1630
[295]1631static int check_port_tcp (int port, int domain)
[67]1632{
[295]1633 return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
[67]1634}
1635
1636
[295]1637static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
1638 int domain, int type, int protocol)
[67]1639{
1640 /*
1641 int min_port = 1024;
1642 int max_port = 65535;
1643 */
1644
[170]1645 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1646 volatile int max_port = max_port_arg;
[67]1647 int retval;
1648 int sock = -1;
[498]1649#if 0
[67]1650 int flag = 1; /* non-zero to enable an option */
[498]1651#endif
[295]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
[132]1660 char errbuf[SH_ERRBUF_SIZE];
[67]1661
1662 if (min_port == -1)
1663 min_port = 0;
1664 if (max_port == -1)
1665 max_port = 65535;
1666
[468]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
[67]1672 for (port = min_port; port <= max_port; ++port)
1673 {
[295]1674 if ((sock = socket(domain, type, protocol)) < 0 )
[67]1675 {
1676#ifdef TEST_ONLY
1677 if (portchk_debug)
1678 perror(_("socket"));
1679#else
[334]1680#ifndef EPROTONOSUPPORT
1681#define EPROTONOSUPPORT 0
[67]1682#endif
[334]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
[149]1694 continue;
[67]1695 }
[498]1696
1697#if 0
[67]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
[149]1705 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1706 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1707 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1708 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1709#endif
[149]1710 continue;
[67]1711 }
[498]1712#endif
[67]1713
[295]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 }
[67]1728
1729 if (retval == 0)
1730 {
1731 /* we can bind the port, thus it is unused
1732 */
[252]1733 sl_close_fd (FIL__, __LINE__, sock);
[67]1734 }
1735 else
1736 {
1737 if (errno == EINVAL || errno == EADDRINUSE)
1738 {
1739 /* try to connect to the port
1740 */
1741 if (protocol == IPPROTO_TCP)
[295]1742 check_port_tcp(port, domain);
[67]1743 else
[295]1744 check_port_udp(port, domain);
[67]1745 }
1746 else
1747 {
1748#ifdef TEST_ONLY
1749 if (portchk_debug)
1750 perror(_("bind"));
1751#else
[149]1752 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1753 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1754 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
[149]1755 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1756#endif
1757 }
[252]1758 sl_close_fd (FIL__, __LINE__, sock);
[67]1759 }
1760 }
[526]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
[67]1767 return 0;
1768}
1769
1770static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1771{
[295]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);
[67]1778}
1779
1780static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1781{
[295]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);
[67]1788}
1789
1790/* Subroutine to add an interface
1791 */
[481]1792void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
[212]1793
[511]1794static int sh_portchk_add_interface_int (const char * str, int type)
[67]1795{
[295]1796 struct sh_sockaddr saddr;
[67]1797 char errbuf[256];
[212]1798 char buf[64];
[67]1799
[481]1800 sh_dummy_1564_str = (void*) &str;
[212]1801
[67]1802 if (iface_initialized == 0)
1803 {
[511]1804 iface_list_used = 0;
[67]1805 iface_initialized = 1;
1806 }
1807
[212]1808 do {
[67]1809
[212]1810 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
[67]1811
[212]1812 if (*str)
1813 {
[295]1814 char ipbuf[SH_IP_BUF];
[212]1815 unsigned int i = 0;
[295]1816 while (*str && i < (sizeof(buf)-1) &&
1817 *str != ',' && *str != ' ' && *str != '\t')
[212]1818 {
1819 buf[i] = *str; ++str; ++i;
1820 }
1821 buf[i] = '\0';
[67]1822
[295]1823 if (0 == sh_ipvx_aton(buf, &saddr))
[212]1824 return -1;
[67]1825
[511]1826 if (iface_list_used == SH_IFACE_MAX)
[212]1827 return -1;
1828
[295]1829 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1830 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
[212]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
[511]1836 memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1837 iface_list[iface_list_used].type = type;
1838 ++iface_list_used;
[212]1839 }
1840 } while (*str);
1841
[481]1842 sh_dummy_1564_str = NULL;
[67]1843 return 0;
1844}
1845
[511]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{
[516]2001 const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
2002 const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
[511]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
[149]2070/* verify whether port/interface is blacklisted (do not check)
2071 */
[295]2072static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
2073 int proto)
[149]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 {
[526]2084 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2085 return 1;
[149]2086 head = head->next;
2087 }
2088 return 0;
2089}
2090
2091
[295]2092static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
[149]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 {
[295]2106 if (black->port == port &&
2107 0 == sh_ipvx_cmp(head->paddr, saddr))
[149]2108 return -1;
2109 black = black->next;
2110 }
[295]2111
[149]2112 black = SH_ALLOC (sizeof(struct sh_port));
[295]2113 black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
[149]2114 black->port = port;
[295]2115 memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
[149]2116 black->next = head;
2117
2118 if (proto == IPPROTO_TCP)
2119 blacklist_tcp = black;
2120 else
2121 blacklist_udp = black;
[468]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 }
[149]2129 return 0;
2130}
[526]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;
[149]2140
[526]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
[67]2200/* Subroutine to add a required or optional port/service
2201 */
[295]2202static int sh_portchk_add_required_port_generic (char * service,
2203 char * interface, int type)
[67]2204{
[473]2205 char buf[256] = { '\0' };
[149]2206 int proto;
[67]2207 char * p;
2208 char * endptr;
2209 unsigned long int port;
[295]2210 struct sh_sockaddr saddr;
[67]2211 struct sh_portentry * portent;
2212
[295]2213 if (0 == sh_ipvx_aton(interface, &saddr))
[67]2214 return -1;
2215
2216 sl_strlcpy (buf, service, sizeof(buf));
2217
2218 p = strchr(buf, '/');
2219 if (!p)
2220 return -1;
[519]2221 if (0 == strcasecmp(p, _("/tcp")))
[149]2222 proto = IPPROTO_TCP;
[519]2223 else if (0 == strcasecmp(p, _("/udp")))
[149]2224 proto = IPPROTO_UDP;
[67]2225 else
2226 return -1;
2227
2228 *p = '\0';
2229 port = strtoul(buf, &endptr, 0);
2230
[468]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
[149]2240 /* Blacklisted ports
2241 */
2242 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
[295]2243 return (sh_portchk_blacklist(port, &saddr, proto));
[149]2244
[67]2245 if (*endptr != '\0')
2246 {
[295]2247 portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
[67]2248 if (!portent)
[380]2249 {
2250 if (portchk_debug)
[383]2251 fprintf(stderr, _("add_required_port %d\n"), (int) port);
[380]2252 sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN);
2253 }
[67]2254 else
2255 {
2256#ifdef TEST_ONLY
[149]2257 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
[67]2258#else
[149]2259 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]2260 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2261 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]2262 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]2263#endif
2264 return -1;
2265 }
2266 }
2267 else if (port <= 65535)
2268 {
[295]2269 portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
[67]2270 if (!portent)
[380]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 }
[67]2277 else
2278 {
2279#ifdef TEST_ONLY
[149]2280 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
[67]2281#else
[149]2282 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]2283 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2284 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]2285 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]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;
[149]2301 int status;
[67]2302
2303 char * interface = NULL;
2304 char * list;
2305 char * p;
[131]2306#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2307 char * saveptr;
2308#endif
[67]2309
2310 if (!str)
2311 return -1;
2312
2313 if (strchr(str, ':'))
2314 {
[468]2315 char *last = strrchr(str, ':');
2316 if (last != NULL)
[67]2317 {
[468]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;
[67]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)
[468]2348 fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
[67]2349
2350 list = sh_util_strdup(&str[ll]);
[131]2351#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2352 p = strtok_r (list, " ,\t", &saveptr);
2353#else
[67]2354 p = strtok (list, " ,\t");
[131]2355#endif
[67]2356 if (!p)
2357 {
2358 SH_FREE(interface);
2359 SH_FREE(list);
2360 return -1;
2361 }
2362 while (p)
2363 {
[149]2364 status = sh_portchk_add_required_port_generic (p, interface, type);
2365
2366 if (-1 == status)
[67]2367 {
2368 SH_FREE(interface);
2369 SH_FREE(list);
2370 return -1;
2371 }
[131]2372#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2373 p = strtok_r (NULL, " ,\t", &saveptr);
2374#else
[67]2375 p = strtok (NULL, " ,\t");
[131]2376#endif
[67]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
[127]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
[149]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
[67]2411/* Interface to run port check
2412 */
2413int sh_portchk_check ()
2414{
[170]2415 volatile int min_port;
[376]2416 static int noprivports = 0;
[67]2417
[149]2418 SH_MUTEX_LOCK(mutex_port_check);
[170]2419
[328]2420 min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
[170]2421
[78]2422 if (sh_portchk_active != S_FALSE)
[67]2423 {
[405]2424 SH_MUTEX_LOCK(mutex_thread_nolog);
[253]2425 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2426 _("Checking for open ports"),
2427 _("sh_portchk_check"));
[405]2428 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[253]2429
[78]2430 sh_portchk_reset_lists();
[511]2431
2432#if defined(HAVE_IFADDRS_H)
2433 recheck_devices();
2434#endif
2435
[328]2436 if ((0 != geteuid()) && (min_port < 1024))
[78]2437 {
2438 min_port = 1024;
[376]2439 if (noprivports == 0)
2440 {
[67]2441#ifdef TEST_ONLY
[376]2442 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
[67]2443#else
[376]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);
[67]2449#endif
[376]2450 noprivports = 1;
2451 }
[78]2452 }
[180]2453
2454 sh_port2proc_prepare();
2455
[78]2456 if (sh_portchk_check_udp == 1)
[328]2457 sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2458 sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
[180]2459
2460
[149]2461 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
[78]2462 if (sh_portchk_check_udp == 1)
[149]2463 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
[180]2464
[67]2465 }
[149]2466 SH_MUTEX_UNLOCK(mutex_port_check);
[67]2467 return 0;
2468}
2469#endif
2470
2471#ifdef SH_CUTEST
2472#include "CuTest.h"
2473
2474void Test_portcheck_lists (CuTest *tc)
2475{
[73]2476#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
[295]2477 struct sh_sockaddr haddr_local;
[67]2478 struct sh_portentry * portent;
[218]2479 char buf[256];
2480 char * p;
[67]2481
[290]2482#ifdef HAVE_RPC_RPC_H
[218]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"));
[290]2495#endif
[218]2496
[300]2497 p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
[218]2498 CuAssertTrue(tc, p == NULL);
2499
[290]2500#if !defined(HOST_IS_CYGWIN)
[218]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"));
[290]2505#endif
[218]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
[295]2512 CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
[67]2513
[295]2514 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
[67]2515
[295]2516 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
[67]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
[149]2524 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2525
2526 CuAssertTrue(tc, NULL == portlist_tcp);
2527
[295]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);
[67]2538
[149]2539 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2540
2541 CuAssertPtrNotNull(tc, portlist_tcp);
2542
[295]2543 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
[67]2544 CuAssertPtrNotNull(tc, portent);
2545
[295]2546 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL);
[67]2547 CuAssertTrue(tc, NULL == portent);
2548
[295]2549 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL);
[67]2550 CuAssertPtrNotNull(tc, portent);
2551
[295]2552 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL);
[67]2553 CuAssertTrue(tc, NULL == portent);
2554
[295]2555 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL);
[127]2556 CuAssertPtrNotNull(tc, portent);
2557
[295]2558 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1");
[67]2559 CuAssertTrue(tc, NULL == portent);
2560
[295]2561 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2");
[67]2562 CuAssertPtrNotNull(tc, portent);
2563 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2564
[295]2565 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3");
[67]2566 CuAssertTrue(tc, NULL == portent);
2567
[295]2568 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4");
[67]2569 CuAssertPtrNotNull(tc, portent);
2570 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
[127]2571
[295]2572 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5");
[127]2573 CuAssertPtrNotNull(tc, portent);
2574 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
[149]2575
[295]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));
[149]2584
[295]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));
[149]2589
[295]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));
[67]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
[237]2629 /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
[67]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.