source: trunk/src/sh_portcheck.c@ 172

Last change on this file since 172 was 171, checked in by katerina, 16 years ago

Include dnmalloc (ticket #108) and fix bugs #106 (EINPROGRESS) and #107 (compressBound).

  • Property svn:executable set to *
File size: 42.7 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 <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <errno.h>
40#include <unistd.h>
41#include <fcntl.h>
42
43#define PORTCHK_VERSION "1.0"
44
45#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
46
47
48#define PORTMAP
49#include <rpc/rpc.h>
50#ifdef HAVE_RPC_RPCENT_H
51#include <rpc/rpcent.h>
52#endif
53#include <rpc/pmap_clnt.h>
54#include <rpc/pmap_prot.h>
55#include <netdb.h>
56
57/*
58 * struct pmaplist {
59 * struct pmap pml_map;
60 * struct pmaplist *pml_next;
61 * };
62 */
63
64/* struct pmap {
65 * long unsigned pm_prog;
66 * long unsigned pm_vers;
67 * long unsigned pm_prot;
68 * long unsigned pm_port;
69 * };
70 */
71
72/* TIME_WAIT ? 60-240 seconds */
73
74/* the size of an interface string
75 */
76#define SH_INTERFACE_SIZE 16
77
78#define SH_PORT_NOT 0
79#define SH_PORT_REQ 1
80#define SH_PORT_OPT 2
81#define SH_PORT_IGN 3
82#define SH_PORT_BLACKLIST 4
83
84#define SH_PORT_MISS 0
85#define SH_PORT_ISOK 1
86#define SH_PORT_UNKN 2
87
88#define SH_PORT_NOREPT 0
89#define SH_PORT_REPORT 1
90
91#define SH_PROTO_TCP 0
92#define SH_PROTO_UDP 1
93#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
94
95struct sh_portentry {
96 int port;
97 char interface[SH_INTERFACE_SIZE];
98 char * service;
99 char * error;
100 int flag; /* required or not */
101 int status; /* missing or not */
102 struct sh_portentry * next;
103};
104
105static struct sh_portentry * portlist_tcp = NULL;
106static struct sh_portentry * portlist_udp = NULL;
107
108struct sh_port {
109 int port;
110 struct in_addr haddr;
111 struct sh_port * next;
112};
113
114static struct sh_port * blacklist_tcp = NULL;
115static struct sh_port * blacklist_udp = NULL;
116
117#define SH_PORTCHK_INTERVAL 300
118
119static int sh_portchk_check_udp = 1;
120static int sh_portchk_active = 1;
121static int sh_portchk_interval = SH_PORTCHK_INTERVAL;
122#if !defined(TEST_ONLY)
123
124#define FIL__ _("sh_portcheck.c")
125#include "samhain.h"
126#include "sh_error.h"
127#include "sh_mem.h"
128#include "sh_calls.h"
129#include "sh_utils.h"
130#include "sh_modules.h"
131#include "sh_static.h"
132#include "sh_pthread.h"
133
134SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
135
136static int sh_portchk_severity = SH_ERR_SEVERE;
137#endif
138
139/* Exported interface to add ignoreable ports as 'iface:portlist'
140 */
141static int sh_portchk_add_ignore (const char * str);
142
143/* Exported interface to add required ports as 'iface:portlist'
144 */
145static int sh_portchk_add_required (const char * str);
146
147/* Exported interface to add optional ports as 'iface:portlist'
148 */
149static int sh_portchk_add_optional (const char * str);
150
151/* Exported interface to add blacklisted ports as 'iface:portlist'
152 */
153static int sh_portchk_add_blacklist (const char * str);
154
155/* Exported interface to add an ethernet interface
156 */
157static int sh_portchk_add_interface (const char * str);
158
159/* verify whether port/interface is blacklisted (do not check)
160 */
161static int sh_portchk_is_blacklisted(int port, struct in_addr haddr, int proto);
162
163#ifndef TEST_ONLY
164
165static int sh_portchk_set_interval (const char * c)
166{
167 int retval = 0;
168 long val;
169
170 SL_ENTER(_("sh_portchk_set_interval"));
171 val = strtol (c, (char **)NULL, 10);
172 if (val <= 0)
173 {
174 SH_MUTEX_LOCK(mutex_thread_nolog);
175 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
176 _("port check interval"), c);
177 SH_MUTEX_UNLOCK(mutex_thread_nolog);
178 retval = -1;
179 }
180
181 sh_portchk_interval = (time_t) val;
182 SL_RETURN(0, _("sh_portchk_set_interval"));
183}
184
185
186static int sh_portchk_set_active (const char * str)
187{
188 return sh_util_flagval(str, &sh_portchk_active);
189}
190
191static int sh_portchk_set_udp (const char * str)
192{
193 return sh_util_flagval(str, &sh_portchk_check_udp);
194}
195
196static int sh_portchk_set_severity (const char * str)
197{
198 char tmp[32];
199 tmp[0] = '='; tmp[1] = '\0';
200 sl_strlcat (tmp, str, 32);
201 return sh_error_set_level (tmp, &sh_portchk_severity);
202}
203
204sh_rconf sh_portchk_table[] = {
205 {
206 N_("severityportcheck"),
207 sh_portchk_set_severity,
208 },
209 {
210 N_("portcheckrequired"),
211 sh_portchk_add_required,
212 },
213 {
214 N_("portcheckoptional"),
215 sh_portchk_add_optional,
216 },
217 {
218 N_("portcheckignore"),
219 sh_portchk_add_ignore,
220 },
221 {
222 N_("portcheckskip"),
223 sh_portchk_add_blacklist,
224 },
225 {
226 N_("portcheckactive"),
227 sh_portchk_set_active,
228 },
229 {
230 N_("portcheckinterface"),
231 sh_portchk_add_interface,
232 },
233 {
234 N_("portcheckinterval"),
235 sh_portchk_set_interval,
236 },
237 {
238 N_("portcheckudp"),
239 sh_portchk_set_udp,
240 },
241 {
242 NULL,
243 NULL
244 }
245};
246
247#endif
248
249/* Interface to initialize port check
250 */
251int sh_portchk_init (struct mod_type * arg);
252
253/* Interface to reset port check
254 */
255int sh_portchk_reset (void);
256
257/* Interface to run port check
258 */
259int sh_portchk_check (void);
260
261
262static char * check_services (int port, int proto);
263
264#ifdef TEST_ONLY
265
266static int portchk_debug = 0;
267#define SH_ALLOC malloc
268#define SH_FREE free
269#define sh_util_strdup strdup
270#define sl_strlcpy strncpy
271#define _(a) a
272
273#else
274
275static int portchk_debug = 0;
276
277#endif
278
279static void sh_portchk_add_to_list (int proto,
280 int port, struct in_addr haddr, char * service,
281 int flag, int status)
282{
283 struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
284
285 if (portchk_debug)
286 fprintf(stderr, _("add to list: port %d/%s %d %d (%s)\n"),
287 port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"));
288
289 new->port = port;
290 sl_strlcpy (new->interface, inet_ntoa(haddr), SH_INTERFACE_SIZE);
291 new->status = status;
292 new->flag = flag;
293
294 new->error = NULL;
295
296 if (service)
297 new->service = sh_util_strdup (service);
298 else
299 new->service = NULL;
300 if (proto == IPPROTO_TCP)
301 {
302 new->next = portlist_tcp;
303 portlist_tcp = new;
304 }
305 else
306 {
307 new->next = portlist_udp;
308 portlist_udp = new;
309 }
310 return;
311}
312
313/* Reset the list by setting all entries to UNKN.
314 * In the next cycle we will check, and set found ports to ISOK.
315 * Thereafter, we check for entries that are still UNKN.
316 */
317static void sh_portchk_reset_lists (void)
318{
319 struct sh_portentry * portlist;
320
321 portlist = portlist_tcp;
322 while (portlist)
323 {
324 if (portlist->status != SH_PORT_MISS)
325 portlist->status = SH_PORT_UNKN;
326 portlist = portlist->next;
327 }
328 portlist = portlist_udp;
329 while (portlist)
330 {
331 if (portlist->status != SH_PORT_MISS)
332 portlist->status = SH_PORT_UNKN;
333 portlist = portlist->next;
334 }
335 return;
336}
337
338static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
339{
340 if (head)
341 {
342 if (head->next)
343 sh_portchk_kill_list (head->next);
344
345 if (head->service)
346 SH_FREE(head->service);
347 SH_FREE(head);
348 }
349 return NULL;
350}
351
352static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
353{
354 if (head)
355 {
356 if (head->next)
357 sh_portchk_kill_blacklist (head->next);
358
359 SH_FREE(head);
360 }
361 return NULL;
362}
363
364/* These variables are not used anywhere. They only exist
365 * to assign &pre, &ptr to them, which keeps gcc from
366 * putting it into a register, and avoids the 'clobbered
367 * by longjmp' warning. And no, 'volatile' proved insufficient.
368 */
369static void * sh_dummy_pre = NULL;
370static void * sh_dummy_ptr = NULL;
371
372/* check the list of open ports for any that are marked as UNKN
373 */
374static void sh_portchk_check_list (struct sh_portentry ** head, int proto, int report)
375{
376 struct sh_portentry * ptr = *head;
377 struct sh_portentry * pre = *head;
378 char errbuf[256];
379
380 /* Take the address to keep gcc from putting them into registers.
381 * Avoids the 'clobbered by longjmp' warning.
382 */
383 sh_dummy_pre = (void*) &pre;
384 sh_dummy_ptr = (void*) &ptr;
385
386 while (ptr)
387 {
388 if (portchk_debug && report)
389 fprintf(stderr, _("check list: port %d/%s %d %d\n"),
390 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
391
392 if (ptr->status == SH_PORT_UNKN)
393 {
394 /* Don't report missing ports that are marked as optional
395 */
396 if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
397 {
398 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
399 ptr->interface, ptr->port, SH_PROTO_STR(proto),
400 ptr->service ? ptr->service : check_services(ptr->port, proto));
401#ifdef TEST_ONLY
402 if (report == SH_PORT_REPORT)
403 fprintf(stderr, _("%s\n"), errbuf);
404#else
405 if (report == SH_PORT_REPORT)
406 {
407 SH_MUTEX_LOCK(mutex_thread_nolog);
408 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
409 MSG_PORT_MISS, errbuf);
410 SH_MUTEX_UNLOCK(mutex_thread_nolog);
411 }
412#endif
413 }
414
415 ptr->status = SH_PORT_MISS;
416
417 if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
418 {
419 if (portchk_debug && report)
420 fprintf(stderr, _("removing: port %d/%s %d %d\n"),
421 ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
422
423 if (ptr == *head)
424 {
425 *head = ptr->next;
426 if (ptr->service)
427 SH_FREE(ptr->service);
428 SH_FREE(ptr);
429 ptr = *head;
430 pre = *head;
431 continue;
432 }
433 else if (ptr->next == NULL)
434 {
435 pre->next = NULL;
436 if (ptr->service)
437 SH_FREE(ptr->service);
438 SH_FREE(ptr);
439 return;
440 }
441 else
442 {
443 pre->next = ptr->next;
444 if (ptr->service)
445 SH_FREE(ptr->service);
446 SH_FREE(ptr);
447 ptr = pre->next;
448 continue;
449 }
450 }
451 }
452 pre = ptr;
453 ptr = ptr->next;
454 }
455 return;
456}
457
458
459static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
460 struct in_addr haddr, char * service)
461{
462 struct sh_portentry * portlist;
463 char iface_all[8];
464
465 sl_strlcpy (iface_all, _("0.0.0.0"), sizeof(iface_all));
466
467 if (proto == IPPROTO_TCP)
468 portlist = portlist_tcp;
469 else
470 portlist = portlist_udp;
471
472 if (service)
473 {
474 while (portlist)
475 {
476 if (portlist->service &&
477 0 == strcmp(service, portlist->service) &&
478 (0 == strcmp(portlist->interface, inet_ntoa(haddr)) ||
479 0 == strcmp(portlist->interface, iface_all)))
480 return portlist;
481 portlist = portlist->next;
482 }
483 }
484 else
485 {
486 while (portlist)
487 {
488 if (port == portlist->port &&
489 (0 == strcmp(portlist->interface, inet_ntoa(haddr)) ||
490 0 == strcmp(portlist->interface, iface_all)))
491 return portlist;
492 portlist = portlist->next;
493 }
494 }
495 return NULL;
496}
497
498
499static void sh_portchk_cmp_to_list (int proto, int port, struct in_addr haddr, char * service)
500{
501 struct sh_portentry * portent;
502 char errbuf[256];
503
504
505 portent = sh_portchk_get_from_list (proto, port, haddr, service);
506
507 if (service)
508 {
509 if (!portent)
510 {
511 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
512 inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
513#ifdef TEST_ONLY
514 fprintf(stderr, _("open port: %s:%d/%s (%s)\n"),
515 inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
516#else
517 SH_MUTEX_LOCK(mutex_thread_nolog);
518 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
519 MSG_PORT_NEW, errbuf);
520 SH_MUTEX_UNLOCK(mutex_thread_nolog);
521#endif
522 /*
523 * was not there, thus it is not in 'required' or 'optional' list
524 */
525 sh_portchk_add_to_list (proto, port, haddr, service, SH_PORT_NOT, SH_PORT_ISOK);
526 }
527 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
528 {
529 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
530 inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
531#ifdef TEST_ONLY
532 fprintf(stderr, _("service: %s\n"), errbuf);
533#else
534 SH_MUTEX_LOCK(mutex_thread_nolog);
535 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
536 MSG_PORT_RESTART, errbuf);
537 SH_MUTEX_UNLOCK(mutex_thread_nolog);
538#endif
539
540 portent->status = SH_PORT_ISOK;
541 }
542 else if (port != portent->port && (-1) != portent->port)
543 {
544 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"),
545 inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
546#ifdef TEST_ONLY
547 fprintf(stderr, _("service: %s\n"), errbuf);
548#else
549 SH_MUTEX_LOCK(mutex_thread_nolog);
550 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
551 MSG_PORT_NEWPORT, errbuf);
552 SH_MUTEX_UNLOCK(mutex_thread_nolog);
553#endif
554 portent->port = port;
555 portent->status = SH_PORT_ISOK;
556 }
557 else
558 {
559 portent->status = SH_PORT_ISOK;
560 }
561 }
562 else
563 {
564 if (!portent)
565 {
566 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
567 inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
568#ifdef TEST_ONLY
569 fprintf(stderr, _("open port: %s:%d/%s (%s)\n"),
570 inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
571#else
572 SH_MUTEX_LOCK(mutex_thread_nolog);
573 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
574 MSG_PORT_NEW, errbuf);
575 SH_MUTEX_UNLOCK(mutex_thread_nolog);
576#endif
577
578 /* was not there, thus it is not in 'required' or 'optional' list
579 */
580 sh_portchk_add_to_list (proto, port, haddr, service, SH_PORT_NOT, SH_PORT_ISOK);
581 }
582 else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
583 {
584 snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"),
585 inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
586#ifdef TEST_ONLY
587 fprintf(stderr, _("port : %s\n"), errbuf);
588#else
589 SH_MUTEX_LOCK(mutex_thread_nolog);
590 sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0,
591 MSG_PORT_RESTART, errbuf);
592 SH_MUTEX_UNLOCK(mutex_thread_nolog);
593#endif
594
595 portent->status = SH_PORT_ISOK;
596 }
597 else
598 {
599 portent->status = SH_PORT_ISOK;
600 }
601 }
602
603 return;
604}
605
606
607/* Returns a static buffer containing the name of the service
608 * running on port <port> (from /etc/services)
609 * Returns NULL on failure
610 */
611static char * check_services (int port, int proto)
612{
613 static char buf[256];
614 struct servent * service = getservbyport(htons(port), SH_PROTO_STR(proto));
615
616 if (service && service->s_name && service->s_name[0] != '\0')
617 {
618 snprintf (buf, sizeof(buf), _("maybe_%s"), service->s_name);
619 }
620 else
621 {
622 snprintf (buf, sizeof(buf), _("unknown"));
623 }
624 return buf;
625}
626
627/* Returns a static buffer containing the name of the service
628 * running on port <port> at <address> (from portmap daemon)
629 * Returns NULL on failure
630 */
631static char * check_rpc_list (int port, struct sockaddr_in * address,
632 unsigned long prot)
633{
634 struct pmaplist * head;
635 struct rpcent *r;
636 static char buf[256];
637
638 head = pmap_getmaps(address);
639
640 if (head)
641 {
642 do /* while (head != NULL) */
643 {
644 if ((head->pml_map.pm_prot == prot) &&
645 (port == (int)head->pml_map.pm_port))
646 {
647 r = getrpcbynumber((int)head->pml_map.pm_prog);
648 if (r && r->r_name && r->r_name[0] != '\0')
649 {
650 snprintf (buf, sizeof(buf), "%s", r->r_name);
651 return buf;
652 }
653 else
654 {
655 snprintf (buf, sizeof(buf), "RPC_%lu",
656 (unsigned long)head->pml_map.pm_prog);
657 return buf;
658 }
659 }
660 head = head->pml_next;
661 }
662 while (head != NULL);
663 }
664
665 return NULL;
666}
667
668static int check_port_udp_internal (int fd, int port, struct in_addr haddr)
669{
670 struct sockaddr_in sinr;
671 /* struct in_addr haddr; */
672 int retval;
673 char * p;
674 char buf[8];
675#ifndef TEST_ONLY
676 char errmsg[256];
677 int nerr;
678#endif
679 char errbuf[SH_ERRBUF_SIZE];
680
681 /* inet_aton(interface, &haddr); */
682
683 sinr.sin_family = AF_INET;
684 sinr.sin_port = htons (port);
685 sinr.sin_addr = haddr;
686
687 do {
688 retval = connect(fd, (struct sockaddr *) &sinr, sizeof(sinr));
689 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
690
691 if (retval == -1)
692 {
693#ifdef TEST_ONLY
694 if (portchk_debug)
695 perror(_("connect"));
696#else
697 nerr = errno;
698 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
699 port, inet_ntoa(haddr), sh_error_message(errno, errbuf, sizeof(errbuf)));
700 SH_MUTEX_LOCK(mutex_thread_nolog);
701 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
702 errmsg, _("connect"));
703 SH_MUTEX_UNLOCK(mutex_thread_nolog);
704#endif
705 }
706 else
707 {
708 do {
709 retval = send (fd, buf, 0, 0);
710 } while (retval < 0 && errno == EINTR);
711
712 if (retval == -1 && errno == ECONNREFUSED)
713 {
714 if (portchk_debug)
715 fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
716 port, inet_ntoa(haddr));
717 }
718 else
719 {
720 /* Only the second send() may catch the error
721 */
722 do {
723 retval = send (fd, buf, 0, 0);
724 } while (retval < 0 && errno == EINTR);
725
726 if (retval == -1 && errno == ECONNREFUSED)
727 {
728 if (portchk_debug)
729 fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
730 port, inet_ntoa(haddr));
731 }
732 else if (retval != -1)
733 {
734 /* Try to get service name from portmap
735 */
736 p = check_rpc_list (port, &sinr, IPPROTO_UDP);
737
738 sh_portchk_cmp_to_list (IPPROTO_UDP, port, haddr, p ? p : NULL);
739
740 /* If not an RPC service, try to get name from /etc/services
741 */
742 if (!p)
743 p = check_services(port, IPPROTO_UDP);
744
745 if (portchk_debug)
746 fprintf(stderr, _("check port: %5d/udp on %15s open %s\n"),
747 port, inet_ntoa(haddr), p);
748
749 }
750 }
751 }
752 close (fd);
753 return 0;
754}
755
756static int check_port_tcp_internal (int fd, int port, struct in_addr haddr)
757{
758 struct sockaddr_in sinr;
759 /* struct in_addr haddr; */
760 int retval;
761 int flags;
762 char * p;
763#ifndef TEST_ONLY
764 char errmsg[256];
765 int nerr;
766#endif
767 char errbuf[SH_ERRBUF_SIZE];
768
769 /* inet_aton(interface, &haddr); */
770
771 sinr.sin_family = AF_INET;
772 sinr.sin_port = htons (port);
773 sinr.sin_addr = haddr;
774
775 do {
776 retval = connect(fd, (struct sockaddr *) &sinr, sizeof(sinr));
777 } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
778
779 if (retval == -1 && errno == ECONNREFUSED)
780 {
781 if (portchk_debug)
782 fprintf(stderr, _("check port: %5d on %15s established/time_wait\n"),
783 port, inet_ntoa(haddr));
784 }
785 else if (retval == -1)
786 {
787#ifdef TEST_ONLY
788 if (portchk_debug)
789 perror(_("connect"));
790#else
791 nerr = errno;
792 sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
793 port, inet_ntoa(haddr), sh_error_message(errno, errbuf, sizeof(errbuf)));
794 SH_MUTEX_LOCK(mutex_thread_nolog);
795 sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
796 errmsg, _("connect"));
797 SH_MUTEX_UNLOCK(mutex_thread_nolog);
798#endif
799 }
800 else
801 {
802 /* Try to get service name from portmap
803 */
804 p = check_rpc_list (port, &sinr, IPPROTO_TCP);
805
806 sh_portchk_cmp_to_list (IPPROTO_TCP, port, haddr, p ? p : NULL);
807
808 /* If not an RPC service, try to get name from /etc/services
809 */
810 if (!p)
811 p = check_services(port, IPPROTO_TCP);
812
813 if (portchk_debug)
814 fprintf(stderr, _("check port: %5d on %15s open %s\n"),
815 port, inet_ntoa(haddr), p);
816
817#if !defined(O_NONBLOCK)
818#if defined(O_NDELAY)
819#define O_NONBLOCK O_NDELAY
820#else
821#define O_NONBLOCK 0
822#endif
823#endif
824
825 /* prepare to close connection gracefully
826 */
827 if (port == 22) /* ssh */
828 {
829 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
830 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
831 retval = write (fd, _("SSH-2.0-Foobar"), 14);
832 if (retval > 0) retval = write (fd, "\r\n", 2);
833 }
834 else if (port == 25) /* smtp */
835 {
836 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
837 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
838 retval = write (fd, _("QUIT"), 4);
839 if (retval > 0) retval = write (fd, "\r\n", 2);
840 }
841 else if (port == 79) /* finger */
842 {
843 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
844 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
845 retval = write (fd, "\r\n", 2);
846 }
847 else if (port == 110) /* pop3 */
848 {
849 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
850 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
851 retval = write (fd, _("QUIT"), 4);
852 if (retval > 0) retval = write (fd, "\r\n", 2);
853 }
854 else if (port == 143) /* imap */
855 {
856 flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
857 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
858 retval = write (fd, _("A01 LOGOUT"), 10);
859 if (retval > 0) retval = write (fd, "\r\n", 2);
860 }
861
862 if (portchk_debug && retval < 0)
863 fprintf(stderr, _("check port: error writing to port %5d\n"),
864 port);
865 }
866 close (fd);
867 return 0;
868}
869
870/* typedef uint32_t in_addr_t;
871 * struct in_addr
872 * {
873 * in_addr_t s_addr;
874 * };
875 */
876
877#define SH_IFACE_MAX 16
878
879struct portchk_interfaces {
880 struct in_addr iface[SH_IFACE_MAX];
881 int used;
882};
883
884static struct portchk_interfaces iface_list;
885static int iface_initialized = 0;
886
887#ifdef TEST_ONLY
888static char * portchk_hostname = NULL;
889#else
890static char * portchk_hostname = sh.host.name;
891#endif
892
893static int sh_portchk_init_internal (void)
894{
895 struct hostent * hent;
896 volatile int i; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
897 char errbuf[256];
898
899 if (portchk_debug)
900 fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
901
902 if (!portchk_hostname)
903 return -1;
904
905 if (sh_portchk_active == S_FALSE)
906 return -1;
907
908 SH_MUTEX_LOCK(mutex_port_check);
909 if (iface_initialized == 0)
910 {
911 iface_list.used = 0;
912 iface_initialized = 1;
913 }
914
915 SH_MUTEX_LOCK(mutex_resolv);
916 hent = sh_gethostbyname(portchk_hostname);
917 i = 0;
918 while (hent && hent->h_addr_list[i] && (iface_list.used < SH_IFACE_MAX))
919 {
920 memcpy (&(iface_list.iface[iface_list.used].s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
921 ++iface_list.used;
922 ++i;
923 }
924 SH_MUTEX_UNLOCK(mutex_resolv);
925
926 for (i = 0; i < iface_list.used; ++i)
927 {
928 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"),
929 inet_ntoa(iface_list.iface[i]));
930 SH_MUTEX_LOCK(mutex_thread_nolog);
931 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
932 errbuf, _("sh_portchk_init"));
933 SH_MUTEX_UNLOCK(mutex_thread_nolog);
934 }
935 SH_MUTEX_UNLOCK(mutex_port_check);
936
937 return 0;
938}
939
940int sh_portchk_init (struct mod_type * arg)
941{
942 if (sh_portchk_active == S_FALSE)
943 return SH_MOD_FAILED;
944 if (!portchk_hostname)
945 return SH_MOD_FAILED;
946
947#ifdef HAVE_PTHREAD
948 if (arg != NULL && arg->initval < 0 &&
949 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
950 {
951 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
952 return SH_MOD_THREAD;
953 else
954 return SH_MOD_FAILED;
955 }
956#endif
957 return sh_portchk_init_internal();
958}
959
960
961
962#if !defined(TEST_ONLY)
963int sh_portchk_reconf (void)
964{
965 SH_MUTEX_LOCK(mutex_port_check);
966 iface_initialized = 0;
967 sh_portchk_active = 1;
968 sh_portchk_check_udp = 1;
969 sh_portchk_interval = SH_PORTCHK_INTERVAL;
970
971 portlist_udp = sh_portchk_kill_list (portlist_udp);
972 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
973
974 blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
975 blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
976 SH_MUTEX_UNLOCK(mutex_port_check);
977 return 0;
978}
979
980int sh_portchk_cleanup (void)
981{
982 return sh_portchk_reconf ();
983}
984
985int sh_portchk_timer (time_t tcurrent)
986{
987 static time_t lastcheck = 0;
988
989 SL_ENTER(_("sh_portchk_timer"));
990 if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
991 {
992 lastcheck = tcurrent;
993 SL_RETURN((-1), _("sh_portchk_timer"));
994 }
995 SL_RETURN(0, _("sh_portchk_timer"));
996}
997#endif
998
999static int check_port_generic (int port, int type, int protocol)
1000{
1001 volatile int i = 0;
1002 int sock = -1;
1003 int flag = 1; /* non-zero to enable an option */
1004 struct in_addr haddr;
1005 char errbuf[SH_ERRBUF_SIZE];
1006
1007 /* Check all interfaces for this host
1008 */
1009 while (i < iface_list.used)
1010 {
1011 haddr.s_addr = iface_list.iface[i].s_addr;
1012
1013 if (0 != sh_portchk_is_blacklisted(port, haddr, protocol))
1014 {
1015 ++i; continue;
1016 }
1017
1018 if ((sock = socket(AF_INET, type, protocol)) < 0 )
1019 {
1020 ++i;
1021#ifdef TEST_ONLY
1022 if (portchk_debug)
1023 perror(_("socket"));
1024#else
1025 SH_MUTEX_LOCK(mutex_thread_nolog);
1026 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1027 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1028 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1029#endif
1030 continue;
1031 }
1032 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1033 (void *) &flag, sizeof(flag)) < 0 )
1034 {
1035 ++i;
1036#ifdef TEST_ONLY
1037 if (portchk_debug)
1038 perror(_("setsockopt"));
1039#else
1040 SH_MUTEX_LOCK(mutex_thread_nolog);
1041 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1042 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1043 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1044#endif
1045 continue;
1046 }
1047
1048
1049 if (protocol == IPPROTO_TCP)
1050 check_port_tcp_internal(sock, port, haddr);
1051 else
1052 check_port_udp_internal(sock, port, haddr);
1053
1054 ++i;
1055 }
1056
1057 return 0;
1058}
1059
1060
1061
1062static int check_port_udp (int port)
1063{
1064 return check_port_generic(port, SOCK_DGRAM, IPPROTO_UDP);
1065}
1066
1067static int check_port_tcp (int port)
1068{
1069 return check_port_generic(port, SOCK_STREAM, IPPROTO_TCP);
1070}
1071
1072
1073
1074static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg, int type, int protocol)
1075{
1076 /*
1077 int min_port = 1024;
1078 int max_port = 65535;
1079 */
1080
1081 volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1082 volatile int max_port = max_port_arg;
1083 int retval;
1084 int sock = -1;
1085 int flag = 1; /* non-zero to enable an option */
1086
1087 struct sockaddr_in addr;
1088 int addrlen = sizeof(addr);
1089 char errbuf[SH_ERRBUF_SIZE];
1090
1091 if (min_port == -1)
1092 min_port = 0;
1093 if (max_port == -1)
1094 max_port = 65535;
1095
1096 for (port = min_port; port <= max_port; ++port)
1097 {
1098
1099 if ((sock = socket(AF_INET, type, protocol)) < 0 )
1100 {
1101#ifdef TEST_ONLY
1102 if (portchk_debug)
1103 perror(_("socket"));
1104#else
1105 SH_MUTEX_LOCK(mutex_thread_nolog);
1106 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1107 sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1108 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1109#endif
1110 continue;
1111 }
1112 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1113 (void *) &flag, sizeof(flag)) < 0 )
1114 {
1115#ifdef TEST_ONLY
1116 if (portchk_debug)
1117 perror(_("setsockopt"));
1118#else
1119 SH_MUTEX_LOCK(mutex_thread_nolog);
1120 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1121 sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1122 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1123#endif
1124 continue;
1125 }
1126
1127 addr.sin_family = AF_INET;
1128 addr.sin_port = htons(port);
1129 addr.sin_addr.s_addr = INADDR_ANY;
1130
1131 retval = bind (sock, (struct sockaddr *) &addr, addrlen);
1132
1133 if (retval == 0)
1134 {
1135 /* we can bind the port, thus it is unused
1136 */
1137 close (sock);
1138 }
1139 else
1140 {
1141 if (errno == EINVAL || errno == EADDRINUSE)
1142 {
1143 /* try to connect to the port
1144 */
1145 if (protocol == IPPROTO_TCP)
1146 check_port_tcp(port);
1147 else
1148 check_port_udp(port);
1149 }
1150 else
1151 {
1152#ifdef TEST_ONLY
1153 if (portchk_debug)
1154 perror(_("bind"));
1155#else
1156 SH_MUTEX_LOCK(mutex_thread_nolog);
1157 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1158 sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1159 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1160#endif
1161 }
1162 close (sock);
1163 }
1164 }
1165 return 0;
1166}
1167
1168static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1169{
1170 return sh_portchk_scan_ports_generic (min_port, max_port, SOCK_STREAM, IPPROTO_TCP);
1171}
1172
1173static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1174{
1175 return sh_portchk_scan_ports_generic (min_port, max_port, SOCK_DGRAM, IPPROTO_UDP);
1176}
1177
1178/* Subroutine to add an interface
1179 */
1180static int sh_portchk_add_interface (const char * str)
1181{
1182 struct in_addr haddr;
1183 char errbuf[256];
1184
1185 if (iface_initialized == 0)
1186 {
1187 iface_list.used = 0;
1188 iface_initialized = 1;
1189 }
1190
1191 if (0 == inet_aton(str, &haddr))
1192 return -1;
1193
1194 if (iface_list.used == SH_IFACE_MAX)
1195 return -1;
1196
1197 sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), inet_ntoa(haddr));
1198 SH_MUTEX_LOCK(mutex_thread_nolog);
1199 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1200 errbuf, _("sh_portchk_add_interface"));
1201 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1202
1203 memcpy (&(iface_list.iface[iface_list.used].s_addr), &(haddr.s_addr), sizeof(in_addr_t));
1204 ++iface_list.used;
1205
1206 return 0;
1207}
1208
1209/* verify whether port/interface is blacklisted (do not check)
1210 */
1211static int sh_portchk_is_blacklisted(int port, struct in_addr haddr, int proto)
1212{
1213 struct sh_port * head;
1214
1215 if (proto == IPPROTO_TCP)
1216 head = blacklist_tcp;
1217 else
1218 head = blacklist_udp;
1219
1220 while (head)
1221 {
1222 if (head->port == port)
1223 {
1224 if ((head->haddr.s_addr == 0) || (head->haddr.s_addr == haddr.s_addr))
1225 return 1;
1226 else
1227 return 0;
1228 }
1229 head = head->next;
1230 }
1231 return 0;
1232}
1233
1234
1235static int sh_portchk_blacklist(int port, struct in_addr haddr, int proto)
1236{
1237 struct sh_port * black;
1238 struct sh_port * head;
1239
1240 if (proto == IPPROTO_TCP)
1241 head = blacklist_tcp;
1242 else
1243 head = blacklist_udp;
1244
1245 black = head;
1246
1247 while (black)
1248 {
1249 if (black->port == port && head->haddr.s_addr == haddr.s_addr)
1250 return -1;
1251 black = black->next;
1252 }
1253 black = SH_ALLOC (sizeof(struct sh_port));
1254 black->port = port;
1255 black->haddr.s_addr = haddr.s_addr;
1256 black->next = head;
1257
1258 if (proto == IPPROTO_TCP)
1259 blacklist_tcp = black;
1260 else
1261 blacklist_udp = black;
1262 return 0;
1263}
1264
1265
1266/* Subroutine to add a required or optional port/service
1267 */
1268static int sh_portchk_add_required_port_generic (char * service, char * interface, int type)
1269{
1270 char buf[256];
1271 int proto;
1272 char * p;
1273 char * endptr;
1274 unsigned long int port;
1275 struct in_addr haddr;
1276 struct sh_portentry * portent;
1277
1278 if (0 == inet_aton(interface, &haddr))
1279 return -1;
1280
1281 sl_strlcpy (buf, service, sizeof(buf));
1282
1283 p = strchr(buf, '/');
1284 if (!p)
1285 return -1;
1286 if (0 == strcmp(p, _("/tcp")))
1287 proto = IPPROTO_TCP;
1288 else if (0 == strcmp(p, _("/udp")))
1289 proto = IPPROTO_UDP;
1290 else
1291 return -1;
1292
1293 *p = '\0';
1294 port = strtoul(buf, &endptr, 0);
1295
1296 /* Blacklisted ports
1297 */
1298 if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
1299 return (sh_portchk_blacklist(port, haddr, proto));
1300
1301 if (*endptr != '\0')
1302 {
1303 portent = sh_portchk_get_from_list (proto, -1, haddr, buf);
1304 if (!portent)
1305 sh_portchk_add_to_list (proto, -1, haddr, buf, type, SH_PORT_UNKN);
1306 else
1307 {
1308#ifdef TEST_ONLY
1309 fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
1310#else
1311 SH_MUTEX_LOCK(mutex_thread_nolog);
1312 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1313 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
1314 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1315#endif
1316 return -1;
1317 }
1318 }
1319 else if (port <= 65535)
1320 {
1321 portent = sh_portchk_get_from_list (proto, port, haddr, NULL);
1322 if (!portent)
1323 sh_portchk_add_to_list (proto, port, haddr, NULL, type, SH_PORT_UNKN);
1324 else
1325 {
1326#ifdef TEST_ONLY
1327 fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
1328#else
1329 SH_MUTEX_LOCK(mutex_thread_nolog);
1330 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1331 _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
1332 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1333#endif
1334 return -1;
1335 }
1336 }
1337 else
1338 return -1;
1339
1340 return 0;
1341}
1342
1343/* Internal interface to add required or optional ports as 'iface:portlist'
1344 */
1345static int sh_portchk_add_required_generic (const char * str, int type)
1346{
1347 size_t len;
1348 size_t ll = 0;
1349 int status;
1350
1351 char * interface = NULL;
1352 char * list;
1353 char * p;
1354#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1355 char * saveptr;
1356#endif
1357
1358 if (!str)
1359 return -1;
1360
1361 if (strchr(str, ':'))
1362 {
1363 len = strlen(str);
1364 for (ll = 0; ll < len; ++ll)
1365 {
1366 if (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
1367 {
1368 interface = SH_ALLOC(ll+1);
1369 sl_strlcpy(interface, str, ll+1);
1370 interface[ll] = '\0';
1371 while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
1372 ++ll;
1373 break;
1374 }
1375 }
1376 }
1377 else
1378 {
1379 interface = SH_ALLOC(8);
1380 sl_strlcpy(interface, _("0.0.0.0"), 8);
1381 interface[7] = '\0';
1382 while (str[ll] == ' ' || str[ll] == '\t')
1383 ++ll;
1384 }
1385
1386 if (!interface)
1387 return -1;
1388
1389 if (str[ll] == '\0')
1390 {
1391 SH_FREE(interface);
1392 return -1;
1393 }
1394
1395 if (portchk_debug)
1396 fprintf(stderr, "add ports for interface: %s\n", interface);
1397
1398 list = sh_util_strdup(&str[ll]);
1399#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1400 p = strtok_r (list, " ,\t", &saveptr);
1401#else
1402 p = strtok (list, " ,\t");
1403#endif
1404 if (!p)
1405 {
1406 SH_FREE(interface);
1407 SH_FREE(list);
1408 return -1;
1409 }
1410 while (p)
1411 {
1412 status = sh_portchk_add_required_port_generic (p, interface, type);
1413
1414 if (-1 == status)
1415 {
1416 SH_FREE(interface);
1417 SH_FREE(list);
1418 return -1;
1419 }
1420#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1421 p = strtok_r (NULL, " ,\t", &saveptr);
1422#else
1423 p = strtok (NULL, " ,\t");
1424#endif
1425 }
1426 SH_FREE(interface);
1427 SH_FREE(list);
1428 return 0;
1429}
1430
1431/* User interface to add required ports as 'iface:portlist'
1432 */
1433static int sh_portchk_add_required (const char * str)
1434{
1435 return sh_portchk_add_required_generic (str, SH_PORT_REQ);
1436}
1437
1438/* User interface to add optional ports as 'iface:portlist'
1439 */
1440static int sh_portchk_add_optional (const char * str)
1441{
1442 return sh_portchk_add_required_generic (str, SH_PORT_OPT);
1443}
1444
1445/* User interface to add ignoreable ports as 'iface:portlist'
1446 */
1447static int sh_portchk_add_ignore (const char * str)
1448{
1449 return sh_portchk_add_required_generic (str, SH_PORT_IGN);
1450}
1451
1452/* User interface to add ports that should not be checked as 'iface:portlist'
1453 */
1454static int sh_portchk_add_blacklist (const char * str)
1455{
1456 return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST);
1457}
1458
1459/* Interface to run port check
1460 */
1461int sh_portchk_check ()
1462{
1463 volatile int min_port;
1464
1465 SH_MUTEX_LOCK(mutex_port_check);
1466
1467 min_port = 0;
1468
1469 if (sh_portchk_active != S_FALSE)
1470 {
1471 sh_portchk_reset_lists();
1472 if (0 != geteuid())
1473 {
1474 min_port = 1024;
1475#ifdef TEST_ONLY
1476 fprintf(stderr, "** WARNING not scanning ports < 1024\n");
1477#else
1478 SH_MUTEX_LOCK(mutex_thread_nolog);
1479 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1480 _("not scanning ports below 1024"), _("sh_portchk_check"));
1481 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1482#endif
1483 }
1484 if (sh_portchk_check_udp == 1)
1485 sh_portchk_scan_ports_udp(min_port, -1);
1486 sh_portchk_scan_ports_tcp(min_port, -1);
1487 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
1488 if (sh_portchk_check_udp == 1)
1489 sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
1490 }
1491 SH_MUTEX_UNLOCK(mutex_port_check);
1492 return 0;
1493}
1494#endif
1495
1496#ifdef SH_CUTEST
1497#include "CuTest.h"
1498
1499void Test_portcheck_lists (CuTest *tc)
1500{
1501#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1502 struct in_addr haddr_local;
1503 struct sh_portentry * portent;
1504
1505 CuAssertTrue(tc, 0 != inet_aton("127.0.0.1", &haddr_local));
1506
1507 sh_portchk_add_to_list (IPPROTO_TCP, 8000, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
1508
1509 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, NULL);
1510 CuAssertPtrNotNull(tc, portent);
1511
1512 CuAssertTrue(tc, portent->port == 8000);
1513 CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
1514 CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
1515 CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
1516
1517 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
1518
1519 CuAssertTrue(tc, NULL == portlist_tcp);
1520
1521 sh_portchk_add_to_list (IPPROTO_TCP, 8000, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
1522 sh_portchk_add_to_list (IPPROTO_TCP, 8001, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
1523 sh_portchk_add_to_list (IPPROTO_TCP, 8002, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
1524 sh_portchk_add_to_list (IPPROTO_TCP, 8003, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
1525 sh_portchk_add_to_list (IPPROTO_TCP, 8004, haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
1526 sh_portchk_add_to_list (IPPROTO_TCP, -1, haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
1527 sh_portchk_add_to_list (IPPROTO_TCP, -1, haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
1528 sh_portchk_add_to_list (IPPROTO_TCP, -1, haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
1529 sh_portchk_add_to_list (IPPROTO_TCP, -1, haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
1530 sh_portchk_add_to_list (IPPROTO_TCP, -1, haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
1531
1532 sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
1533
1534 CuAssertPtrNotNull(tc, portlist_tcp);
1535
1536 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, NULL);
1537 CuAssertPtrNotNull(tc, portent);
1538
1539 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, haddr_local, NULL);
1540 CuAssertTrue(tc, NULL == portent);
1541
1542 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, haddr_local, NULL);
1543 CuAssertPtrNotNull(tc, portent);
1544
1545 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, haddr_local, NULL);
1546 CuAssertTrue(tc, NULL == portent);
1547
1548 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, haddr_local, NULL);
1549 CuAssertPtrNotNull(tc, portent);
1550
1551 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, "foo1");
1552 CuAssertTrue(tc, NULL == portent);
1553
1554 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, "foo2");
1555 CuAssertPtrNotNull(tc, portent);
1556 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
1557
1558 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, "foo3");
1559 CuAssertTrue(tc, NULL == portent);
1560
1561 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, "foo4");
1562 CuAssertPtrNotNull(tc, portent);
1563 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
1564
1565 portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, haddr_local, "foo5");
1566 CuAssertPtrNotNull(tc, portent);
1567 CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
1568
1569 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, haddr_local, IPPROTO_TCP));
1570 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, haddr_local, IPPROTO_TCP));
1571 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, haddr_local, IPPROTO_TCP));
1572 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, haddr_local, IPPROTO_TCP));
1573 CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, haddr_local, IPPROTO_UDP));
1574 CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, haddr_local, IPPROTO_UDP));
1575 CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, haddr_local, IPPROTO_UDP));
1576 CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, haddr_local, IPPROTO_UDP));
1577
1578 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, haddr_local, IPPROTO_UDP));
1579 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, haddr_local, IPPROTO_UDP));
1580 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, haddr_local, IPPROTO_UDP));
1581 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, haddr_local, IPPROTO_UDP));
1582
1583 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, haddr_local, IPPROTO_TCP));
1584 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, haddr_local, IPPROTO_TCP));
1585 CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, haddr_local, IPPROTO_TCP));
1586 CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, haddr_local, IPPROTO_TCP));
1587#else
1588 (void) tc; /* fix compiler warning */
1589#endif
1590 return;
1591}
1592#endif
1593
1594#ifdef TEST_ONLY
1595
1596void usage (char * pname)
1597{
1598 printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
1599 printf (" Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
1600 printf (" Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
1601 printf (" Portlist: List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
1602 printf (" required -> must be open\n");
1603 printf (" optional -> may be open or closed\n");
1604 printf (" RPC services must be specified with service **name**, others with **port number**\n\n");
1605 printf (" Example:\n");
1606 printf (" %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
1607 return;
1608}
1609
1610int main(int argc, char *argv[])
1611{
1612 char * pname = argv[0];
1613
1614
1615 /*
1616 test_lists();
1617
1618 portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1619 portlist_udp = sh_portchk_kill_list (portlist_udp);
1620 */
1621
1622 // sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp");
1623
1624 while (argc > 1 && argv[1][0] == '-')
1625 {
1626 if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
1627 {
1628 usage(pname);
1629 exit (0);
1630 }
1631 else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
1632 {
1633 if (argc < 3)
1634 {
1635 usage(pname);
1636 exit (1);
1637 }
1638 sh_portchk_add_required (argv[2]);
1639 --argc; ++argv;
1640 }
1641 else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
1642 {
1643 if (argc < 3)
1644 {
1645 usage(pname);
1646 exit (1);
1647 }
1648 sh_portchk_add_optional (argv[2]);
1649 --argc; ++argv;
1650 }
1651 else if (0 == strcmp(argv[1], "--no-udp"))
1652 {
1653 sh_portchk_check_udp = 0;
1654 }
1655 else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
1656 {
1657 portchk_debug = 1;
1658 }
1659 else
1660 {
1661 usage(pname);
1662 exit (1);
1663 }
1664 --argc; ++argv;
1665 }
1666
1667 if (argc < 2)
1668 {
1669 usage(pname);
1670 exit (1);
1671 }
1672
1673 portchk_hostname = argv[1];
1674
1675 if (0 != sh_portchk_init ())
1676 {
1677 usage(pname);
1678 exit (1);
1679 }
1680
1681 sh_portchk_check();
1682
1683 return 0;
1684}
1685#endif
Note: See TracBrowser for help on using the repository browser.