/* * SSLsplit - transparent and scalable SSL/TLS interception * Copyright (c) 2009-2014, Daniel Roethlisberger * All rights reserved. * http://www.roe.ch/SSLsplit * * 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 unmodified, 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 AUTHOR ``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 AUTHOR 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. */ #include "proc.h" #include "log.h" #include "attrib.h" #include #include #include #include #ifdef HAVE_DARWIN_LIBPROC #include #endif /* HAVE_DARWIN_LIBPROC */ /* * Local process lookup. */ #ifdef HAVE_DARWIN_LIBPROC int proc_lookup_by_addr(pid_t *result, struct sockaddr *dst_addr, UNUSED socklen_t dst_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); pids = malloc(sizeof(pid_t) * pid_count); if (!pids) { goto errout1; } pid_count = proc_listallpids(pids, sizeof(pid_t) * pid_count); 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 == -1) { /* 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)) == -1) { /* process may have exited or socket may have * been released. */ continue; } if (sinfo.psi.soi_kind != SOCKINFO_TCP) { continue; } uint16_t sock_fport = sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport; if (sinfo.psi.soi_family == AF_INET && dst_addr->sa_family == AF_INET) { struct sockaddr_in *dst_sai = (struct sockaddr_in *)dst_addr; if (dst_sai->sin_addr.s_addr != sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4.s_addr) { continue; } if (dst_sai->sin_port != sock_fport) { continue; } } else if (sinfo.psi.soi_family == AF_INET6 && dst_addr->sa_family == AF_INET6) { struct sockaddr_in6 *dst_sai = (struct sockaddr_in6 *)dst_addr; if (memcmp(dst_sai->sin6_addr.s6_addr, sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6.s6_addr, 16) != 0) { continue; } if (dst_sai->sin6_port != sock_fport) { continue; } } /* valid match */ *result = pid; break; } } ret = 0; free(fds); errout2: free(pids); errout1: return ret; } #else /* HAVE_DARWIN_LIBPROC */ int proc_lookup_by_addr(pid_t *result, UNUSED struct sockaddr *dst_addr, UNUSED socklen_t dst_addrlen) { *result = -1; return 0; } #endif /* !HAVE_DARWIN_LIBPROC */ /* vim: set noet ft=c: */