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
RevLine 
[67]1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2006 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to check for open ports
23 * on the local machine.
24 *
25 */
26
27
28/* #define TEST_ONLY */
29#ifndef TEST_ONLY
30#include "config_xor.h"
31#endif
32
33#include <stdio.h>
34#include <string.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <errno.h>
40#include <unistd.h>
[109]41#include <fcntl.h>
[67]42
[76]43#define PORTCHK_VERSION "1.0"
44
45#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
46
47
[67]48#define PORTMAP
[290]49#ifdef  HAVE_RPC_RPC_H
[67]50#include <rpc/rpc.h>
51#ifdef  HAVE_RPC_RPCENT_H
52#include <rpc/rpcent.h>
53#endif
54#include <rpc/pmap_clnt.h>
55#include <rpc/pmap_prot.h>
[290]56#endif
[67]57#include <netdb.h>
58
59/*
60 * struct pmaplist {
61 *      struct pmap     pml_map;
62 *      struct pmaplist *pml_next;
63 * };
64 */
65
66/* struct pmap {
67 *      long unsigned pm_prog;
68 *      long unsigned pm_vers;
69 *      long unsigned pm_prot;
70 *      long unsigned pm_port;
71 * };
72 */
73
74/* TIME_WAIT ? 60-240 seconds */
75
[295]76#if !defined(TEST_ONLY)
77
78#define FIL__ _("sh_portcheck.c")
79#include "samhain.h"
80#include "sh_error.h"
81#include "sh_mem.h"
82#include "sh_calls.h"
83#include "sh_utils.h"
84#include "sh_modules.h"
85#define SH_NEED_GETHOSTBYXXX
86#include "sh_static.h"
87#include "sh_pthread.h"
88#include "sh_ipvx.h"
89
[67]90/* the size of an interface string
91 */
[295]92#define SH_INTERFACE_SIZE SH_IP_BUF
[67]93
94#define SH_PORT_NOT 0
95#define SH_PORT_REQ 1
96#define SH_PORT_OPT 2
[127]97#define SH_PORT_IGN 3
[149]98#define SH_PORT_BLACKLIST 4
[67]99
[468]100static char * sh_port_type2str (int type)
101{
102  if (type == 0) return _("not");
103  if (type == 1) return _("req");
104  if (type == 2) return _("opt");
105  if (type == 3) return _("ign");
106  if (type == 4) return _("blc");
107  return _("???");
108}
109
[67]110#define SH_PORT_MISS 0
111#define SH_PORT_ISOK 1
112#define SH_PORT_UNKN 2
113
114#define SH_PORT_NOREPT 0
115#define SH_PORT_REPORT 1
116
[149]117#define SH_PROTO_TCP 0
118#define SH_PROTO_UDP 1
119#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
120
[67]121struct sh_portentry {
122  int  port;
123  char interface[SH_INTERFACE_SIZE];
124  char * service;
125  char * error;
126  int  flag;    /* required or not */
127  int  status;  /* missing or not  */
128  struct sh_portentry * next;
129};
130
131static struct sh_portentry * portlist_tcp = NULL;
132static struct sh_portentry * portlist_udp = NULL;
133
[149]134
[67]135#define SH_PORTCHK_INTERVAL 300
136
137static int sh_portchk_check_udp = 1;
138static int sh_portchk_active    = 1;
139static int sh_portchk_interval  = SH_PORTCHK_INTERVAL;
140
[328]141static int sh_portchk_minport = -1;
142static int sh_portchk_maxport = -1;
143
[295]144struct sh_port {
145  int                  port;
146  struct sh_sockaddr * paddr;
147  struct sh_port     * next;
148};
[67]149
[295]150static struct sh_port * blacklist_tcp = NULL;
151static struct sh_port * blacklist_udp = NULL;
152
[149]153SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
154
[67]155static int sh_portchk_severity  = SH_ERR_SEVERE;
[180]156
[295]157extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
[206]158                                 unsigned long * pid, char * user, size_t userlen);
[180]159extern int sh_port2proc_prepare();
[235]160extern void sh_port2proc_finish();
[180]161
[67]162#endif
163
[127]164/* Exported interface to add ignoreable ports as 'iface:portlist'
165 */
166static int sh_portchk_add_ignore (const char * str);
167
[67]168/* Exported interface to add required ports as 'iface:portlist'
169 */
170static int sh_portchk_add_required (const char * str);
171
172/* Exported interface to add optional ports as 'iface:portlist'
173 */
174static int sh_portchk_add_optional (const char * str);
175
[149]176/* Exported interface to add blacklisted ports as 'iface:portlist'
177 */
178static int sh_portchk_add_blacklist (const char * str);
179
[67]180/* Exported interface to add an ethernet interface
181 */
182static int sh_portchk_add_interface (const char * str);
183
[149]184/* verify whether port/interface is blacklisted (do not check)
185 */
[295]186static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
[67]187
188#ifndef TEST_ONLY
189
190static int sh_portchk_set_interval (const char * c)
191{
192  int retval = 0;
193  long val;
194
195  SL_ENTER(_("sh_portchk_set_interval"));
196  val = strtol (c, (char **)NULL, 10);
197  if (val <= 0)
198    {
[149]199      SH_MUTEX_LOCK(mutex_thread_nolog);
[67]200      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
201                       _("port check interval"), c);
[149]202      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]203      retval = -1;
204    }
[362]205  else
206    {
207      sh_portchk_interval = (time_t) val;
208    }
209  SL_RETURN(retval, _("sh_portchk_set_interval"));
[67]210}
211
[328]212static int sh_portchk_set_port_minmax (const char * c, int * setthis)
213{
214  int retval = 0;
215  long val;
[67]216
[328]217  SL_ENTER(_("sh_portchk_set_port_minmax"));
218  val = strtol (c, (char **)NULL, 10);
219  if (val < 0 || val > 65535)
220    {
221      SH_MUTEX_LOCK(mutex_thread_nolog);
222      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
223                       _("port check port minmax"), c);
224      SH_MUTEX_UNLOCK(mutex_thread_nolog);
225      retval = -1;
226    }
[362]227  else
228    {
229      *setthis = (int) val;
230    }
231  SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
[328]232}
233
234
235static int sh_portchk_set_minport   (const char * str)
236{
237  return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
238}
239
240static int sh_portchk_set_maxport   (const char * str)
241{
242  return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
243}
244
[67]245static int sh_portchk_set_active   (const char * str)
246{
247  return sh_util_flagval(str, &sh_portchk_active);
248}
249
250static int sh_portchk_set_udp      (const char * str)
251{
252  return sh_util_flagval(str, &sh_portchk_check_udp);
253}
254
255static int sh_portchk_set_severity (const char * str)
256{
257  char tmp[32];
258  tmp[0] = '='; tmp[1] = '\0';
259  sl_strlcat (tmp, str, 32);
260  return sh_error_set_level (tmp, &sh_portchk_severity);
261}
262
263sh_rconf sh_portchk_table[] = {
264    {
265        N_("severityportcheck"),
266        sh_portchk_set_severity,
267    },
268    {
269        N_("portcheckrequired"),
270        sh_portchk_add_required,
271    },
272    {
273        N_("portcheckoptional"),
274        sh_portchk_add_optional,
275    },
276    {
[127]277        N_("portcheckignore"),
278        sh_portchk_add_ignore,
279    },
280    {
[149]281        N_("portcheckskip"),
282        sh_portchk_add_blacklist,
283    },
284    {
[67]285        N_("portcheckactive"),
286        sh_portchk_set_active,
287    },
288    {
289        N_("portcheckinterface"),
290        sh_portchk_add_interface,
291    },
292    {
293        N_("portcheckinterval"),
294        sh_portchk_set_interval,
295    },
296    {
[328]297        N_("portcheckminport"),
298        sh_portchk_set_minport,
299    },
300    {
301        N_("portcheckmaxport"),
302        sh_portchk_set_maxport,
303    },
304    {
[67]305        N_("portcheckudp"),
306        sh_portchk_set_udp,
307    },
308    {
309        NULL,
310        NULL
311    }
312};
313
314#endif
315
316/* Interface to initialize port check
317 */
[170]318int sh_portchk_init (struct mod_type * arg);
[67]319
320/* Interface to reset port check
321 */
[170]322int sh_portchk_reset (void);
[67]323
324/* Interface to run port check
325 */
[170]326int sh_portchk_check (void);
[67]327
328
[149]329static char * check_services (int port, int proto);
[67]330
331#ifdef TEST_ONLY
332
[380]333static int portchk_debug = 0; 
[67]334#define SH_ALLOC       malloc
335#define SH_FREE        free
336#define sh_util_strdup strdup
337#define sl_strlcpy     strncpy
338#define _(a)           a
339
340#else
341
342static int portchk_debug = 0;
343
344#endif
345
[290]346#ifdef  HAVE_RPC_RPC_H
[218]347static char * sh_getrpcbynumber (int number, char * buf, size_t len)
348{
349  FILE * fp;
350
351  if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
352    {
353      sh_string * s = sh_string_new(0);
354      while (0 < sh_string_read(s, fp, 1024))
355        {
356          char * p = sh_string_str(s);
357          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
358          if (*p == '\0' || *p == '#') 
359            continue; /* skip comment */
360          else
361            {
362              size_t lengths[3];
363              unsigned int  fields = 3;
364              char * q             = sh_string_str(s);
365              char ** splits       = split_array_ws(q, &fields, lengths);
366
367              if (fields >= 2)
368                {
369                  int n = atoi(splits[1]);
370                  if (n == number)
371                    {
372                      sl_strlcpy(buf, splits[0], len);
373                      SH_FREE(splits);
374                      sh_string_destroy(&s);
[252]375                      sl_fclose(FIL__, __LINE__, fp);
[218]376                      return buf;
377                    }
378                }
379              SH_FREE(splits);
380            }
381        }
382      sh_string_destroy(&s);
[252]383      sl_fclose(FIL__, __LINE__, fp);
[218]384    }
385  return NULL;
386}
[290]387#endif
[218]388
389static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
390{
391  FILE * fp;
392  char   proto[8];
393
394  sl_strlcpy(proto, proto_in, sizeof(proto));
395
396  if (NULL != (fp = fopen(_("/etc/services"), "r")))
397    {
398      sh_string * s = sh_string_new(0);
399      while (0 < sh_string_read(s, fp, 1024))
400        {
401          char * p = sh_string_str(s);
402          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
403          if (*p == '\0' || *p == '#')
404            continue; /* skip comment */
405          else
406            {
407              size_t lengths[3];
408              unsigned int  fields = 3;
409              char * q             = sh_string_str(s);
410              char ** splits       = split_array_ws(q, &fields, lengths);
411
412              if (fields >= 2)
413                {
414                  char * end;
415                  long n = strtol(splits[1], &end, 10);
416                  if (n == port && end && (*end == '/' || *end == ','))
417                    {
418                      ++end;
419                      if (0 == strcmp(end, proto))
420                        {
421                          sl_strlcpy(buf, splits[0], len);
422                          SH_FREE(splits);
423                          sh_string_destroy(&s);
[252]424                          sl_fclose(FIL__, __LINE__, fp);
[218]425                          return buf;
426                        }
427                    }
428                }
429              SH_FREE(splits);
430            }
431        }
432      sh_string_destroy(&s);
[252]433      sl_fclose(FIL__, __LINE__, fp);
[218]434    }
435  return NULL;
436}
437
[149]438static void sh_portchk_add_to_list (int proto, 
[295]439                                    int port, struct sh_sockaddr * paddr, 
[218]440                                    char * service,
[67]441                                    int flag, int status)
442{
443  struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
444
445  new->port = port;
[295]446  sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
[67]447  new->status = status;
448  new->flag   = flag;
449
450  new->error  = NULL;
451
[380]452  if (portchk_debug)
453    fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"),
454            port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"),
455            new->interface);
456
[67]457  if (service)
458    new->service = sh_util_strdup (service);
459  else
460    new->service = NULL;
[149]461  if (proto == IPPROTO_TCP)
[67]462    {
463      new->next = portlist_tcp;
464      portlist_tcp = new;
465    }
466  else
467    {
468      new->next = portlist_udp;
469      portlist_udp = new;
470    }
471  return;
472}
473
474/* Reset the list by setting all entries to UNKN.
475 * In the next cycle we will check, and set found ports to ISOK.
476 * Thereafter, we check for entries that are still UNKN.
477 */
[170]478static void sh_portchk_reset_lists (void)
[67]479{
480  struct sh_portentry * portlist;
481
482  portlist = portlist_tcp;
483  while (portlist)
484    {
485      if (portlist->status != SH_PORT_MISS)
486        portlist->status = SH_PORT_UNKN;
487      portlist = portlist->next;
488    }
489  portlist = portlist_udp;
490  while (portlist)
491    {
492      if (portlist->status != SH_PORT_MISS)
493        portlist->status = SH_PORT_UNKN;
494      portlist = portlist->next;
495    }
496  return;
497}
498
499static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
500{
501  if (head)
502    {
503      if (head->next)
504        sh_portchk_kill_list (head->next);
505
506      if (head->service)
507        SH_FREE(head->service);
508      SH_FREE(head);
509    }
510  return NULL;
511}
512 
[149]513static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
514{
515  if (head)
516    {
517      if (head->next)
518        sh_portchk_kill_blacklist (head->next);
519
[295]520      SH_FREE(head->paddr);
[149]521      SH_FREE(head);
522    }
523  return NULL;
524}
525 
[170]526/* These variables are not used anywhere. They only exist
527 * to assign &pre, &ptr to them, which keeps gcc from
528 * putting it into a register, and avoids the 'clobbered
529 * by longjmp' warning. And no, 'volatile' proved insufficient.
530 */
[481]531void * sh_dummy_531_pre = NULL;
532void * sh_dummy_532_ptr = NULL;
[170]533
[67]534/* check the list of open ports for any that are marked as UNKN
535 */
[481]536static void sh_portchk_check_list (struct sh_portentry ** head, 
537                                   int proto, int report)
[67]538{
539  struct sh_portentry * ptr = *head;
540  struct sh_portentry * pre = *head;
541  char errbuf[256];
542
[170]543  /* Take the address to keep gcc from putting them into registers.
544   * Avoids the 'clobbered by longjmp' warning.
545   */
[481]546  sh_dummy_531_pre = (void*) &pre;
547  sh_dummy_532_ptr = (void*) &ptr;
[170]548 
[67]549  while (ptr)
550    {
551      if (portchk_debug && report)
552        fprintf(stderr, _("check list: port %d/%s %d %d\n"),
[149]553                ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]554
555      if (ptr->status == SH_PORT_UNKN)
556        {
557          /* Don't report missing ports that are marked as optional
558           */
[127]559          if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
[67]560            {
[169]561              snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
[149]562                        ptr->interface, ptr->port, SH_PROTO_STR(proto), 
[67]563                        ptr->service ? ptr->service : check_services(ptr->port, proto));
564#ifdef TEST_ONLY
565              if (report == SH_PORT_REPORT)
566                fprintf(stderr, _("%s\n"), errbuf);
567#else
568              if (report == SH_PORT_REPORT)
[149]569                {
570                  SH_MUTEX_LOCK(mutex_thread_nolog);
571                  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[169]572                                  MSG_PORT_MISS, errbuf);
[149]573                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
574                }
[67]575#endif
576            }
577
578          ptr->status = SH_PORT_MISS;
579
[128]580          if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
[67]581            {
582              if (portchk_debug && report)
583                fprintf(stderr, _("removing: port %d/%s %d %d\n"),
[149]584                        ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
[67]585             
586              if (ptr == *head)
587                {
588                  *head = ptr->next;
589                  if (ptr->service)
590                    SH_FREE(ptr->service);
591                  SH_FREE(ptr);
592                  ptr = *head;
593                  pre = *head;
594                  continue;
595                }
596              else if (ptr->next == NULL)
597                {
598                  pre->next = NULL;
599                  if (ptr->service)
600                    SH_FREE(ptr->service);
601                  SH_FREE(ptr);
602                  return;
603                }
604              else
605                {
606                  pre->next = ptr->next;
607                  if (ptr->service)
608                    SH_FREE(ptr->service);
609                  SH_FREE(ptr);
610                  ptr = pre->next;
611                  continue;
612                }
613            }
614        }
615      pre = ptr;
616      ptr = ptr->next;
617    }
[383]618
[481]619  sh_dummy_532_ptr = NULL;
620  sh_dummy_531_pre = NULL;
[383]621
[67]622  return;
623}
624
625
[149]626static struct sh_portentry * sh_portchk_get_from_list (int proto, int port, 
[295]627                                                       struct sh_sockaddr * paddr, char * service)
[67]628{
629  struct sh_portentry * portlist;
[295]630  char str_addr[SH_IP_BUF];
[75]631
[149]632  if (proto == IPPROTO_TCP)
[67]633    portlist = portlist_tcp;
634  else
635    portlist = portlist_udp;
636
[295]637  sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
638
[67]639  if (service)
640    {
641      while (portlist) 
642        {
643          if (portlist->service && 
644              0 == strcmp(service, portlist->service) &&
[295]645              ( 0 == strcmp(portlist->interface, str_addr) ||
646                sh_ipvx_isany(paddr) ))
[67]647            return portlist;
648          portlist = portlist->next;
649        }
650    }
651  else
652    {
653      while (portlist) 
654        {
655          if (port == portlist->port &&
[295]656              (0 == strcmp(portlist->interface, str_addr)  ||
657               sh_ipvx_isany(paddr) ))
[67]658            return portlist;
659          portlist = portlist->next;
660        }
661    }
662  return NULL;
663}
664     
665
[380]666static void sh_portchk_cmp_to_list (int proto, int port, 
667                                    struct sh_sockaddr * paddr, char * service)
[67]668{
669  struct sh_portentry * portent;
670  char errbuf[256];
671
672 
[295]673  portent = sh_portchk_get_from_list (proto, port, paddr, service);
[67]674
675  if (service)
676    {
677      if (!portent)
678        {
[180]679          char * path;
[206]680          unsigned long qpid;
[180]681          char   user[USER_MAX];
[295]682          char   saddr[SH_IP_BUF];
[180]683
[295]684          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
685
[169]686          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
[295]687                    saddr, port, SH_PROTO_STR(proto), service);
[380]688
689          if (portchk_debug)
690            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"), 
691                    saddr, port, SH_PROTO_STR(proto), service);
692
693#ifndef TEST_ONLY
[295]694          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]695          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]696          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[206]697                          MSG_PORT_NEW, errbuf, path, qpid, user);
[149]698          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]699          SH_FREE(path);
[67]700#endif
701          /*
702           * was not there, thus it is not in 'required' or 'optional' list
703           */
[295]704          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]705        }
[127]706      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]707        {
[180]708          char * path;
[206]709          unsigned long qpid;
[180]710          char   user[USER_MAX];
[295]711          char   saddr[SH_IP_BUF];
[180]712
[295]713          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
714
[169]715          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
[295]716                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]717#ifdef TEST_ONLY
718          fprintf(stderr, _("service: %s\n"), errbuf);
719#else
[295]720          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]721          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]722          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[206]723                          MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]724          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]725          SH_FREE(path);
[67]726#endif
727
728          portent->status = SH_PORT_ISOK;
729        }
730      else if (port != portent->port && (-1) != portent->port)
731        {
[180]732          char * path;
[206]733          unsigned long qpid;
[180]734          char   user[USER_MAX];
[295]735          char   saddr[SH_IP_BUF];
[180]736
[295]737          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
738
[169]739          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
[295]740                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
[67]741#ifdef TEST_ONLY
742          fprintf(stderr, _("service: %s\n"), errbuf);
743#else
[295]744          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]745          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]746          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[206]747                          MSG_PORT_NEWPORT, errbuf, path, qpid, user);
[149]748          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]749          SH_FREE(path);
[67]750#endif
[127]751          portent->port   = port;
[67]752          portent->status = SH_PORT_ISOK;
753        }
754      else
755        {
756          portent->status = SH_PORT_ISOK;
757        }
758    }
759  else
760    {
761      if (!portent)
762        {
[180]763          char * path;
[206]764          unsigned long qpid;
[180]765          char   user[USER_MAX];
[295]766          char   saddr[SH_IP_BUF];
[180]767
[468]768          if (portchk_debug)
769            fprintf(stderr, _("call to  sh_ipvx_ntoa (port %d)\n"), port);
770 
[295]771          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
772
[169]773          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
[295]774                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[380]775
776          if (portchk_debug)
777            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"), 
778                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
779
780#ifndef TEST_ONLY
[295]781          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]782          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]783          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[206]784                          MSG_PORT_NEW, errbuf, path, qpid, user);
[149]785          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]786          SH_FREE(path);
[67]787#endif
788
789          /* was not there, thus it is not in 'required' or 'optional' list
790           */
[295]791          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
[67]792        }
[127]793      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
[67]794        {
[180]795          char * path;
[206]796          unsigned long qpid;
[180]797          char   user[USER_MAX];
[295]798          char   saddr[SH_IP_BUF];
[180]799
[295]800          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
801
[169]802          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
[295]803                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
[67]804#ifdef TEST_ONLY
805          fprintf(stderr, _("port   : %s\n"), errbuf);
806#else
[295]807          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
[149]808          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]809          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
[206]810                          MSG_PORT_RESTART, errbuf, path, qpid, user);
[149]811          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[180]812          SH_FREE(path);
[67]813#endif
814
815          portent->status = SH_PORT_ISOK;
816        }
817      else
818        {
819          portent->status = SH_PORT_ISOK;
820        }
821    }
822
823  return;
824}
825
826                               
827/* Returns a static buffer containing the name of the service
828 * running on port <port> (from /etc/services)
829 * Returns NULL on failure
830 */
[149]831static char * check_services (int port, int proto)
[67]832{
833  static char buf[256];
[218]834  char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
[67]835
[218]836  if (!service)
[67]837    {
[210]838      snprintf (buf, sizeof(buf), "%s",_("unknown"));
[67]839    }
840  return buf;
841}
842
843/* Returns a static buffer containing the name of the service
844 * running on port <port> at <address> (from portmap daemon)
845 * Returns NULL on failure
846 */
847static char * check_rpc_list (int port, struct sockaddr_in * address, 
848                              unsigned long prot)
849{
[439]850#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
[67]851  struct pmaplist * head;
[218]852  char *r;
[67]853  static char buf[256];
854
855  head = pmap_getmaps(address);
856
857  if (head) 
858    {
859      do /* while (head != NULL) */
860        {
861          if ((head->pml_map.pm_prot == prot) && 
862              (port == (int)head->pml_map.pm_port)) 
863            {
[218]864              r = sh_getrpcbynumber((int)head->pml_map.pm_prog, 
865                                    buf, sizeof(buf));
866              if (r)
[67]867                {
868                  return buf;
869                }
870              else
871                {
872                  snprintf (buf, sizeof(buf), "RPC_%lu",
873                            (unsigned long)head->pml_map.pm_prog);
874                  return buf;
875                }
876            }
877          head = head->pml_next;
878        }
879      while (head != NULL);
880    }
[290]881#else
882  (void) port;
883  (void) address;
884  (void) prot;
885#endif
[67]886  return NULL;
887}
888
[295]889static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]890{
891  int                retval;
[295]892  char             * p = NULL;
[67]893  char               buf[8];
[78]894#ifndef TEST_ONLY
895  char               errmsg[256];
896  int                nerr;
897#endif
[132]898  char errbuf[SH_ERRBUF_SIZE];
[295]899  char ipbuf[SH_IP_BUF];
[67]900
[295]901  sh_ipvx_set_port(paddr, port);
[67]902
[78]903  do {
[295]904    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]905  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]906
[67]907  if (retval == -1)
908    {
909#ifdef TEST_ONLY
910      if (portchk_debug)
911        perror(_("connect"));
912#else
[295]913      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
914
[78]915      nerr = errno;
916      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
[295]917                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]918      SH_MUTEX_LOCK(mutex_thread_nolog);
[78]919      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
920                      errmsg, _("connect"));
[149]921      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]922#endif
923    }
924  else
925    {
[78]926      do {
927        retval = send (fd, buf, 0, 0);
928      } while (retval < 0 && errno == EINTR);
[67]929
930      if (retval == -1 && errno == ECONNREFUSED)
931        {
[295]932          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[67]933          if (portchk_debug)
[380]934            fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
[295]935                    port, ipbuf);
[67]936        }
937      else 
938        {
[78]939          /* Only the second send() may catch the error
940           */
941          do {
942            retval = send (fd, buf, 0, 0);
943          } while (retval < 0 && errno == EINTR);
944
[67]945          if (retval == -1 && errno == ECONNREFUSED)
946            {
[295]947              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[67]948              if (portchk_debug)
949                fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
[295]950                        port, ipbuf);
[67]951            }
952          else if (retval != -1)
953            {
954              /* Try to get service name from portmap
955               */
[295]956              if (paddr->ss_family == AF_INET)
957                {
[380]958                  p = check_rpc_list (port, 
959                                      (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
960                                      IPPROTO_UDP);
[295]961                }
[380]962
[295]963              sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
[67]964             
965              /* If not an RPC service, try to get name from /etc/services
966               */
967              if (!p)
[149]968                p = check_services(port, IPPROTO_UDP);
[67]969             
970              if (portchk_debug)
[295]971                {
972                  sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[380]973                  fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"), 
[295]974                          port, ipbuf, p);
975                }
[67]976             
977            }
978        }
979    }
[252]980  sl_close_fd (FIL__, __LINE__, fd);
[67]981  return 0;
982}
983
[295]984static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
[67]985{
986  int                retval;
[109]987  int                flags;
[295]988  char             * p = NULL;
[78]989#ifndef TEST_ONLY
990  char               errmsg[256];
991  int                nerr;
992#endif
[132]993  char errbuf[SH_ERRBUF_SIZE];
[295]994  char ipbuf[SH_IP_BUF];
[67]995
[295]996  sh_ipvx_set_port(paddr, port);
[67]997
[78]998  do {
[295]999    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
[171]1000  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
[78]1001
[67]1002  if (retval == -1 && errno == ECONNREFUSED)
1003    {
1004      if (portchk_debug)
[295]1005        {
1006          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[468]1007          fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
[295]1008                  port, ipbuf);
1009        }
[67]1010    }
1011  else if (retval == -1)
1012    {
1013#ifdef TEST_ONLY
1014      if (portchk_debug)
1015        perror(_("connect"));
1016#else
[295]1017      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[78]1018      nerr = errno;
1019      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
[295]1020                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
[149]1021      SH_MUTEX_LOCK(mutex_thread_nolog);
[78]1022      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
1023                      errmsg, _("connect"));
[149]1024      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1025#endif
1026    }
1027  else
1028    {
1029      /* Try to get service name from portmap
1030       */
[295]1031      if (paddr->ss_family == AF_INET)
1032        {
[380]1033          p = check_rpc_list (port, 
1034                              (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
1035                              IPPROTO_TCP);
[295]1036        }
[67]1037
[295]1038      sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
[67]1039
1040      /* If not an RPC service, try to get name from /etc/services
1041       */
1042      if (!p)
[149]1043        p = check_services(port, IPPROTO_TCP);
[67]1044
1045      if (portchk_debug)
[295]1046        {
1047          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
[380]1048          fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"), 
[295]1049                  port, ipbuf, p);
1050        }
[109]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);
[170]1066          retval = write (fd, _("SSH-2.0-Foobar"), 14);
1067          if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1073          retval = write (fd, _("QUIT"), 4);
1074          if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1080          retval = write (fd, "\r\n", 2);
[109]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);
[170]1086          retval = write (fd, _("QUIT"), 4);
1087          if (retval > 0) retval = write (fd, "\r\n", 2);
[109]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);
[170]1093          retval = write (fd, _("A01 LOGOUT"), 10);
1094          if (retval > 0) retval = write (fd, "\r\n", 2);
[109]1095        }
[170]1096
1097      if (portchk_debug && retval < 0)
1098        fprintf(stderr, _("check port: error writing to port %5d\n"), 
1099                port);
[67]1100     }
[252]1101  sl_close_fd (FIL__, __LINE__, fd);
[67]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 {
[295]1115  struct sh_sockaddr iface[SH_IFACE_MAX];
[67]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
[149]1128static int sh_portchk_init_internal (void)
[67]1129{
[468]1130  volatile int     i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
[67]1131  char errbuf[256];
[295]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];
[67]1139
1140  if (portchk_debug)
1141    fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
[78]1142
[67]1143  if (!portchk_hostname)
1144    return -1;
1145
[78]1146  if (sh_portchk_active == S_FALSE)
1147    return -1;
1148
[149]1149  SH_MUTEX_LOCK(mutex_port_check);
[67]1150  if (iface_initialized == 0)
1151    {
1152      iface_list.used   = 0;
1153      iface_initialized = 1;
1154    }
[295]1155
1156#if !defined(USE_IPVX)
[134]1157  SH_MUTEX_LOCK(mutex_resolv);
[162]1158  hent = sh_gethostbyname(portchk_hostname);
[170]1159  i = 0;
[67]1160  while (hent && hent->h_addr_list[i] && (iface_list.used < SH_IFACE_MAX))
1161    {
[295]1162      struct sockaddr_in sin;
[468]1163      struct sh_sockaddr iface_tmp;
[295]1164
1165      memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
[468]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
[295]1176      sh_ipvx_save(&(iface_list.iface[iface_list.used]), 
1177                   AF_INET, (struct sockaddr *)&sin);
[380]1178     
1179      if (portchk_debug)
1180        {
1181          char buf[256];
1182          sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used]));
[468]1183          fprintf(stderr, _("added interface[%d]: %s\n"), i, buf); 
[380]1184        }
[134]1185      ++iface_list.used;
[468]1186
1187    next_iface:
[134]1188      ++i;
1189    }
1190  SH_MUTEX_UNLOCK(mutex_resolv);
[295]1191#else
1192  memset(&hints, '\0', sizeof(hints));
1193  hints.ai_family = PF_UNSPEC;
1194  hints.ai_flags  = AI_ADDRCONFIG;
[134]1195
[295]1196  if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1197    {
1198      struct addrinfo *p = res;
[468]1199      struct sh_sockaddr iface_tmp;
[295]1200
1201      while ((p != NULL) && (iface_list.used < SH_IFACE_MAX))
1202        {
[468]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            }
[295]1221          sh_ipvx_save(&(iface_list.iface[iface_list.used]), 
1222                       p->ai_family, p->ai_addr);
[468]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
[295]1231          ++iface_list.used;
[468]1232
1233        next_iface:
[295]1234          p = p->ai_next;
1235        }
1236      freeaddrinfo(res);
1237    } 
1238#endif
1239
[134]1240  for (i = 0; i < iface_list.used; ++i)
1241    {
[295]1242      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list.iface[i]));
[468]1243      sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
[295]1244
[149]1245      SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1246      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1247                      errbuf, _("sh_portchk_init"));
[149]1248      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1249    }
[149]1250  SH_MUTEX_UNLOCK(mutex_port_check);
[67]1251
1252  return 0;
1253}
1254
[149]1255int sh_portchk_init (struct mod_type * arg)
1256{
[210]1257#ifndef HAVE_PTHREAD
1258  (void) arg;
1259#endif
1260
[149]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    }
[335]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    }
[149]1280#endif
1281  return sh_portchk_init_internal();
1282}
1283
1284
1285
[67]1286#if !defined(TEST_ONLY)
[170]1287int sh_portchk_reconf (void)
[67]1288{
[149]1289  SH_MUTEX_LOCK(mutex_port_check);
[78]1290  iface_initialized    = 0;
1291  sh_portchk_active    = 1;
[80]1292  sh_portchk_check_udp = 1;
[149]1293  sh_portchk_interval  = SH_PORTCHK_INTERVAL;
[78]1294
[328]1295  sh_portchk_minport = -1;
1296  sh_portchk_maxport = -1;
1297
[67]1298  portlist_udp = sh_portchk_kill_list (portlist_udp);
1299  portlist_tcp = sh_portchk_kill_list (portlist_tcp);
[149]1300
1301  blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1302  blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
[235]1303  sh_port2proc_finish();
1304
[149]1305  SH_MUTEX_UNLOCK(mutex_port_check);
[67]1306  return 0;
1307}
1308
[170]1309int sh_portchk_cleanup (void)
[67]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
[295]1328static int check_port_generic (int port, int domain, int type, int protocol)
[67]1329{
[170]1330  volatile int     i    =  0;
[67]1331  int              sock = -1;
1332  int              flag =  1; /* non-zero to enable an option */
[295]1333  struct sh_sockaddr   paddr;
[132]1334  char errbuf[SH_ERRBUF_SIZE];
1335
[67]1336  /* Check all interfaces for this host
1337   */
1338  while (i < iface_list.used)
1339    {
[295]1340      memcpy(&paddr, &(iface_list.iface[i]), sizeof(paddr));
[149]1341
[295]1342      if (paddr.ss_family != domain)
[149]1343        {
[295]1344          ++i;
1345          continue;
[149]1346        }
1347
[295]1348      if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
[67]1349        {
[295]1350          ++i; 
1351          continue;
1352        }
1353
1354      if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1355        {
[170]1356          ++i;
[67]1357#ifdef TEST_ONLY
1358          if (portchk_debug)
1359            perror(_("socket"));
1360#else
[334]1361
1362#ifndef EPROTONOSUPPORT
1363#define EPROTONOSUPPORT 0
[170]1364#endif
[334]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
[149]1376          continue;
[67]1377        }
1378      if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1379                      (void *) &flag, sizeof(flag)) < 0 )
1380        {
[170]1381          ++i;
[67]1382#ifdef TEST_ONLY
1383          if (portchk_debug)
1384            perror(_("setsockopt"));
1385#else
[149]1386          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1387          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
[132]1388                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1389          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1390#endif
[149]1391          continue;
[67]1392        }
1393
1394
1395      if (protocol == IPPROTO_TCP)
[295]1396        check_port_tcp_internal(sock, port, &paddr);
[67]1397      else
[295]1398        check_port_udp_internal(sock, port, &paddr);
[67]1399
1400      ++i;
1401    }
1402
1403  return 0;
1404}
1405
1406
1407
[295]1408static int check_port_udp (int port, int domain)
[67]1409{
[295]1410  return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
[67]1411}
1412
[295]1413static int check_port_tcp (int port, int domain)
[67]1414{
[295]1415  return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
[67]1416}
1417
1418
[295]1419static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg, 
1420                                          int domain, int type, int protocol)
[67]1421{
1422  /*
1423  int min_port = 1024;
1424  int max_port = 65535;
1425  */
1426
[170]1427  volatile int port; /*  might be clobbered by ‘longjmp’ or ‘vfork’*/
1428  volatile int max_port = max_port_arg;
[67]1429  int retval;
1430  int sock   = -1;
1431  int flag   = 1; /* non-zero to enable an option */
1432
[295]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
[132]1441  char errbuf[SH_ERRBUF_SIZE];
[67]1442
1443  if (min_port == -1)
1444     min_port = 0;
1445  if (max_port == -1)
1446    max_port = 65535;
1447
[468]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           
[67]1453  for (port = min_port; port <= max_port; ++port) 
1454    {
[295]1455      if ((sock = socket(domain, type, protocol)) < 0 )
[67]1456        {
1457#ifdef TEST_ONLY
1458          if (portchk_debug)
1459            perror(_("socket"));
1460#else
[334]1461#ifndef EPROTONOSUPPORT
1462#define EPROTONOSUPPORT 0
[67]1463#endif
[334]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
[149]1475          continue;
[67]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
[149]1484          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1485          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
[132]1486                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
[149]1487          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1488#endif
[149]1489          continue;
[67]1490        }
1491
[295]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        }
[67]1506
1507      if (retval == 0)
1508        {
1509          /* we can bind the port, thus it is unused
1510           */
[252]1511          sl_close_fd (FIL__, __LINE__, sock);
[67]1512        }
1513      else
1514        {
1515          if (errno == EINVAL || errno == EADDRINUSE)
1516            {
1517              /* try to connect to the port
1518               */
1519              if (protocol == IPPROTO_TCP)
[295]1520                check_port_tcp(port, domain);
[67]1521              else
[295]1522                check_port_udp(port, domain);
[67]1523            }
1524          else
1525            {
1526#ifdef TEST_ONLY
1527              if (portchk_debug)
1528                perror(_("bind"));
1529#else
[149]1530              SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1531              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
[132]1532                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
[149]1533              SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1534#endif
1535            }
[252]1536          sl_close_fd (FIL__, __LINE__, sock);
[67]1537        }
1538    }
1539  return 0;
1540}
1541
1542static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1543{
[295]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);
[67]1550}
1551 
1552static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1553{
[295]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);
[67]1560}
1561
1562/* Subroutine to add an interface
1563 */
[481]1564void * sh_dummy_1564_str    = NULL; /* fix clobbered by.. warning */
[212]1565
[67]1566static int sh_portchk_add_interface (const char * str)
1567{
[295]1568  struct sh_sockaddr saddr;
[67]1569  char errbuf[256];
[212]1570  char buf[64];
[67]1571
[481]1572  sh_dummy_1564_str    = (void*) &str;
[212]1573
[67]1574  if (iface_initialized == 0)
1575    {
1576      iface_list.used   = 0;
1577      iface_initialized = 1;
1578    }
1579
[212]1580  do {
[67]1581
[212]1582    while (*str == ',' || *str == ' ' || *str == '\t') ++str;
[67]1583
[212]1584    if (*str)
1585      {
[295]1586        char ipbuf[SH_IP_BUF];
[212]1587        unsigned int i = 0;
[295]1588        while (*str && i < (sizeof(buf)-1) && 
1589               *str != ',' && *str != ' ' && *str != '\t')
[212]1590          {
1591            buf[i] = *str; ++str; ++i;
1592          }
1593        buf[i] = '\0';
[67]1594
[295]1595        if (0 == sh_ipvx_aton(buf, &saddr))
[212]1596          return -1;
[67]1597
[212]1598        if (iface_list.used == SH_IFACE_MAX)
1599          return -1;
1600
[295]1601        sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1602        sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
[212]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       
[295]1608        memcpy (&(iface_list.iface[iface_list.used]), &(saddr), sizeof(saddr));
[212]1609        ++iface_list.used;
1610      }
1611  } while (*str);
1612
[481]1613  sh_dummy_1564_str = NULL;
[67]1614  return 0;
1615}
1616
[149]1617/* verify whether port/interface is blacklisted (do not check)
1618 */
[295]1619static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr, 
1620                                     int proto)
[149]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        {
[295]1633          if (sh_ipvx_isany(head->paddr) || 
1634              0 == sh_ipvx_cmp(head->paddr, saddr))
[149]1635            return 1;
1636          else
1637            return 0;
1638        }
1639      head = head->next;
1640    }
1641  return 0;
1642}
1643
1644
[295]1645static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
[149]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    {
[295]1659      if (black->port == port && 
1660          0 == sh_ipvx_cmp(head->paddr, saddr))
[149]1661        return -1;
1662      black = black->next;
1663    }
[295]1664
[149]1665  black = SH_ALLOC (sizeof(struct sh_port));
[295]1666  black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
[149]1667  black->port  = port;
[295]1668  memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
[149]1669  black->next  = head;
1670
1671  if (proto == IPPROTO_TCP)
1672    blacklist_tcp = black;
1673  else
1674    blacklist_udp = black;
[468]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    }
[149]1682  return 0;
1683}
1684 
[67]1685 
1686/* Subroutine to add a required or optional port/service
1687 */
[295]1688static int sh_portchk_add_required_port_generic (char * service, 
1689                                                 char * interface, int type)
[67]1690{
[473]1691  char buf[256] = { '\0' };
[149]1692  int proto;
[67]1693  char * p;
1694  char * endptr;
1695  unsigned long int  port;
[295]1696  struct sh_sockaddr   saddr;
[67]1697  struct sh_portentry * portent;
1698
[295]1699  if (0 == sh_ipvx_aton(interface, &saddr))
[67]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")))
[149]1708    proto = IPPROTO_TCP;
1709  else if  (0 == strcmp(p, _("/udp")))
1710    proto = IPPROTO_UDP;
[67]1711  else
1712    return -1;
1713
1714  *p = '\0';
1715  port = strtoul(buf, &endptr, 0);
1716
[468]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
[149]1726  /* Blacklisted ports
1727   */
1728  if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
[295]1729    return (sh_portchk_blacklist(port, &saddr, proto));
[149]1730
[67]1731  if (*endptr != '\0')
1732    { 
[295]1733      portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
[67]1734      if (!portent)
[380]1735        {
1736          if (portchk_debug)
[383]1737            fprintf(stderr, _("add_required_port %d\n"), (int) port);
[380]1738          sh_portchk_add_to_list (proto,   -1, &saddr,  buf, type, SH_PORT_UNKN);
1739        }
[67]1740      else
1741        {
1742#ifdef TEST_ONLY
[149]1743          fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
[67]1744#else
[149]1745          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1746          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1747                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]1748          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]1749#endif
1750          return -1;
1751        }
1752    }
1753  else if (port <= 65535)
1754    {
[295]1755      portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
[67]1756      if (!portent)
[380]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        }
[67]1763      else
1764        {
1765#ifdef TEST_ONLY
[149]1766          fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
[67]1767#else
[149]1768          SH_MUTEX_LOCK(mutex_thread_nolog);
[67]1769          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1770                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
[149]1771          SH_MUTEX_UNLOCK(mutex_thread_nolog);
[67]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;
[149]1787  int    status;
[67]1788
1789  char * interface = NULL;
1790  char * list;
1791  char * p;
[131]1792#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1793  char * saveptr;
1794#endif
[67]1795
1796  if (!str)
1797    return -1;
1798
1799  if (strchr(str, ':'))
1800    {
[468]1801      char *last = strrchr(str, ':');
1802      if (last != NULL)
[67]1803        {
[468]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;
[67]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)
[468]1834    fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
[67]1835
1836  list = sh_util_strdup(&str[ll]);
[131]1837#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1838  p    = strtok_r (list, " ,\t", &saveptr);
1839#else
[67]1840  p    = strtok (list, " ,\t");
[131]1841#endif
[67]1842  if (!p)
1843    {
1844      SH_FREE(interface);
1845      SH_FREE(list);
1846      return -1;
1847    }
1848  while (p)
1849    {
[149]1850      status = sh_portchk_add_required_port_generic (p, interface, type);
1851
1852      if (-1 == status)
[67]1853        {
1854          SH_FREE(interface);
1855          SH_FREE(list);
1856          return -1;
1857        }
[131]1858#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1859      p    = strtok_r (NULL, " ,\t", &saveptr);
1860#else
[67]1861      p    = strtok (NULL, " ,\t");
[131]1862#endif
[67]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
[127]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
[149]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
[67]1897/* Interface to run port check
1898 */
1899int sh_portchk_check ()
1900{
[170]1901  volatile int min_port;
[376]1902  static int noprivports = 0;
[67]1903
[149]1904  SH_MUTEX_LOCK(mutex_port_check);
[170]1905
[328]1906  min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
[170]1907
[78]1908  if (sh_portchk_active != S_FALSE)
[67]1909    {
[405]1910      SH_MUTEX_LOCK(mutex_thread_nolog);
[253]1911      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1912                      _("Checking for open ports"),
1913                      _("sh_portchk_check"));
[405]1914      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[253]1915
[78]1916      sh_portchk_reset_lists();
[328]1917      if ((0 != geteuid()) && (min_port < 1024))
[78]1918        {
1919          min_port = 1024;
[376]1920          if (noprivports == 0)
1921            {
[67]1922#ifdef TEST_ONLY
[376]1923              fprintf(stderr, "** WARNING not scanning ports < 1024\n");
[67]1924#else
[376]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);
[67]1930#endif
[376]1931              noprivports = 1;
1932            }
[78]1933        }
[180]1934
1935      sh_port2proc_prepare();
1936
[78]1937      if (sh_portchk_check_udp == 1)
[328]1938        sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
1939      sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
[180]1940
1941
[149]1942      sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
[78]1943      if (sh_portchk_check_udp == 1)
[149]1944        sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
[180]1945
[67]1946    }
[149]1947  SH_MUTEX_UNLOCK(mutex_port_check);
[67]1948  return 0;
1949}
1950#endif
1951
1952#ifdef SH_CUTEST
1953#include "CuTest.h"
1954
1955void Test_portcheck_lists (CuTest *tc)
1956{
[73]1957#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
[295]1958  struct sh_sockaddr    haddr_local;
[67]1959  struct sh_portentry * portent;
[218]1960  char   buf[256];
1961  char * p;
[67]1962
[290]1963#ifdef HAVE_RPC_RPC_H
[218]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"));
[290]1976#endif
[218]1977
[300]1978  p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
[218]1979  CuAssertTrue(tc, p == NULL);
1980
[290]1981#if !defined(HOST_IS_CYGWIN)
[218]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"));
[290]1986#endif
[218]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
[295]1993  CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
[67]1994
[295]1995  sh_portchk_add_to_list (IPPROTO_TCP,  8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
[67]1996
[295]1997  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
[67]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
[149]2005  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2006
2007  CuAssertTrue(tc, NULL == portlist_tcp);
2008
[295]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);
[67]2019
[149]2020  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
[67]2021
2022  CuAssertPtrNotNull(tc, portlist_tcp);
2023
[295]2024  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
[67]2025  CuAssertPtrNotNull(tc, portent);
2026
[295]2027  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8001, &haddr_local, NULL);
[67]2028  CuAssertTrue(tc, NULL == portent);
2029
[295]2030  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8002, &haddr_local, NULL);
[67]2031  CuAssertPtrNotNull(tc, portent);
2032
[295]2033  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8003, &haddr_local, NULL);
[67]2034  CuAssertTrue(tc, NULL == portent);
2035
[295]2036  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8004, &haddr_local, NULL);
[127]2037  CuAssertPtrNotNull(tc, portent);
2038
[295]2039  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo1");
[67]2040  CuAssertTrue(tc, NULL == portent);
2041
[295]2042  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo2");
[67]2043  CuAssertPtrNotNull(tc, portent);
2044  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2045
[295]2046  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo3");
[67]2047  CuAssertTrue(tc, NULL == portent);
2048
[295]2049  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo4");
[67]2050  CuAssertPtrNotNull(tc, portent);
2051  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
[127]2052
[295]2053  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo5");
[127]2054  CuAssertPtrNotNull(tc, portent);
2055  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
[149]2056
[295]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));
[149]2065
[295]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));
[149]2070
[295]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));
[67]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
[237]2110  /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
[67]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.