source: trunk/src/sh_portcheck.c@ 369

Last change on this file since 369 was 362, checked in by katerina, 13 years ago

Fix for ticket #267 (Multiple compiler warnings with gcc 4.6.1).

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