source: trunk/src/sh_port2proc.c @ 541

Last change on this file since 541 was 541, checked in by katerina, 3 years ago

Fix for ticket #433 (coding standardisation).

File size: 27.9 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2008 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#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <netinet/in.h>
27#include <arpa/inet.h>
28#include <unistd.h>
29
30#ifdef HAVE_DIRENT_H
31#include <dirent.h>
32#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
33#else
34#define dirent direct
35#define NAMLEN(dirent) (dirent)->d_namlen
36#ifdef HAVE_SYS_NDIR_H
37#include <sys/ndir.h>
38#endif
39#ifdef HAVE_SYS_DIR_H
40#include <sys/dir.h>
41#endif
42#ifdef HAVE_NDIR_H
43#include <ndir.h>
44#endif
45#endif
46#define NEED_ADD_DIRENT
47
48#if defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
49
50/* #define DEBUG_P2P 1 */
51
52#include "samhain.h"
53#include "sh_utils.h"
54
55/****************************************************************************
56 *
57 *  >>> COMMON CODE <<<
58 *
59 ****************************************************************************/
60#if defined(__linux__) || defined(__FreeBSD__)
61 
62#include "sh_error_min.h"
63#include "sh_pthread.h"
64#include "sh_ipvx.h"
65
66#define FIL__  _("sh_port2proc.c")
67
68struct sock_store {
69  unsigned long sock;
70  size_t        pid;
71  char *        path;
72  char *        user;
73  struct sock_store * next;
74};
75
76/* /proc:
77 *        linux:     /proc/pid/exe
78 *        freebsd:   /proc/pid/file
79 *        solaris10: /proc/pid/path/a.out
80 */
81static void get_user_and_path (struct sock_store * add)
82{
83  extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
84
85  char        path[128];
86  char *      buf;
87  struct stat sbuf;
88  int         len;
89  char *      tmp;
90
91  sl_snprintf (path, sizeof(path), "/proc/%ld/exe", (unsigned long) add->pid);
92
93  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
94    {
95      goto linkread;
96    }
97
98  sl_snprintf (path, sizeof(path), "/proc/%ld/file", (unsigned long) add->pid);
99
100  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
101    {
102      goto linkread;
103    }
104
105  sl_snprintf (path, sizeof(path), "/proc/%ld/path/a.out", (unsigned long) add->pid);
106
107  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
108    {
109      goto linkread;
110    }
111
112  return;
113
114 linkread:
115
116  buf = SH_ALLOC(PATH_MAX);
117  len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
118  len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
119
120  if (len > 0)
121    { 
122      buf[len] = '\0';
123      add->path = buf;
124    }
125  else
126    {
127      SH_FREE(buf);
128    }
129
130  add->user = SH_ALLOC(USER_MAX);
131  tmp  = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, add->user, USER_MAX);
132
133  if (!tmp)
134    sl_snprintf (add->user, USER_MAX, "%ld", (unsigned long) sbuf.st_uid);
135
136  return;
137}
138
139#endif
140
141/****************************************************************************
142 *
143 *  >>> LINUX CODE <<<
144 *
145 ****************************************************************************/
146
147#if defined(__linux__)
148
149static  size_t  sh_minpid = 0x0001;
150static  size_t  sh_maxpid = 0x8000;
151
152#ifndef HAVE_LSTAT
153#define lstat(x,y) stat(x,y)
154#endif /* HAVE_LSTAT */
155
156#if defined(S_IFLNK) && !defined(S_ISLNK)
157# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
158#else
159# if !defined(S_ISLNK)
160#  define S_ISLNK(mode) (0)
161# endif
162#endif
163
164#if defined(__linux__)
165#define PROC_PID_MAX _("/proc/sys/kernel/pid_max")
166
167static int proc_max_pid (size_t * procpid)
168{
169  char * ret;
170  unsigned long  pid;
171  FILE * fd;
172  char   str[128];
173  char * ptr;
174
175  SL_ENTER(_("proc_max_pid"));
176   
177  if (0 == access(PROC_PID_MAX, R_OK)) /* flawfinder: ignore */
178    {
179      if (NULL != (fd = fopen(PROC_PID_MAX, "r")))
180        {
181          str[0] = '\0';
182          ret = fgets(str, 128, fd);
183          if (ret && *str != '\0')
184            {
185              pid = strtoul(str, &ptr, 0);
186              if (*ptr == '\0' || *ptr == '\n')
187                {
188                  sl_fclose(FIL__, __LINE__, fd);
189                  *procpid = (size_t) pid;
190                  SL_RETURN(0, _("proc_max_pid"));
191                }
192            }
193          sl_fclose(FIL__, __LINE__, fd);
194        }
195    }
196  SL_RETURN((-1), _("proc_max_pid"));
197}
198#else
199static int proc_max_pid(size_t * procpid)
200{
201  *procpid = sh_maxpid;
202  return 0;
203}
204#endif
205
206static struct sock_store * socklist = NULL;
207
208static void del_sock_all()
209{
210  struct sock_store * del = socklist;
211
212  while (del)
213    {
214      socklist = del->next;
215      if (del->path)
216        SH_FREE(del->path);
217      if (del->user)
218        SH_FREE(del->user);
219      SH_FREE(del);
220      del = socklist;
221    }
222  socklist = NULL;
223  return;
224}
225
226static void add_sock(unsigned long sock, size_t pid)
227{
228  struct sock_store * add = SH_ALLOC(sizeof(struct sock_store));
229
230  add->sock = sock;
231  add->pid  = pid;
232  add->path = NULL;
233  add->user = NULL;
234  SH_MUTEX_LOCK(mutex_thread_nolog);
235  get_user_and_path(add);
236  SH_MUTEX_UNLOCK(mutex_thread_nolog);
237  add->next = socklist;
238  socklist  = add;
239  return;
240}
241
242static void check_and_add_sock(char * fbuf, size_t pid)
243{
244  if (0 == strncmp(_("socket:["), fbuf, 8))
245    {
246      char * end;
247      unsigned long sock;
248      size_t len = strlen(fbuf);
249      if (fbuf[len-1] == ']')
250        fbuf[len-1] = '\0';
251      sock = strtoul(&fbuf[8], &end, 0);
252      if (*end == '\0' && fbuf[8] != '\0')
253        {
254          add_sock(sock, pid);
255        }
256    }
257}
258
259static void fetch_socks(size_t pid)
260{
261  char path[128];
262  DIR * dir;
263  sl_snprintf(path, sizeof(path), _("/proc/%lu/fd"), (unsigned long) pid);
264
265  dir = opendir(path);
266  if (dir)
267    {
268      struct dirent *entry;
269      while (NULL != (entry = readdir(dir)))
270        {
271          char fpath[384];
272          char fbuf[64];
273          int  ret;
274          /* /proc/PID/fd/N-> socket:[15713] */
275          sl_snprintf(fpath, sizeof(fpath), _("%s/%s"), path, entry->d_name);
276          ret = readlink(fpath, fbuf, sizeof(fbuf)-1);   /* flawfinder: ignore */
277          if (ret > 0)
278            {
279              fbuf[ret] = '\0';
280              check_and_add_sock(fbuf, pid);
281            }
282        }
283      closedir(dir);
284    }
285}
286
287int sh_port2proc_prepare()
288{
289  size_t i;
290 
291  if (0 != proc_max_pid(&sh_maxpid))
292    {
293      SH_MUTEX_LOCK(mutex_thread_nolog);
294      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
295                      _("Failed to detect max_pid"), 
296                      _("sh_port2proc"));
297      SH_MUTEX_UNLOCK(mutex_thread_nolog);
298      SL_RETURN ((-1), _("sh_port2proc"));
299    }
300
301  /* Delete old socket list and re-create it
302   */
303  del_sock_all();
304
305  for (i = sh_minpid; i < sh_maxpid; ++i)
306    {
307      fetch_socks(i);
308    }
309
310  return 0;
311}
312
313void sh_port2proc_finish()
314{
315  /* Delete old socket list
316   */
317  del_sock_all();
318  return;
319}
320
321
322#include <sys/socket.h>
323#include <netinet/in.h>
324#include <arpa/inet.h>
325
326/* returns the command and fills the 'user' array
327 */
328static char * port2proc_query(char * file, int proto, int domain,
329                              struct sh_sockaddr * saddr, int sport, 
330                              unsigned long * pid, char * user, size_t userlen)
331{
332  FILE * fd;
333
334  fd = fopen(file, "r");
335
336  *pid = 0;
337
338#ifdef DEBUG_P2P
339  {
340    char errmsg[256];
341    char siface[SH_IP_BUF];
342    sh_ipvx_ntoa(siface, sizeof(siface), saddr);
343    sl_snprintf(errmsg, sizeof(errmsg), 
344                "query, file=%s, proto=%d, port=%d, iface=%s\n",
345                file, proto, sport, siface);
346    fprintf(stderr, "%s", errmsg);
347  }
348#endif
349
350  if (fd)
351    {
352      unsigned int n, i, port, niface, inode, istatus;
353      char line[512];
354      char ip_port[128];
355      char iface[SH_IP_BUF];
356
357      while (NULL != fgets(line, sizeof(line), fd))
358        {
359       
360#ifdef DEBUG_P2P
361          {
362            fprintf(stderr, "%s", line);
363          }
364#endif
365
366          if (4 == sscanf(line, 
367                          "%u: %127s %*X:%*X %X %*X:%*X %*X:%*X %*X %*d %*d %u %*s",
368                          &n, ip_port, &istatus, &inode))
369            {
370              struct sockaddr_in  addr4;
371              struct sockaddr_in6 addr6;
372              struct sh_sockaddr  ss;
373             
374              char * p;
375
376              ip_port[127] = '\0';
377
378              p = strchr(ip_port, ':');
379
380              if (p)
381                {
382                  *p = '\0'; ++p;
383                  port = (unsigned int) strtoul(p, NULL, 16);
384                  sl_strlcpy(iface, ip_port, sizeof(iface));
385                }
386              else
387                {
388                  continue;
389                }
390
391              niface = 0;
392
393              switch (domain) 
394                {
395                case AF_INET:
396                  addr4.sin_addr.s_addr = (int) strtol(iface, NULL, 16);
397                  niface = (unsigned int) addr4.sin_addr.s_addr;
398                  sh_ipvx_save(&ss, AF_INET, (struct sockaddr *)&addr4);
399                  break;
400
401                case AF_INET6:
402                  sscanf(iface, 
403                         "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", 
404                         &addr6.sin6_addr.s6_addr[3], &addr6.sin6_addr.s6_addr[2], &addr6.sin6_addr.s6_addr[1], &addr6.sin6_addr.s6_addr[0], 
405                         &addr6.sin6_addr.s6_addr[7], &addr6.sin6_addr.s6_addr[6], &addr6.sin6_addr.s6_addr[5], &addr6.sin6_addr.s6_addr[4], 
406                         &addr6.sin6_addr.s6_addr[11], &addr6.sin6_addr.s6_addr[10], &addr6.sin6_addr.s6_addr[9], &addr6.sin6_addr.s6_addr[8], 
407                         &addr6.sin6_addr.s6_addr[15], &addr6.sin6_addr.s6_addr[14], &addr6.sin6_addr.s6_addr[13], &addr6.sin6_addr.s6_addr[12]);
408                 
409                  for (i = 0; i < 16; ++i)
410                    {
411                      if (0 != (unsigned int) addr6.sin6_addr.s6_addr[i]) 
412                        ++niface;
413                    }
414                  sh_ipvx_save(&ss, AF_INET6, (struct sockaddr *)&addr6);
415                  break;
416                }
417
418#ifdef DEBUG_P2P
419              {
420                char a[SH_IP_BUF];
421                char b[SH_IP_BUF];
422
423                sh_ipvx_ntoa(a, sizeof(a), &ss);
424                sh_ipvx_ntoa(b, sizeof(b), saddr);
425
426                fprintf(stderr, " -> inode %u, iface/port %s,%u, status %u, searching %s,%u, %u\n", 
427                        inode, a, port, istatus, b, sport, 
428                        proto == IPPROTO_TCP ? 0x0a : 0x07);
429              }
430#endif
431
432              if (proto == IPPROTO_TCP && istatus != 0x0a)
433                continue;
434              if (proto == IPPROTO_UDP && istatus == 0x01)
435                continue;
436
437#ifdef DEBUG_P2P
438              {
439                fprintf(stderr, "check iface %u..\n", iface);
440              }
441#endif
442
443              if ((proto == IPPROTO_UDP || niface == 0 || 0 == sh_ipvx_cmp(&ss, saddr)) && 
444                  port == (unsigned int)sport)
445                {
446                  struct sock_store * new = socklist;
447
448#ifdef DEBUG_P2P
449                  {
450                    fprintf(stderr, "found it\n");
451                  }
452#endif
453
454                  while (new)
455                    {
456#ifdef DEBUG_P2P
457                      {
458                        fprintf(stderr, "searching inode %u: %lu\n", 
459                                inode, new->sock);
460                      }
461#endif
462                      if (inode == new->sock)
463                        {
464#ifdef DEBUG_P2P
465                          {
466                            fprintf(stderr, "found it: path=(%s), user=(%s)\n",
467                                    new->path == NULL ? "NULL" : new->path,
468                                    new->user == NULL ? "NULL" : new->user);
469                          }
470#endif
471                          sl_fclose(FIL__, __LINE__, fd);
472                          *pid = (unsigned long) new->pid;
473                          if (new->path)
474                            {
475                              if (new->user)
476                                sl_strlcpy(user, new->user, userlen);
477                              else
478                                sl_strlcpy(user, "-", userlen);
479                              return sh_util_strdup(new->path);
480                            }
481                          goto err_out;
482                        }
483                      new = new->next;
484                    }
485                }
486            }
487        }
488      sl_fclose(FIL__, __LINE__, fd);
489    }
490 err_out:
491  sl_strlcpy(user, "-", userlen);
492  return sh_util_strdup("-");
493}
494
495/* returns the command and fills the 'user' array
496 */
497char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport, 
498                          unsigned long * pid, char * user, size_t userlen)
499{
500  char file[32];
501  char * ret;
502 
503  if (proto == IPPROTO_TCP)
504    {
505      sl_strlcpy(file, _("/proc/net/tcp"), sizeof(file));
506      ret = port2proc_query(file, proto, AF_INET, saddr, sport, pid, user, userlen);
507
508      if (ret[0] == '-' && ret[1] == '\0')
509        {
510          SH_FREE(ret);
511          sl_strlcpy(file, _("/proc/net/tcp6"), sizeof(file));
512          ret = port2proc_query(file, proto, AF_INET6, saddr, sport, pid, user, userlen);
513        }
514      return ret;
515    }
516  else
517    {
518      char * ret;
519      sl_strlcpy(file, _("/proc/net/udp"), sizeof(file));
520      ret = port2proc_query(file, proto, AF_INET, saddr, sport, pid, user, userlen);
521
522      if (ret[0] == '-' && ret[1] == '\0')
523        {
524          SH_FREE(ret);
525          sl_strlcpy(file, _("/proc/net/udp6"), sizeof(file));
526          ret = port2proc_query(file, proto, AF_INET6, saddr, sport, pid, user, userlen);
527        }
528      return ret;
529    }
530}
531
532
533/****************************************************************************
534 *
535 *  >>> FREEBSD CODE <<<
536 *
537 ****************************************************************************/
538
539#elif defined(__FreeBSD__)
540
541/* Uses code from sockstat.c. Error and memory handling modified.
542 * Only required functions from sockstat.c are included.
543 */
544
545/*-
546 * Copyright (c) 2002 Dag-Erling Co<EF>dan Sm<F8>rgrav
547 * All rights reserved.
548 *
549 * Redistribution and use in source and binary forms, with or without
550 * modification, are permitted provided that the following conditions
551 * are met:
552 * 1. Redistributions of source code must retain the above copyright
553 *    notice, this list of conditions and the following disclaimer
554 *    in this position and unchanged.
555 * 2. Redistributions in binary form must reproduce the above copyright
556 *    notice, this list of conditions and the following disclaimer in the
557 *    documentation and/or other materials provided with the distribution.
558 * 3. The name of the author may not be used to endorse or promote products
559 *    derived from this software without specific prior written permission.
560 *
561 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
562 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
563 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
564 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
565 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
566 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
567 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
568 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
569 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
570 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
571 */
572#include <sys/cdefs.h>
573__FBSDID("$FreeBSD: src/usr.bin/sockstat/sockstat.c,v 1.13.2.1.4.1 2008/10/02 02:57:24 kensmith Exp $");
574
575#include <sys/param.h>
576#include <sys/socket.h>
577#include <sys/socketvar.h>
578#include <sys/sysctl.h>
579#include <sys/file.h>
580#include <sys/user.h>
581
582#include <sys/un.h>
583#include <sys/unpcb.h>
584
585#include <net/route.h>
586
587#include <netinet/in.h>
588#include <netinet/in_pcb.h>
589#include <netinet/tcp.h>
590#include <netinet/tcp_seq.h>
591#include <netinet/tcp_var.h>
592#include <arpa/inet.h>
593
594#include <ctype.h>
595#include <errno.h>
596#include <netdb.h>
597#include <stdio.h>
598#include <stdlib.h>
599
600#include <unistd.h>
601
602static int       opt_4 = 1;         /* Show IPv4 sockets */
603static int       opt_6 = 1;         /* Show IPv6 sockets */
604static int       opt_c = 0;         /* Show connected sockets */
605static int       opt_l = 1;         /* Show listening sockets */
606static int       opt_v = 0;         /* Verbose mode */
607
608struct sock {
609        void *socket;
610        void *pcb;
611        int vflag;
612        int family;
613        int proto;
614
615        struct sockaddr_storage laddr;
616        struct sockaddr_storage faddr;
617        struct sock *next;
618};
619
620#define HASHSIZE 1009
621static struct sock *sockhash[HASHSIZE];
622
623static struct xfile *xfiles;
624static int nxfiles;
625
626
627static void * xrealloc(void * buf, size_t len0, size_t len)
628{
629  if (len > 0)
630    {
631      void * xbuf = SH_ALLOC(len);
632      if (buf)
633        {
634          if (len0 <= len)
635            memcpy(xbuf, buf, len0);
636          else
637            memset(xbuf, 0, len);
638          SH_FREE(buf);
639        }
640      return xbuf;
641    }
642  SH_FREE(buf);
643  return NULL;
644}
645
646/* Sets address and port in struct sockaddr_storage *sa
647 */
648static void
649sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port)
650{
651        struct sockaddr_in *sin4;
652        struct sockaddr_in6 *sin6;
653
654        bzero(sa, sizeof *sa);
655        switch (af) {
656        case AF_INET:
657                sin4 = (struct sockaddr_in *)sa;
658                sin4->sin_len = sizeof *sin4;
659                sin4->sin_family = af;
660                sin4->sin_port = port;
661                sin4->sin_addr = *(struct in_addr *)addr;
662                break;
663        case AF_INET6:
664                sin6 = (struct sockaddr_in6 *)sa;
665                sin6->sin6_len = sizeof *sin6;
666                sin6->sin6_family = af;
667                sin6->sin6_port = port;
668                sin6->sin6_addr = *(struct in6_addr *)addr;
669                break;
670        default:
671                return;
672        }
673}
674
675/* Get socket information from the kernel.
676 */
677static void
678gather_inet(int proto)
679{
680        struct xinpgen *xig, *exig;
681        struct xinpcb *xip;
682        struct xtcpcb *xtp;
683        struct inpcb *inp;
684        struct xsocket *so;
685        struct sock *sock;
686        char varname[32];
687        size_t len, bufsize, bufsize0;
688        void *buf;
689        int hash, retry, vflag;
690
691        vflag = 0;
692        if (opt_4)
693                vflag |= INP_IPV4;
694        if (opt_6)
695                vflag |= INP_IPV6;
696
697        switch (proto) {
698        case IPPROTO_TCP:
699          sl_strlcpy(varname, _("net.inet.tcp.pcblist"), sizeof(varname));
700                break;
701        case IPPROTO_UDP:
702                sl_strlcpy(varname, _("net.inet.udp.pcblist"), sizeof(varname));
703                break;
704        case IPPROTO_DIVERT:
705                sl_strlcpy(varname, _("net.inet.divert.pcblist"), sizeof(varname));
706                break;
707        default:
708                return;
709        }
710
711        buf = NULL;
712        bufsize  = 8192;
713        bufsize0 = bufsize;
714        retry = 5;
715        do {
716                for (;;) {
717                        buf = xrealloc(buf, bufsize0, bufsize);
718                        bufsize0 = bufsize;
719                        len = bufsize;
720                        if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
721                                break;
722                        if (errno == ENOENT)
723                                goto out;
724                        if (errno != ENOMEM)
725                          {
726                            SH_MUTEX_LOCK(mutex_thread_nolog);
727                            sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 
728                                            0, MSG_E_SUBGEN, 
729                                            _("sysctlbyname()"), 
730                                            _("gather_inet"));
731                            SH_MUTEX_UNLOCK(mutex_thread_nolog);
732                            SH_FREE(buf);
733                            return;
734                          }
735                        bufsize *= 2;
736                }
737                xig = (struct xinpgen *)buf;
738                exig = (struct xinpgen *)(void *)
739                    ((char *)buf + len - sizeof *exig);
740                if (xig->xig_len != sizeof *xig ||
741                    exig->xig_len != sizeof *exig)
742                  {
743                    SH_MUTEX_LOCK(mutex_thread_nolog);
744                    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
745                                    _("struct xinpgen size mismatch"), 
746                                    _("gather_inet"));
747                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
748                    goto out;
749                  }
750
751        } while (xig->xig_gen != exig->xig_gen && retry--);
752
753        if (xig->xig_gen != exig->xig_gen && opt_v)
754                  {
755                    SH_MUTEX_LOCK(mutex_thread_nolog);
756                    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
757                                    _("data may be inconsistent"), 
758                                    _("gather_inet"));
759                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
760                  }
761
762        for (;;) {
763                xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
764                if (xig >= exig)
765                        break;
766                switch (proto) {
767                case IPPROTO_TCP:
768                        xtp = (struct xtcpcb *)xig;
769                        if (xtp->xt_len != sizeof *xtp) {
770                                SH_MUTEX_LOCK(mutex_thread_nolog);
771                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
772                                                _("struct xtcpcb size mismatch"), 
773                                                _("gather_inet"));
774                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
775                                goto out;
776                        }
777                        inp = &xtp->xt_inp;
778                        so = &xtp->xt_socket;
779                        break;
780                case IPPROTO_UDP:
781                case IPPROTO_DIVERT:
782                        xip = (struct xinpcb *)xig;
783                        if (xip->xi_len != sizeof *xip) {
784                                SH_MUTEX_LOCK(mutex_thread_nolog);
785                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
786                                                _("struct xinpcb size mismatch"), 
787                                                _("gather_inet"));
788                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
789                                goto out;
790                        }
791                        inp = &xip->xi_inp;
792                        so = &xip->xi_socket;
793                        break;
794                default:
795                        return;
796                }
797                if ((inp->inp_vflag & vflag) == 0)
798                        continue;
799                if (inp->inp_vflag & INP_IPV4) {
800                        if ((inp->inp_fport == 0 && !opt_l) ||
801                            (inp->inp_fport != 0 && !opt_c))
802                                continue;
803                } else if (inp->inp_vflag & INP_IPV6) {
804#ifndef in6p_fport
805#define in6p_fport inp_fport
806#endif
807                        if ((inp->in6p_fport == 0 && !opt_l) ||
808                            (inp->in6p_fport != 0 && !opt_c))
809                                continue;
810                } else {
811                        if (opt_v) {
812                                char errmsg[64];
813                                sl_snprintf(errmsg, sizeof(errmsg), 
814                                            _("invalid vflag 0x%x"), inp->inp_vflag);
815                                SH_MUTEX_LOCK(mutex_thread_nolog);
816                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
817                                                errmsg, 
818                                                _("gather_inet"));
819                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
820                                continue;
821                        }
822                }
823
824                sock = SH_ALLOC(sizeof *sock);
825                memset(sock, 0, sizeof (*sock));
826
827#ifndef in6p_lport
828#define in6p_lport inp_lport
829#endif
830                sock->socket = so->xso_so;
831                sock->proto = proto;
832                if (inp->inp_vflag & INP_IPV4) {
833                        sock->family = AF_INET;
834                        sockaddr(&sock->laddr, sock->family,
835                            &inp->inp_laddr, inp->inp_lport);
836                        sockaddr(&sock->faddr, sock->family,
837                            &inp->inp_faddr, inp->inp_fport);
838                } else if (inp->inp_vflag & INP_IPV6) {
839                        sock->family = AF_INET6;
840                        sockaddr(&sock->laddr, sock->family,
841                            &inp->in6p_laddr, inp->in6p_lport);
842                        sockaddr(&sock->faddr, sock->family,
843                            &inp->in6p_faddr, inp->in6p_fport);
844                }
845                sock->vflag = inp->inp_vflag;
846
847                hash = (int)((uintptr_t)sock->socket % HASHSIZE);
848                sock->next = sockhash[hash];
849                sockhash[hash] = sock;
850        }
851out:
852        if (buf)
853          SH_FREE(buf);
854}
855
856static void
857getfiles(void)
858{
859        size_t len;
860        size_t len0;
861
862        xfiles = SH_ALLOC(len = sizeof *xfiles);
863        len0   = len;
864
865        while (sysctlbyname(_("kern.file"), xfiles, &len, 0, 0) == -1) {
866                if (errno != ENOMEM)
867                  {
868                    volatile int status = errno;
869                    SH_MUTEX_LOCK(mutex_thread_nolog);
870                    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
871                                    _("sysctlbyname()"),
872                                    _("getfiles"));
873                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
874                  }
875                len *= 2;
876                xfiles = xrealloc(xfiles, len0, len);
877                len0   = len;
878        }
879        if (len > 0 && xfiles->xf_size != sizeof *xfiles)
880                if (errno != ENOMEM)
881                  {
882                    volatile int status = errno;
883                    SH_MUTEX_LOCK(mutex_thread_nolog);
884                    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
885                                    _("struct xfile size mismatch"),
886                                    _("getfiles"));
887                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
888                  }
889        nxfiles = len / sizeof *xfiles;
890}
891
892static const char *
893getprocname(pid_t pid)
894{
895        static struct kinfo_proc proc;
896        size_t len;
897        int mib[4];
898
899        mib[0] = CTL_KERN;
900        mib[1] = KERN_PROC;
901        mib[2] = KERN_PROC_PID;
902        mib[3] = (int)pid;
903        len = sizeof proc;
904        if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
905                /* Do not warn if the process exits before we get its name. */
906                if (errno != ESRCH)
907                  {
908                    volatile int status = errno;
909                    SH_MUTEX_LOCK(mutex_thread_nolog);
910                    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_SUBGEN,
911                                    _("sysctl()"),
912                                    _("getfiles"));
913                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
914                  }
915                return ("-");
916        }
917        return (proc.ki_ocomm);
918}
919
920char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
921                          unsigned long * pid, char * user, size_t userlen)
922{
923  int n, hash;
924  struct xfile *xf;
925  struct in_addr  * haddr  = NULL;
926  struct in6_addr * haddr6 = NULL;
927  struct sock * s;
928  struct in6_addr   anyaddr = IN6ADDR_ANY_INIT; 
929
930  *pid = 0;
931 
932  for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
933   
934    if (xf->xf_data == NULL)
935      continue;
936   
937    /* Find the socket in sockhash[] that corresponds to it
938     */
939    hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
940    for (s = sockhash[hash]; s != NULL; s = s->next)
941      if ((void *)s->socket == xf->xf_data)
942        break;
943   
944    if (!s)
945      continue;
946
947    if (s->proto != proto)
948      continue;
949
950    if (s->family != AF_INET && s->family != AF_INET6)
951      continue;
952
953    if (s->family == AF_INET &&
954        (sport != ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port)))
955      continue;
956
957    if (s->family == AF_INET6 &&
958        (sport != ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port)))
959      continue;
960
961    if (s->family == AF_INET)
962      haddr  = &((struct sockaddr_in  *)(&s->laddr))->sin_addr;
963    if (s->family == AF_INET6)
964      haddr6 = &((struct sockaddr_in6 *)(&s->laddr))->sin6_addr;
965   
966
967    if ( (s->family == AF_INET && 
968          (haddr->s_addr == (saddr->sin).sin_addr.s_addr || 
969           sh_ipvx_isany(saddr) || 
970           inet_lnaof(*haddr) == INADDR_ANY))
971         ||
972         (s->family == AF_INET6 &&
973          (0 == memcmp(haddr6->s6_addr, &((saddr->sin6).sin6_addr.s6_addr), 16) ||
974           0 == memcmp(haddr6->s6_addr, &(anyaddr.s6_addr), 16) ||
975           sh_ipvx_isany(saddr) ))
976         )
977      {
978        struct sock_store try;
979       
980        *pid = xf->xf_pid;
981
982        try.pid  = xf->xf_pid;
983        try.path = NULL;
984        try.user = NULL;
985        get_user_and_path (&try); /* Try to get info from /proc */
986
987        if (try.path == NULL)
988          {
989            extern char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
990            char * tmp  = sh_unix_getUIDname (SH_ERR_ALL, xf->xf_uid, user, userlen);
991            if (!tmp)
992              sl_snprintf (user, userlen, "%ld", (unsigned long) xf->xf_uid);
993            return sh_util_strdup(getprocname(xf->xf_pid));
994          }
995        else
996          {
997            sl_strlcpy(user, try.user, userlen);
998            SH_FREE(try.user);
999            return try.path;
1000          }
1001      }
1002  }
1003  sl_strlcpy(user, "-", userlen);
1004  return sh_util_strdup("-");
1005}
1006
1007static void sockdel(struct sock * sock)
1008{
1009  if (sock)
1010    {
1011      if (sock->next)
1012        sockdel(sock->next);
1013      SH_FREE(sock);
1014    }
1015  return;
1016}
1017
1018int sh_port2proc_prepare()
1019{
1020  int i;
1021
1022  if (xfiles)
1023    {
1024      SH_FREE(xfiles);
1025      xfiles = NULL;
1026    }
1027
1028  for (i = 0; i < HASHSIZE; ++i)
1029    {
1030      sockdel(sockhash[i]);
1031      sockhash[i] = NULL;
1032    }
1033
1034  /* Inet connections
1035   */
1036  gather_inet(IPPROTO_TCP);
1037  gather_inet(IPPROTO_UDP);
1038  gather_inet(IPPROTO_DIVERT);
1039
1040  getfiles();
1041
1042  return 0;
1043}
1044
1045void sh_port2proc_finish()
1046{
1047  return;
1048}
1049
1050#else /* !defined(__linux__) && !defined(__FreeBSD__) */
1051
1052#include "samhain.h"
1053#include "sh_utils.h"
1054#include "sh_ipvx.h"
1055
1056char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
1057                          unsigned long * pid, char * user, size_t userlen)
1058{
1059  (void) proto;
1060  (void) saddr;
1061  (void) sport;
1062
1063  *pid = 0;
1064
1065  sl_strlcpy(user, "-", userlen);
1066  return sh_util_strdup("-");
1067}
1068
1069int sh_port2proc_prepare()
1070{
1071  return 0;
1072}
1073
1074void sh_port2proc_finish()
1075{
1076  return;
1077}
1078#endif
1079
1080#endif /* defined(SH_USE_PORTCHECK) */
Note: See TracBrowser for help on using the repository browser.