source: trunk/src/sh_portcheck.c@ 538

Last change on this file since 538 was 530, checked in by katerina, 7 years ago

Fix for ticket #428 (compiler warnings).

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