source: trunk/src/sh_portcheck.c@ 169

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

Fixes for tickes #93 to #104 (yes, big commit, bad, bad,...).

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