source: trunk/src/sh_portcheck.c@ 517

Last change on this file since 517 was 516, checked in by katerina, 8 years ago

Fix for ticket #409 and #410 (unprivileged suidcheck and gcc 6.2 compiler warnings).

  • Property svn:executable set to *
File size: 60.4 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2006 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to check for open ports
23 * on the local machine.
24 *
25 */
26
27
28/* #define TEST_ONLY */
29#ifndef TEST_ONLY
30#include "config_xor.h"
31#endif
32
33#include <stdio.h>
34#include <string.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#ifdef HAVE_IFADDRS_H
41#include <ifaddrs.h>
42#include <netdb.h>
43#endif
44#include <errno.h>
45#include <unistd.h>
46#include <fcntl.h>
47
48#define PORTCHK_VERSION "1.0"
49
50#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
51
52
53#define PORTMAP
54#ifdef HAVE_RPC_RPC_H
55#include <rpc/rpc.h>
56#ifdef HAVE_RPC_RPCENT_H
57#include <rpc/rpcent.h>
58#endif
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61#endif
62#include <netdb.h>
63
64/*
65 * struct pmaplist {
66 * struct pmap pml_map;
67 * struct pmaplist *pml_next;
68 * };
69 */
70
71/* struct pmap {
72 * long unsigned pm_prog;
73 * long unsigned pm_vers;
74 * long unsigned pm_prot;
75 * long unsigned pm_port;
76 * };
77 */
78
79/* TIME_WAIT ? 60-240 seconds */
80
81#if !defined(TEST_ONLY)
82
83#define FIL__ _("sh_portcheck.c")
84#include "samhain.h"
85#include "sh_error.h"
86#include "sh_mem.h"
87#include "sh_calls.h"
88#include "sh_utils.h"
89#include "sh_modules.h"
90#define SH_NEED_GETHOSTBYXXX
91#include "sh_static.h"
92#include "sh_pthread.h"
93#include "sh_ipvx.h"
94
95/* the size of an interface string
96 */
97#define SH_INTERFACE_SIZE SH_IP_BUF
98
99#define SH_PORT_NOT 0
100#define SH_PORT_REQ 1
101#define SH_PORT_OPT 2
102#define SH_PORT_IGN 3
103#define SH_PORT_BLACKLIST 4
104
105static char * sh_port_type2str (int type)
106{
107 if (type == 0) return _("not");
108 if (type == 1) return _("req");
109 if (type == 2) return _("opt");
110 if (type == 3) return _("ign");
111 if (type == 4) return _("blc");
112 return _("???");
113}
114
115#define SH_PORT_MISS 0
116#define SH_PORT_ISOK 1
117#define SH_PORT_UNKN 2
118
119#define SH_PORT_NOREPT 0
120#define SH_PORT_REPORT 1
121
122#define SH_PROTO_TCP 0
123#define SH_PROTO_UDP 1
124#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
125
126struct sh_portentry {
127 int port;
128 char interface[SH_INTERFACE_SIZE];
129 char * service;
130 char * error;
131 int flag; /* required or not */
132 int status; /* missing or not */
133 struct sh_portentry * next;
134};
135
136static struct sh_portentry * portlist_tcp = NULL;
137static struct sh_portentry * portlist_udp = NULL;
138
139
140#define SH_PORTCHK_INTERVAL 300
141
142static int sh_portchk_check_udp = 1;
143static int sh_portchk_active = 1;
144static int sh_portchk_interval = SH_PORTCHK_INTERVAL;
145
146static int sh_portchk_minport = -1;
147static int sh_portchk_maxport = -1;
148
149struct sh_port {
150 int port;
151 struct sh_sockaddr * paddr;
152 struct sh_port * next;
153};
154
155static struct sh_port * blacklist_tcp = NULL;
156static struct sh_port * blacklist_udp = NULL;
157
158SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
159
160static int sh_portchk_severity = SH_ERR_SEVERE;
161
162extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
163 unsigned long * pid, char * user, size_t userlen);
164extern int sh_port2proc_prepare();
165extern void sh_port2proc_finish();
166
167#endif
168
169/* Exported interface to add ignoreable ports as 'iface:portlist'
170 */
171static int sh_portchk_add_ignore (const char * str);
172
173/* Exported interface to add required ports as 'iface:portlist'
174 */
175static int sh_portchk_add_required (const char * str);
176
177/* Exported interface to add optional ports as 'iface:portlist'
178 */
179static int sh_portchk_add_optional (const char * str);
180
181/* Exported interface to add blacklisted ports as 'iface:portlist'
182 */
183static int sh_portchk_add_blacklist (const char * str);
184
185/* Exported interface to add an ethernet interface
186 */
187static int sh_portchk_add_interface (const char * str);
188
189#if defined(HAVE_IFADDRS_H)
190/* Exported interface to add an ethernet device
191 */
192static int sh_portchk_add_device (const char * str);
193#endif
194
195/* verify whether port/interface is blacklisted (do not check)
196 */
197static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
198
199#ifndef TEST_ONLY
200
201static int sh_portchk_set_interval (const char * c)
202{
203 int retval = 0;
204 long val;
205
206 SL_ENTER(_("sh_portchk_set_interval"));
207 val = strtol (c, (char **)NULL, 10);
208 if (val <= 0)
209 {
210 SH_MUTEX_LOCK(mutex_thread_nolog);
211 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
212 _("port check interval"), c);
213 SH_MUTEX_UNLOCK(mutex_thread_nolog);
214 retval = -1;
215 }
216 else
217 {
218 sh_portchk_interval = (time_t) val;
219 }
220 SL_RETURN(retval, _("sh_portchk_set_interval"));
221}
222
223static int sh_portchk_set_port_minmax (const char * c, int * setthis)
224{
225 int retval = 0;
226 long val;
227
228 SL_ENTER(_("sh_portchk_set_port_minmax"));
229 val = strtol (c, (char **)NULL, 10);
230 if (val < 0 || val > 65535)
231 {
232 SH_MUTEX_LOCK(mutex_thread_nolog);
233 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
234 _("port check port minmax"), c);
235 SH_MUTEX_UNLOCK(mutex_thread_nolog);
236 retval = -1;
237 }
238 else
239 {
240 *setthis = (int) val;
241 }
242 SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
243}
244
245
246static int sh_portchk_set_minport (const char * str)
247{
248 return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
249}
250
251static int sh_portchk_set_maxport (const char * str)
252{
253 return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
254}
255
256static int sh_portchk_set_active (const char * str)
257{
258 return sh_util_flagval(str, &sh_portchk_active);
259}
260
261static int sh_portchk_set_udp (const char * str)
262{
263 return sh_util_flagval(str, &sh_portchk_check_udp);
264}
265
266static int sh_portchk_set_severity (const char * str)
267{
268 char tmp[32];
269 tmp[0] = '='; tmp[1] = '\0';
270 sl_strlcat (tmp, str, 32);
271 return sh_error_set_level (tmp, &sh_portchk_severity);
272}
273
274sh_rconf sh_portchk_table[] = {
275 {
276 N_("severityportcheck"),
277 sh_portchk_set_severity,
278 },
279 {
280 N_("portcheckrequired"),
281 sh_portchk_add_required,
282 },
283 {
284 N_("portcheckoptional"),
285 sh_portchk_add_optional,
286 },
287 {
288 N_("portcheckignore"),
289 sh_portchk_add_ignore,
290 },
291 {
292 N_("portcheckskip"),
293 sh_portchk_add_blacklist,
294 },
295 {
296 N_("portcheckactive"),
297 sh_portchk_set_active,
298 },
299#if defined(HAVE_IFADDRS_H)
300 {
301 N_("portcheckdevice"),
302 sh_portchk_add_device,
303 },
304#endif
305 {
306 N_("portcheckinterface"),
307 sh_portchk_add_interface,
308 },
309 {
310 N_("portcheckinterval"),
311 sh_portchk_set_interval,
312 },
313 {
314 N_("portcheckminport"),
315 sh_portchk_set_minport,
316 },
317 {
318 N_("portcheckmaxport"),
319 sh_portchk_set_maxport,
320 },
321 {
322 N_("portcheckudp"),
323 sh_portchk_set_udp,
324 },
325 {
326 NULL,
327 NULL
328 }
329};
330
331#endif
332
333/* Interface to initialize port check
334 */
335int sh_portchk_init (struct mod_type * arg);
336
337/* Interface to reset port check
338 */
339int sh_portchk_reset (void);
340
341/* Interface to run port check
342 */
343int sh_portchk_check (void);
344
345
346static char * check_services (int port, int proto);
347
348#ifdef TEST_ONLY
349
350static int portchk_debug = 0;
351#define SH_ALLOC malloc
352#define SH_FREE free
353#define sh_util_strdup strdup
354#define sl_strlcpy strncpy
355#define _(a) a
356
357#else
358
359static int portchk_debug = 0;
360
361#endif
362
363#ifdef HAVE_RPC_RPC_H
364static char * sh_getrpcbynumber (int number, char * buf, size_t len)
365{
366 FILE * fp;
367
368 if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
369 {
370 sh_string * s = sh_string_new(0);
371 while (0 < sh_string_read(s, fp, 1024))
372 {
373 char * p = sh_string_str(s);
374 while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
375 if (*p == '\0' || *p == '#')
376 continue; /* skip comment */
377 else
378 {
379 size_t lengths[3];
380 unsigned int fields = 3;
381 char * q = sh_string_str(s);
382 char ** splits = split_array_ws(q, &fields, lengths);
383
384 if (fields >= 2)
385 {
386 int n = atoi(splits[1]);
387 if (n == number)
388 {
389 sl_strlcpy(buf, splits[0], len);
390 SH_FREE(splits);
391 sh_string_destroy(&s);
392 sl_fclose(FIL__, __LINE__, fp);
393 return buf;
394 }
395 }
396 SH_FREE(splits);
397 }
398 }
399 sh_string_destroy(&s);
400 sl_fclose(FIL__, __LINE__, fp);
401 }
402 return NULL;
403}
404#endif
405
406static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
407{
408 FILE * fp;
409 char proto[8];
410
411 sl_strlcpy(proto, proto_in, sizeof(proto));
412
413 if (NULL != (fp = fopen(_("/etc/services"), "r")))
414 {
415 sh_string * s = sh_string_new(0);
416 while (0 < sh_string_read(s, fp, 1024))
417 {
418 char * p = sh_string_str(s);
419 while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
420 if (*p == '\0' || *p == '#')
421 continue; /* skip comment */
422 else
423 {
424 size_t lengths[3];
425 unsigned int fields = 3;
426 char * q = sh_string_str(s);
427 char ** splits = split_array_ws(q, &fields, lengths);
428
429 if (fields >= 2)
430 {
431 char * end;
432 long n = strtol(splits[1], &end, 10);
433 if (n == port && end && (*end == '/' || *end == ','))
434 {
435 ++end;
436 if (0 == strcmp(end, proto))
437 {
438 sl_strlcpy(buf, splits[0], len);
439 SH_FREE(splits);
440 sh_string_destroy(&s);
441 sl_fclose(FIL__, __LINE__, fp);
442 return buf;
443 }
444 }
445 }
446 SH_FREE(splits);
447 }
448 }
449 sh_string_destroy(&s);
450 sl_fclose(FIL__, __LINE__, fp);
451 }
452 return NULL;
453}
454
455static void sh_portchk_add_to_list (int proto,
456 int port, struct sh_sockaddr * paddr,
457 char * service,
458 int flag, int status)
459{
460 struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
461
462 new->port = port;
463 sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
464 new->status = status;
465 new->flag = flag;
466
467 new->error = NULL;
468
469 if (portchk_debug)
470 fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"),
471 port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"),
472 new->interface);
473
474 if (service)
475 new->service = sh_util_strdup (service);
476 else
477 new->service = NULL;
478 if (proto == IPPROTO_TCP)
479 {
480 new->next = portlist_tcp;
481 portlist_tcp = new;
482 }
483 else
484 {
485 new->next = portlist_udp;
486 portlist_udp = new;
487 }
488 return;
489}
490
491/* Reset the list by setting all entries to UNKN.
492 * In the next cycle we will check, and set found ports to ISOK.
493 * Thereafter, we check for entries that are still UNKN.
494 */
495static void sh_portchk_reset_lists (void)
496{
497 struct sh_portentry * portlist;
498
499 portlist = portlist_tcp;
500 while (portlist)
501 {
502 if (portlist->status != SH_PORT_MISS)
503 portlist->status = SH_PORT_UNKN;
504 portlist = portlist->next;
505 }
506 portlist = portlist_udp;
507 while (portlist)
508 {
509 if (portlist->status != SH_PORT_MISS)
510 portlist->status = SH_PORT_UNKN;
511 portlist = portlist->next;
512 }
513 return;
514}
515
516static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
517{
518 if (head)
519 {
520 if (head->next)
521 sh_portchk_kill_list (head->next);
522
523 if (head->service)
524 SH_FREE(head->service);
525 SH_FREE(head);
526 }
527 return NULL;
528}
529
530static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
531{
532 if (head)
533 {
534 if (head->next)
535 sh_portchk_kill_blacklist (head->next);
536
537 SH_FREE(head->paddr);
538 SH_FREE(head);
539 }
540 return NULL;
541}
542
543/* These variables are not used anywhere. They only exist
544 * to assign &pre, &ptr to them, which keeps gcc from
545 * putting it into a register, and avoids the 'clobbered
546 * by longjmp' warning. And no, 'volatile' proved insufficient.
547 */
548void * sh_dummy_531_pre = NULL;
549void * sh_dummy_532_ptr = NULL;
550
551/* check the list of open ports for any that are marked as UNKN
552 */
553static void sh_portchk_check_list (struct sh_portentry ** head,
554 int proto, int report)
555{
556 struct sh_portentry * ptr = *head;
557 struct sh_portentry * pre = *head;
558 char errbuf[256];
559
560 /* Take the address to keep gcc from putting them into registers.
561 * Avoids the 'clobbered by longjmp' warning.
562 */
563 sh_dummy_531_pre = (void*) &pre;
564 sh_dummy_532_ptr = (void*) &ptr;
565
566 while (ptr)
567 {
568 if (portchk_debug && report)
569 fprintf(stderr, _("check list: port %d/%s %d %d\n"),
570 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
571
572 if (ptr->status == SH_PORT_UNKN)
573 {
574 /* Don't report missing ports that are marked as optional
575 */
576 if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
577 {
578 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
579 ptr->interface, ptr->port, SH_PROTO_STR(proto),
580 ptr->service ? ptr->service : check_services(ptr->port, proto));
581#ifdef TEST_ONLY
582 if (report == SH_PORT_REPORT)
583 fprintf(stderr, _("%s\n"), errbuf);
584#else
585 if (report == SH_PORT_REPORT)
586 {
587 SH_MUTEX_LOCK(mutex_thread_nolog);
588 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
589 MSG_PORT_MISS, errbuf);
590 SH_MUTEX_UNLOCK(mutex_thread_nolog);
591 }
592#endif
593 }
594
595 ptr->status = SH_PORT_MISS;
596
597 if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
598 {
599 if (portchk_debug && report)
600 fprintf(stderr, _("removing: port %d/%s %d %d\n"),
601 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
602
603 if (ptr == *head)
604 {
605 *head = ptr->next;
606 if (ptr->service)
607 SH_FREE(ptr->service);
608 SH_FREE(ptr);
609 ptr = *head;
610 pre = *head;
611 continue;
612 }
613 else if (ptr->next == NULL)
614 {
615 pre->next = NULL;
616 if (ptr->service)
617 SH_FREE(ptr->service);
618 SH_FREE(ptr);
619 return;
620 }
621 else
622 {
623 pre->next = ptr->next;
624 if (ptr->service)
625 SH_FREE(ptr->service);
626 SH_FREE(ptr);
627 ptr = pre->next;
628 continue;
629 }
630 }
631 }
632 pre = ptr;
633 ptr = ptr->next;
634 }
635
636 sh_dummy_532_ptr = NULL;
637 sh_dummy_531_pre = NULL;
638
639 return;
640}
641
642
643static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
644 struct sh_sockaddr * paddr, char * service)
645{
646 struct sh_portentry * portlist;
647 char str_addr[SH_IP_BUF];
648
649 if (proto == IPPROTO_TCP)
650 portlist = portlist_tcp;
651 else
652 portlist = portlist_udp;
653
654 sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
655
656 if (service)
657 {
658 while (portlist)
659 {
660 if (portlist->service &&
661 0 == strcmp(service, portlist->service) &&
662 ( 0 == strcmp(portlist->interface, str_addr) ||
663 sh_ipvx_isany(paddr) ))
664 return portlist;
665 portlist = portlist->next;
666 }
667 }
668 else
669 {
670 while (portlist)
671 {
672 if (port == portlist->port &&
673 (0 == strcmp(portlist->interface, str_addr) ||
674 sh_ipvx_isany(paddr) ))
675 return portlist;
676 portlist = portlist->next;
677 }
678 }
679 return NULL;
680}
681
682
683static void sh_portchk_cmp_to_list (int proto, int port,
684 struct sh_sockaddr * paddr, char * service)
685{
686 struct sh_portentry * portent;
687 char errbuf[256];
688
689
690 portent = sh_portchk_get_from_list (proto, port, paddr, service);
691
692 if (service)
693 {
694 if (!portent)
695 {
696 char * path;
697 unsigned long qpid;
698 char user[USER_MAX];
699 char saddr[SH_IP_BUF];
700
701 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
702
703 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
704 saddr, port, SH_PROTO_STR(proto), service);
705
706 if (portchk_debug)
707 fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"),
708 saddr, port, SH_PROTO_STR(proto), service);
709
710#ifndef TEST_ONLY
711 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
712 SH_MUTEX_LOCK(mutex_thread_nolog);
713 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
714 MSG_PORT_NEW, errbuf, path, qpid, user);
715 SH_MUTEX_UNLOCK(mutex_thread_nolog);
716 SH_FREE(path);
717#endif
718 /*
719 * was not there, thus it is not in 'required' or 'optional' list
720 */
721 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
722 }
723 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
724 {
725 char * path;
726 unsigned long qpid;
727 char user[USER_MAX];
728 char saddr[SH_IP_BUF];
729
730 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
731
732 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
733 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
734#ifdef TEST_ONLY
735 fprintf(stderr, _("service: %s\n"), errbuf);
736#else
737 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
738 SH_MUTEX_LOCK(mutex_thread_nolog);
739 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
740 MSG_PORT_RESTART, errbuf, path, qpid, user);
741 SH_MUTEX_UNLOCK(mutex_thread_nolog);
742 SH_FREE(path);
743#endif
744
745 portent->status = SH_PORT_ISOK;
746 }
747 else if (port != portent->port && (-1) != portent->port)
748 {
749 char * path;
750 unsigned long qpid;
751 char user[USER_MAX];
752 char saddr[SH_IP_BUF];
753
754 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
755
756 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
757 saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
758#ifdef TEST_ONLY
759 fprintf(stderr, _("service: %s\n"), errbuf);
760#else
761 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
762 SH_MUTEX_LOCK(mutex_thread_nolog);
763 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
764 MSG_PORT_NEWPORT, errbuf, path, qpid, user);
765 SH_MUTEX_UNLOCK(mutex_thread_nolog);
766 SH_FREE(path);
767#endif
768 portent->port = port;
769 portent->status = SH_PORT_ISOK;
770 }
771 else
772 {
773 portent->status = SH_PORT_ISOK;
774 }
775 }
776 else
777 {
778 if (!portent)
779 {
780 char * path;
781 unsigned long qpid;
782 char user[USER_MAX];
783 char saddr[SH_IP_BUF];
784
785 if (portchk_debug)
786 fprintf(stderr, _("call to sh_ipvx_ntoa (port %d)\n"), port);
787
788 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
789
790 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
791 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
792
793 if (portchk_debug)
794 fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"),
795 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
796
797#ifndef TEST_ONLY
798 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
799 SH_MUTEX_LOCK(mutex_thread_nolog);
800 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
801 MSG_PORT_NEW, errbuf, path, qpid, user);
802 SH_MUTEX_UNLOCK(mutex_thread_nolog);
803 SH_FREE(path);
804#endif
805
806 /* was not there, thus it is not in 'required' or 'optional' list
807 */
808 sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
809 }
810 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
811 {
812 char * path;
813 unsigned long qpid;
814 char user[USER_MAX];
815 char saddr[SH_IP_BUF];
816
817 sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
818
819 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
820 saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
821#ifdef TEST_ONLY
822 fprintf(stderr, _("port : %s\n"), errbuf);
823#else
824 path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
825 SH_MUTEX_LOCK(mutex_thread_nolog);
826 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
827 MSG_PORT_RESTART, errbuf, path, qpid, user);
828 SH_MUTEX_UNLOCK(mutex_thread_nolog);
829 SH_FREE(path);
830#endif
831
832 portent->status = SH_PORT_ISOK;
833 }
834 else
835 {
836 portent->status = SH_PORT_ISOK;
837 }
838 }
839
840 return;
841}
842
843
844/* Returns a static buffer containing the name of the service
845 * running on port <port> (from /etc/services)
846 * Returns NULL on failure
847 */
848static char * check_services (int port, int proto)
849{
850 static char buf[256];
851 char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
852
853 if (!service)
854 {
855 snprintf (buf, sizeof(buf), "%s",_("unknown"));
856 }
857 return buf;
858}
859
860/* Returns a static buffer containing the name of the service
861 * running on port <port> at <address> (from portmap daemon)
862 * Returns NULL on failure
863 */
864static char * check_rpc_list (int port, struct sockaddr_in * address,
865 unsigned long prot)
866{
867#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
868 struct pmaplist * head;
869 char *r;
870 static char buf[256];
871
872 head = pmap_getmaps(address);
873
874 if (head)
875 {
876 do /* while (head != NULL) */
877 {
878 if ((head->pml_map.pm_prot == prot) &&
879 (port == (int)head->pml_map.pm_port))
880 {
881 r = sh_getrpcbynumber((int)head->pml_map.pm_prog,
882 buf, sizeof(buf));
883 if (r)
884 {
885 return buf;
886 }
887 else
888 {
889 snprintf (buf, sizeof(buf), "RPC_%lu",
890 (unsigned long)head->pml_map.pm_prog);
891 return buf;
892 }
893 }
894 head = head->pml_next;
895 }
896 while (head != NULL);
897 }
898#else
899 (void) port;
900 (void) address;
901 (void) prot;
902#endif
903 return NULL;
904}
905
906static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
907{
908 int retval;
909 char * p = NULL;
910 char buf[8];
911#ifndef TEST_ONLY
912 char errmsg[256];
913 int nerr;
914#endif
915 char errbuf[SH_ERRBUF_SIZE];
916 char ipbuf[SH_IP_BUF];
917
918 sh_ipvx_set_port(paddr, port);
919
920 do {
921 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
922 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
923
924 if (retval == -1)
925 {
926#ifdef TEST_ONLY
927 if (portchk_debug)
928 perror(_("connect"));
929#else
930 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
931
932 nerr = errno;
933 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
934 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
935 SH_MUTEX_LOCK(mutex_thread_nolog);
936 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
937 errmsg, _("connect"));
938 SH_MUTEX_UNLOCK(mutex_thread_nolog);
939#endif
940 }
941 else
942 {
943 do {
944 retval = send (fd, buf, 0, 0);
945 } while (retval < 0 && errno == EINTR);
946
947 if (retval == -1 && errno == ECONNREFUSED)
948 {
949 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
950 if (portchk_debug)
951 fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
952 port, ipbuf);
953 }
954 else
955 {
956 /* Only the second send() may catch the error
957 */
958 do {
959 retval = send (fd, buf, 0, 0);
960 } while (retval < 0 && errno == EINTR);
961
962 if (retval == -1 && errno == ECONNREFUSED)
963 {
964 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
965 if (portchk_debug)
966 fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
967 port, ipbuf);
968 }
969 else if (retval != -1)
970 {
971 /* Try to get service name from portmap
972 */
973 if (paddr->ss_family == AF_INET)
974 {
975 p = check_rpc_list (port,
976 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
977 IPPROTO_UDP);
978 }
979
980 sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
981
982 /* If not an RPC service, try to get name from /etc/services
983 */
984 if (!p)
985 p = check_services(port, IPPROTO_UDP);
986
987 if (portchk_debug)
988 {
989 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
990 fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"),
991 port, ipbuf, p);
992 }
993
994 }
995 else
996 {
997 if (portchk_debug)
998 {
999 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1000 fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"),
1001 port, ipbuf, errno);
1002 }
1003 }
1004 }
1005 }
1006 sl_close_fd (FIL__, __LINE__, fd);
1007 return 0;
1008}
1009
1010static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
1011{
1012 int retval;
1013 int flags;
1014 char * p = NULL;
1015#ifndef TEST_ONLY
1016 char errmsg[256];
1017 int nerr;
1018#endif
1019 char errbuf[SH_ERRBUF_SIZE];
1020 char ipbuf[SH_IP_BUF];
1021
1022 sh_ipvx_set_port(paddr, port);
1023
1024 do {
1025 retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
1026 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
1027
1028 if (retval == -1 && errno == ECONNREFUSED)
1029 {
1030 if (portchk_debug)
1031 {
1032 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1033 fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
1034 port, ipbuf);
1035 }
1036 }
1037 else if (retval == -1)
1038 {
1039#ifdef TEST_ONLY
1040 if (portchk_debug)
1041 perror(_("connect"));
1042#else
1043 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1044 nerr = errno;
1045 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
1046 port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
1047 SH_MUTEX_LOCK(mutex_thread_nolog);
1048 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1049 errmsg, _("connect"));
1050 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1051#endif
1052 }
1053 else
1054 {
1055 /* Try to get service name from portmap
1056 */
1057 if (paddr->ss_family == AF_INET)
1058 {
1059 p = check_rpc_list (port,
1060 (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
1061 IPPROTO_TCP);
1062 }
1063
1064 sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
1065
1066 /* If not an RPC service, try to get name from /etc/services
1067 */
1068 if (!p)
1069 p = check_services(port, IPPROTO_TCP);
1070
1071 if (portchk_debug)
1072 {
1073 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1074 fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"),
1075 port, ipbuf, p);
1076 }
1077
1078#if !defined(O_NONBLOCK)
1079#if defined(O_NDELAY)
1080#define O_NONBLOCK O_NDELAY
1081#else
1082#define O_NONBLOCK 0
1083#endif
1084#endif
1085
1086 /* prepare to close connection gracefully
1087 */
1088 if (port == 22) /* ssh */
1089 {
1090 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1091 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1092 retval = write (fd, _("SSH-2.0-Foobar"), 14);
1093 if (retval > 0) retval = write (fd, "\r\n", 2);
1094 }
1095 else if (port == 25) /* smtp */
1096 {
1097 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1098 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1099 retval = write (fd, _("QUIT"), 4);
1100 if (retval > 0) retval = write (fd, "\r\n", 2);
1101 }
1102 else if (port == 79) /* finger */
1103 {
1104 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1105 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1106 retval = write (fd, "\r\n", 2);
1107 }
1108 else if (port == 110) /* pop3 */
1109 {
1110 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1111 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1112 retval = write (fd, _("QUIT"), 4);
1113 if (retval > 0) retval = write (fd, "\r\n", 2);
1114 }
1115 else if (port == 143) /* imap */
1116 {
1117 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1118 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1119 retval = write (fd, _("A01 LOGOUT"), 10);
1120 if (retval > 0) retval = write (fd, "\r\n", 2);
1121 }
1122
1123 if (portchk_debug && retval < 0)
1124 fprintf(stderr, _("check port: error writing to port %5d\n"),
1125 port);
1126 }
1127 sl_close_fd (FIL__, __LINE__, fd);
1128 return 0;
1129}
1130
1131/* typedef uint32_t in_addr_t;
1132 * struct in_addr
1133 * {
1134 * in_addr_t s_addr;
1135 * };
1136 */
1137
1138#define SH_IFACE_MAX 64
1139#define SH_IFACE_ADDR 0
1140#define SH_IFACE_DEV 1
1141
1142struct portchk_interfaces {
1143 struct sh_sockaddr iface;
1144 int type;
1145};
1146
1147static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1148static int iface_list_used = 0;
1149static int iface_initialized = 0;
1150
1151#ifdef TEST_ONLY
1152static char * portchk_hostname = NULL;
1153#else
1154static char * portchk_hostname = sh.host.name;
1155#endif
1156
1157static int sh_portchk_init_internal (void)
1158{
1159 volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1160 char errbuf[256];
1161#if defined(USE_IPVX)
1162 struct addrinfo hints;
1163 struct addrinfo *res;
1164#else
1165 struct hostent * hent;
1166#endif
1167 char ipbuf[SH_IP_BUF];
1168
1169 if (portchk_debug)
1170 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
1171
1172 if (!portchk_hostname)
1173 return -1;
1174
1175 if (sh_portchk_active == S_FALSE)
1176 return -1;
1177
1178 SH_MUTEX_LOCK(mutex_port_check);
1179 if (iface_initialized == 0)
1180 {
1181 iface_list_used = 0;
1182 iface_initialized = 1;
1183 }
1184
1185#if !defined(USE_IPVX)
1186 SH_MUTEX_LOCK(mutex_resolv);
1187 hent = sh_gethostbyname(portchk_hostname);
1188 i = 0;
1189 while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
1190 {
1191 struct sockaddr_in sin;
1192 struct sh_sockaddr iface_tmp;
1193
1194 memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
1195 sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1196
1197 for (j = 0; j < iface_list_used; ++j)
1198 {
1199 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1200 {
1201 goto next_iface;
1202 }
1203 }
1204
1205 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1206 AF_INET, (struct sockaddr *)&sin);
1207 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1208
1209 if (portchk_debug)
1210 {
1211 char buf[256];
1212 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1213 fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
1214 }
1215 ++iface_list_used;
1216
1217 next_iface:
1218 ++i;
1219 }
1220 SH_MUTEX_UNLOCK(mutex_resolv);
1221#else
1222 memset(&hints, '\0', sizeof(hints));
1223 hints.ai_family = PF_UNSPEC;
1224 hints.ai_flags = AI_ADDRCONFIG;
1225
1226 if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1227 {
1228 struct addrinfo *p = res;
1229 struct sh_sockaddr iface_tmp;
1230
1231 while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
1232 {
1233 sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1234
1235 for (j = 0; j < iface_list_used; ++j)
1236 {
1237 if (portchk_debug)
1238 {
1239 char buf1[256], buf2[256];
1240 sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
1241 sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1242 fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
1243 }
1244 if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1245 {
1246 if (portchk_debug)
1247 fprintf(stderr, _("skipping interface[%d]\n"), j);
1248 goto next_iface;
1249 }
1250 }
1251 sh_ipvx_save(&(iface_list[iface_list_used].iface),
1252 p->ai_family, p->ai_addr);
1253 iface_list[iface_list_used].type = SH_IFACE_ADDR;
1254 if (portchk_debug)
1255 {
1256 char buf[256];
1257 sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1258 fprintf(stderr, _("added interface[%d]: %s\n"), iface_list_used, buf);
1259 }
1260
1261 ++iface_list_used;
1262
1263 next_iface:
1264 p = p->ai_next;
1265 }
1266 freeaddrinfo(res);
1267 }
1268#endif
1269
1270 for (i = 0; i < iface_list_used; ++i)
1271 {
1272 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
1273 sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
1274
1275 SH_MUTEX_LOCK(mutex_thread_nolog);
1276 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1277 errbuf, _("sh_portchk_init"));
1278 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1279 }
1280 SH_MUTEX_UNLOCK(mutex_port_check);
1281
1282 return 0;
1283}
1284
1285int sh_portchk_init (struct mod_type * arg)
1286{
1287#ifndef HAVE_PTHREAD
1288 (void) arg;
1289#endif
1290
1291 if (sh_portchk_active == S_FALSE)
1292 return SH_MOD_FAILED;
1293 if (!portchk_hostname)
1294 return SH_MOD_FAILED;
1295
1296#ifdef HAVE_PTHREAD
1297 if (arg != NULL && arg->initval < 0 &&
1298 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1299 {
1300 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1301 return SH_MOD_THREAD;
1302 else
1303 return SH_MOD_FAILED;
1304 }
1305 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1306 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1307 {
1308 (void) sh_portchk_init_internal();
1309 return SH_MOD_THREAD;
1310 }
1311#endif
1312 return sh_portchk_init_internal();
1313}
1314
1315static void dev_list_kill();
1316
1317#if !defined(TEST_ONLY)
1318int sh_portchk_reconf (void)
1319{
1320 SH_MUTEX_LOCK(mutex_port_check);
1321 iface_initialized = 0;
1322 sh_portchk_active = 1;
1323 sh_portchk_check_udp = 1;
1324 sh_portchk_interval = SH_PORTCHK_INTERVAL;
1325
1326 sh_portchk_minport = -1;
1327 sh_portchk_maxport = -1;
1328
1329 dev_list_kill();
1330
1331 portlist_udp = sh_portchk_kill_list (portlist_udp);
1332 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1333
1334 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1335 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
1336 sh_port2proc_finish();
1337
1338 SH_MUTEX_UNLOCK(mutex_port_check);
1339 return 0;
1340}
1341
1342int sh_portchk_cleanup (void)
1343{
1344 return sh_portchk_reconf ();
1345}
1346
1347int sh_portchk_timer (time_t tcurrent)
1348{
1349 static time_t lastcheck = 0;
1350
1351 SL_ENTER(_("sh_portchk_timer"));
1352 if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
1353 {
1354 lastcheck = tcurrent;
1355 SL_RETURN((-1), _("sh_portchk_timer"));
1356 }
1357 SL_RETURN(0, _("sh_portchk_timer"));
1358}
1359#endif
1360
1361static int check_port_generic (int port, int domain, int type, int protocol)
1362{
1363 volatile int i = 0;
1364 int sock = -1;
1365 int flag = 1; /* non-zero to enable an option */
1366 struct sh_sockaddr paddr;
1367 char errbuf[SH_ERRBUF_SIZE];
1368
1369 /* Check all interfaces for this host
1370 */
1371 while (i < iface_list_used)
1372 {
1373 memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
1374
1375 if (paddr.ss_family != domain)
1376 {
1377 ++i;
1378 continue;
1379 }
1380
1381 if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
1382 {
1383 ++i;
1384 continue;
1385 }
1386
1387 if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1388 {
1389 ++i;
1390#ifdef TEST_ONLY
1391 if (portchk_debug)
1392 perror(_("socket"));
1393#else
1394
1395#ifndef EPROTONOSUPPORT
1396#define EPROTONOSUPPORT 0
1397#endif
1398#ifndef EAFNOSUPPORT
1399#define EAFNOSUPPORT 0
1400#endif
1401 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1402 {
1403 SH_MUTEX_LOCK(mutex_thread_nolog);
1404 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1405 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1406 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1407 }
1408#endif
1409 continue;
1410 }
1411 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1412 (void *) &flag, sizeof(flag)) < 0 )
1413 {
1414 ++i;
1415#ifdef TEST_ONLY
1416 if (portchk_debug)
1417 perror(_("setsockopt"));
1418#else
1419 SH_MUTEX_LOCK(mutex_thread_nolog);
1420 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1421 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1422 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1423#endif
1424 continue;
1425 }
1426
1427
1428 if (protocol == IPPROTO_TCP)
1429 check_port_tcp_internal(sock, port, &paddr);
1430 else
1431 check_port_udp_internal(sock, port, &paddr);
1432
1433 ++i;
1434 }
1435
1436 return 0;
1437}
1438
1439
1440
1441static int check_port_udp (int port, int domain)
1442{
1443 return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
1444}
1445
1446static int check_port_tcp (int port, int domain)
1447{
1448 return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
1449}
1450
1451
1452static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
1453 int domain, int type, int protocol)
1454{
1455 /*
1456 int min_port = 1024;
1457 int max_port = 65535;
1458 */
1459
1460 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1461 volatile int max_port = max_port_arg;
1462 int retval;
1463 int sock = -1;
1464#if 0
1465 int flag = 1; /* non-zero to enable an option */
1466#endif
1467 struct sockaddr_in addr4;
1468 struct sockaddr_in6 addr6;
1469
1470 int addrlen4 = sizeof(addr4);
1471 int addrlen6 = sizeof(addr6);
1472
1473 struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
1474
1475 char errbuf[SH_ERRBUF_SIZE];
1476
1477 if (min_port == -1)
1478 min_port = 0;
1479 if (max_port == -1)
1480 max_port = 65535;
1481
1482 if (portchk_debug)
1483 fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"),
1484 min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"),
1485 (protocol == IPPROTO_TCP) ? _("tcp") : _("udp"));
1486
1487 for (port = min_port; port <= max_port; ++port)
1488 {
1489 if ((sock = socket(domain, type, protocol)) < 0 )
1490 {
1491#ifdef TEST_ONLY
1492 if (portchk_debug)
1493 perror(_("socket"));
1494#else
1495#ifndef EPROTONOSUPPORT
1496#define EPROTONOSUPPORT 0
1497#endif
1498#ifndef EAFNOSUPPORT
1499#define EAFNOSUPPORT 0
1500#endif
1501 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1502 {
1503 SH_MUTEX_LOCK(mutex_thread_nolog);
1504 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1505 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1506 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1507 }
1508#endif
1509 continue;
1510 }
1511
1512#if 0
1513 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1514 (void *) &flag, sizeof(flag)) < 0 )
1515 {
1516#ifdef TEST_ONLY
1517 if (portchk_debug)
1518 perror(_("setsockopt"));
1519#else
1520 SH_MUTEX_LOCK(mutex_thread_nolog);
1521 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1522 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1523 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1524#endif
1525 continue;
1526 }
1527#endif
1528
1529 if (domain == AF_INET)
1530 {
1531 addr4.sin_family = AF_INET;
1532 addr4.sin_port = htons(port);
1533 addr4.sin_addr.s_addr = INADDR_ANY;
1534 retval = bind (sock, (struct sockaddr *) &addr4, addrlen4);
1535 }
1536 else
1537 {
1538 addr6.sin6_family = AF_INET6;
1539 addr6.sin6_port = htons(port);
1540 memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr));
1541 retval = bind (sock, (struct sockaddr *) &addr6, addrlen6);
1542 }
1543
1544 if (retval == 0)
1545 {
1546 /* we can bind the port, thus it is unused
1547 */
1548 sl_close_fd (FIL__, __LINE__, sock);
1549 }
1550 else
1551 {
1552 if (errno == EINVAL || errno == EADDRINUSE)
1553 {
1554 /* try to connect to the port
1555 */
1556 if (protocol == IPPROTO_TCP)
1557 check_port_tcp(port, domain);
1558 else
1559 check_port_udp(port, domain);
1560 }
1561 else
1562 {
1563#ifdef TEST_ONLY
1564 if (portchk_debug)
1565 perror(_("bind"));
1566#else
1567 SH_MUTEX_LOCK(mutex_thread_nolog);
1568 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1569 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1570 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1571#endif
1572 }
1573 sl_close_fd (FIL__, __LINE__, sock);
1574 }
1575 }
1576 return 0;
1577}
1578
1579static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1580{
1581#if defined(USE_IPVX)
1582 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1583 SOCK_STREAM, IPPROTO_TCP);
1584#endif
1585 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1586 SOCK_STREAM, IPPROTO_TCP);
1587}
1588
1589static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1590{
1591#if defined(USE_IPVX)
1592 sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6,
1593 SOCK_DGRAM, IPPROTO_UDP);
1594#endif
1595 return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1596 SOCK_DGRAM, IPPROTO_UDP);
1597}
1598
1599/* Subroutine to add an interface
1600 */
1601void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
1602
1603static int sh_portchk_add_interface_int (const char * str, int type)
1604{
1605 struct sh_sockaddr saddr;
1606 char errbuf[256];
1607 char buf[64];
1608
1609 sh_dummy_1564_str = (void*) &str;
1610
1611 if (iface_initialized == 0)
1612 {
1613 iface_list_used = 0;
1614 iface_initialized = 1;
1615 }
1616
1617 do {
1618
1619 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1620
1621 if (*str)
1622 {
1623 char ipbuf[SH_IP_BUF];
1624 unsigned int i = 0;
1625 while (*str && i < (sizeof(buf)-1) &&
1626 *str != ',' && *str != ' ' && *str != '\t')
1627 {
1628 buf[i] = *str; ++str; ++i;
1629 }
1630 buf[i] = '\0';
1631
1632 if (0 == sh_ipvx_aton(buf, &saddr))
1633 return -1;
1634
1635 if (iface_list_used == SH_IFACE_MAX)
1636 return -1;
1637
1638 sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1639 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
1640 SH_MUTEX_LOCK(mutex_thread_nolog);
1641 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1642 errbuf, _("sh_portchk_add_interface"));
1643 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1644
1645 memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1646 iface_list[iface_list_used].type = type;
1647 ++iface_list_used;
1648 }
1649 } while (*str);
1650
1651 sh_dummy_1564_str = NULL;
1652 return 0;
1653}
1654
1655static int sh_portchk_add_interface (const char * str)
1656{
1657 return sh_portchk_add_interface_int (str, SH_IFACE_ADDR);
1658}
1659
1660#if defined(HAVE_IFADDRS_H)
1661/*
1662 * subroutines to add a device
1663 */
1664void * sh_dummy_1651_ifa = NULL; /* fix clobbered by.. warning */
1665
1666static int portchk_add_device_int (const char * buf)
1667{
1668 struct ifaddrs *ifaddr, *ifa;
1669 int family;
1670#ifndef NI_MAXHOST
1671#define NI_MAXHOST 1025
1672#endif
1673 char host[NI_MAXHOST];
1674
1675 sh_dummy_1651_ifa = (void*) &ifa;
1676
1677 if (getifaddrs(&ifaddr) == -1)
1678 {
1679 volatile int nerr = errno;
1680 char errbuf[SH_ERRBUF_SIZE];
1681 sh_error_message(errno, errbuf, sizeof(errbuf));
1682 SH_MUTEX_LOCK(mutex_thread_nolog);
1683 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
1684 errbuf, _("getifaddrs"));
1685 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1686 return -1;
1687 }
1688
1689 for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1690 {
1691 if (ifa->ifa_addr == NULL)
1692 continue;
1693
1694 if (strcmp(ifa->ifa_name, buf) == 0)
1695 {
1696 volatile int s = 0;
1697 family = ifa->ifa_addr->sa_family;
1698
1699 if (family == AF_INET)
1700 {
1701 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in),
1702 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1703
1704 if (s == 0)
1705 {
1706 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1707 {
1708 freeifaddrs(ifaddr);
1709 return -1;
1710 }
1711 }
1712 }
1713
1714#if defined(USE_IPVX)
1715 if (family == AF_INET6)
1716 {
1717 s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in6),
1718 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1719
1720 if (s == 0)
1721 {
1722 if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1723 {
1724 freeifaddrs(ifaddr);
1725 return -1;
1726 }
1727 }
1728 }
1729#endif
1730
1731 if (s != 0)
1732 {
1733 char errbuf[SH_ERRBUF_SIZE];
1734 sl_strlcpy(errbuf, buf, sizeof(errbuf));
1735 sl_strlcat(errbuf, ": ", sizeof(errbuf));
1736 sl_strlcat(errbuf, gai_strerror(s), sizeof(errbuf));
1737 SH_MUTEX_LOCK(mutex_thread_nolog);
1738 sh_error_handle((-1), FIL__, __LINE__, s, MSG_E_SUBGEN,
1739 errbuf, _("getnameinfo"));
1740 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1741 }
1742
1743 }
1744 }
1745
1746 freeifaddrs(ifaddr);
1747 return 0;
1748}
1749
1750struct added_dev {
1751 char dev[64];
1752 struct added_dev * next;
1753};
1754
1755static struct added_dev * dev_list = NULL;
1756
1757static void dev_list_add (char * buf)
1758{
1759 struct added_dev * new = SH_ALLOC(sizeof(struct added_dev));
1760 sl_strlcpy(new->dev, buf, 64);
1761 new->next = dev_list;
1762 dev_list = new;
1763 return;
1764}
1765
1766static void dev_list_kill ()
1767{
1768 struct added_dev * old;
1769 struct added_dev * new = dev_list;
1770 dev_list = NULL;
1771
1772 while (new)
1773 {
1774 old = new;
1775 new = new->next;
1776 SH_FREE(old);
1777 }
1778 return;
1779}
1780
1781static int sh_portchk_add_device (const char * str)
1782{
1783 char buf[64];
1784
1785 do {
1786
1787 while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1788
1789 if (*str)
1790 {
1791 unsigned int i = 0;
1792 while (*str && i < (sizeof(buf)-1) &&
1793 *str != ',' && *str != ' ' && *str != '\t') {
1794 buf[i] = *str; ++str; ++i;
1795 }
1796 buf[i] = '\0';
1797
1798 if (portchk_add_device_int (buf) < 0)
1799 return -1;
1800
1801 dev_list_add(buf);
1802 }
1803 } while (*str);
1804
1805 return 0;
1806}
1807
1808static int iface_comp (const void *a, const void *b)
1809{
1810 const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
1811 const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
1812 return (aa->type - bb->type);
1813}
1814
1815static void iface_qsort()
1816{
1817 qsort(&iface_list[0], iface_list_used, sizeof(struct portchk_interfaces),
1818 iface_comp);
1819 return;
1820}
1821
1822static void recheck_devices()
1823{
1824 if (dev_list)
1825 {
1826 struct added_dev * dev = dev_list;
1827 int i, j;
1828
1829 if (portchk_debug)
1830 {
1831 for (j = 0; j < iface_list_used; ++j)
1832 {
1833 char buf[SH_IP_BUF];
1834 struct portchk_interfaces * aa = &(iface_list[j]);
1835 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
1836 fprintf(stderr, _("presort: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
1837 }
1838 }
1839
1840 iface_qsort();
1841
1842 if (portchk_debug)
1843 {
1844 for (j = 0; j < iface_list_used; ++j)
1845 {
1846 char buf[SH_IP_BUF];
1847 struct portchk_interfaces * aa = &(iface_list[j]);
1848 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
1849 fprintf(stderr, _("postsor: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
1850 }
1851 }
1852
1853 i = 0;
1854 for (j = 0; j < iface_list_used; ++j)
1855 if (iface_list[j].type == SH_IFACE_DEV) ++i;
1856 iface_list_used -= i;
1857
1858 if (portchk_debug)
1859 {
1860 for (j = 0; j < iface_list_used; ++j)
1861 {
1862 char buf[SH_IP_BUF];
1863 struct portchk_interfaces * aa = &(iface_list[j]);
1864 sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
1865 fprintf(stderr, _("postdel: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
1866 }
1867 }
1868
1869 while (dev)
1870 {
1871 portchk_add_device_int (dev->dev);
1872 dev = dev->next;
1873 }
1874 }
1875 return;
1876}
1877#endif
1878
1879/* verify whether port/interface is blacklisted (do not check)
1880 */
1881static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
1882 int proto)
1883{
1884 struct sh_port * head;
1885
1886 if (proto == IPPROTO_TCP)
1887 head = blacklist_tcp;
1888 else
1889 head = blacklist_udp;
1890
1891 while (head)
1892 {
1893 if (head->port == port)
1894 {
1895 if (sh_ipvx_isany(head->paddr) ||
1896 0 == sh_ipvx_cmp(head->paddr, saddr))
1897 return 1;
1898 else
1899 return 0;
1900 }
1901 head = head->next;
1902 }
1903 return 0;
1904}
1905
1906
1907static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
1908{
1909 struct sh_port * black;
1910 struct sh_port * head;
1911
1912 if (proto == IPPROTO_TCP)
1913 head = blacklist_tcp;
1914 else
1915 head = blacklist_udp;
1916
1917 black = head;
1918
1919 while (black)
1920 {
1921 if (black->port == port &&
1922 0 == sh_ipvx_cmp(head->paddr, saddr))
1923 return -1;
1924 black = black->next;
1925 }
1926
1927 black = SH_ALLOC (sizeof(struct sh_port));
1928 black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
1929 black->port = port;
1930 memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
1931 black->next = head;
1932
1933 if (proto == IPPROTO_TCP)
1934 blacklist_tcp = black;
1935 else
1936 blacklist_udp = black;
1937
1938 if (portchk_debug)
1939 {
1940 int checkit = sh_portchk_is_blacklisted(port, saddr, proto);
1941 fprintf(stderr, _("port blacklisted: %d %s\n"), port,
1942 (checkit == 1) ? _("ok") : _("fail"));
1943 }
1944 return 0;
1945}
1946
1947
1948/* Subroutine to add a required or optional port/service
1949 */
1950static int sh_portchk_add_required_port_generic (char * service,
1951 char * interface, int type)
1952{
1953 char buf[256] = { '\0' };
1954 int proto;
1955 char * p;
1956 char * endptr;
1957 unsigned long int port;
1958 struct sh_sockaddr saddr;
1959 struct sh_portentry * portent;
1960
1961 if (0 == sh_ipvx_aton(interface, &saddr))
1962 return -1;
1963
1964 sl_strlcpy (buf, service, sizeof(buf));
1965
1966 p = strchr(buf, '/');
1967 if (!p)
1968 return -1;
1969 if (0 == strcmp(p, _("/tcp")))
1970 proto = IPPROTO_TCP;
1971 else if (0 == strcmp(p, _("/udp")))
1972 proto = IPPROTO_UDP;
1973 else
1974 return -1;
1975
1976 *p = '\0';
1977 port = strtoul(buf, &endptr, 0);
1978
1979 if (portchk_debug)
1980 {
1981 char buf[SH_IP_BUF];
1982 sh_ipvx_ntoa(buf, sizeof(buf), &saddr);
1983 fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"),
1984 interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"),
1985 sh_port_type2str(type));
1986 }
1987
1988 /* Blacklisted ports
1989 */
1990 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
1991 return (sh_portchk_blacklist(port, &saddr, proto));
1992
1993 if (*endptr != '\0')
1994 {
1995 portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
1996 if (!portent)
1997 {
1998 if (portchk_debug)
1999 fprintf(stderr, _("add_required_port %d\n"), (int) port);
2000 sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN);
2001 }
2002 else
2003 {
2004#ifdef TEST_ONLY
2005 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
2006#else
2007 SH_MUTEX_LOCK(mutex_thread_nolog);
2008 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2009 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2010 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2011#endif
2012 return -1;
2013 }
2014 }
2015 else if (port <= 65535)
2016 {
2017 portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
2018 if (!portent)
2019 {
2020 if (portchk_debug)
2021 fprintf(stderr, _("add_required_port: open port: %d/%s\n"),
2022 (int) port, SH_PROTO_STR(proto));
2023 sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN);
2024 }
2025 else
2026 {
2027#ifdef TEST_ONLY
2028 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
2029#else
2030 SH_MUTEX_LOCK(mutex_thread_nolog);
2031 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2032 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2033 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2034#endif
2035 return -1;
2036 }
2037 }
2038 else
2039 return -1;
2040
2041 return 0;
2042}
2043
2044/* Internal interface to add required or optional ports as 'iface:portlist'
2045 */
2046static int sh_portchk_add_required_generic (const char * str, int type)
2047{
2048 size_t ll = 0;
2049 int status;
2050
2051 char * interface = NULL;
2052 char * list;
2053 char * p;
2054#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2055 char * saveptr;
2056#endif
2057
2058 if (!str)
2059 return -1;
2060
2061 if (strchr(str, ':'))
2062 {
2063 char *last = strrchr(str, ':');
2064 if (last != NULL)
2065 {
2066 size_t tolast = (last - str);
2067 interface = SH_ALLOC(tolast+1);
2068 sl_strlcpy(interface, str, tolast+1);
2069 interface[tolast] = '\0';
2070
2071 ll = tolast;
2072
2073 while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
2074 ++ll;
2075 }
2076 }
2077 else
2078 {
2079 interface = SH_ALLOC(8);
2080 sl_strlcpy(interface, _("0.0.0.0"), 8);
2081 interface[7] = '\0';
2082 while (str[ll] == ' ' || str[ll] == '\t')
2083 ++ll;
2084 }
2085
2086 if (!interface)
2087 return -1;
2088
2089 if (str[ll] == '\0')
2090 {
2091 SH_FREE(interface);
2092 return -1;
2093 }
2094
2095 if (portchk_debug)
2096 fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
2097
2098 list = sh_util_strdup(&str[ll]);
2099#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2100 p = strtok_r (list, " ,\t", &saveptr);
2101#else
2102 p = strtok (list, " ,\t");
2103#endif
2104 if (!p)
2105 {
2106 SH_FREE(interface);
2107 SH_FREE(list);
2108 return -1;
2109 }
2110 while (p)
2111 {
2112 status = sh_portchk_add_required_port_generic (p, interface, type);
2113
2114 if (-1 == status)
2115 {
2116 SH_FREE(interface);
2117 SH_FREE(list);
2118 return -1;
2119 }
2120#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2121 p = strtok_r (NULL, " ,\t", &saveptr);
2122#else
2123 p = strtok (NULL, " ,\t");
2124#endif
2125 }
2126 SH_FREE(interface);
2127 SH_FREE(list);
2128 return 0;
2129}
2130
2131/* User interface to add required ports as 'iface:portlist'
2132 */
2133static int sh_portchk_add_required (const char * str)
2134{
2135 return sh_portchk_add_required_generic (str, SH_PORT_REQ);
2136}
2137
2138/* User interface to add optional ports as 'iface:portlist'
2139 */
2140static int sh_portchk_add_optional (const char * str)
2141{
2142 return sh_portchk_add_required_generic (str, SH_PORT_OPT);
2143}
2144
2145/* User interface to add ignoreable ports as 'iface:portlist'
2146 */
2147static int sh_portchk_add_ignore (const char * str)
2148{
2149 return sh_portchk_add_required_generic (str, SH_PORT_IGN);
2150}
2151
2152/* User interface to add ports that should not be checked as 'iface:portlist'
2153 */
2154static int sh_portchk_add_blacklist (const char * str)
2155{
2156 return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST);
2157}
2158
2159/* Interface to run port check
2160 */
2161int sh_portchk_check ()
2162{
2163 volatile int min_port;
2164 static int noprivports = 0;
2165
2166 SH_MUTEX_LOCK(mutex_port_check);
2167
2168 min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
2169
2170 if (sh_portchk_active != S_FALSE)
2171 {
2172 SH_MUTEX_LOCK(mutex_thread_nolog);
2173 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2174 _("Checking for open ports"),
2175 _("sh_portchk_check"));
2176 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2177
2178 sh_portchk_reset_lists();
2179
2180#if defined(HAVE_IFADDRS_H)
2181 recheck_devices();
2182#endif
2183
2184 if ((0 != geteuid()) && (min_port < 1024))
2185 {
2186 min_port = 1024;
2187 if (noprivports == 0)
2188 {
2189#ifdef TEST_ONLY
2190 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
2191#else
2192 SH_MUTEX_LOCK(mutex_thread_nolog);
2193 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2194 _("not scanning ports below 1024"),
2195 _("sh_portchk_check"));
2196 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2197#endif
2198 noprivports = 1;
2199 }
2200 }
2201
2202 sh_port2proc_prepare();
2203
2204 if (sh_portchk_check_udp == 1)
2205 sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2206 sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
2207
2208
2209 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
2210 if (sh_portchk_check_udp == 1)
2211 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
2212
2213 }
2214 SH_MUTEX_UNLOCK(mutex_port_check);
2215 return 0;
2216}
2217#endif
2218
2219#ifdef SH_CUTEST
2220#include "CuTest.h"
2221
2222void Test_portcheck_lists (CuTest *tc)
2223{
2224#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
2225 struct sh_sockaddr haddr_local;
2226 struct sh_portentry * portent;
2227 char buf[256];
2228 char * p;
2229
2230#ifdef HAVE_RPC_RPC_H
2231 p = sh_getrpcbynumber(0, buf, sizeof(buf));
2232 CuAssertTrue(tc, p == NULL);
2233
2234 p = sh_getrpcbynumber(100000, buf, sizeof(buf));
2235 CuAssertPtrNotNull(tc, p);
2236 CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
2237 CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
2238
2239 p = sh_getrpcbynumber(100007, buf, sizeof(buf));
2240 CuAssertPtrNotNull(tc, p);
2241 CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
2242 CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
2243#endif
2244
2245 p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2246 CuAssertTrue(tc, p == NULL);
2247
2248#if !defined(HOST_IS_CYGWIN)
2249 p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
2250 CuAssertPtrNotNull(tc, p);
2251 CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
2252 CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
2253#endif
2254
2255 p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2256 CuAssertPtrNotNull(tc, p);
2257 CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
2258 CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
2259
2260 CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
2261
2262 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2263
2264 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2265 CuAssertPtrNotNull(tc, portent);
2266
2267 CuAssertTrue(tc, portent->port == 8000);
2268 CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
2269 CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
2270 CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
2271
2272 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2273
2274 CuAssertTrue(tc, NULL == portlist_tcp);
2275
2276 sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2277 sh_portchk_add_to_list (IPPROTO_TCP, 8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2278 sh_portchk_add_to_list (IPPROTO_TCP, 8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2279 sh_portchk_add_to_list (IPPROTO_TCP, 8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2280 sh_portchk_add_to_list (IPPROTO_TCP, 8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
2281 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
2282 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
2283 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
2284 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
2285 sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
2286
2287 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2288
2289 CuAssertPtrNotNull(tc, portlist_tcp);
2290
2291 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL);
2292 CuAssertPtrNotNull(tc, portent);
2293
2294 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL);
2295 CuAssertTrue(tc, NULL == portent);
2296
2297 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL);
2298 CuAssertPtrNotNull(tc, portent);
2299
2300 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL);
2301 CuAssertTrue(tc, NULL == portent);
2302
2303 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL);
2304 CuAssertPtrNotNull(tc, portent);
2305
2306 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1");
2307 CuAssertTrue(tc, NULL == portent);
2308
2309 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2");
2310 CuAssertPtrNotNull(tc, portent);
2311 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2312
2313 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3");
2314 CuAssertTrue(tc, NULL == portent);
2315
2316 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4");
2317 CuAssertPtrNotNull(tc, portent);
2318 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
2319
2320 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5");
2321 CuAssertPtrNotNull(tc, portent);
2322 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
2323
2324 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2325 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2326 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP));
2327 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP));
2328 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2329 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2330 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP));
2331 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP));
2332
2333 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP));
2334 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP));
2335 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP));
2336 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP));
2337
2338 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP));
2339 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP));
2340 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP));
2341 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP));
2342#else
2343 (void) tc; /* fix compiler warning */
2344#endif
2345 return;
2346}
2347#endif
2348
2349#ifdef TEST_ONLY
2350
2351void usage (char * pname)
2352{
2353 printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
2354 printf (" Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
2355 printf (" Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
2356 printf (" Portlist: List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
2357 printf (" required -> must be open\n");
2358 printf (" optional -> may be open or closed\n");
2359 printf (" RPC services must be specified with service **name**, others with **port number**\n\n");
2360 printf (" Example:\n");
2361 printf (" %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
2362 return;
2363}
2364
2365int main(int argc, char *argv[])
2366{
2367 char * pname = argv[0];
2368
2369
2370 /*
2371 test_lists();
2372
2373 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
2374 portlist_udp = sh_portchk_kill_list (portlist_udp);
2375 */
2376
2377 /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
2378
2379 while (argc > 1 && argv[1][0] == '-')
2380 {
2381 if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
2382 {
2383 usage(pname);
2384 exit (0);
2385 }
2386 else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
2387 {
2388 if (argc < 3)
2389 {
2390 usage(pname);
2391 exit (1);
2392 }
2393 sh_portchk_add_required (argv[2]);
2394 --argc; ++argv;
2395 }
2396 else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
2397 {
2398 if (argc < 3)
2399 {
2400 usage(pname);
2401 exit (1);
2402 }
2403 sh_portchk_add_optional (argv[2]);
2404 --argc; ++argv;
2405 }
2406 else if (0 == strcmp(argv[1], "--no-udp"))
2407 {
2408 sh_portchk_check_udp = 0;
2409 }
2410 else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
2411 {
2412 portchk_debug = 1;
2413 }
2414 else
2415 {
2416 usage(pname);
2417 exit (1);
2418 }
2419 --argc; ++argv;
2420 }
2421
2422 if (argc < 2)
2423 {
2424 usage(pname);
2425 exit (1);
2426 }
2427
2428 portchk_hostname = argv[1];
2429
2430 if (0 != sh_portchk_init ())
2431 {
2432 usage(pname);
2433 exit (1);
2434 }
2435
2436 sh_portchk_check();
2437
2438 return 0;
2439}
2440#endif
Note: See TracBrowser for help on using the repository browser.