Changeset 193


Ignore:
Timestamp:
Nov 14, 2008, 8:12:32 PM (16 years ago)
Author:
katerina
Message:

Report command/user for open ports on FreeBSD.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/sh_port2proc.c

    r180 r193  
    4646#if defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
    4747
    48 #if defined(__linux__)
     48/****************************************************************************
     49 *
     50 *  >>> COMMON CODE <<<
     51 *
     52 ****************************************************************************/
     53#if defined(__linux__) || defined(__FreeBSD__)
    4954 
    5055#include "samhain.h"
     
    5560#define FIL__  _("sh_port2proc.c")
    5661
     62#endif
     63
     64/****************************************************************************
     65 *
     66 *  >>> LINUX CODE <<<
     67 *
     68 ****************************************************************************/
     69
     70#if defined(__linux__)
     71
    5772static  size_t  sh_minpid = 0x0001;
    5873static  size_t  sh_maxpid = 0x8000;
     
    6378
    6479#if defined(S_IFLNK) && !defined(S_ISLNK)
    65 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
     80# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
    6681#else
    67 #if !defined(S_ISLNK)
    68 #define S_ISLNK(mode) (0)
    69 #endif
     82# if !defined(S_ISLNK)
     83#  define S_ISLNK(mode) (0)
     84# endif
    7085#endif
    7186
     
    294309#include <arpa/inet.h>
    295310
     311/* returns the command and fills the 'user' array
     312 */
    296313char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
    297314                          char * user, size_t userlen)
     
    350367}
    351368
    352 #else /* !defined(__linux__) */
     369
     370/****************************************************************************
     371 *
     372 *  >>> FREEBSD CODE <<<
     373 *
     374 ****************************************************************************/
     375
     376#elif defined(__FreeBSD__)
     377
     378/* Uses code from sockstat.c. Error and memory handling modified.
     379 * Only required functions from sockstat.c are included.
     380 */
     381
     382/*-
     383 * Copyright (c) 2002 Dag-Erling Co<EF>dan Sm<F8>rgrav
     384 * All rights reserved.
     385 *
     386 * Redistribution and use in source and binary forms, with or without
     387 * modification, are permitted provided that the following conditions
     388 * are met:
     389 * 1. Redistributions of source code must retain the above copyright
     390 *    notice, this list of conditions and the following disclaimer
     391 *    in this position and unchanged.
     392 * 2. Redistributions in binary form must reproduce the above copyright
     393 *    notice, this list of conditions and the following disclaimer in the
     394 *    documentation and/or other materials provided with the distribution.
     395 * 3. The name of the author may not be used to endorse or promote products
     396 *    derived from this software without specific prior written permission.
     397 *
     398 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     399 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     400 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     401 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     402 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     403 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     404 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     405 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     406 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     407 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     408 */
     409#include <sys/cdefs.h>
     410__FBSDID("$FreeBSD: src/usr.bin/sockstat/sockstat.c,v 1.13.2.1.4.1 2008/10/02 02:57:24 kensmith Exp $");
     411
     412#include <sys/param.h>
     413#include <sys/socket.h>
     414#include <sys/socketvar.h>
     415#include <sys/sysctl.h>
     416#include <sys/file.h>
     417#include <sys/user.h>
     418
     419#include <sys/un.h>
     420#include <sys/unpcb.h>
     421
     422#include <net/route.h>
     423
     424#include <netinet/in.h>
     425#include <netinet/in_pcb.h>
     426#include <netinet/tcp.h>
     427#include <netinet/tcp_seq.h>
     428#include <netinet/tcp_var.h>
     429#include <arpa/inet.h>
     430
     431#include <ctype.h>
     432#include <errno.h>
     433#include <netdb.h>
     434#include <stdio.h>
     435#include <stdlib.h>
     436
     437#include <unistd.h>
     438
     439static int       opt_4 = 1;         /* Show IPv4 sockets */
     440static int       opt_6 = 0;         /* Show IPv6 sockets */
     441static int       opt_c = 0;         /* Show connected sockets */
     442static int       opt_l = 1;         /* Show listening sockets */
     443static int       opt_u = 0;         /* Show Unix domain sockets */
     444static int       opt_v = 0;         /* Verbose mode */
     445
     446struct sock {
     447        void *socket;
     448        void *pcb;
     449        int vflag;
     450        int family;
     451        int proto;
     452
     453        struct sockaddr_storage laddr;
     454        struct sockaddr_storage faddr;
     455        struct sock *next;
     456};
     457
     458#define HASHSIZE 1009
     459static struct sock *sockhash[HASHSIZE];
     460
     461static struct xfile *xfiles;
     462static int nxfiles;
     463
     464
     465static void * xrealloc(void * buf, size_t len0, size_t len)
     466{
     467  if (len > 0)
     468    {
     469      void xbuf = SH_ALLOC(len);
     470      memcpy(xbuf, buf, len0);
     471      SH_FREE(buf);
     472      return xbuf;
     473    }
     474  SH_FREE(buf);
     475  return NULL;
     476}
     477
     478/* Sets address and port in struct sockaddr_storage *sa
     479 */
     480static void
     481sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port)
     482{
     483        struct sockaddr_in *sin4;
     484        struct sockaddr_in6 *sin6;
     485
     486        bzero(sa, sizeof *sa);
     487        switch (af) {
     488        case AF_INET:
     489                sin4 = (struct sockaddr_in *)sa;
     490                sin4->sin_len = sizeof *sin4;
     491                sin4->sin_family = af;
     492                sin4->sin_port = port;
     493                sin4->sin_addr = *(struct in_addr *)addr;
     494                break;
     495        case AF_INET6:
     496                sin6 = (struct sockaddr_in6 *)sa;
     497                sin6->sin6_len = sizeof *sin6;
     498                sin6->sin6_family = af;
     499                sin6->sin6_port = port;
     500                sin6->sin6_addr = *(struct in6_addr *)addr;
     501                break;
     502        default:
     503                return;
     504        }
     505}
     506
     507/* Get socket information from the kernel.
     508 */
     509static void
     510gather_inet(int proto)
     511{
     512        struct xinpgen *xig, *exig;
     513        struct xinpcb *xip;
     514        struct xtcpcb *xtp;
     515        struct inpcb *inp;
     516        struct xsocket *so;
     517        struct sock *sock;
     518        char varname[32];
     519        size_t len, bufsize, bufsize0;
     520        void *buf;
     521        int hash, retry, vflag;
     522
     523        vflag = 0;
     524        if (opt_4)
     525                vflag |= INP_IPV4;
     526        if (opt_6)
     527                vflag |= INP_IPV6;
     528
     529        switch (proto) {
     530        case IPPROTO_TCP:
     531          sl_strlcpy(varname, _("net.inet.tcp.pcblist"), sizeof(varname));
     532                break;
     533        case IPPROTO_UDP:
     534                sl_strlcpy(varname, _("net.inet.udp.pcblist"), sizeof(varname));
     535                break;
     536        case IPPROTO_DIVERT:
     537                sl_strlcpy(varname, _("net.inet.divert.pcblist"), sizeof(varname));
     538                break;
     539        default:
     540                return;
     541        }
     542
     543        buf = NULL;
     544        bufsize  = 8192;
     545        bufsize0 = bufsize;
     546        retry = 5;
     547        do {
     548                for (;;) {
     549                        buf = xrealloc(buf, bufsize0, bufsize);
     550                        bufsize0 = bufsize;
     551                        len = bufsize;
     552                        if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
     553                                break;
     554                        if (errno == ENOENT)
     555                                goto out;
     556                        if (errno != ENOMEM)
     557                          {
     558                            SH_MUTEX_LOCK(mutex_thread_nolog);
     559                            sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     560                                            _("sysctlbyname()"),
     561                                            _("gather_inet"));
     562                            SH_MUTEX_UNLOCK(mutex_thread_nolog);
     563                            return;
     564                          }
     565                        bufsize *= 2;
     566                }
     567                xig = (struct xinpgen *)buf;
     568                exig = (struct xinpgen *)(void *)
     569                    ((char *)buf + len - sizeof *exig);
     570                if (xig->xig_len != sizeof *xig ||
     571                    exig->xig_len != sizeof *exig)
     572                  {
     573                    SH_MUTEX_LOCK(mutex_thread_nolog);
     574                    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     575                                    _("struct xinpgen size mismatch"),
     576                                    _("gather_inet"));
     577                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
     578                    goto out;
     579                  }
     580
     581        } while (xig->xig_gen != exig->xig_gen && retry--);
     582
     583        if (xig->xig_gen != exig->xig_gen && opt_v)
     584                  {
     585                    SH_MUTEX_LOCK(mutex_thread_nolog);
     586                    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     587                                    _("data may be inconsistent"),
     588                                    _("gather_inet"));
     589                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
     590                  }
     591
     592        for (;;) {
     593                xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
     594                if (xig >= exig)
     595                        break;
     596                switch (proto) {
     597                case IPPROTO_TCP:
     598                        xtp = (struct xtcpcb *)xig;
     599                        if (xtp->xt_len != sizeof *xtp) {
     600                                SH_MUTEX_LOCK(mutex_thread_nolog);
     601                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     602                                                _("struct xtcpcb size mismatch"),
     603                                                _("gather_inet"));
     604                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
     605                                goto out;
     606                        }
     607                        inp = &xtp->xt_inp;
     608                        so = &xtp->xt_socket;
     609                        break;
     610                case IPPROTO_UDP:
     611                case IPPROTO_DIVERT:
     612                        xip = (struct xinpcb *)xig;
     613                        if (xip->xi_len != sizeof *xip) {
     614                                SH_MUTEX_LOCK(mutex_thread_nolog);
     615                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     616                                                _("struct xinpcb size mismatch"),
     617                                                _("gather_inet"));
     618                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
     619                                goto out;
     620                        }
     621                        inp = &xip->xi_inp;
     622                        so = &xip->xi_socket;
     623                        break;
     624                default:
     625                        return;
     626                }
     627                if ((inp->inp_vflag & vflag) == 0)
     628                        continue;
     629                if (inp->inp_vflag & INP_IPV4) {
     630                        if ((inp->inp_fport == 0 && !opt_l) ||
     631                            (inp->inp_fport != 0 && !opt_c))
     632                                continue;
     633                } else if (inp->inp_vflag & INP_IPV6) {
     634                        if ((inp->in6p_fport == 0 && !opt_l) ||
     635                            (inp->in6p_fport != 0 && !opt_c))
     636                                continue;
     637                } else {
     638                        if (opt_v) {
     639                                char errmsg[64];
     640                                sl_snprintf(errmsg, sizeof(errmsg),
     641                                            _("invalid vflag 0x%x"), inp->inp_vflag);
     642                                SH_MUTEX_LOCK(mutex_thread_nolog);
     643                                sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     644                                                errmsg,
     645                                                _("gather_inet"));
     646                                SH_MUTEX_UNLOCK(mutex_thread_nolog);
     647                                continue;
     648                        }
     649                }
     650
     651                sock = SH_ALLOC(sizeof *sock);
     652                memset(sock, '\0', sizeof (*sock));
     653
     654                sock->socket = so->xso_so;
     655                sock->proto = proto;
     656                if (inp->inp_vflag & INP_IPV4) {
     657                        sock->family = AF_INET;
     658                        sockaddr(&sock->laddr, sock->family,
     659                            &inp->inp_laddr, inp->inp_lport);
     660                        sockaddr(&sock->faddr, sock->family,
     661                            &inp->inp_faddr, inp->inp_fport);
     662                } else if (inp->inp_vflag & INP_IPV6) {
     663                        sock->family = AF_INET6;
     664                        sockaddr(&sock->laddr, sock->family,
     665                            &inp->in6p_laddr, inp->in6p_lport);
     666                        sockaddr(&sock->faddr, sock->family,
     667                            &inp->in6p_faddr, inp->in6p_fport);
     668                }
     669                sock->vflag = inp->inp_vflag;
     670
     671                hash = (int)((uintptr_t)sock->socket % HASHSIZE);
     672                sock->next = sockhash[hash];
     673                sockhash[hash] = sock;
     674        }
     675out:
     676        free(buf);
     677}
     678
     679static void
     680getfiles(void)
     681{
     682        size_t len;
     683        size_t len0;
     684
     685        xfiles = SH_ALLOC(len = sizeof *xfiles);
     686        len0   = len;
     687
     688        while (sysctlbyname(_("kern.file"), xfiles, &len, 0, 0) == -1) {
     689                if (errno != ENOMEM)
     690                  {
     691                    SH_MUTEX_LOCK(mutex_thread_nolog);
     692                    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
     693                                    _("sysctlbyname()"),
     694                                    _("getfiles"));
     695                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
     696                  }
     697                len *= 2;
     698                xfiles = xrealloc(xfiles, len0, len);
     699                len0   = len;
     700        }
     701        if (len > 0 && xfiles->xf_size != sizeof *xfiles)
     702                if (errno != ENOMEM)
     703                  {
     704                    SH_MUTEX_LOCK(mutex_thread_nolog);
     705                    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
     706                                    _("struct xfile size mismatch"),
     707                                    _("getfiles"));
     708                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
     709                  }
     710        nxfiles = len / sizeof *xfiles;
     711}
     712
     713static const char *
     714getprocname(pid_t pid)
     715{
     716        static struct kinfo_proc proc;
     717        size_t len;
     718        int mib[4];
     719
     720        mib[0] = CTL_KERN;
     721        mib[1] = KERN_PROC;
     722        mib[2] = KERN_PROC_PID;
     723        mib[3] = (int)pid;
     724        len = sizeof proc;
     725        if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
     726                /* Do not warn if the process exits before we get its name. */
     727                if (errno != ESRCH)
     728                  {
     729                    SH_MUTEX_LOCK(mutex_thread_nolog);
     730                    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_SUBGEN,
     731                                    _("sysctl()"),
     732                                    _("getfiles"));
     733                    SH_MUTEX_UNLOCK(mutex_thread_nolog);
     734                  }
     735                return ("-");
     736        }
     737        return (proc.ki_ocomm);
     738}
     739
     740char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
     741                          char * user, size_t userlen)
     742{
     743  struct xfile *xf;
     744  struct in_addr * haddr;
     745 
     746  for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
     747   
     748    if (xf->xf_data == NULL)
     749      continue;
     750   
     751    /* Find the socket in sockhash[] that corresponds to it
     752     */
     753    hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
     754    for (s = sockhash[hash]; s != NULL; s = s->next)
     755      if ((void *)s->socket == xf->xf_data)
     756        break;
     757   
     758    if (s->proto != proto)
     759      continue;
     760
     761    if (s->family != AF_INET /* && s->family != AF_INET6 */)
     762      continue;
     763
     764    if (sport != ntohs(((struct sockaddr_in *)s)->sin_port))
     765      continue;
     766
     767    haddr = &((struct sockaddr_in *)s)->sin_addr;
     768    if (haddr.s_addr == saddr->s_addr)
     769      {
     770        char * tmp  = sh_unix_getUIDname (SH_ERR_ALL, xf->xf_uid, user, userlen);
     771        if (!tmp)
     772          sl_snprintf (user, userlen, "%ld", (unsigned long) xf->xf_uid);
     773        return sh_util_strdup(getprocname(xf->xf_pid));
     774      }
     775  }
     776}
     777
     778static void sockdel(struct sock * sock)
     779{
     780  if (sock)
     781    {
     782      if (sock->next)
     783        sockdel(sock->next);
     784      SH_FREE(sock);
     785    }
     786  return;
     787}
     788
     789int sh_port2proc_prepare()
     790{
     791  int i;
     792
     793  if (xfiles)
     794    {
     795      SH_FREE(xfiles);
     796      xfiles = NULL;
     797    }
     798
     799  for (i = 0; i < HASHSIZE; ++i)
     800    sockdel(sockhash[i]);
     801
     802  /* Inet connections
     803   */
     804  gather_inet(IPPROTO_TCP);
     805  gather_inet(IPPROTO_UDP);
     806  gather_inet(IPPROTO_DIVERT);
     807
     808  getfiles();
     809
     810  return 0;
     811}
     812
     813#else /* !defined(__linux__) && !defined(__FreeBSD__) */
    353814
    354815char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
Note: See TracChangeset for help on using the changeset viewer.