source: trunk/src/sh_portcheck.c@ 340

Last change on this file since 340 was 335, checked in by katerina, 14 years ago

Module cleanup/thread restart at configuration reload.

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