source: trunk/src/sh_portcheck.c

Last change on this file was 560, checked in by katerina, 13 months ago

Fix for ticket #449 (gcc 10 compile issues).

  • Property svn:executable set to *
File size: 68.1 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 <stdlib.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#ifdef HAVE_IFADDRS_H
41#include <ifaddrs.h>
42#include <netdb.h>
43#endif
44#include <errno.h>
45#include <unistd.h>
46#include <fcntl.h>
47
48#define PORTCHK_VERSION "1.1"
49
50#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
51
52
53#define PORTMAP
54#ifdef  HAVE_RPC_RPC_H
55#include <rpc/rpc.h>
56#ifdef  HAVE_RPC_RPCENT_H
57#include <rpc/rpcent.h>
58#endif
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61#endif
62#include <netdb.h>
63
64/*
65 * struct pmaplist {
66 *      struct pmap     pml_map;
67 *      struct pmaplist *pml_next;
68 * };
69 */
70
71/* struct pmap {
72 *      long unsigned pm_prog;
73 *      long unsigned pm_vers;
74 *      long unsigned pm_prot;
75 *      long unsigned pm_port;
76 * };
77 */
78
79/* TIME_WAIT ? 60-240 seconds */
80
81#if !defined(TEST_ONLY)
82
83#define FIL__ _("sh_portcheck.c")
84#include "samhain.h"
85#include "sh_error.h"
86#include "sh_mem.h"
87#include "sh_calls.h"
88#include "sh_utils.h"
89#include "sh_modules.h"
90#define SH_NEED_GETHOSTBYXXX
91#include "sh_static.h"
92#include "sh_pthread.h"
93#include "sh_ipvx.h"
94
95/* the size of an interface string
96 */
97#define SH_INTERFACE_SIZE SH_IP_BUF
98
99#define SH_PORT_NOT 0
100#define SH_PORT_REQ 1
101#define SH_PORT_OPT 2
102#define SH_PORT_IGN 3
103#define SH_PORT_BLACKLIST 4
104
105static char * sh_port_type2str (int type)
106{
107  if (type == 0) return _("not");
108  if (type == 1) return _("req");
109  if (type == 2) return _("opt");
110  if (type == 3) return _("ign");
111  if (type == 4) return _("blc");
112  return _("???");
113}
114
115#define SH_PORT_MISS 0
116#define SH_PORT_ISOK 1
117#define SH_PORT_UNKN 2
118
119#define SH_PORT_NOREPT 0
120#define SH_PORT_REPORT 1
121
122#define SH_PROTO_TCP 0
123#define SH_PROTO_UDP 1
124#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
125
126struct sh_portentry {
127  int  port;
128  char interface[SH_INTERFACE_SIZE];
129  char * service;
130  char * error;
131  int  flag;    /* required or not */
132  int  status;  /* missing or not  */
133  struct sh_portentry * next;
134};
135
136static struct sh_portentry * portlist_tcp = NULL;
137static struct sh_portentry * portlist_udp = NULL;
138
139
140#define SH_PORTCHK_INTERVAL 300
141
142static int sh_portchk_check_udp  = 1;
143static int sh_portchk_active     = 1;
144static int sh_portchk_same_ports = 1;
145static int sh_portchk_transients = 1;
146static int sh_portchk_interval   = SH_PORTCHK_INTERVAL;
147
148static int sh_portchk_minport = -1;
149static int sh_portchk_maxport = -1;
150
151struct sh_port {
152  int                  port;
153  struct sh_sockaddr * paddr;
154  struct sh_port     * next;
155};
156
157static struct sh_port * blacklist_tcp = NULL;
158static struct sh_port * blacklist_udp = NULL;
159
160static struct sh_port * transient_tcp = NULL;
161static struct sh_port * transient_udp = NULL;
162
163SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
164
165static int sh_portchk_severity  = SH_ERR_SEVERE;
166
167extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
168                                 unsigned long * pid, char * user, size_t userlen);
169extern int sh_port2proc_prepare();
170extern void sh_port2proc_finish();
171
172#endif
173
174/* Exported interface to add ignoreable ports as 'iface:portlist'
175 */
176static int sh_portchk_add_ignore (const char * str);
177
178/* Exported interface to add required ports as 'iface:portlist'
179 */
180static int sh_portchk_add_required (const char * str);
181
182/* Exported interface to add optional ports as 'iface:portlist'
183 */
184static int sh_portchk_add_optional (const char * str);
185
186/* Exported interface to add blacklisted ports as 'iface:portlist'
187 */
188static int sh_portchk_add_blacklist (const char * str);
189
190/* Exported interface to add an ethernet interface
191 */
192static int sh_portchk_add_interface (const char * str);
193
194#if defined(HAVE_IFADDRS_H)
195/* Exported interface to add an ethernet device
196 */
197static int sh_portchk_add_device (const char * str);
198#endif
199
200/* verify whether port/interface is blacklisted (do not check)
201 */
202static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
203
204/* verify whether port/interface is transient (used as source port hence no check required)
205 */
206static int sh_portchk_is_transient(int port, struct sh_sockaddr * haddr, int proto);
207static int sh_portchk_transient(int port, struct sh_sockaddr * haddr, int proto);
208
209#ifndef TEST_ONLY
210
211static int sh_portchk_set_interval (const char * c)
212{
213  int retval = 0;
214  long val;
215
216  SL_ENTER(_("sh_portchk_set_interval"));
217  val = strtol (c, (char **)NULL, 10);
218  if (val <= 0)
219    {
220      SH_MUTEX_LOCK(mutex_thread_nolog);
221      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
222                       _("port check interval"), c);
223      SH_MUTEX_UNLOCK(mutex_thread_nolog);
224      retval = -1;
225    }
226  else
227    {
228      sh_portchk_interval = (time_t) val;
229    }
230  SL_RETURN(retval, _("sh_portchk_set_interval"));
231}
232
233static int sh_portchk_set_port_minmax (const char * c, int * setthis)
234{
235  int retval = 0;
236  long val;
237
238  SL_ENTER(_("sh_portchk_set_port_minmax"));
239  val = strtol (c, (char **)NULL, 10);
240  if (val < 0 || val > 65535)
241    {
242      SH_MUTEX_LOCK(mutex_thread_nolog);
243      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
244                       _("port check port minmax"), c);
245      SH_MUTEX_UNLOCK(mutex_thread_nolog);
246      retval = -1;
247    }
248  else
249    {
250      *setthis = (int) val;
251    }
252  SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
253}
254
255
256static int sh_portchk_set_minport     (const char * str)
257{
258  return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
259}
260
261static int sh_portchk_set_maxport     (const char * str)
262{
263  return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
264}
265
266static int sh_portchk_set_active     (const char * str)
267{
268  return sh_util_flagval(str, &sh_portchk_active);
269}
270
271static int sh_portchk_set_udp        (const char * str)
272{
273  return sh_util_flagval(str, &sh_portchk_check_udp);
274}
275#if defined(SH_ALLOW_RESTORE)
276static int sh_portchk_set_transients (const char * str)
277{
278  return sh_util_flagval(str, &sh_portchk_transients);
279}
280
281static int sh_portchk_set_same_ports (const char * str)
282{
283  return sh_util_flagval(str, &sh_portchk_same_ports);
284}
285#endif
286static int sh_portchk_set_severity   (const char * str)
287{
288  char tmp[32];
289  tmp[0] = '='; tmp[1] = '\0';
290  sl_strlcat (tmp, str, 32);
291  return sh_error_set_level (tmp, &sh_portchk_severity);
292}
293
294sh_rconf sh_portchk_table[] = {
295    {
296        N_("severityportcheck"),
297        sh_portchk_set_severity,
298    },
299    {
300        N_("portcheckrequired"),
301        sh_portchk_add_required,
302    },
303    {
304        N_("portcheckoptional"),
305        sh_portchk_add_optional,
306    },
307    {
308        N_("portcheckignore"),
309        sh_portchk_add_ignore,
310    },
311    {
312        N_("portcheckskip"),
313        sh_portchk_add_blacklist,
314    },
315    {
316        N_("portcheckactive"),
317        sh_portchk_set_active,
318    },
319#if defined(HAVE_IFADDRS_H)
320    {
321        N_("portcheckdevice"),
322        sh_portchk_add_device,
323    },
324#endif
325    {
326        N_("portcheckinterface"),
327        sh_portchk_add_interface,
328    },
329    {
330        N_("portcheckinterval"),
331        sh_portchk_set_interval,
332    },
333    {
334        N_("portcheckminport"),
335        sh_portchk_set_minport,
336    },
337    {
338        N_("portcheckmaxport"),
339        sh_portchk_set_maxport,
340    },
341    {
342        N_("portcheckudp"),
343        sh_portchk_set_udp,
344    },
345#if defined(SH_ALLOW_RESTORE)
346    {
347        N_("portchecktransients"),
348        sh_portchk_set_transients,
349    },
350    {
351        N_("portchecksameports"),
352        sh_portchk_set_same_ports,
353    },
354#endif
355    {
356        NULL,
357        NULL
358    }
359};
360
361#endif
362
363/* Interface to initialize port check
364 */
365int sh_portchk_init (struct mod_type * arg);
366
367/* Interface to reset port check
368 */
369int sh_portchk_reset (void);
370
371/* Interface to run port check
372 */
373int sh_portchk_check (void);
374
375
376static char * check_services (int port, int proto);
377
378#ifdef TEST_ONLY
379
380static int portchk_debug = 0; 
381#define SH_ALLOC       malloc
382#define SH_FREE        free
383#define sh_util_strdup strdup
384#define sl_strlcpy     strncpy
385#define _(a)           a
386
387#else
388
389static int portchk_debug = 0;
390
391#endif
392
393#ifdef  HAVE_RPC_RPC_H
394static char * sh_getrpcbynumber (int number, char * buf, size_t len)
395{
396  FILE * fp;
397
398  if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
399    {
400      sh_string * s = sh_string_new(0);
401      while (0 < sh_string_read(s, fp, 1024))
402        {
403          char * p = sh_string_str(s);
404          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
405          if (*p == '\0' || *p == '#') 
406            continue; /* skip comment */
407          else
408            {
409              size_t lengths[3];
410              unsigned int  fields = 3;
411              char * q             = sh_string_str(s);
412              char ** splits       = split_array_ws(q, &fields, lengths);
413
414              if (fields >= 2)
415                {
416                  int n = atoi(splits[1]);
417                  if (n == number)
418                    {
419                      sl_strlcpy(buf, splits[0], len);
420                      SH_FREE(splits);
421                      sh_string_destroy(&s);
422                      sl_fclose(FIL__, __LINE__, fp);
423                      return buf;
424                    }
425                }
426              SH_FREE(splits);
427            }
428        }
429      sh_string_destroy(&s);
430      sl_fclose(FIL__, __LINE__, fp);
431    }
432  /* cppcheck-suppress resourceLeak */
433  return NULL;
434}
435#endif
436
437static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
438{
439  FILE * fp;
440  char   proto[8];
441
442  sl_strlcpy(proto, proto_in, sizeof(proto));
443
444  if (NULL != (fp = fopen(_("/etc/services"), "r")))
445    {
446      sh_string * s = sh_string_new(0);
447      while (0 < sh_string_read(s, fp, 1024))
448        {
449          char * p = sh_string_str(s);
450          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
451          if (*p == '\0' || *p == '#')
452            continue; /* skip comment */
453          else
454            {
455              size_t lengths[3];
456              unsigned int  fields = 3;
457              char * q             = sh_string_str(s);
458              char ** splits       = split_array_ws(q, &fields, lengths);
459
460              if (fields >= 2)
461                {
462                  char * end;
463                  long n = strtol(splits[1], &end, 10);
464                  if (n == port && end && (*end == '/' || *end == ','))
465                    {
466                      ++end;
467                      if (0 == strcmp(end, proto))
468                        {
469                          sl_strlcpy(buf, splits[0], len);
470                          SH_FREE(splits);
471                          sh_string_destroy(&s);
472                          sl_fclose(FIL__, __LINE__, fp);
473                          return buf;
474                        }
475                    }
476                }
477              SH_FREE(splits);
478            }
479        }
480      sh_string_destroy(&s);
481      sl_fclose(FIL__, __LINE__, fp);
482    }
483  /* cppcheck-suppress resourceLeak */
484  return NULL;
485}
486
487static void sh_portchk_add_to_list (int proto, 
488                                    int port, struct sh_sockaddr * paddr, 
489                                    char * service,
490                                    int flag, int status)
491{
492  struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
493
494  new->port = port;
495  sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
496  new->status = status;
497  new->flag   = flag;
498
499  new->error  = NULL;
500
501  if (portchk_debug)
502    fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"),
503            port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"),
504            new->interface);
505
506  if (service)
507    new->service = sh_util_strdup (service);
508  else
509    new->service = NULL;
510  if (proto == IPPROTO_TCP)
511    {
512      new->next = portlist_tcp;
513      portlist_tcp = new;
514    }
515  else
516    {
517      new->next = portlist_udp;
518      portlist_udp = new;
519    }
520  return;
521}
522
523/* Reset the list by setting all entries to UNKN.
524 * In the next cycle we will check, and set found ports to ISOK.
525 * Thereafter, we check for entries that are still UNKN.
526 */
527static void sh_portchk_reset_lists (void)
528{
529  struct sh_portentry * portlist;
530
531  portlist = portlist_tcp;
532  while (portlist)
533    {
534      if (portlist->status != SH_PORT_MISS)
535        portlist->status = SH_PORT_UNKN;
536      portlist = portlist->next;
537    }
538  portlist = portlist_udp;
539  while (portlist)
540    {
541      if (portlist->status != SH_PORT_MISS)
542        portlist->status = SH_PORT_UNKN;
543      portlist = portlist->next;
544    }
545  return;
546}
547
548static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
549{
550  if (head)
551    {
552      if (head->next)
553        sh_portchk_kill_list (head->next);
554
555      if (head->service)
556        SH_FREE(head->service);
557      SH_FREE(head);
558    }
559  return NULL;
560}
561 
562static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
563{
564  if (head)
565    {
566      if (head->next)
567        sh_portchk_kill_blacklist (head->next);
568
569      SH_FREE(head->paddr);
570      SH_FREE(head);
571    }
572  return NULL;
573}
574 
575static struct sh_port * sh_portchk_kill_transient (struct sh_port * head)
576{
577  if (head)
578    {
579      if (head->next)
580        sh_portchk_kill_transient (head->next);
581
582      SH_FREE(head->paddr);
583      SH_FREE(head);
584    }
585  return NULL;
586}
587 
588/* These variables are not used anywhere. They only exist
589 * to assign &pre, &ptr to them, which keeps gcc from
590 * putting it into a register, and avoids the 'clobbered
591 * by longjmp' warning. And no, 'volatile' proved insufficient.
592 */
593void * sh_dummy_531_pre = NULL;
594void * sh_dummy_532_ptr = NULL;
595
596/* check the list of open ports for any that are marked as UNKN
597 */
598static void sh_portchk_check_list (struct sh_portentry ** head, 
599                                   int proto, int report)
600{
601  struct sh_portentry * ptr = *head;
602  struct sh_portentry * pre = *head;
603  char errbuf[512];
604
605  /* Take the address to keep gcc from putting them into registers.
606   * Avoids the 'clobbered by longjmp' warning.
607   */
608  sh_dummy_531_pre = (void*) &pre;
609  sh_dummy_532_ptr = (void*) &ptr;
610 
611  while (ptr)
612    {
613      if (portchk_debug && report)
614        fprintf(stderr, _("check list: port %d/%s %d %d\n"),
615                ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
616
617      if (ptr->status == SH_PORT_UNKN)
618        {
619          /* Don't report missing ports that are marked as optional
620           */
621          if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
622            {
623              snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
624                        ptr->interface, ptr->port, SH_PROTO_STR(proto), 
625                        ptr->service ? ptr->service : check_services(ptr->port, proto));
626#ifdef TEST_ONLY
627              if (report == SH_PORT_REPORT)
628                fprintf(stderr, _("%s\n"), errbuf);
629#else
630              if (report == SH_PORT_REPORT)
631                {
632                  SH_MUTEX_LOCK(mutex_thread_nolog);
633                  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
634                                  MSG_PORT_MISS, errbuf);
635                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
636                }
637#endif
638            }
639
640          ptr->status = SH_PORT_MISS;
641
642          if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
643            {
644              if (portchk_debug && report)
645                fprintf(stderr, _("removing: port %d/%s %d %d\n"),
646                        ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
647             
648              if (ptr == *head)
649                {
650                  *head = ptr->next;
651                  if (ptr->service)
652                    SH_FREE(ptr->service);
653                  SH_FREE(ptr);
654                  ptr = *head;
655                  pre = *head;
656                  continue;
657                }
658              else if (ptr->next == NULL)
659                {
660                  pre->next = NULL;
661                  if (ptr->service)
662                    SH_FREE(ptr->service);
663                  SH_FREE(ptr);
664                  return;
665                }
666              else
667                {
668                  pre->next = ptr->next;
669                  if (ptr->service)
670                    SH_FREE(ptr->service);
671                  SH_FREE(ptr);
672                  ptr = pre->next;
673                  continue;
674                }
675            }
676        }
677      pre = ptr;
678      ptr = ptr->next;
679    }
680
681  sh_dummy_532_ptr = NULL;
682  sh_dummy_531_pre = NULL;
683
684  return;
685}
686
687
688static struct sh_portentry * sh_portchk_get_from_list (int proto, int port, 
689                                                       struct sh_sockaddr * paddr, char * service)
690{
691  struct sh_portentry * portlist;
692  char str_addr[SH_IP_BUF];
693
694
695  if (proto == IPPROTO_TCP)
696    portlist = portlist_tcp;
697  else
698    portlist = portlist_udp;
699
700  sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
701
702  if (service)
703    {
704      while (portlist) 
705        {
706          if (portlist->service && 
707              0 == strcmp(service, portlist->service) &&
708              ( 0 == strcmp(portlist->interface, str_addr) ||
709                sh_ipvx_isany(paddr) ))
710            return portlist;
711          portlist = portlist->next;
712        }
713    }
714  else
715    {
716      while (portlist) 
717        {
718          if (port == portlist->port &&
719              (0 == strcmp(portlist->interface, str_addr)  ||
720               sh_ipvx_isany(paddr) ))
721            return portlist;
722          portlist = portlist->next;
723        }
724    }
725  return NULL;
726}
727     
728
729static void sh_portchk_cmp_to_list (int proto, int port, 
730                                    struct sh_sockaddr * paddr, char * service)
731{
732  struct sh_portentry * portent;
733  char errbuf[512];
734
735 
736  portent = sh_portchk_get_from_list (proto, port, paddr, service);
737
738  if (service)
739    {
740      if (!portent)
741        {
742          char * path;
743          unsigned long qpid;
744          char   user[USER_MAX];
745          char   saddr[SH_IP_BUF];
746
747          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
748
749          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
750                    saddr, port, SH_PROTO_STR(proto), service);
751
752          if (portchk_debug)
753            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"), 
754                    saddr, port, SH_PROTO_STR(proto), service);
755
756#ifndef TEST_ONLY
757          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
758          SH_MUTEX_LOCK(mutex_thread_nolog);
759          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
760                          MSG_PORT_NEW, errbuf, path, qpid, user);
761          SH_MUTEX_UNLOCK(mutex_thread_nolog);
762          SH_FREE(path);
763#endif
764          /*
765           * was not there, thus it is not in 'required' or 'optional' list
766           */
767          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
768        }
769      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
770        {
771          char * path;
772          unsigned long qpid;
773          char   user[USER_MAX];
774          char   saddr[SH_IP_BUF];
775
776          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
777
778          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
779                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
780#ifdef TEST_ONLY
781          fprintf(stderr, _("service: %s\n"), errbuf);
782#else
783          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
784          SH_MUTEX_LOCK(mutex_thread_nolog);
785          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
786                          MSG_PORT_RESTART, errbuf, path, qpid, user);
787          SH_MUTEX_UNLOCK(mutex_thread_nolog);
788          SH_FREE(path);
789#endif
790
791          portent->status = SH_PORT_ISOK;
792        }
793      else if (port != portent->port && (-1) != portent->port)
794        {
795          char * path;
796          unsigned long qpid;
797          char   user[USER_MAX];
798          char   saddr[SH_IP_BUF];
799
800          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
801
802          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
803                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
804#ifdef TEST_ONLY
805          fprintf(stderr, _("service: %s\n"), errbuf);
806#else
807          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
808          SH_MUTEX_LOCK(mutex_thread_nolog);
809          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
810                          MSG_PORT_NEWPORT, errbuf, path, qpid, user);
811          SH_MUTEX_UNLOCK(mutex_thread_nolog);
812          SH_FREE(path);
813#endif
814          portent->port   = port;
815          portent->status = SH_PORT_ISOK;
816        }
817      else
818        {
819          portent->status = SH_PORT_ISOK;
820        }
821    }
822  else
823    {
824      if (!portent)
825        {
826          char * path;
827          unsigned long qpid;
828          char   user[USER_MAX];
829          char   saddr[SH_IP_BUF];
830
831          if (portchk_debug)
832            fprintf(stderr, _("call to  sh_ipvx_ntoa (port %d)\n"), port);
833 
834          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
835
836          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
837                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
838
839          if (portchk_debug)
840            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"), 
841                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
842
843#ifndef TEST_ONLY
844          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
845          SH_MUTEX_LOCK(mutex_thread_nolog);
846          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
847                          MSG_PORT_NEW, errbuf, path, qpid, user);
848          SH_MUTEX_UNLOCK(mutex_thread_nolog);
849          SH_FREE(path);
850#endif
851
852          /* was not there, thus it is not in 'required' or 'optional' list
853           */
854          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
855        }
856      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
857        {
858          char * path;
859          unsigned long qpid;
860          char   user[USER_MAX];
861          char   saddr[SH_IP_BUF];
862
863          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
864
865          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
866                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
867#ifdef TEST_ONLY
868          fprintf(stderr, _("port   : %s\n"), errbuf);
869#else
870          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
871          SH_MUTEX_LOCK(mutex_thread_nolog);
872          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
873                          MSG_PORT_RESTART, errbuf, path, qpid, user);
874          SH_MUTEX_UNLOCK(mutex_thread_nolog);
875          SH_FREE(path);
876#endif
877
878          portent->status = SH_PORT_ISOK;
879        }
880      else
881        {
882          portent->status = SH_PORT_ISOK;
883        }
884    }
885
886  return;
887}
888
889                               
890/* Returns a static buffer containing the name of the service
891 * running on port <port> (from /etc/services)
892 * Returns NULL on failure
893 */
894static char * check_services (int port, int proto)
895{
896  static char buf[256];
897  char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
898
899  if (!service)
900    {
901      snprintf (buf, sizeof(buf), "%s",_("unknown"));
902    }
903  return buf;
904}
905
906/* Returns a static buffer containing the name of the service
907 * running on port <port> at <address> (from portmap daemon)
908 * Returns NULL on failure
909 */
910static char * check_rpc_list (int port, struct sockaddr_in * address, 
911                              unsigned long prot)
912{
913#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
914  struct pmaplist * head;
915  char *r;
916  static char buf[256];
917
918  head = pmap_getmaps(address);
919
920  if (head) 
921    {
922      do /* while (head != NULL) */
923        {
924          if ((head->pml_map.pm_prot == prot) && 
925              (port == (int)head->pml_map.pm_port)) 
926            {
927              r = sh_getrpcbynumber((int)head->pml_map.pm_prog, 
928                                    buf, sizeof(buf));
929              if (r)
930                {
931                  return buf;
932                }
933              else
934                {
935                  snprintf (buf, sizeof(buf), "RPC_%lu",
936                            (unsigned long)head->pml_map.pm_prog);
937                  return buf;
938                }
939            }
940          head = head->pml_next;
941        }
942      while (head != NULL);
943    }
944#else
945  (void) port;
946  (void) address;
947  (void) prot;
948#endif
949  return NULL;
950}
951
952void * sh_dummy_950_p = NULL;
953void * sh_dummy_951_p = NULL;
954
955static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
956{
957  int                retval;
958  char             * p = NULL;
959  char               buf[8];
960#ifndef TEST_ONLY
961  char               errmsg[256];
962  volatile int       nerr;
963#endif
964  char errbuf[SH_ERRBUF_SIZE];
965  char ipbuf[SH_IP_BUF];
966
967  struct sh_sockaddr    saddr;
968  socklen_t             slen  = 0;
969  volatile int          sport = 0;
970
971  sh_dummy_950_p = (void*) &p;
972 
973  sh_ipvx_set_port(paddr, port);
974
975  do {
976    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
977  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
978
979  if (retval == -1)
980    {
981#ifdef TEST_ONLY
982      if (portchk_debug)
983        perror(_("connect"));
984#else
985      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
986
987      nerr = errno;
988      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
989                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
990      SH_MUTEX_LOCK(mutex_thread_nolog);
991      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
992                      errmsg, _("connect"));
993      SH_MUTEX_UNLOCK(mutex_thread_nolog);
994#endif
995    }
996  else
997    {
998      /* Register the used source port as transient. This will avoid
999       * the issue of lingering source ports being reported as a spurious
1000       * service. The lingering source port is effectvely a race condition.
1001       *
1002       * Also use this code to obtain the source port. Sometimes Samhain
1003       * reports on a port where it connects back to itself. In that case
1004       * source and destination port are the same.
1005       *
1006       * AGH, 23 Apr 2017 (www.2024sight.com).
1007       */
1008
1009#if defined(USE_IPVX)
1010      if (paddr->ss_family == AF_INET)
1011        {
1012          saddr.ss_family = AF_INET;
1013          slen = sizeof( struct sockaddr_in );
1014          retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1015        }
1016      else
1017        {
1018          saddr.ss_family = AF_INET6;
1019          slen = sizeof( struct sockaddr_in6 );
1020          retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1021        }
1022#else
1023      saddr.ss_family = AF_INET;
1024      slen = sizeof( struct sockaddr_in );
1025      retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1026#endif
1027
1028      if ( retval == 0 )
1029        {
1030          sport = sh_ipvx_get_port(&saddr);
1031          sh_portchk_transient(sport, &saddr, IPPROTO_UDP);
1032        }
1033      else
1034        {
1035#ifdef TEST_ONLY
1036          if (portchk_debug)
1037            perror(_("getsockname"));
1038#else
1039            sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1040            nerr = errno;
1041            sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/udp: %s"),
1042                            ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1043            SH_MUTEX_LOCK(mutex_thread_nolog);
1044            sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("getsockname"));
1045            SH_MUTEX_UNLOCK(mutex_thread_nolog);
1046#endif
1047        }
1048
1049      if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1050        {
1051          do {
1052            retval = send (fd, buf, 0, 0);
1053          } while (retval < 0 && errno == EINTR);
1054
1055          if (retval == -1 && errno == ECONNREFUSED)
1056            {
1057              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1058              if (portchk_debug)
1059                fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
1060                        port, ipbuf);
1061            }
1062          else 
1063            {
1064              /* Only the second send() may catch the error
1065               */
1066              do {
1067                retval = send (fd, buf, 0, 0);
1068              } while (retval < 0 && errno == EINTR);
1069
1070              if (retval == -1 && errno == ECONNREFUSED)
1071                {
1072                  sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1073                  if (portchk_debug)
1074                    fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
1075                            port, ipbuf);
1076                }
1077              else if (retval != -1)
1078                {
1079                  /* Try to get service name from portmap
1080                   */
1081                  if (paddr->ss_family == AF_INET)
1082                    {
1083                      p = check_rpc_list (port, 
1084                                          (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
1085                                          IPPROTO_UDP);
1086                    }
1087
1088                  sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
1089             
1090                  /* If not an RPC service, try to get name from /etc/services
1091                   */
1092                  if (!p)
1093                    p = check_services(port, IPPROTO_UDP);
1094             
1095                  if (portchk_debug)
1096                    {
1097                      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1098                      fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"), 
1099                              port, ipbuf, p);
1100                    }
1101             
1102                }
1103              else
1104                {
1105                  if (portchk_debug)
1106                    {
1107                      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1108                      fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"), 
1109                              port, ipbuf, errno);
1110                    }
1111                }
1112            }
1113        }
1114      else
1115        {
1116          if (portchk_debug)
1117            {
1118              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1119              fprintf(stderr, _("check port_udp: %5d/udp on %15s same source and destination port\n"), 
1120                      port, ipbuf);
1121            }
1122        }
1123    }
1124  sl_close_fd (FIL__, __LINE__, fd);
1125  sh_dummy_950_p = NULL; 
1126  return 0;
1127}
1128
1129static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
1130{
1131  volatile int       retval;
1132  int                flags;
1133  char             * p = NULL;
1134#ifndef TEST_ONLY
1135  char               errmsg[256];
1136  volatile int       nerr;
1137#endif
1138  char errbuf[SH_ERRBUF_SIZE];
1139  char ipbuf[SH_IP_BUF];
1140
1141  struct sh_sockaddr    saddr;
1142  socklen_t             slen  = 0;
1143  volatile int          sport = 0;
1144
1145  sh_dummy_951_p = (void*) &p;
1146
1147  sh_ipvx_set_port(paddr, port);
1148
1149  do {
1150    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
1151  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
1152
1153  if (retval == -1 && errno == ECONNREFUSED)
1154    {
1155      if (portchk_debug)
1156        {
1157          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1158          fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
1159                  port, ipbuf);
1160        }
1161    }
1162  else if (retval == -1)
1163    {
1164#ifdef TEST_ONLY
1165      if (portchk_debug)
1166        perror(_("connect"));
1167#else
1168      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1169      nerr = errno;
1170      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
1171                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
1172      SH_MUTEX_LOCK(mutex_thread_nolog);
1173      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
1174                      errmsg, _("connect"));
1175      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1176#endif
1177    }
1178  else
1179    {
1180      /* Register the used source port as transient. This will avoid
1181       * the issue of lingering source ports being reported as a spurious
1182       * service. The lingering source port is effectively a race condition.
1183       *
1184       * Also use this code to obtain the source port. Sometimes Samhain
1185       * reports on a port where it connects back to itself. In that case
1186       * source and destination port are the same.
1187       *
1188       * AGH, 23 Apr 2017 (www.2024sight.com).
1189       */
1190
1191#if defined(USE_IPVX)
1192      if (paddr->ss_family == AF_INET)
1193        {
1194          saddr.ss_family = AF_INET;
1195          slen = sizeof( struct sockaddr_in );
1196          retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1197        }
1198      else
1199        {
1200          saddr.ss_family = AF_INET6;
1201          slen = sizeof( struct sockaddr_in6 );
1202          retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
1203        }
1204#else
1205      saddr.ss_family = AF_INET;
1206      slen = sizeof( struct sockaddr_in );
1207      retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
1208#endif
1209
1210      if ( retval == 0 )
1211        {
1212          sport = sh_ipvx_get_port(&saddr);
1213          sh_portchk_transient(sport, &saddr, IPPROTO_TCP);
1214        }
1215      else
1216        {
1217#ifdef TEST_ONLY
1218          if (portchk_debug)
1219            perror(_("getsockname"));
1220#else
1221            sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1222            nerr = errno;
1223            sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/tcp: %s"),
1224                        ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
1225            SH_MUTEX_LOCK(mutex_thread_nolog);
1226            sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
1227                            errmsg, _("getsockname"));
1228            SH_MUTEX_UNLOCK(mutex_thread_nolog);
1229#endif
1230        }
1231
1232      if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
1233        {
1234          /* Try to get service name from portmap
1235           */
1236          if (paddr->ss_family == AF_INET)
1237            {
1238              p = check_rpc_list (port, 
1239                                  (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
1240                                  IPPROTO_TCP);
1241            }
1242
1243          sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
1244
1245          /* If not an RPC service, try to get name from /etc/services
1246           */
1247          if (!p)
1248            p = check_services(port, IPPROTO_TCP);
1249
1250          if (portchk_debug)
1251            {
1252              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1253              fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"), 
1254                      port, ipbuf, p);
1255            }
1256        }
1257      else
1258        {
1259          if (portchk_debug)
1260            {
1261              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1262              fprintf(stderr, _("check port_udp: %5d/tcp on %15s same source and destination port\n"), 
1263                      port, ipbuf);
1264            }
1265        }
1266
1267#if !defined(O_NONBLOCK)
1268#if defined(O_NDELAY)
1269#define O_NONBLOCK  O_NDELAY
1270#else
1271#define O_NONBLOCK  0
1272#endif
1273#endif
1274
1275      /* prepare to close connection gracefully
1276       */
1277      if      (port == 22)  /* ssh */
1278        {
1279          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1280          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1281          retval = write (fd, _("SSH-2.0-Foobar"), 14);
1282          if (retval > 0) retval = write (fd, "\r\n", 2);
1283        }
1284      else if (port == 25)  /* smtp */
1285        {
1286          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1287          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1288          retval = write (fd, _("QUIT"), 4);
1289          if (retval > 0) retval = write (fd, "\r\n", 2);
1290        }
1291      else if (port == 79)  /* finger */
1292        {
1293          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1294          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1295          retval = write (fd, "\r\n", 2);
1296        }
1297      else if (port == 110) /* pop3 */
1298        {
1299          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1300          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1301          retval = write (fd, _("QUIT"), 4);
1302          if (retval > 0) retval = write (fd, "\r\n", 2);
1303        }
1304      else if (port == 143) /* imap */
1305        {
1306          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1307          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1308          retval = write (fd, _("A01 LOGOUT"), 10);
1309          if (retval > 0) retval = write (fd, "\r\n", 2);
1310        }
1311
1312      if (portchk_debug && retval < 0)
1313        fprintf(stderr, _("check port: error writing to port %5d\n"), 
1314                port);
1315     }
1316  sl_close_fd (FIL__, __LINE__, fd);
1317  sh_dummy_951_p = NULL;
1318  return 0;
1319}
1320
1321/* typedef uint32_t in_addr_t;
1322 * struct in_addr
1323 * {
1324 * in_addr_t s_addr;
1325 * };
1326 */
1327
1328#define SH_IFACE_MAX 64
1329#define SH_IFACE_ADDR 0
1330#define SH_IFACE_DEV  1
1331
1332struct portchk_interfaces {
1333  struct sh_sockaddr iface;
1334  int            type;
1335};
1336
1337static struct portchk_interfaces iface_list[SH_IFACE_MAX];
1338static int iface_list_used   = 0;
1339static int iface_initialized = 0;
1340
1341#ifdef TEST_ONLY
1342static char * portchk_hostname = NULL;
1343#else
1344static char * portchk_hostname = sh.host.name;
1345#endif
1346
1347static int sh_portchk_init_internal (void)
1348{
1349  volatile int     i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1350  char errbuf[256];
1351#if defined(USE_IPVX)
1352  struct addrinfo hints;
1353  struct addrinfo *res;
1354#else
1355  struct hostent * hent;
1356#endif
1357  char ipbuf[SH_IP_BUF];
1358
1359  if (portchk_debug)
1360    fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
1361
1362  if (!portchk_hostname)
1363    return -1;
1364
1365  if (sh_portchk_active == S_FALSE)
1366    return -1;
1367
1368  SH_MUTEX_LOCK(mutex_port_check);
1369  if (iface_initialized == 0)
1370    {
1371      iface_list_used   = 0;
1372      iface_initialized = 1;
1373    }
1374
1375#if !defined(USE_IPVX)
1376  SH_MUTEX_LOCK(mutex_resolv);
1377  hent = sh_gethostbyname(portchk_hostname);
1378  i = 0;
1379  while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
1380    {
1381      struct sockaddr_in sin;
1382      struct sh_sockaddr iface_tmp;
1383
1384      memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
1385      sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1386
1387      for (j = 0; j < iface_list_used; ++j)
1388        {
1389          if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1390            {
1391              goto next_iface;
1392            }
1393        }
1394
1395      sh_ipvx_save(&(iface_list[iface_list_used].iface), 
1396                   AF_INET, (struct sockaddr *)&sin);
1397      iface_list[iface_list_used].type = SH_IFACE_ADDR;
1398     
1399      if (portchk_debug)
1400        {
1401          char buf[256];
1402          sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1403          fprintf(stderr, _("added interface[%d]: %s\n"), i, buf); 
1404        }
1405      ++iface_list_used;
1406
1407    next_iface:
1408      ++i;
1409    }
1410  SH_MUTEX_UNLOCK(mutex_resolv);
1411#else
1412  memset(&hints, 0, sizeof(hints));
1413  hints.ai_family = PF_UNSPEC;
1414  hints.ai_flags  = AI_ADDRCONFIG;
1415
1416  if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1417    {
1418      struct addrinfo *p = res;
1419      struct sh_sockaddr iface_tmp;
1420
1421      while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
1422        {
1423          sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1424
1425          for (j = 0; j < iface_list_used; ++j)
1426            {
1427              if (portchk_debug)
1428                {
1429                  char buf1[256], buf2[256];
1430                  sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
1431                  sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1432                  fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2); 
1433                }
1434              if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
1435                {
1436                  if (portchk_debug) 
1437                    fprintf(stderr, _("skipping interface[%d]\n"), j);
1438                  goto next_iface;
1439                }
1440            }
1441          sh_ipvx_save(&(iface_list[iface_list_used].iface), 
1442                       p->ai_family, p->ai_addr);
1443          iface_list[iface_list_used].type = SH_IFACE_ADDR;
1444          if (portchk_debug)
1445            {
1446              char buf[256];
1447              sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
1448              fprintf(stderr, _("added interface[%d]: %s\n"), iface_list_used, buf); 
1449            }
1450
1451          ++iface_list_used;
1452
1453        next_iface:
1454          p = p->ai_next;
1455        }
1456      freeaddrinfo(res);
1457    } 
1458#endif
1459
1460  for (i = 0; i < iface_list_used; ++i)
1461    {
1462      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
1463      sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
1464
1465      SH_MUTEX_LOCK(mutex_thread_nolog);
1466      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1467                      errbuf, _("sh_portchk_init"));
1468      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1469    }
1470  SH_MUTEX_UNLOCK(mutex_port_check);
1471
1472  return 0;
1473}
1474
1475int sh_portchk_init (struct mod_type * arg)
1476{
1477#ifndef HAVE_PTHREAD
1478  (void) arg;
1479#endif
1480
1481  if (sh_portchk_active == S_FALSE)
1482    return SH_MOD_FAILED;
1483  if (!portchk_hostname)
1484    return SH_MOD_FAILED;
1485
1486#ifdef HAVE_PTHREAD
1487  if (arg != NULL && arg->initval < 0 &&
1488      (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1489    {
1490      if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1491        return SH_MOD_THREAD;
1492      else
1493        return SH_MOD_FAILED;
1494    }
1495  else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1496           (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1497    {
1498      (void) sh_portchk_init_internal();
1499      return SH_MOD_THREAD;
1500    }
1501#endif
1502  return sh_portchk_init_internal();
1503}
1504
1505static void dev_list_kill();
1506
1507#if !defined(TEST_ONLY)
1508int sh_portchk_reconf (void)
1509{
1510  SH_MUTEX_LOCK(mutex_port_check);
1511  iface_initialized    = 0;
1512  sh_portchk_active    = 1;
1513  sh_portchk_check_udp = 1;
1514  sh_portchk_interval  = SH_PORTCHK_INTERVAL;
1515
1516  sh_portchk_minport = -1;
1517  sh_portchk_maxport = -1;
1518
1519  dev_list_kill();
1520 
1521  portlist_udp = sh_portchk_kill_list (portlist_udp);
1522  portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1523
1524  blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1525  blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
1526  sh_port2proc_finish();
1527
1528  SH_MUTEX_UNLOCK(mutex_port_check);
1529  return 0;
1530}
1531
1532int sh_portchk_cleanup (void)
1533{
1534  return sh_portchk_reconf ();
1535}
1536
1537int sh_portchk_timer (time_t tcurrent) 
1538{
1539  static time_t lastcheck = 0;
1540
1541  SL_ENTER(_("sh_portchk_timer"));
1542  if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
1543    {
1544      lastcheck  = tcurrent;
1545      SL_RETURN((-1), _("sh_portchk_timer"));
1546    }
1547  SL_RETURN(0, _("sh_portchk_timer"));
1548}
1549#endif
1550
1551static int check_port_generic (int port, int domain, int type, int protocol)
1552{
1553  volatile int     i    =  0;
1554  int              sock = -1;
1555  int              flag =  1; /* non-zero to enable an option */
1556  struct sh_sockaddr   paddr;
1557  char errbuf[SH_ERRBUF_SIZE];
1558
1559  /* Check all interfaces for this host
1560   */
1561  while (i < iface_list_used)
1562    {
1563      memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
1564
1565      if (paddr.ss_family != domain)
1566        {
1567          ++i;
1568          continue;
1569        }
1570
1571      if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
1572        {
1573          ++i; 
1574          continue;
1575        }
1576
1577      if (0 != sh_portchk_is_transient(port, &paddr, protocol))
1578        {
1579          ++i; 
1580          continue;
1581        }
1582
1583      if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1584        {
1585          ++i;
1586#ifdef TEST_ONLY
1587          if (portchk_debug)
1588            perror(_("socket"));
1589#else
1590
1591#ifndef EPROTONOSUPPORT
1592#define EPROTONOSUPPORT 0
1593#endif
1594#ifndef EAFNOSUPPORT
1595#define EAFNOSUPPORT    0
1596#endif
1597          if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1598            {
1599              SH_MUTEX_LOCK(mutex_thread_nolog);
1600              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1601                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1602              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1603            }
1604#endif
1605          continue;
1606        }
1607      if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1608                      (void *) &flag, sizeof(flag)) < 0 )
1609        {
1610          ++i;
1611#ifdef TEST_ONLY
1612          if (portchk_debug)
1613            perror(_("setsockopt"));
1614#else
1615          SH_MUTEX_LOCK(mutex_thread_nolog);
1616          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1617                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1618          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1619#endif
1620          continue;
1621        }
1622
1623
1624      if (protocol == IPPROTO_TCP)
1625        check_port_tcp_internal(sock, port, &paddr);
1626      else
1627        check_port_udp_internal(sock, port, &paddr);
1628
1629      ++i;
1630    }
1631
1632  return 0;
1633}
1634
1635
1636
1637static int check_port_udp (int port, int domain)
1638{
1639  return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
1640}
1641
1642static int check_port_tcp (int port, int domain)
1643{
1644  return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
1645}
1646
1647
1648static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg, 
1649                                          int domain, int type, int protocol)
1650{
1651  /*
1652  int min_port = 1024;
1653  int max_port = 65535;
1654  */
1655
1656  volatile int port; /*  might be clobbered by ‘longjmp’ or ‘vfork’*/
1657  volatile int max_port = max_port_arg;
1658  int retval;
1659  int sock   = -1;
1660#if 0
1661  int flag   = 1; /* non-zero to enable an option */
1662#endif
1663  struct sockaddr_in  addr4;
1664  struct sockaddr_in6 addr6;
1665
1666  int addrlen4      = sizeof(addr4);
1667  int addrlen6      = sizeof(addr6);
1668
1669  struct in6_addr anyaddr = IN6ADDR_ANY_INIT; 
1670
1671  char errbuf[SH_ERRBUF_SIZE];
1672
1673  if (min_port == -1)
1674     min_port = 0;
1675  if (max_port == -1)
1676    max_port = 65535;
1677
1678  if (portchk_debug)
1679    fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"), 
1680            min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"),
1681            (protocol == IPPROTO_TCP) ? _("tcp") : _("udp"));
1682           
1683  for (port = min_port; port <= max_port; ++port) 
1684    {
1685      if ((sock = socket(domain, type, protocol)) < 0 )
1686        {
1687#ifdef TEST_ONLY
1688          if (portchk_debug)
1689            perror(_("socket"));
1690#else
1691#ifndef EPROTONOSUPPORT
1692#define EPROTONOSUPPORT 0
1693#endif
1694#ifndef EAFNOSUPPORT
1695#define EAFNOSUPPORT    0
1696#endif
1697          if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1698            {
1699              SH_MUTEX_LOCK(mutex_thread_nolog);
1700              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1701                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1702              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1703            }
1704#endif
1705          continue;
1706        }
1707
1708#if 0
1709      if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1710                      (void *) &flag, sizeof(flag)) < 0 )
1711        {
1712#ifdef TEST_ONLY
1713          if (portchk_debug)
1714            perror(_("setsockopt"));
1715#else
1716          SH_MUTEX_LOCK(mutex_thread_nolog);
1717          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1718                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1719          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1720#endif
1721          continue;
1722        }
1723#endif
1724
1725      if (domain == AF_INET)
1726        {
1727          addr4.sin_family      = AF_INET;
1728          addr4.sin_port        = htons(port);
1729          addr4.sin_addr.s_addr = INADDR_ANY;
1730          retval = bind (sock, (struct sockaddr *) &addr4, addrlen4);
1731        }
1732      else
1733        {
1734          addr6.sin6_family       = AF_INET6;
1735          addr6.sin6_port         = htons(port);
1736          memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr));
1737          retval = bind (sock, (struct sockaddr *) &addr6, addrlen6);
1738        }
1739
1740      if (retval == 0)
1741        {
1742          /* we can bind the port, thus it is unused
1743           */
1744          sl_close_fd (FIL__, __LINE__, sock);
1745        }
1746      else
1747        {
1748          if (errno == EINVAL || errno == EADDRINUSE)
1749            {
1750              /* try to connect to the port
1751               */
1752              if (protocol == IPPROTO_TCP)
1753                check_port_tcp(port, domain);
1754              else
1755                check_port_udp(port, domain);
1756            }
1757          else
1758            {
1759#ifdef TEST_ONLY
1760              if (portchk_debug)
1761                perror(_("bind"));
1762#else
1763              SH_MUTEX_LOCK(mutex_thread_nolog);
1764              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1765                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1766              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1767#endif
1768            }
1769          sl_close_fd (FIL__, __LINE__, sock);
1770        }
1771    }
1772
1773  if (protocol == IPPROTO_TCP)
1774    transient_tcp=sh_portchk_kill_transient(transient_tcp);
1775  else
1776    transient_udp=sh_portchk_kill_transient(transient_udp);
1777 
1778  return 0;
1779}
1780
1781static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1782{
1783#if defined(USE_IPVX)
1784  sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, 
1785                                 SOCK_STREAM, IPPROTO_TCP);
1786#endif
1787  return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET, 
1788                                        SOCK_STREAM, IPPROTO_TCP);
1789}
1790 
1791static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1792{
1793#if defined(USE_IPVX)
1794  sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, 
1795                                 SOCK_DGRAM, IPPROTO_UDP);
1796#endif
1797  return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1798                                        SOCK_DGRAM, IPPROTO_UDP);
1799}
1800
1801/* Subroutine to add an interface
1802 */
1803void * sh_dummy_1564_str    = NULL; /* fix clobbered by.. warning */
1804
1805static int sh_portchk_add_interface_int (const char * str, int type)
1806{
1807  struct sh_sockaddr saddr;
1808  char errbuf[256];
1809  char buf[64];
1810
1811  sh_dummy_1564_str    = (void*) &str;
1812
1813  if (iface_initialized == 0)
1814    {
1815      iface_list_used   = 0;
1816      iface_initialized = 1;
1817    }
1818
1819  do {
1820
1821    while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1822
1823    if (*str)
1824      {
1825        char ipbuf[SH_IP_BUF];
1826        unsigned int i = 0;
1827        while (*str && i < (sizeof(buf)-1) && 
1828               *str != ',' && *str != ' ' && *str != '\t')
1829          {
1830            buf[i] = *str; ++str; ++i;
1831          }
1832        buf[i] = '\0';
1833
1834        if (0 == sh_ipvx_aton(buf, &saddr))
1835          return -1;
1836
1837        if (iface_list_used == SH_IFACE_MAX)
1838          return -1;
1839
1840        sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1841        sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
1842        SH_MUTEX_LOCK(mutex_thread_nolog);
1843        sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1844                        errbuf, _("sh_portchk_add_interface"));
1845        SH_MUTEX_UNLOCK(mutex_thread_nolog);
1846       
1847        memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
1848        iface_list[iface_list_used].type = type;
1849        ++iface_list_used;
1850      }
1851  } while (*str);
1852
1853  sh_dummy_1564_str = NULL;
1854  return 0;
1855}
1856
1857static int sh_portchk_add_interface (const char * str)
1858{
1859  return sh_portchk_add_interface_int (str, SH_IFACE_ADDR);
1860}
1861
1862#if defined(HAVE_IFADDRS_H)
1863/*
1864 * subroutines to add a device
1865 */
1866void * sh_dummy_1651_ifa    = NULL; /* fix clobbered by.. warning */
1867
1868static int portchk_add_device_int (const char * buf)
1869{
1870  struct ifaddrs *ifaddr, *ifa;
1871  int family;
1872#ifndef NI_MAXHOST
1873#define NI_MAXHOST 1025
1874#endif
1875  char host[NI_MAXHOST];
1876
1877  sh_dummy_1651_ifa = (void*) &ifa;
1878 
1879  if (getifaddrs(&ifaddr) == -1)
1880    {
1881      volatile int nerr = errno;
1882      char errbuf[SH_ERRBUF_SIZE];
1883      sh_error_message(errno, errbuf, sizeof(errbuf));
1884      SH_MUTEX_LOCK(mutex_thread_nolog);
1885      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
1886                      errbuf, _("getifaddrs"));
1887      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1888      return -1;
1889    }
1890
1891  for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1892    {
1893      if (ifa->ifa_addr == NULL)
1894        continue;
1895     
1896      if (strcmp(ifa->ifa_name, buf) == 0)
1897        {
1898          volatile int s = 0;
1899          family = ifa->ifa_addr->sa_family;
1900         
1901          if (family == AF_INET)
1902            {
1903              s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in),
1904                               host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1905             
1906              if (s == 0)
1907                {
1908                  if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1909                    {
1910                      freeifaddrs(ifaddr);
1911                      return -1;
1912                    }
1913                }
1914            }
1915         
1916#if defined(USE_IPVX)
1917          if (family == AF_INET6)
1918            {
1919              s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in6),
1920                               host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
1921             
1922              if (s == 0)
1923                {
1924                  if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
1925                    {
1926                      freeifaddrs(ifaddr);
1927                      return -1;
1928                    }
1929                }
1930            }
1931#endif
1932         
1933          if (s != 0)
1934            {
1935              char errbuf[SH_ERRBUF_SIZE];
1936              sl_strlcpy(errbuf, buf,             sizeof(errbuf));
1937              sl_strlcat(errbuf, ": ",            sizeof(errbuf));
1938              sl_strlcat(errbuf, gai_strerror(s), sizeof(errbuf));
1939              SH_MUTEX_LOCK(mutex_thread_nolog);
1940              sh_error_handle((-1), FIL__, __LINE__, s, MSG_E_SUBGEN, 
1941                              errbuf, _("getnameinfo"));
1942              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1943            }
1944         
1945        }
1946    }
1947
1948  freeifaddrs(ifaddr);
1949  return 0;
1950}
1951
1952struct added_dev {
1953  char dev[64];
1954  struct added_dev * next;
1955};
1956
1957static struct added_dev * dev_list = NULL;
1958
1959static void dev_list_add (char * buf)
1960{
1961  struct added_dev * new = SH_ALLOC(sizeof(struct added_dev));
1962  sl_strlcpy(new->dev, buf, 64);
1963  new->next = dev_list;
1964  dev_list  = new;
1965  return;
1966}
1967
1968static void dev_list_kill ()
1969{
1970  struct added_dev * old;
1971  struct added_dev * new = dev_list;
1972  dev_list = NULL;
1973
1974  while (new)
1975    {
1976      old = new;
1977      new = new->next;
1978      SH_FREE(old);
1979    }
1980  return;
1981}
1982 
1983static int sh_portchk_add_device (const char * str)
1984{
1985  char buf[64];
1986               
1987  do {
1988
1989    while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1990
1991    if (*str)
1992      {
1993        unsigned int i = 0;
1994        while (*str && i < (sizeof(buf)-1) &&
1995               *str != ',' && *str != ' ' && *str != '\t') {
1996          buf[i] = *str; ++str; ++i;
1997        }
1998        buf[i] = '\0';
1999       
2000        if (portchk_add_device_int (buf) < 0)
2001          return -1;
2002       
2003        dev_list_add(buf);
2004      }
2005  } while (*str);
2006
2007  return 0;
2008}
2009
2010static int iface_comp (const void *a, const void *b)
2011{
2012  const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
2013  const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
2014  return (aa->type - bb->type);
2015}
2016
2017static void iface_qsort()
2018{
2019  qsort(&iface_list[0], iface_list_used, sizeof(struct portchk_interfaces),
2020        iface_comp);
2021  return;
2022}
2023
2024static void recheck_devices()
2025{
2026  if (dev_list)
2027    {
2028      struct added_dev * dev = dev_list;
2029      int i, j;
2030
2031      if (portchk_debug)
2032        {
2033          for (j = 0; j < iface_list_used; ++j)
2034            {
2035              char buf[SH_IP_BUF];
2036              struct portchk_interfaces * aa = &(iface_list[j]);
2037              sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2038              fprintf(stderr, _("presort: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2039            }
2040        }
2041
2042      iface_qsort();
2043     
2044      if (portchk_debug)
2045        {
2046          for (j = 0; j < iface_list_used; ++j)
2047            {
2048              char buf[SH_IP_BUF];
2049              struct portchk_interfaces * aa = &(iface_list[j]);
2050              sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2051              fprintf(stderr, _("postsor: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2052            }
2053        }
2054
2055      i = 0;
2056      for (j = 0; j < iface_list_used; ++j)
2057        if (iface_list[j].type == SH_IFACE_DEV) ++i;
2058      iface_list_used -= i;
2059
2060      if (portchk_debug)
2061        {
2062          for (j = 0; j < iface_list_used; ++j)
2063            {
2064              char buf[SH_IP_BUF];
2065              struct portchk_interfaces * aa = &(iface_list[j]);
2066              sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
2067              fprintf(stderr, _("postdel: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
2068            }
2069        }
2070
2071      while (dev)
2072        {
2073          portchk_add_device_int (dev->dev);
2074          dev = dev->next;
2075        }
2076    }
2077  return;
2078}
2079#endif
2080
2081/* verify whether port/interface is blacklisted (do not check)
2082 */
2083static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr, 
2084                                     int proto)
2085{
2086  struct sh_port * head;
2087
2088  if (proto == IPPROTO_TCP)
2089    head = blacklist_tcp;
2090  else
2091    head = blacklist_udp;
2092
2093  while (head)
2094    {
2095      if (head->port == port && ( sh_ipvx_isany(head->paddr) ||  0 == sh_ipvx_cmp(head->paddr, saddr) ))
2096        return 1;
2097      head = head->next;
2098    }
2099  return 0;
2100}
2101
2102
2103static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
2104{
2105  struct sh_port * black;
2106  struct sh_port * head;
2107
2108  if (proto == IPPROTO_TCP)
2109    head = blacklist_tcp;
2110  else
2111    head = blacklist_udp;
2112
2113  black = head;
2114
2115  while (black)
2116    {
2117      if (black->port == port && 
2118          0 == sh_ipvx_cmp(head->paddr, saddr))
2119        return -1;
2120      black = black->next;
2121    }
2122
2123  black = SH_ALLOC (sizeof(struct sh_port));
2124  black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2125  black->port  = port;
2126  memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
2127  black->next  = head;
2128
2129  if (proto == IPPROTO_TCP)
2130    blacklist_tcp = black;
2131  else
2132    blacklist_udp = black;
2133
2134  if (portchk_debug)
2135    {
2136      int checkit = sh_portchk_is_blacklisted(port, saddr, proto);
2137      fprintf(stderr, _("port blacklisted: %d %s\n"), port, 
2138              (checkit == 1) ? _("ok") : _("fail"));
2139    }
2140  return 0;
2141}
2142
2143
2144/* verify whether port/interface is transient (used as source port
2145 *hence no check required)
2146 */
2147static int sh_portchk_is_transient(int port, struct sh_sockaddr * saddr, 
2148                                     int proto)
2149{
2150  struct sh_port * head;
2151 
2152  if (proto == IPPROTO_TCP)
2153    head = transient_tcp;
2154  else
2155    head = transient_udp;
2156 
2157  while (head)
2158    {
2159      if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
2160        return 1;
2161      head = head->next;
2162    }
2163  return 0;
2164}
2165
2166
2167static int sh_portchk_transient(int port, struct sh_sockaddr * saddr, int proto)
2168{
2169  struct sh_port * transient;
2170  struct sh_port * head;
2171
2172  if (sh_portchk_transients == S_FALSE)
2173    return 0;
2174
2175  if (proto == IPPROTO_TCP)
2176    head = transient_tcp;
2177  else
2178    head = transient_udp;
2179
2180  transient = head;
2181
2182  while (transient)
2183    {
2184      if (transient->port == port && 
2185          0 == sh_ipvx_cmp(head->paddr, saddr))
2186        return -1;
2187      transient = transient->next;
2188    }
2189
2190  transient = SH_ALLOC (sizeof(struct sh_port));
2191  transient->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
2192  transient->port  = port;
2193  memcpy(transient->paddr, saddr, sizeof(struct sh_sockaddr));
2194  transient->next  = head;
2195
2196  if (proto == IPPROTO_TCP)
2197    transient_tcp = transient;
2198  else
2199    transient_udp = transient;
2200
2201  if (portchk_debug)
2202    {
2203      int checkit = sh_portchk_is_transient(port, saddr, proto);
2204      fprintf(stderr, _("port transient: %d %s\n"), port, 
2205              (checkit == 1) ? _("ok") : _("fail"));
2206    }
2207  return 0;
2208}
2209
2210
2211/* Subroutine to add a required or optional port/service
2212 */
2213static int sh_portchk_add_required_port_generic (char * service, 
2214                                                 char * interface, int type)
2215{
2216  char buf[256] = { '\0' };
2217  int proto;
2218  char * p;
2219  char * endptr;
2220  unsigned long int  port;
2221  struct sh_sockaddr   saddr;
2222  struct sh_portentry * portent;
2223
2224  if (0 == sh_ipvx_aton(interface, &saddr))
2225    return -1;
2226
2227  sl_strlcpy (buf, service, sizeof(buf));
2228
2229  p = strchr(buf, '/');
2230  if (!p)
2231    return -1;
2232  if (0 == strcasecmp(p, _("/tcp")))
2233    proto = IPPROTO_TCP;
2234  else if  (0 == strcasecmp(p, _("/udp")))
2235    proto = IPPROTO_UDP;
2236  else
2237    return -1;
2238
2239  *p = '\0';
2240  port = strtoul(buf, &endptr, 0);
2241
2242  if (portchk_debug)
2243    {
2244      char buf[SH_IP_BUF];
2245      sh_ipvx_ntoa(buf, sizeof(buf), &saddr);
2246      fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"),
2247              interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"),
2248              sh_port_type2str(type));
2249    }
2250
2251  /* Blacklisted ports
2252   */
2253  if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
2254    return (sh_portchk_blacklist(port, &saddr, proto));
2255
2256  if (*endptr != '\0')
2257    { 
2258      portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
2259      if (!portent)
2260        {
2261          if (portchk_debug)
2262            fprintf(stderr, _("add_required_port %d\n"), (int) port);
2263          sh_portchk_add_to_list (proto,   -1, &saddr,  buf, type, SH_PORT_UNKN);
2264        }
2265      else
2266        {
2267#ifdef TEST_ONLY
2268          fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
2269#else
2270          SH_MUTEX_LOCK(mutex_thread_nolog);
2271          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
2272                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2273          SH_MUTEX_UNLOCK(mutex_thread_nolog);
2274#endif
2275          return -1;
2276        }
2277    }
2278  else if (port <= 65535)
2279    {
2280      portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
2281      if (!portent)
2282        {
2283          if (portchk_debug)
2284            fprintf(stderr, _("add_required_port: open port: %d/%s\n"), 
2285                    (int) port, SH_PROTO_STR(proto));
2286          sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN);
2287        }
2288      else
2289        {
2290#ifdef TEST_ONLY
2291          fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
2292#else
2293          SH_MUTEX_LOCK(mutex_thread_nolog);
2294          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
2295                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
2296          SH_MUTEX_UNLOCK(mutex_thread_nolog);
2297#endif
2298          return -1;
2299        }
2300    }
2301  else
2302    return -1;
2303
2304  return 0;
2305}
2306
2307/* Internal interface to add required or optional ports as 'iface:portlist'
2308 */
2309static int sh_portchk_add_required_generic (const char * str, int type)
2310{
2311  size_t ll = 0;
2312  int    status;
2313
2314  char * interface = NULL;
2315  char * list;
2316  char * p;
2317#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2318  char * saveptr;
2319#endif
2320
2321  if (!str)
2322    return -1;
2323
2324  if (strchr(str, ':'))
2325    {
2326      char *last = strrchr(str, ':');
2327      if (last != NULL)
2328        {
2329          size_t tolast = (last - str);
2330          interface = SH_ALLOC(tolast+1);
2331          sl_strlcpy(interface, str, tolast+1);
2332          interface[tolast] = '\0';
2333
2334          ll = tolast;
2335
2336          while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
2337            ++ll;
2338        }
2339    }
2340  else
2341    {
2342      interface = SH_ALLOC(8);
2343      sl_strlcpy(interface, _("0.0.0.0"), 8);
2344      interface[7] = '\0';
2345      while (str[ll] == ' ' || str[ll] == '\t')
2346        ++ll;     
2347    }
2348
2349  if (!interface)
2350    return -1;
2351
2352  if (str[ll] == '\0')
2353    {
2354      SH_FREE(interface);
2355      return -1;
2356    }
2357
2358  if (portchk_debug)
2359    fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
2360
2361  list = sh_util_strdup(&str[ll]);
2362#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2363  p    = strtok_r (list, " ,\t", &saveptr);
2364#else
2365  p    = strtok (list, " ,\t");
2366#endif
2367  if (!p)
2368    {
2369      SH_FREE(interface);
2370      SH_FREE(list);
2371      return -1;
2372    }
2373  while (p)
2374    {
2375      status = sh_portchk_add_required_port_generic (p, interface, type);
2376
2377      if (-1 == status)
2378        {
2379          SH_FREE(interface);
2380          SH_FREE(list);
2381          return -1;
2382        }
2383#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
2384      p    = strtok_r (NULL, " ,\t", &saveptr);
2385#else
2386      p    = strtok (NULL, " ,\t");
2387#endif
2388    }
2389  SH_FREE(interface);
2390  SH_FREE(list);
2391  return 0;
2392}
2393
2394/* User interface to add required ports as 'iface:portlist'
2395 */
2396static int sh_portchk_add_required (const char * str)
2397{
2398  return sh_portchk_add_required_generic (str, SH_PORT_REQ); 
2399}
2400
2401/* User interface to add optional ports as 'iface:portlist'
2402 */
2403static int sh_portchk_add_optional (const char * str)
2404{
2405  return sh_portchk_add_required_generic (str, SH_PORT_OPT); 
2406}
2407
2408/* User interface to add ignoreable ports as 'iface:portlist'
2409 */
2410static int sh_portchk_add_ignore (const char * str)
2411{
2412  return sh_portchk_add_required_generic (str, SH_PORT_IGN); 
2413}
2414
2415/* User interface to add ports that should not be checked as 'iface:portlist'
2416 */
2417static int sh_portchk_add_blacklist (const char * str)
2418{
2419  return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST); 
2420}
2421
2422/* Interface to run port check
2423 */
2424int sh_portchk_check ()
2425{
2426  volatile int min_port;
2427  static int noprivports = 0;
2428
2429  SH_MUTEX_LOCK(mutex_port_check);
2430
2431  min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
2432
2433  if (sh_portchk_active != S_FALSE)
2434    {
2435      SH_MUTEX_LOCK(mutex_thread_nolog);
2436      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
2437                      _("Checking for open ports"),
2438                      _("sh_portchk_check"));
2439      SH_MUTEX_UNLOCK(mutex_thread_nolog);
2440
2441      sh_portchk_reset_lists();
2442
2443#if defined(HAVE_IFADDRS_H)
2444      recheck_devices();
2445#endif
2446
2447      if ((0 != geteuid()) && (min_port < 1024))
2448        {
2449          min_port = 1024;
2450          if (noprivports == 0)
2451            {
2452#ifdef TEST_ONLY
2453              fprintf(stderr, "** WARNING not scanning ports < 1024\n");
2454#else
2455              SH_MUTEX_LOCK(mutex_thread_nolog);
2456              sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
2457                              _("not scanning ports below 1024"), 
2458                              _("sh_portchk_check"));
2459              SH_MUTEX_UNLOCK(mutex_thread_nolog);
2460#endif
2461              noprivports = 1;
2462            }
2463        }
2464
2465      sh_port2proc_prepare();
2466
2467      if (sh_portchk_check_udp == 1)
2468        sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
2469      sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
2470
2471
2472      sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
2473      if (sh_portchk_check_udp == 1)
2474        sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
2475
2476    }
2477  SH_MUTEX_UNLOCK(mutex_port_check);
2478  return 0;
2479}
2480#endif
2481
2482#ifdef SH_CUTEST
2483#include "CuTest.h"
2484
2485void Test_portcheck_lists (CuTest *tc)
2486{
2487#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
2488  struct sh_sockaddr    haddr_local;
2489  struct sh_portentry * portent;
2490  char   buf[256];
2491  char * p;
2492
2493#ifdef HAVE_RPC_RPC_H
2494  p = sh_getrpcbynumber(0, buf, sizeof(buf));
2495  CuAssertTrue(tc, p == NULL);
2496
2497  p = sh_getrpcbynumber(100000, buf, sizeof(buf));
2498  CuAssertPtrNotNull(tc, p);
2499  CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
2500  CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
2501
2502  p = sh_getrpcbynumber(100007, buf, sizeof(buf));
2503  CuAssertPtrNotNull(tc, p);
2504  CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
2505  CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
2506#endif
2507
2508  p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2509  CuAssertTrue(tc, p == NULL);
2510
2511#if !defined(HOST_IS_CYGWIN)
2512  p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
2513  CuAssertPtrNotNull(tc, p);
2514  CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
2515  CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
2516#endif
2517
2518  p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2519  CuAssertPtrNotNull(tc, p);
2520  CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
2521  CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
2522
2523  CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
2524
2525  sh_portchk_add_to_list (IPPROTO_TCP,  8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2526
2527  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
2528  CuAssertPtrNotNull(tc, portent);
2529
2530  CuAssertTrue(tc, portent->port == 8000);
2531  CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
2532  CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
2533  CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
2534
2535  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2536
2537  CuAssertTrue(tc, NULL == portlist_tcp);
2538
2539  sh_portchk_add_to_list (IPPROTO_TCP,  8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2540  sh_portchk_add_to_list (IPPROTO_TCP,  8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2541  sh_portchk_add_to_list (IPPROTO_TCP,  8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2542  sh_portchk_add_to_list (IPPROTO_TCP,  8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2543  sh_portchk_add_to_list (IPPROTO_TCP,  8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
2544  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
2545  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
2546  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
2547  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
2548  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
2549
2550  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2551
2552  CuAssertPtrNotNull(tc, portlist_tcp);
2553
2554  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
2555  CuAssertPtrNotNull(tc, portent);
2556
2557  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8001, &haddr_local, NULL);
2558  CuAssertTrue(tc, NULL == portent);
2559
2560  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8002, &haddr_local, NULL);
2561  CuAssertPtrNotNull(tc, portent);
2562
2563  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8003, &haddr_local, NULL);
2564  CuAssertTrue(tc, NULL == portent);
2565
2566  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8004, &haddr_local, NULL);
2567  CuAssertPtrNotNull(tc, portent);
2568
2569  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo1");
2570  CuAssertTrue(tc, NULL == portent);
2571
2572  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo2");
2573  CuAssertPtrNotNull(tc, portent);
2574  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2575
2576  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo3");
2577  CuAssertTrue(tc, NULL == portent);
2578
2579  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo4");
2580  CuAssertPtrNotNull(tc, portent);
2581  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
2582
2583  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo5");
2584  CuAssertPtrNotNull(tc, portent);
2585  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
2586
2587  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2588  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2589  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP));
2590  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP));
2591  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2592  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2593  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP));
2594  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP));
2595
2596  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP));
2597  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP));
2598  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP));
2599  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP));
2600
2601  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP));
2602  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP));
2603  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP));
2604  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP));
2605#else
2606  (void) tc; /* fix compiler warning */
2607#endif
2608  return;
2609}
2610#endif
2611
2612#ifdef TEST_ONLY
2613
2614void usage (char * pname)
2615{
2616  printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
2617  printf ("   Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
2618  printf ("   Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
2619  printf ("   Portlist:  List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
2620  printf ("     required -> must be open\n");
2621  printf ("     optional ->  may be open or closed\n");
2622  printf ("   RPC services must be specified with service **name**, others with **port number**\n\n");
2623  printf ("   Example:\n");
2624  printf ("      %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
2625  return;
2626}
2627
2628int main(int argc, char *argv[])
2629{
2630  char * pname = argv[0];
2631
2632
2633  /*
2634  test_lists();
2635
2636  portlist_tcp = sh_portchk_kill_list (portlist_tcp);
2637  portlist_udp = sh_portchk_kill_list (portlist_udp);
2638  */
2639
2640  /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
2641
2642  while (argc > 1 && argv[1][0] == '-')
2643    {
2644      if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
2645        {
2646          usage(pname);
2647          exit (0);
2648        }
2649      else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
2650        {
2651          if (argc < 3)
2652            {
2653              usage(pname);
2654              exit (1);
2655            }
2656          sh_portchk_add_required (argv[2]);
2657          --argc; ++argv;
2658        }
2659      else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
2660        {
2661          if (argc < 3)
2662            {
2663              usage(pname);
2664              exit (1);
2665            }
2666          sh_portchk_add_optional (argv[2]);
2667          --argc; ++argv;
2668        }
2669      else if (0 == strcmp(argv[1], "--no-udp"))
2670        {
2671          sh_portchk_check_udp = 0;
2672        }
2673      else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
2674        {
2675          portchk_debug = 1;
2676        }
2677      else
2678        {
2679          usage(pname);
2680          exit (1);
2681        }
2682      --argc; ++argv;
2683    }
2684
2685  if (argc < 2)
2686    {
2687      usage(pname);
2688      exit (1);
2689    }
2690
2691  portchk_hostname = argv[1];
2692     
2693  if (0 != sh_portchk_init ())
2694    {
2695      usage(pname);
2696      exit (1);
2697    }
2698
2699  sh_portchk_check();
2700
2701  return 0;
2702}
2703#endif
Note: See TracBrowser for help on using the repository browser.