source: trunk/src/sh_portcheck.c @ 473

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

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

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