source: trunk/src/sh_portcheck.c@ 480

Last change on this file since 480 was 473, checked in by katerina, 9 years ago

Fix for ticket #371 (use cppcheck instead of uno for static checking).

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