source: trunk/src/sh_portcheck.c@ 196

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

Process lookup (Linux) for open ports (ticket #117). Also fix for minor dnmalloc bug (ticket #119).

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