source: trunk/src/sh_portcheck.c@ 550

Last change on this file since 550 was 541, checked in by katerina, 6 years ago

Fix for ticket #433 (coding standardisation).

  • Property svn:executable set to *
File size: 68.1 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 }
[539]432 /* cppcheck-suppress resourceLeak */
[218]433 return NULL;
434}
[290]435#endif
[218]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);
[252]472 sl_fclose(FIL__, __LINE__, fp);
[218]473 return buf;
474 }
475 }
476 }
477 SH_FREE(splits);
478 }
479 }
480 sh_string_destroy(&s);
[252]481 sl_fclose(FIL__, __LINE__, fp);
[218]482 }
[539]483 /* cppcheck-suppress resourceLeak */
[218]484 return NULL;
485}
486
[149]487static void sh_portchk_add_to_list (int proto,
[295]488 int port, struct sh_sockaddr * paddr,
[218]489 char * service,
[67]490 int flag, int status)
491{
492 struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
493
494 new->port = port;
[295]495 sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
[67]496 new->status = status;
497 new->flag = flag;
498
499 new->error = NULL;
500
[380]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
[67]506 if (service)
507 new->service = sh_util_strdup (service);
508 else
509 new->service = NULL;
[149]510 if (proto == IPPROTO_TCP)
[67]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 */
[170]527static void sh_portchk_reset_lists (void)
[67]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
[149]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
[295]569 SH_FREE(head->paddr);
[149]570 SH_FREE(head);
571 }
572 return NULL;
573}
574
[526]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
[170]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 */
[481]593void * sh_dummy_531_pre = NULL;
594void * sh_dummy_532_ptr = NULL;
[170]595
[67]596/* check the list of open ports for any that are marked as UNKN
597 */
[481]598static void sh_portchk_check_list (struct sh_portentry ** head,
599 int proto, int report)
[67]600{
601 struct sh_portentry * ptr = *head;
602 struct sh_portentry * pre = *head;
603 char errbuf[256];
604
[170]605 /* Take the address to keep gcc from putting them into registers.
606 * Avoids the 'clobbered by longjmp' warning.
607 */
[481]608 sh_dummy_531_pre = (void*) &pre;
609 sh_dummy_532_ptr = (void*) &ptr;
[170]610
[67]611 while (ptr)
612 {
613 if (portchk_debug && report)
614 fprintf(stderr, _("check list: port %d/%s %d %d\n"),
[149]615 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]616
617 if (ptr->status == SH_PORT_UNKN)
618 {
619 /* Don't report missing ports that are marked as optional
620 */
[127]621 if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
[67]622 {
[169]623 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[149]624 ptr->interface, ptr->port, SH_PROTO_STR(proto),
[67]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)
[149]631 {
632 SH_MUTEX_LOCK(mutex_thread_nolog);
633 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[169]634 MSG_PORT_MISS, errbuf);
[149]635 SH_MUTEX_UNLOCK(mutex_thread_nolog);
636 }
[67]637#endif
638 }
639
640 ptr->status = SH_PORT_MISS;
641
[128]642 if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
[67]643 {
644 if (portchk_debug && report)
645 fprintf(stderr, _("removing: port %d/%s %d %d\n"),
[149]646 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]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 }
[383]680
[481]681 sh_dummy_532_ptr = NULL;
682 sh_dummy_531_pre = NULL;
[383]683
[67]684 return;
685}
686
687
[149]688static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
[295]689 struct sh_sockaddr * paddr, char * service)
[67]690{
691 struct sh_portentry * portlist;
[295]692 char str_addr[SH_IP_BUF];
[75]693
[526]694
[149]695 if (proto == IPPROTO_TCP)
[67]696 portlist = portlist_tcp;
697 else
698 portlist = portlist_udp;
699
[295]700 sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
701
[67]702 if (service)
703 {
704 while (portlist)
705 {
706 if (portlist->service &&
707 0 == strcmp(service, portlist->service) &&
[295]708 ( 0 == strcmp(portlist->interface, str_addr) ||
709 sh_ipvx_isany(paddr) ))
[67]710 return portlist;
711 portlist = portlist->next;
712 }
713 }
714 else
715 {
716 while (portlist)
717 {
718 if (port == portlist->port &&
[295]719 (0 == strcmp(portlist->interface, str_addr) ||
720 sh_ipvx_isany(paddr) ))
[67]721 return portlist;
722 portlist = portlist->next;
723 }
724 }
725 return NULL;
726}
727
728
[380]729static void sh_portchk_cmp_to_list (int proto, int port,
730 struct sh_sockaddr * paddr, char * service)
[67]731{
732 struct sh_portentry * portent;
733 char errbuf[256];
734
735
[295]736 portent = sh_portchk_get_from_list (proto, port, paddr, service);
[67]737
738 if (service)
739 {
740 if (!portent)
741 {
[180]742 char * path;
[206]743 unsigned long qpid;
[180]744 char user[USER_MAX];
[295]745 char saddr[SH_IP_BUF];
[180]746
[295]747 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
748
[169]749 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]750 saddr, port, SH_PROTO_STR(proto), service);
[380]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
[295]757 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]758 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]759 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]760 MSG_PORT_NEW, errbuf, path, qpid, user);
[149]761 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]762 SH_FREE(path);
[67]763#endif
764 /*
765 * was not there, thus it is not in 'required' or 'optional' list
766 */
[295]767 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]768 }
[127]769 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]770 {
[180]771 char * path;
[206]772 unsigned long qpid;
[180]773 char user[USER_MAX];
[295]774 char saddr[SH_IP_BUF];
[180]775
[295]776 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
777
[169]778 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
[295]779 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]780#ifdef TEST_ONLY
781 fprintf(stderr, _("service: %s\n"), errbuf);
782#else
[295]783 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]784 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]785 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]786 MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]787 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]788 SH_FREE(path);
[67]789#endif
790
791 portent->status = SH_PORT_ISOK;
792 }
793 else if (port != portent->port && (-1) != portent->port)
794 {
[180]795 char * path;
[206]796 unsigned long qpid;
[180]797 char user[USER_MAX];
[295]798 char saddr[SH_IP_BUF];
[180]799
[295]800 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
801
[169]802 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
[295]803 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]804#ifdef TEST_ONLY
805 fprintf(stderr, _("service: %s\n"), errbuf);
806#else
[295]807 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]808 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]809 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]810 MSG_PORT_NEWPORT, errbuf, path, qpid, user);
[149]811 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]812 SH_FREE(path);
[67]813#endif
[127]814 portent->port = port;
[67]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 {
[180]826 char * path;
[206]827 unsigned long qpid;
[180]828 char user[USER_MAX];
[295]829 char saddr[SH_IP_BUF];
[180]830
[468]831 if (portchk_debug)
832 fprintf(stderr, _("call to sh_ipvx_ntoa (port %d)\n"), port);
833
[295]834 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
835
[169]836 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]837 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[380]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
[295]844 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]845 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]846 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]847 MSG_PORT_NEW, errbuf, path, qpid, user);
[149]848 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]849 SH_FREE(path);
[67]850#endif
851
852 /* was not there, thus it is not in 'required' or 'optional' list
853 */
[295]854 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]855 }
[127]856 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]857 {
[180]858 char * path;
[206]859 unsigned long qpid;
[180]860 char user[USER_MAX];
[295]861 char saddr[SH_IP_BUF];
[180]862
[295]863 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
864
[169]865 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
[295]866 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[67]867#ifdef TEST_ONLY
868 fprintf(stderr, _("port : %s\n"), errbuf);
869#else
[295]870 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]871 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]872 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
[206]873 MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]874 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]875 SH_FREE(path);
[67]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 */
[149]894static char * check_services (int port, int proto)
[67]895{
896 static char buf[256];
[218]897 char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
[67]898
[218]899 if (!service)
[67]900 {
[210]901 snprintf (buf, sizeof(buf), "%s",_("unknown"));
[67]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{
[439]913#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
[67]914 struct pmaplist * head;
[218]915 char *r;
[67]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 {
[218]927 r = sh_getrpcbynumber((int)head->pml_map.pm_prog,
928 buf, sizeof(buf));
929 if (r)
[67]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 }
[290]944#else
945 (void) port;
946 (void) address;
947 (void) prot;
948#endif
[67]949 return NULL;
950}
951
[530]952void * sh_dummy_950_p = NULL;
953void * sh_dummy_951_p = NULL;
954
[295]955static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]956{
957 int retval;
[295]958 char * p = NULL;
[67]959 char buf[8];
[78]960#ifndef TEST_ONLY
961 char errmsg[256];
[526]962 volatile int nerr;
[78]963#endif
[132]964 char errbuf[SH_ERRBUF_SIZE];
[295]965 char ipbuf[SH_IP_BUF];
[67]966
[526]967 struct sh_sockaddr saddr;
968 socklen_t slen = 0;
969 volatile int sport = 0;
970
[530]971 sh_dummy_950_p = (void*) &p;
972
[295]973 sh_ipvx_set_port(paddr, port);
[67]974
[78]975 do {
[295]976 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]977 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]978
[67]979 if (retval == -1)
980 {
981#ifdef TEST_ONLY
982 if (portchk_debug)
983 perror(_("connect"));
984#else
[295]985 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
986
[78]987 nerr = errno;
988 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
[295]989 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]990 SH_MUTEX_LOCK(mutex_thread_nolog);
[78]991 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
992 errmsg, _("connect"));
[149]993 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]994#endif
995 }
996 else
997 {
[526]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 */
[67]1008
[526]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 {
[78]1052 retval = send (fd, buf, 0, 0);
[526]1053 } while (retval < 0 && errno == EINTR);
[78]1054
[526]1055 if (retval == -1 && errno == ECONNREFUSED)
[67]1056 {
[295]1057 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[67]1058 if (portchk_debug)
[526]1059 fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
1060 port, ipbuf);
[67]1061 }
[526]1062 else
[67]1063 {
[526]1064 /* Only the second send() may catch the error
[67]1065 */
[526]1066 do {
1067 retval = send (fd, buf, 0, 0);
1068 } while (retval < 0 && errno == EINTR);
[380]1069
[526]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);
[67]1089
[526]1090 /* If not an RPC service, try to get name from /etc/services
1091 */
1092 if (!p)
1093 p = check_services(port, IPPROTO_UDP);
[67]1094
[526]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 }
[67]1101
[526]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 }
[67]1112 }
[526]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 }
[67]1123 }
[252]1124 sl_close_fd (FIL__, __LINE__, fd);
[530]1125 sh_dummy_950_p = NULL;
[67]1126 return 0;
1127}
1128
[295]1129static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]1130{
[526]1131 volatile int retval;
[109]1132 int flags;
[295]1133 char * p = NULL;
[78]1134#ifndef TEST_ONLY
1135 char errmsg[256];
[526]1136 volatile int nerr;
[78]1137#endif
[132]1138 char errbuf[SH_ERRBUF_SIZE];
[295]1139 char ipbuf[SH_IP_BUF];
[67]1140
[526]1141 struct sh_sockaddr saddr;
1142 socklen_t slen = 0;
1143 volatile int sport = 0;
1144
[530]1145 sh_dummy_951_p = (void*) &p;
1146
[295]1147 sh_ipvx_set_port(paddr, port);
[67]1148
[78]1149 do {
[295]1150 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]1151 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]1152
[67]1153 if (retval == -1 && errno == ECONNREFUSED)
1154 {
1155 if (portchk_debug)
[295]1156 {
1157 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[468]1158 fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
[295]1159 port, ipbuf);
1160 }
[67]1161 }
1162 else if (retval == -1)
1163 {
1164#ifdef TEST_ONLY
1165 if (portchk_debug)
1166 perror(_("connect"));
1167#else
[295]1168 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[78]1169 nerr = errno;
1170 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
[295]1171 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]1172 SH_MUTEX_LOCK(mutex_thread_nolog);
[78]1173 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1174 errmsg, _("connect"));
[149]1175 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1176#endif
1177 }
1178 else
1179 {
[526]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).
[67]1189 */
[526]1190
1191#if defined(USE_IPVX)
[295]1192 if (paddr->ss_family == AF_INET)
[526]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
[67]1209
[526]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 }
[67]1231
[526]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 }
[67]1242
[526]1243 sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
[109]1244
[526]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
[109]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);
[170]1281 retval = write (fd, _("SSH-2.0-Foobar"), 14);
1282 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1288 retval = write (fd, _("QUIT"), 4);
1289 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1295 retval = write (fd, "\r\n", 2);
[109]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);
[170]1301 retval = write (fd, _("QUIT"), 4);
1302 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1308 retval = write (fd, _("A01 LOGOUT"), 10);
1309 if (retval > 0) retval = write (fd, "\r\n", 2);
[109]1310 }
[170]1311
1312 if (portchk_debug && retval < 0)
1313 fprintf(stderr, _("check port: error writing to port %5d\n"),
1314 port);
[67]1315 }
[252]1316 sl_close_fd (FIL__, __LINE__, fd);
[530]1317 sh_dummy_951_p = NULL;
[67]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
[511]1328#define SH_IFACE_MAX 64
1329#define SH_IFACE_ADDR 0
1330#define SH_IFACE_DEV 1
[67]1331
1332struct portchk_interfaces {
[511]1333 struct sh_sockaddr iface;
1334 int type;
[67]1335};
1336
[511]1337static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1338static int iface_list_used = 0;
[67]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
[149]1347static int sh_portchk_init_internal (void)
[67]1348{
[468]1349 volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
[67]1350 char errbuf[256];
[295]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];
[67]1358
1359 if (portchk_debug)
1360 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
[78]1361
[67]1362 if (!portchk_hostname)
1363 return -1;
1364
[78]1365 if (sh_portchk_active == S_FALSE)
1366 return -1;
1367
[149]1368 SH_MUTEX_LOCK(mutex_port_check);
[67]1369 if (iface_initialized == 0)
1370 {
[511]1371 iface_list_used = 0;
[67]1372 iface_initialized = 1;
1373 }
[295]1374
1375#if !defined(USE_IPVX)
[134]1376 SH_MUTEX_LOCK(mutex_resolv);
[162]1377 hent = sh_gethostbyname(portchk_hostname);
[170]1378 i = 0;
[511]1379 while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
[67]1380 {
[295]1381 struct sockaddr_in sin;
[468]1382 struct sh_sockaddr iface_tmp;
[295]1383
1384 memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
[468]1385 sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1386
[511]1387 for (j = 0; j < iface_list_used; ++j)
[468]1388 {
[511]1389 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
[468]1390 {
1391 goto next_iface;
1392 }
1393 }
1394
[511]1395 sh_ipvx_save(&(iface_list[iface_list_used].iface),
[295]1396 AF_INET, (struct sockaddr *)&sin);
[511]1397 iface_list[iface_list_used].type = SH_IFACE_ADDR;
[380]1398
1399 if (portchk_debug)
1400 {
1401 char buf[256];
[511]1402 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
[468]1403 fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
[380]1404 }
[511]1405 ++iface_list_used;
[468]1406
1407 next_iface:
[134]1408 ++i;
1409 }
1410 SH_MUTEX_UNLOCK(mutex_resolv);
[295]1411#else
[541]1412 memset(&hints, 0, sizeof(hints));
[295]1413 hints.ai_family = PF_UNSPEC;
1414 hints.ai_flags = AI_ADDRCONFIG;
[134]1415
[295]1416 if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1417 {
1418 struct addrinfo *p = res;
[468]1419 struct sh_sockaddr iface_tmp;
[295]1420
[511]1421 while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
[295]1422 {
[468]1423 sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1424
[511]1425 for (j = 0; j < iface_list_used; ++j)
[468]1426 {
1427 if (portchk_debug)
1428 {
1429 char buf1[256], buf2[256];
[511]1430 sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
[468]1431 sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1432 fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
1433 }
[511]1434 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
[468]1435 {
1436 if (portchk_debug)
1437 fprintf(stderr, _("skipping interface[%d]\n"), j);
1438 goto next_iface;
1439 }
1440 }
[511]1441 sh_ipvx_save(&(iface_list[iface_list_used].iface),
[295]1442 p->ai_family, p->ai_addr);
[511]1443 iface_list[iface_list_used].type = SH_IFACE_ADDR;
[468]1444 if (portchk_debug)
1445 {
1446 char buf[256];
[511]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);
[468]1449 }
1450
[511]1451 ++iface_list_used;
[468]1452
1453 next_iface:
[295]1454 p = p->ai_next;
1455 }
1456 freeaddrinfo(res);
1457 }
1458#endif
1459
[511]1460 for (i = 0; i < iface_list_used; ++i)
[134]1461 {
[511]1462 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
[468]1463 sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
[295]1464
[149]1465 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1466 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1467 errbuf, _("sh_portchk_init"));
[149]1468 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1469 }
[149]1470 SH_MUTEX_UNLOCK(mutex_port_check);
[67]1471
1472 return 0;
1473}
1474
[149]1475int sh_portchk_init (struct mod_type * arg)
1476{
[210]1477#ifndef HAVE_PTHREAD
1478 (void) arg;
1479#endif
1480
[149]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 }
[335]1495 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1496 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1497 {
[511]1498 (void) sh_portchk_init_internal();
[335]1499 return SH_MOD_THREAD;
1500 }
[149]1501#endif
1502 return sh_portchk_init_internal();
1503}
1504
[511]1505static void dev_list_kill();
[149]1506
[67]1507#if !defined(TEST_ONLY)
[170]1508int sh_portchk_reconf (void)
[67]1509{
[149]1510 SH_MUTEX_LOCK(mutex_port_check);
[78]1511 iface_initialized = 0;
1512 sh_portchk_active = 1;
[80]1513 sh_portchk_check_udp = 1;
[149]1514 sh_portchk_interval = SH_PORTCHK_INTERVAL;
[78]1515
[328]1516 sh_portchk_minport = -1;
1517 sh_portchk_maxport = -1;
1518
[511]1519 dev_list_kill();
1520
[67]1521 portlist_udp = sh_portchk_kill_list (portlist_udp);
1522 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
[149]1523
1524 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1525 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
[235]1526 sh_port2proc_finish();
1527
[149]1528 SH_MUTEX_UNLOCK(mutex_port_check);
[67]1529 return 0;
1530}
1531
[170]1532int sh_portchk_cleanup (void)
[67]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
[295]1551static int check_port_generic (int port, int domain, int type, int protocol)
[67]1552{
[170]1553 volatile int i = 0;
[67]1554 int sock = -1;
1555 int flag = 1; /* non-zero to enable an option */
[295]1556 struct sh_sockaddr paddr;
[132]1557 char errbuf[SH_ERRBUF_SIZE];
1558
[67]1559 /* Check all interfaces for this host
1560 */
[511]1561 while (i < iface_list_used)
[67]1562 {
[511]1563 memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
[149]1564
[295]1565 if (paddr.ss_family != domain)
[149]1566 {
[295]1567 ++i;
1568 continue;
[149]1569 }
1570
[295]1571 if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
[67]1572 {
[295]1573 ++i;
1574 continue;
1575 }
1576
[526]1577 if (0 != sh_portchk_is_transient(port, &paddr, protocol))
1578 {
1579 ++i;
1580 continue;
1581 }
1582
[295]1583 if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1584 {
[170]1585 ++i;
[67]1586#ifdef TEST_ONLY
1587 if (portchk_debug)
1588 perror(_("socket"));
1589#else
[334]1590
1591#ifndef EPROTONOSUPPORT
1592#define EPROTONOSUPPORT 0
[170]1593#endif
[334]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
[149]1605 continue;
[67]1606 }
1607 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1608 (void *) &flag, sizeof(flag)) < 0 )
1609 {
[170]1610 ++i;
[67]1611#ifdef TEST_ONLY
1612 if (portchk_debug)
1613 perror(_("setsockopt"));
1614#else
[149]1615 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1616 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1617 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1618 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1619#endif
[149]1620 continue;
[67]1621 }
1622
1623
1624 if (protocol == IPPROTO_TCP)
[295]1625 check_port_tcp_internal(sock, port, &paddr);
[67]1626 else
[295]1627 check_port_udp_internal(sock, port, &paddr);
[67]1628
1629 ++i;
1630 }
1631
1632 return 0;
1633}
1634
1635
1636
[295]1637static int check_port_udp (int port, int domain)
[67]1638{
[295]1639 return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
[67]1640}
1641
[295]1642static int check_port_tcp (int port, int domain)
[67]1643{
[295]1644 return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
[67]1645}
1646
1647
[295]1648static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
1649 int domain, int type, int protocol)
[67]1650{
1651 /*
1652 int min_port = 1024;
1653 int max_port = 65535;
1654 */
1655
[170]1656 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1657 volatile int max_port = max_port_arg;
[67]1658 int retval;
1659 int sock = -1;
[498]1660#if 0
[67]1661 int flag = 1; /* non-zero to enable an option */
[498]1662#endif
[295]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
[132]1671 char errbuf[SH_ERRBUF_SIZE];
[67]1672
1673 if (min_port == -1)
1674 min_port = 0;
1675 if (max_port == -1)
1676 max_port = 65535;
1677
[468]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
[67]1683 for (port = min_port; port <= max_port; ++port)
1684 {
[295]1685 if ((sock = socket(domain, type, protocol)) < 0 )
[67]1686 {
1687#ifdef TEST_ONLY
1688 if (portchk_debug)
1689 perror(_("socket"));
1690#else
[334]1691#ifndef EPROTONOSUPPORT
1692#define EPROTONOSUPPORT 0
[67]1693#endif
[334]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
[149]1705 continue;
[67]1706 }
[498]1707
1708#if 0
[67]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
[149]1716 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1717 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1718 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1719 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1720#endif
[149]1721 continue;
[67]1722 }
[498]1723#endif
[67]1724
[295]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 }
[67]1739
1740 if (retval == 0)
1741 {
1742 /* we can bind the port, thus it is unused
1743 */
[252]1744 sl_close_fd (FIL__, __LINE__, sock);
[67]1745 }
1746 else
1747 {
1748 if (errno == EINVAL || errno == EADDRINUSE)
1749 {
1750 /* try to connect to the port
1751 */
1752 if (protocol == IPPROTO_TCP)
[295]1753 check_port_tcp(port, domain);
[67]1754 else
[295]1755 check_port_udp(port, domain);
[67]1756 }
1757 else
1758 {
1759#ifdef TEST_ONLY
1760 if (portchk_debug)
1761 perror(_("bind"));
1762#else
[149]1763 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1764 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]1765 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
[149]1766 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1767#endif
1768 }
[252]1769 sl_close_fd (FIL__, __LINE__, sock);
[67]1770 }
1771 }
[526]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
[67]1778 return 0;
1779}
1780
1781static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1782{
[295]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);
[67]1789}
1790
1791static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1792{
[295]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);
[67]1799}
1800
1801/* Subroutine to add an interface
1802 */
[481]1803void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
[212]1804
[511]1805static int sh_portchk_add_interface_int (const char * str, int type)
[67]1806{
[295]1807 struct sh_sockaddr saddr;
[67]1808 char errbuf[256];
[212]1809 char buf[64];
[67]1810
[481]1811 sh_dummy_1564_str = (void*) &str;
[212]1812
[67]1813 if (iface_initialized == 0)
1814 {
[511]1815 iface_list_used = 0;
[67]1816 iface_initialized = 1;
1817 }
1818
[212]1819 do {
[67]1820
[212]1821 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
[67]1822
[212]1823 if (*str)
1824 {
[295]1825 char ipbuf[SH_IP_BUF];
[212]1826 unsigned int i = 0;
[295]1827 while (*str && i < (sizeof(buf)-1) &&
1828 *str != ',' && *str != ' ' && *str != '\t')
[212]1829 {
1830 buf[i] = *str; ++str; ++i;
1831 }
1832 buf[i] = '\0';
[67]1833
[295]1834 if (0 == sh_ipvx_aton(buf, &saddr))
[212]1835 return -1;
[67]1836
[511]1837 if (iface_list_used == SH_IFACE_MAX)
[212]1838 return -1;
1839
[295]1840 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1841 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
[212]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
[511]1847 memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1848 iface_list[iface_list_used].type = type;
1849 ++iface_list_used;
[212]1850 }
1851 } while (*str);
1852
[481]1853 sh_dummy_1564_str = NULL;
[67]1854 return 0;
1855}
1856
[511]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{
[516]2012 const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
2013 const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
[511]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
[149]2081/* verify whether port/interface is blacklisted (do not check)
2082 */
[295]2083static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
2084 int proto)
[149]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 {
[526]2095 if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2096 return 1;
[149]2097 head = head->next;
2098 }
2099 return 0;
2100}
2101
2102
[295]2103static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
[149]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 {
[295]2117 if (black->port == port &&
2118 0 == sh_ipvx_cmp(head->paddr, saddr))
[149]2119 return -1;
2120 black = black->next;
2121 }
[295]2122
[149]2123 black = SH_ALLOC (sizeof(struct sh_port));
[295]2124 black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
[149]2125 black->port = port;
[295]2126 memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
[149]2127 black->next = head;
2128
2129 if (proto == IPPROTO_TCP)
2130 blacklist_tcp = black;
2131 else
2132 blacklist_udp = black;
[468]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 }
[149]2140 return 0;
2141}
[526]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;
[149]2151
[526]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
[67]2211/* Subroutine to add a required or optional port/service
2212 */
[295]2213static int sh_portchk_add_required_port_generic (char * service,
2214 char * interface, int type)
[67]2215{
[473]2216 char buf[256] = { '\0' };
[149]2217 int proto;
[67]2218 char * p;
2219 char * endptr;
2220 unsigned long int port;
[295]2221 struct sh_sockaddr saddr;
[67]2222 struct sh_portentry * portent;
2223
[295]2224 if (0 == sh_ipvx_aton(interface, &saddr))
[67]2225 return -1;
2226
2227 sl_strlcpy (buf, service, sizeof(buf));
2228
2229 p = strchr(buf, '/');
2230 if (!p)
2231 return -1;
[519]2232 if (0 == strcasecmp(p, _("/tcp")))
[149]2233 proto = IPPROTO_TCP;
[519]2234 else if (0 == strcasecmp(p, _("/udp")))
[149]2235 proto = IPPROTO_UDP;
[67]2236 else
2237 return -1;
2238
2239 *p = '\0';
2240 port = strtoul(buf, &endptr, 0);
2241
[468]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
[149]2251 /* Blacklisted ports
2252 */
2253 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
[295]2254 return (sh_portchk_blacklist(port, &saddr, proto));
[149]2255
[67]2256 if (*endptr != '\0')
2257 {
[295]2258 portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
[67]2259 if (!portent)
[380]2260 {
2261 if (portchk_debug)
[383]2262 fprintf(stderr, _("add_required_port %d\n"), (int) port);
[380]2263 sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN);
2264 }
[67]2265 else
2266 {
2267#ifdef TEST_ONLY
[149]2268 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
[67]2269#else
[149]2270 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]2271 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2272 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]2273 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]2274#endif
2275 return -1;
2276 }
2277 }
2278 else if (port <= 65535)
2279 {
[295]2280 portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
[67]2281 if (!portent)
[380]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 }
[67]2288 else
2289 {
2290#ifdef TEST_ONLY
[149]2291 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
[67]2292#else
[149]2293 SH_MUTEX_LOCK(mutex_thread_nolog);
[67]2294 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2295 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]2296 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]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;
[149]2312 int status;
[67]2313
2314 char * interface = NULL;
2315 char * list;
2316 char * p;
[131]2317#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2318 char * saveptr;
2319#endif
[67]2320
2321 if (!str)
2322 return -1;
2323
2324 if (strchr(str, ':'))
2325 {
[468]2326 char *last = strrchr(str, ':');
2327 if (last != NULL)
[67]2328 {
[468]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;
[67]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)
[468]2359 fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
[67]2360
2361 list = sh_util_strdup(&str[ll]);
[131]2362#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2363 p = strtok_r (list, " ,\t", &saveptr);
2364#else
[67]2365 p = strtok (list, " ,\t");
[131]2366#endif
[67]2367 if (!p)
2368 {
2369 SH_FREE(interface);
2370 SH_FREE(list);
2371 return -1;
2372 }
2373 while (p)
2374 {
[149]2375 status = sh_portchk_add_required_port_generic (p, interface, type);
2376
2377 if (-1 == status)
[67]2378 {
2379 SH_FREE(interface);
2380 SH_FREE(list);
2381 return -1;
2382 }
[131]2383#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2384 p = strtok_r (NULL, " ,\t", &saveptr);
2385#else
[67]2386 p = strtok (NULL, " ,\t");
[131]2387#endif
[67]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
[127]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
[149]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
[67]2422/* Interface to run port check
2423 */
2424int sh_portchk_check ()
2425{
[170]2426 volatile int min_port;
[376]2427 static int noprivports = 0;
[67]2428
[149]2429 SH_MUTEX_LOCK(mutex_port_check);
[170]2430
[328]2431 min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
[170]2432
[78]2433 if (sh_portchk_active != S_FALSE)
[67]2434 {
[405]2435 SH_MUTEX_LOCK(mutex_thread_nolog);
[253]2436 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2437 _("Checking for open ports"),
2438 _("sh_portchk_check"));
[405]2439 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[253]2440
[78]2441 sh_portchk_reset_lists();
[511]2442
2443#if defined(HAVE_IFADDRS_H)
2444 recheck_devices();
2445#endif
2446
[328]2447 if ((0 != geteuid()) && (min_port < 1024))
[78]2448 {
2449 min_port = 1024;
[376]2450 if (noprivports == 0)
2451 {
[67]2452#ifdef TEST_ONLY
[376]2453 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
[67]2454#else
[376]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);
[67]2460#endif
[376]2461 noprivports = 1;
2462 }
[78]2463 }
[180]2464
2465 sh_port2proc_prepare();
2466
[78]2467 if (sh_portchk_check_udp == 1)
[328]2468 sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2469 sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
[180]2470
2471
[149]2472 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
[78]2473 if (sh_portchk_check_udp == 1)
[149]2474 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
[180]2475
[67]2476 }
[149]2477 SH_MUTEX_UNLOCK(mutex_port_check);
[67]2478 return 0;
2479}
2480#endif
2481
2482#ifdef SH_CUTEST
2483#include "CuTest.h"
2484
2485void Test_portcheck_lists (CuTest *tc)
2486{
[73]2487#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
[295]2488 struct sh_sockaddr haddr_local;
[67]2489 struct sh_portentry * portent;
[218]2490 char buf[256];
2491 char * p;
[67]2492
[290]2493#ifdef HAVE_RPC_RPC_H
[218]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"));
[290]2506#endif
[218]2507
[300]2508 p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
[218]2509 CuAssertTrue(tc, p == NULL);
2510
[290]2511#if !defined(HOST_IS_CYGWIN)
[218]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"));
[290]2516#endif
[218]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
[295]2523 CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
[67]2524
[295]2525 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
[67]2526
[295]2527 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
[67]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
[149]2535 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2536
2537 CuAssertTrue(tc, NULL == portlist_tcp);
2538
[295]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);
[67]2549
[149]2550 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2551
2552 CuAssertPtrNotNull(tc, portlist_tcp);
2553
[295]2554 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
[67]2555 CuAssertPtrNotNull(tc, portent);
2556
[295]2557 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL);
[67]2558 CuAssertTrue(tc, NULL == portent);
2559
[295]2560 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL);
[67]2561 CuAssertPtrNotNull(tc, portent);
2562
[295]2563 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL);
[67]2564 CuAssertTrue(tc, NULL == portent);
2565
[295]2566 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL);
[127]2567 CuAssertPtrNotNull(tc, portent);
2568
[295]2569 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1");
[67]2570 CuAssertTrue(tc, NULL == portent);
2571
[295]2572 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2");
[67]2573 CuAssertPtrNotNull(tc, portent);
2574 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2575
[295]2576 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3");
[67]2577 CuAssertTrue(tc, NULL == portent);
2578
[295]2579 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4");
[67]2580 CuAssertPtrNotNull(tc, portent);
2581 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
[127]2582
[295]2583 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5");
[127]2584 CuAssertPtrNotNull(tc, portent);
2585 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
[149]2586
[295]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));
[149]2595
[295]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));
[149]2600
[295]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));
[67]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
[237]2640 /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
[67]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.