source: trunk/src/sh_portcheck.c@ 158

Last change on this file since 158 was 149, checked in by katerina, 17 years ago

Make sh_hash.c thread-safe, remove plenty of tiny allocations, improve sh_mem_dump, modify port check to run as thread, and fix unsetting of sh_thread_pause_flag (was too early).

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