source: trunk/src/sh_portcheck.c@ 504

Last change on this file since 504 was 498, checked in by katerina, 9 years ago

Fix for ticket #395 (Port check fails for some UDP daemons).

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