source: trunk/src/sh_port2proc.c@ 592

Last change on this file since 592 was 592, checked in by katerina, 2 days ago

Fixes for compiler warnings.

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