From 2dc13e96f14e0f3fea89ba8209e14c6917f7450f Mon Sep 17 00:00:00 2001 From: OldGregg Date: Mon, 3 Mar 2014 16:26:08 -0500 Subject: [PATCH] Completely remote the need for /proc filesytem and iproute2. This commit uses lsof, which is available in Linux, OSX, and other BSD variants. Auto-logins should fail to a login prompt with this patch when run under cygwin. --- butterfly/routes.py | 4 +-- butterfly/utils.py | 86 +++++++++++---------------------------------- 2 files changed, 23 insertions(+), 67 deletions(-) diff --git a/butterfly/routes.py b/butterfly/routes.py index bdcdcbe..8d3abbe 100644 --- a/butterfly/routes.py +++ b/butterfly/routes.py @@ -208,8 +208,8 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler): if field[0][0] == 'commonName': self.user = self.callee = field[0][1] - if self.socket.local and self.socket.uid is not None: - self.caller = utils.User(uid=self.socket.uid) + if self.socket.local and self.socket.user is not None: + self.caller = utils.User(name=self.socket.user) else: # We don't know uid is on the other machine pass diff --git a/butterfly/utils.py b/butterfly/utils.py index 82dc34d..93c2055 100644 --- a/butterfly/utils.py +++ b/butterfly/utils.py @@ -19,11 +19,11 @@ import os import pwd from logging import getLogger - +import subprocess +import re log = getLogger('butterfly') - class User(object): def __init__(self, uid=None, name=None): if uid is None and not name: @@ -62,53 +62,20 @@ class User(object): return "%s [%r]" % (self.name, self.uid) -def get_socket_line(port): - try: - with open('/proc/net/tcp') as k: - lines = k.readlines() - for line in lines: - # Look for local address with peer port - if line.split()[1] == '0100007F:%X' % port: - # We got the socket - return line.split() - except: - log.debug('getting socket inet4 line fail', exc_info=True) - - try: - with open('/proc/net/tcp6') as k: - lines = k.readlines() - for line in lines: - # Look for local address with peer port - if line.split()[1] == ( - '00000000000000000000000001000000:%X' % port): - # We got the socket - return line.split() - except: - log.debug('getting socket inet6 line fail', exc_info=True) - - -def get_env(inode): - for pid in os.listdir("/proc/"): - if not pid.isdigit(): - continue - for fd in os.listdir("/proc/%s/fd/" % pid): - lnk = "/proc/%s/fd/%s" % (pid, fd) - if not os.path.islink(lnk): - continue - if 'socket:[%s]' % inode == os.readlink(lnk): - with open('/proc/%s/status' % pid) as s: - for line in s.readlines(): - if line.startswith('PPid:'): - with open('/proc/%s/environ' % - line[len('PPid:'):].strip()) as e: - keyvals = e.read().split('\x00') - env = {} - for keyval in keyvals: - if '=' in keyval: - key, val = keyval.split('=', 1) - env[key] = val - return env - +def get_socket_line(addr, port): + # May want to make this into a dictionary in the future... + regex = "\w+\s+(?P\d+)\s+(?P\w+).*\s" \ + "(?P.*?):(?P\d+)->(?P.*?):(?P\d+)" + output = subprocess.check_output(['lsof', '-Pni']) + lines = output.split('\n') + for line in lines: + # Look for local address with peer port + match = re.findall(regex, line) + if len(match): + match = match[0] + if int(match[5]) == port: + return match + raise Exception("Couldn't find a match!") class Socket(object): @@ -120,30 +87,19 @@ class Socket(object): self.remote_addr = pn[0] self.remote_port = pn[1] try: - line = get_socket_line(self.remote_port) + self.user = get_socket_line(self.remote_addr, self.remote_port)[1] except Exception: - line = None - - if line: - self.uid = int(line[7]) - self.inode = line[9] - else: - self.uid = None - self.inode = None + self.user = None + # su will handle setting up the user environment, so make this empty. self.env = {} - if self.local and self.inode: - try: - self.env = get_env(self.inode) - except Exception: - log.debug('Unable to get env', exc_info=True) @property def local(self): return self.remote_addr in ['127.0.0.1', '::1'] def __repr__(self): - return '' % ( + return '' % ( self.local_addr, self.local_port, self.remote_addr, self.remote_port, - self.uid, self.inode, len(self.env)) + self.user)