summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c462
1 files changed, 0 insertions, 462 deletions
diff --git a/proc.c b/proc.c
deleted file mode 100644
index 234875d..0000000
--- a/proc.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*-
- * SSLsplit - transparent SSL/TLS interception
- * https://www.roe.ch/SSLsplit
- *
- * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef __FreeBSD__
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/user.h>
-
-#include <netinet/in.h>
-#include <netinet/in_pcb.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_var.h>
-#include <arpa/inet.h>
-#endif /* __FreeBSD__ */
-
-#include "proc.h"
-
-#include "log.h"
-#include "attrib.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#ifdef HAVE_DARWIN_LIBPROC
-#include <libproc.h>
-#endif /* HAVE_DARWIN_LIBPROC */
-
-
-/*
- * Local process lookup.
- */
-
-
-#ifdef __FreeBSD__
-
-/*
- * Get the list of open files from the kernel and do basic consistency checks.
- * If successful, returns 0, and *pxfiles will receive a pointer to the
- * received xfiles structure and *pnxfiles the number of file records in it.
- * If unsuccessful, returns -1 and *pxfiles will be NULL.
- * Caller is responsible to free() *pxfiles after use.
- */
-static int
-proc_freebsd_getfiles(struct xfile **pxfiles, int *pnxfiles)
-{
- int mib[4];
- size_t sz;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_FILE;
- mib[2] = mib[3] = 0;
-
- for (;;) {
- if (sysctl(mib, 2, NULL, &sz, NULL, 0) < 0) {
- *pxfiles = NULL;
- return -1;
- }
- if (!(*pxfiles = malloc(sz))) {
- return -1;
- }
- if (sysctl(mib, 2, *pxfiles, &sz, NULL, 0) < 0) {
- free(*pxfiles);
- if (errno == ENOMEM)
- continue;
- *pxfiles = NULL;
- return -1;
- }
- break;
- }
-
- if (sz > 0 && (*pxfiles)->xf_size != sizeof **pxfiles) {
- log_err_printf("struct xfile size mismatch\n");
- return -1;
- }
- *pnxfiles = sz / sizeof **pxfiles;
-
- return 0;
-}
-
-/*
- * Get the list of active TCP connections and do basic consistency checks.
- * If successful, returns 0, and *pxig will receive a pointer to the
- * received data structure, *pexig a pointer to the end of the buffer.
- * If unsuccessful, returns -1 and *pxig will be NULL.
- * Caller is responsible to free() *pxig after use.
- */
-static int
-proc_freebsd_gettcppcblist(struct xinpgen **pxig, struct xinpgen **pexig)
-{
- int mib[4];
- size_t sz;
- int retry = 5;
-
- mib[0] = CTL_NET;
- mib[1] = PF_INET;
- mib[2] = IPPROTO_TCP;
- mib[3] = TCPCTL_PCBLIST;
- do {
- for (;;) {
- if (sysctl(mib, 4, NULL, &sz, NULL, 0) < 0) {
- *pxig = NULL;
- return -1;
- }
- if (!(*pxig = malloc(sz))) {
- return -1;
- }
- if (sysctl(mib, 4, *pxig, &sz, NULL, 0) < 0) {
- free(*pxig);
- if (errno == ENOMEM)
- continue;
- *pxig = NULL;
- return -1;
- }
- break;
- }
-
- *pexig = (struct xinpgen *)(void *)
- ((char *)(*pxig) + sz - sizeof(**pexig));
- if ((*pxig)->xig_len != sizeof(**pxig) ||
- (*pexig)->xig_len != sizeof(**pexig)) {
- log_err_printf("struct xinpgen size mismatch\n");
- free(*pxig);
- *pxig = NULL;
- return -1;
- }
- } while ((*pxig)->xig_gen != (*pexig)->xig_gen && retry--);
-
- /* check if first and last record are from same generation */
- if ((*pxig)->xig_gen != (*pexig)->xig_gen) {
- log_err_printf("Warning: data inconsistent "
- "(xig->xig_gen != exig->xig_gen)\n");
- }
-
- return 0;
-}
-
-int
-proc_freebsd_pid_for_addr(pid_t *result, struct sockaddr *src_addr,
- UNUSED socklen_t src_addrlen)
-{
- struct xfile *xfiles;
- int nxfiles;
- struct xfile *xf;
-
- struct xinpgen *xig, *exig, *txig;
- struct xtcpcb *xtp;
-#if __FreeBSD_version >= 1200026
- struct xinpcb *inp;
-#else
- struct inpcb *inp;
-#endif
- struct xsocket *so;
-
- if (proc_freebsd_getfiles(&xfiles, &nxfiles) == -1) {
- return -1;
- }
-
- if (proc_freebsd_gettcppcblist(&xig, &exig) == -1) {
- free(xfiles);
- return -1;
- }
-
- for (txig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
- txig < exig;
- txig = (struct xinpgen *)(void *)((char *)txig + txig->xig_len)) {
- xtp = (struct xtcpcb *)txig;
- if (xtp->xt_len != sizeof *xtp) {
- free(xfiles);
- free(xig);
- return -1;
- }
- inp = &xtp->xt_inp;
-#if __FreeBSD_version >= 1200026
- so = &inp->xi_socket;
-#else
- so = &xtp->xt_socket;
-#endif
-
- if (!(so->so_state & SS_ISCONNECTED))
- /* we are only interested in connected sockets */
- continue;
-
- if ((inp->inp_vflag & INP_IPV4) &&
- (src_addr->sa_family == AF_INET)) {
- struct sockaddr_in *src_sai =
- (struct sockaddr_in *)src_addr;
-
- if (src_sai->sin_addr.s_addr != inp->inp_laddr.s_addr) {
- continue;
- }
-
- if (src_sai->sin_port != inp->inp_lport) {
- continue;
- }
- } else if ((inp->inp_vflag & INP_IPV6) &&
- (src_addr->sa_family == AF_INET6)) {
- struct sockaddr_in6 *src_sai =
- (struct sockaddr_in6 *)src_addr;
-
- if (memcmp(src_sai->sin6_addr.s6_addr, inp->in6p_laddr.s6_addr, 16) != 0) {
- continue;
- }
-
- if (src_sai->sin6_port != inp->inp_lport) {
- continue;
- }
- } else {
- /* other address family */
- continue;
- }
-
- /* valid match */
-
- /* only do this if we have a match */
- xf = NULL;
- for (int i = 0; i < nxfiles; ++i) {
- if (so->xso_so == xfiles[i].xf_data) {
- /* there can be several processes sharing a
- * connected socket file descriptor */
- xf = &xfiles[i];
- }
- }
- if (!xf)
- continue;
- *result = xf->xf_pid;
- break;
- }
-
- free(xfiles);
- free(xig);
- return 0;
-}
-
-int
-proc_freebsd_get_info(pid_t pid, char **path, uid_t *uid, gid_t *gid) {
- static struct kinfo_proc proc;
- size_t len;
- int mib[4];
- char buf[PATH_MAX + 1];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PATHNAME;
- mib[3] = (int)pid;
- len = sizeof(buf);
- if (sysctl(mib, 4, buf, &len, NULL, 0) == -1) {
- if (errno != ESRCH) {
- log_err_printf("Failed to get proc pathname: %s (%i)",
- strerror(errno), errno);
- }
- *path = NULL;
- } else {
- *path = strdup(buf);
- }
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = (int)pid;
- len = sizeof proc;
- if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
- if (errno != ESRCH) {
- log_err_printf("Failed to get proc info: %s (%i)",
- strerror(errno), errno);
- }
- *uid = -1;
- *gid = -1;
- } else {
- if (*path == NULL)
- *path = strdup(proc.ki_comm);
- *uid = proc.ki_uid;
- *gid = proc.ki_groups[0];
- }
-
- return 0;
-}
-
-#endif /* __FreeBSD__ */
-
-
-#ifdef HAVE_DARWIN_LIBPROC
-
-int
-proc_darwin_pid_for_addr(pid_t *result, struct sockaddr *src_addr,
- UNUSED socklen_t src_addrlen)
-{
- pid_t *pids = NULL;
- struct proc_fdinfo *fds = NULL;
- int ret = -1;
-
- /* default result if no pid matches */
- *result = -1;
-
- /* iterate over all pids to find a matching socket */
- int pid_count = proc_listallpids(NULL, 0);
- if (pid_count <= 0)
- goto errout1;
- pids = malloc(sizeof(pid_t) * pid_count);
- if (!pids) {
- goto errout1;
- }
-
- pid_count = proc_listallpids(pids, sizeof(pid_t) * pid_count);
- if (pid_count <= 0)
- goto errout2;
-
- for (int i = 0; i < pid_count; i++) {
- pid_t pid = pids[i];
-
- /* fetch fd info for this pid */
- int fd_count = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
- if (fd_count <= 0) {
- /* failed to fetch pidinfo; process may have exited */
- continue;
- }
-
- if (fds) {
- free(fds);
- }
- fds = malloc(PROC_PIDLISTFD_SIZE * fd_count);
- if (!fds) {
- goto errout2;
- }
- fd_count = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds,
- sizeof(fds[0]) * fd_count);
-
- /* look for a matching socket file descriptor */
- for (int j = 0; j < fd_count; j++) {
- struct proc_fdinfo *fd = &fds[j];
- struct socket_fdinfo sinfo;
-
- if (fd->proc_fdtype != PROX_FDTYPE_SOCKET) {
- continue;
- }
-
- if (proc_pidfdinfo(pid, fd->proc_fd,
- PROC_PIDFDSOCKETINFO,
- &sinfo,
- sizeof(struct socket_fdinfo)) <= 0) {
- /* process may have exited or socket may have
- * been released. */
- continue;
- }
-
- if (sinfo.psi.soi_kind != SOCKINFO_TCP) {
- continue;
- }
-
- uint16_t sock_lport = sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport;
- if (sinfo.psi.soi_family == AF_INET &&
- src_addr->sa_family == AF_INET) {
- struct sockaddr_in *src_sai = (struct sockaddr_in *)src_addr;
-
- if (src_sai->sin_addr.s_addr != sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4.s_addr) {
- continue;
- }
-
- if (src_sai->sin_port != sock_lport) {
- continue;
- }
- } else if (sinfo.psi.soi_family == AF_INET6 &&
- src_addr->sa_family == AF_INET6) {
- struct sockaddr_in6 *src_sai = (struct sockaddr_in6 *)src_addr;
-
- if (memcmp(src_sai->sin6_addr.s6_addr, sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6.s6_addr, 16) != 0) {
- continue;
- }
-
- if (src_sai->sin6_port != sock_lport) {
- continue;
- }
- } else {
- /* other address family */
- continue;
- }
-
- /* valid match */
- *result = pid;
- goto success;
- }
- }
-
-success:
- ret = 0;
- free(fds);
-errout2:
- free(pids);
-errout1:
- return ret;
-}
-
-/*
- * Fetch process info for the given pid.
- * On success, returns 0 and fills in path, uid, and gid.
- * Caller must free returned path string.
- * Returns -1 on failure, or if unsupported on this platform.
- */
-int
-proc_darwin_get_info(pid_t pid, char **path, uid_t *uid, gid_t *gid) {
- /* fetch process structure */
- struct proc_bsdinfo bsd_info;
- if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &bsd_info,
- sizeof(bsd_info)) <= 0) {
- return -1;
- }
-
- *uid = bsd_info.pbi_uid;
- *gid = bsd_info.pbi_gid;
-
- /* fetch process path */
- *path = malloc(PROC_PIDPATHINFO_MAXSIZE);
- if (!*path) {
- return -1;
- }
- int path_len = proc_pidpath(pid, *path, PROC_PIDPATHINFO_MAXSIZE);
- if (path_len <= 0) {
- free(*path);
- *path = NULL;
- return -1;
- }
-
- return 0;
-}
-
-#endif /* HAVE_DARWIN_LIBPROC */
-
-/* vim: set noet ft=c: */
-
-
-