source: trunk/src/sh_portcheck.c@ 592

Last change on this file since 592 was 592, checked in by katerina, 4 days ago

Fixes for compiler warnings.

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