source: trunk/src/sh_portcheck.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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