Example #1
0
 def send(self, dstip, data):
     debug2('UDP: sending to %r port %d\n' % dstip)
     try:
         self.sock.sendto(data, dstip)
     except socket.error, e:
         log('UDP send to %r port %d: %s\n' % (dstip[0], dstip[1], e))
         return
Example #2
0
 def __init__(self, mux, channel):
     SockWrapper.__init__(self, mux.rsock, mux.wsock)
     self.mux = mux
     self.channel = channel
     self.mux.channels[channel] = self.got_packet
     self.socks = []
     debug2('new channel: %d\n' % channel)
Example #3
0
def connect_dst(family, ip, port):
    debug2('Connecting to %s:%d\n' % (ip, port))
    outsock = socket.socket(family)
    outsock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
    return SockWrapper(outsock, outsock,
                       connect_to=(ip, port),
                       peername = '%s:%d' % (ip, port))
Example #4
0
def runonce(handlers, mux):
    r = []
    w = []
    x = []
    to_remove = filter(lambda s: not s.ok, handlers)
    for h in to_remove:
        handlers.remove(h)

    for s in handlers:
        s.pre_select(r, w, x)
    debug2('Waiting: %d r=%r w=%r x=%r (fullness=%d/%d)\n'
           % (len(handlers), _fds(r), _fds(w), _fds(x),
               mux.fullness, mux.too_full))
    (r, w, x) = select.select(r, w, x)
    debug2('  Ready: %d r=%r w=%r x=%r\n'
           % (len(handlers), _fds(r), _fds(w), _fds(x)))
    ready = r + w + x
    did = {}
    for h in handlers:
        for s in h.socks:
            if s in ready:
                h.callback()
                did[s] = 1
    for s in ready:
        if not s in did:
            raise Fatal('socket %r was not used by any handler' % s)
Example #5
0
 def send(self, dstip, data):
     debug2('UDP: sending to %r port %d\n' % dstip)
     try:
         self.sock.sendto(data, dstip)
     except socket.error, e:
         log('UDP send to %r port %d: %s\n' % (dstip[0], dstip[1], e))
         return
Example #6
0
 def nowrite(self):
     if not self.shut_write:
         debug2('%r: done writing\n' % self)
         self.shut_write = True
         try:
             self.wsock.shutdown(SHUT_WR)
         except socket.error, e:
             self.seterr('nowrite: %s' % e)
Example #7
0
def _sname(typ, t, fromdir=None):
    # FIXME: t.replace(...) is non-reversible and non-unique here!
    if fromdir:
        t = os.path.join(fromdir, t)
    tnew = relpath(t, vars.BASE)
    v = vars.BASE + ("/.redo/%s^%s" % (typ, tnew.replace("/", "^")))
    debug2("sname: (%r) %r -> %r\n" % (os.getcwd(), t, tnew))
    return v
Example #8
0
 def send(self, channel, cmd, data):
     data = str(data)
     assert(len(data) <= 65535)
     p = struct.pack('!ccHHH', 'S', 'S', channel, cmd, len(data)) + data
     self.outbuf.append(p)
     debug2(' > channel=%d cmd=%s len=%d (fullness=%d)\n'
            % (channel, cmd_to_name.get(cmd, hex(cmd)),
               len(data), self.fullness))
     self.fullness += len(data)
Example #9
0
def _check_revdns(ip):
    debug2(' > rev: %s\n' % ip)
    try:
        r = socket.gethostbyaddr(ip)
        debug3('<    %s\n' % r[0])
        check_host(r[0])
        found_host(r[0], ip)
    except socket.herror:
        pass
Example #10
0
 def flush(self):
     self.wsock.setblocking(False)
     if self.outbuf and self.outbuf[0]:
         wrote = _nb_clean(os.write, self.wsock.fileno(), self.outbuf[0])
         debug2('mux wrote: %r/%d\n' % (wrote, len(self.outbuf[0])))
         if wrote:
             self.outbuf[0] = self.outbuf[0][wrote:]
     while self.outbuf and not self.outbuf[0]:
         self.outbuf[0:1] = []
Example #11
0
def _check_dns(hostname):
    debug2(' > dns: %s\n' % hostname)
    try:
        ip = socket.gethostbyname(hostname)
        debug3('<    %s\n' % ip)
        check_host(ip)
        found_host(hostname, ip)
    except socket.gaierror:
        pass
Example #12
0
def _check_revdns(ip):
    debug2(' > rev: %s\n' % ip)
    try:
        r = socket.gethostbyaddr(ip)
        debug3('<    %s\n' % r[0])
        check_host(r[0])
        found_host(r[0], ip)
    except socket.herror:
        pass
Example #13
0
def _check_dns(hostname):
    debug2(' > dns: %s\n' % hostname)
    try:
        ip = socket.gethostbyname(hostname)
        debug3('<    %s\n' % ip)
        check_host(ip)
        found_host(hostname, ip)
    except socket.gaierror:
        pass
Example #14
0
def _find_do_file(t):
    for dofile,basename,ext in _possible_do_files(t):
        debug2('%s: %s ?\n' % (t, dofile))
        if os.path.exists(dofile):
            state.add_dep(t, 'm', dofile)
            return dofile,basename,ext
        else:
            state.add_dep(t, 'c', dofile)
    return None,None,None
Example #15
0
def _check_netstat():
    debug2(' > netstat\n')
    argv = ['netstat', '-n']
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        content = p.stdout.read()
        p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        return
Example #16
0
 def udp_open(channel, data):
     debug2('Incoming UDP open.\n')
     family = int(data)
     mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
     if channel in udphandlers:
         raise Fatal('UDP connection channel %d already open' % channel)
     else:
         h = UdpProxy(mux, channel, family)
         handlers.append(h)
         udphandlers[channel] = h
Example #17
0
def _check_netstat():
    debug2(' > netstat\n')
    argv = ['netstat', '-n']
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        content = p.stdout.read()
        p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        return
Example #18
0
 def udp_open(channel, data):
     debug2('Incoming UDP open.\n')
     family = int(data)
     mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
     if channel in udphandlers:
         raise Fatal('UDP connection channel %d already open' % channel)
     else:
         h = UdpProxy(mux, channel, family)
         handlers.append(h)
         udphandlers[channel] = h
Example #19
0
 def callback(self):
     try:
         data = self.sock.recv(4096)
     except socket.error, e:
         if e.args[0] in ssnet.NET_ERRS:
             # might have been spurious; try again.
             # Note: these errors sometimes are reported by recv(),
             # and sometimes by send().  We have to catch both.
             debug2('DNS recv from %r: %s\n' % (self.peer, e))
             self.try_send()
             return
         else:
             log('DNS recv from %r: %s\n' % (self.peer, e))
             return
Example #20
0
def _check_etc_hosts():
    debug2(' > hosts\n')
    for line in open('/etc/hosts'):
        line = re.sub(r'#.*', '', line)
        words = line.strip().split()
        if not words:
            continue
        ip = words[0]
        names = words[1:]
        if _is_ip(ip):
            debug3('<    %s %r\n' % (ip, names))
            for n in names:
                check_host(n)
                found_host(n, ip)
Example #21
0
def _check_etc_hosts():
    debug2(' > hosts\n')
    for line in open('/etc/hosts'):
        line = re.sub(r'#.*', '', line)
        words = line.strip().split()
        if not words:
            continue
        ip = words[0]
        names = words[1:]
        if _is_ip(ip):
            debug3('<    %s %r\n' % (ip, names))
            for n in names:
                check_host(n)
                found_host(n, ip)
Example #22
0
def pf_dst(sock):
    peer = sock.getpeername()
    proxy = sock.getsockname()

    argv = (sock.family, socket.IPPROTO_TCP, peer[0], peer[1], proxy[0], proxy[1])
    pf_command_file.write("QUERY_PF_NAT %r,%r,%s,%r,%s,%r\n" % argv)
    pf_command_file.flush()
    line = pf_command_file.readline()
    debug2("QUERY_PF_NAT %r,%r,%s,%r,%s,%r" % argv + ' > ' + line)
    if line.startswith('QUERY_PF_NAT_SUCCESS '):
        (ip, port) = line[21:].split(',')
        return (ip, int(port))

    return sock.getsockname()
Example #23
0
 def callback(self):
     try:
         data = self.sock.recv(4096)
     except socket.error, e:
         if e.args[0] in ssnet.NET_ERRS:
             # might have been spurious; try again.
             # Note: these errors sometimes are reported by recv(),
             # and sometimes by send().  We have to catch both.
             debug2('DNS recv from %r: %s\n' % (self.peer, e))
             self.try_send()
             return
         else:
             log('DNS recv from %r: %s\n' % (self.peer, e))
             return
Example #24
0
def _check_smb(hostname):
    return
    global _smb_ok
    if not _smb_ok:
        return
    argv = ['smbclient', '-U', '%', '-L', hostname]
    debug2(' > smb: %s\n' % hostname)
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        lines = p.stdout.readlines()
        p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        _smb_ok = False
        return
Example #25
0
def _check_nmb(hostname, is_workgroup, is_master):
    return
    global _nmb_ok
    if not _nmb_ok:
        return
    argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname]
    debug2(' > n%d%d: %s\n' % (is_workgroup, is_master, hostname))
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        lines = p.stdout.readlines()
        rv = p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        _nmb_ok = False
        return
Example #26
0
def _check_smb(hostname):
    return
    global _smb_ok
    if not _smb_ok:
        return
    argv = ['smbclient', '-U', '%', '-L', hostname]
    debug2(' > smb: %s\n' % hostname)
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        lines = p.stdout.readlines()
        p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        _smb_ok = False
        return
Example #27
0
def _check_nmb(hostname, is_workgroup, is_master):
    return
    global _nmb_ok
    if not _nmb_ok:
        return
    argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname]
    debug2(' > n%d%d: %s\n' % (is_workgroup, is_master, hostname))
    try:
        p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null)
        lines = p.stdout.readlines()
        rv = p.wait()
    except OSError, e:
        log('%r failed: %r\n' % (argv, e))
        _nmb_ok = False
        return
Example #28
0
def pf_dst(sock):
    peer = sock.getpeername()
    proxy = sock.getsockname()

    argv = (sock.family, socket.IPPROTO_TCP, peer[0], peer[1], proxy[0],
            proxy[1])
    pf_command_file.write("QUERY_PF_NAT %r,%r,%s,%r,%s,%r\n" % argv)
    pf_command_file.flush()
    line = pf_command_file.readline()
    debug2("QUERY_PF_NAT %r,%r,%s,%r,%s,%r" % argv + ' > ' + line)
    if line.startswith('QUERY_PF_NAT_SUCCESS '):
        (ip, port) = line[21:].split(',')
        return (ip, int(port))

    return sock.getsockname()
Example #29
0
 def next(self, size):
     out = ''
     while len(out) < size:
         if self.it and not self.blob:
             try:
                 self.blob = self.it.next()
             except StopIteration:
                 self.it = None
         if self.blob:
             want = size - len(out)
             out += self.blob[:want]
             self.blob = self.blob[want:]
         if not self.it:
             break
     debug2('next(%d) returned %d\n' % (size, len(out)))
     self.ofs += len(out)
     return out
Example #30
0
 def got_packet(self, channel, cmd, data):
     debug2('<  channel=%d cmd=%s len=%d\n'
            % (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
     if cmd == CMD_PING:
         self.send(0, CMD_PONG, data)
     elif cmd == CMD_PONG:
         debug2('received PING response\n')
         self.too_full = False
         self.fullness = 0
     elif cmd == CMD_EXIT:
         self.ok = False
     elif cmd == CMD_TCP_CONNECT:
         assert(not self.channels.get(channel))
         if self.new_channel:
             self.new_channel(channel, data)
     elif cmd == CMD_DNS_REQ:
         assert(not self.channels.get(channel))
         if self.got_dns_req:
             self.got_dns_req(channel, data)
     elif cmd == CMD_UDP_OPEN:
         assert(not self.channels.get(channel))
         if self.got_udp_open:
             self.got_udp_open(channel, data)
     elif cmd == CMD_ROUTES:
         if self.got_routes:
             self.got_routes(data)
         else:
             raise Exception('got CMD_ROUTES without got_routes?')
     elif cmd == CMD_HOST_REQ:
         if self.got_host_req:
             self.got_host_req(data)
         else:
             raise Exception('got CMD_HOST_REQ without got_host_req?')
     elif cmd == CMD_HOST_LIST:
         if self.got_host_list:
             self.got_host_list(data)
         else:
             raise Exception('got CMD_HOST_LIST without got_host_list?')
     else:
         callback = self.channels.get(channel)
         if not callback:
             log('warning: closed channel %d got cmd=%s len=%d\n'
                 % (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
         else:
             callback(cmd, data)
Example #31
0
 def try_send(self):
     if self.tries >= 3:
         return
     self.tries += 1
     # FIXME! Support IPv6 nameservers
     self.peer = resolvconf_random_nameserver()[1]
     self.sock.connect((self.peer, 53))
     debug2('DNS: sending to %r\n' % self.peer)
     try:
         self.sock.send(self.request)
     except socket.error, e:
         if e.args[0] in ssnet.NET_ERRS:
             # might have been spurious; try again.
             # Note: these errors sometimes are reported by recv(),
             # and sometimes by send().  We have to catch both.
             debug2('DNS send to %r: %s\n' % (self.peer, e))
             self.try_send()
             return
         else:
             log('DNS send to %r: %s\n' % (self.peer, e))
             return
Example #32
0
 def try_send(self):
     if self.tries >= 3:
         return
     self.tries += 1
     # FIXME! Support IPv6 nameservers
     self.peer = resolvconf_random_nameserver()[1]
     self.sock.connect((self.peer, 53))
     debug2('DNS: sending to %r\n' % self.peer)
     try:
         self.sock.send(self.request)
     except socket.error, e:
         if e.args[0] in ssnet.NET_ERRS:
             # might have been spurious; try again.
             # Note: these errors sometimes are reported by recv(),
             # and sometimes by send().  We have to catch both.
             debug2('DNS send to %r: %s\n' % (self.peer, e))
             self.try_send()
             return
         else:
             log('DNS send to %r: %s\n' % (self.peer, e))
             return
Example #33
0
 def udp_req(channel, cmd, data):
     debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
     if cmd == ssnet.CMD_UDP_DATA:
         (dstip, dstport, data) = data.split(",", 2)
         dstport = int(dstport)
         debug2('is incoming UDP data. %r %d.\n' % (dstip, dstport))
         h = udphandlers[channel]
         h.send((dstip, dstport), data)
     elif cmd == ssnet.CMD_UDP_CLOSE:
         debug2('is incoming UDP close\n')
         h = udphandlers[channel]
         h.ok = False
         del mux.channels[channel]
Example #34
0
 def udp_req(channel, cmd, data):
     debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
     if cmd == ssnet.CMD_UDP_DATA:
         (dstip, dstport, data) = data.split(",", 2)
         dstport = int(dstport)
         debug2('is incoming UDP data. %r %d.\n' % (dstip, dstport))
         h = udphandlers[channel]
         h.send((dstip, dstport), data)
     elif cmd == ssnet.CMD_UDP_CLOSE:
         debug2('is incoming UDP close\n')
         h = udphandlers[channel]
         h.ok = False
         del mux.channels[channel]
Example #35
0
def connect(ssh_cmd, rhostport, python, stderr, options):
    portl = []

    if (rhostport or '').count(':') > 1:
        if rhostport.count(']') or rhostport.count('['):
            result = rhostport.split(']')
            rhost = result[0].strip('[')
            if len(result) > 1:
                result[1] = result[1].strip(':')
                if result[1] is not '':
                    portl = ['-p', str(int(result[1]))]
        # can't disambiguate IPv6 colons and a port number. pass the hostname
        # through.
        else:
            rhost = rhostport
    else:  # IPv4
        l = (rhostport or '').split(':', 1)
        rhost = l[0]
        if len(l) > 1:
            portl = ['-p', str(int(l[1]))]

    if rhost == '-':
        rhost = None

    z = zlib.compressobj(1)
    content = readfile('assembler.py')
    optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in options.items())
    content2 = (empackage(z, 'cmdline_options.py', optdata) +
                empackage(z, 'helpers.py') +
                empackage(z, 'compat/ssubprocess.py') +
                empackage(z, 'ssnet.py') + empackage(z, 'hostwatch.py') +
                empackage(z, 'server.py') + "\n")

    pyscript = r"""
                import sys;
                skip_imports=1;
                verbosity=%d;
                exec compile(sys.stdin.read(%d), "assembler.py", "exec")
                """ % (helpers.verbose or 0, len(content))
    pyscript = re.sub(r'\s+', ' ', pyscript.strip())

    if not rhost:
        # ignore the --python argument when running locally; we already know
        # which python version works.
        argv = [sys.argv[1], '-c', pyscript]
    else:
        if ssh_cmd:
            sshl = ssh_cmd.split(' ')
        else:
            sshl = ['ssh']
        if python:
            pycmd = "'%s' -c '%s'" % (python, pyscript)
        else:
            pycmd = ("P=python2; $P -V 2>/dev/null || P=python; "
                     "exec \"$P\" -c '%s'") % pyscript
        argv = (sshl + portl + [rhost, '--', pycmd])
    (s1, s2) = socket.socketpair()

    def setup():
        # runs in the child process
        s2.close()

    s1a, s1b = os.dup(s1.fileno()), os.dup(s1.fileno())
    s1.close()
    debug2('executing: %r\n' % argv)
    p = ssubprocess.Popen(argv,
                          stdin=s1a,
                          stdout=s1b,
                          preexec_fn=setup,
                          close_fds=True,
                          stderr=stderr)
    os.close(s1a)
    os.close(s1b)
    s2.sendall(content)
    s2.sendall(content2)
    return p, s2
Example #36
0
 def noread(self):
     if not self.shut_read:
         debug2('%r: done reading\n' % self)
         self.shut_read = True
Example #37
0
 def dns_req(channel, data):
     debug2('Incoming DNS request channel=%d.\n' % channel)
     h = DnsProxy(mux, channel, data)
     handlers.append(h)
     dnshandlers[channel] = h
Example #38
0
    def callback(self):
        try:
            data = self.sock.recv(4096)
        except socket.error, e:
            if e.args[0] in ssnet.NET_ERRS:
                # might have been spurious; try again.
                # Note: these errors sometimes are reported by recv(),
                # and sometimes by send().  We have to catch both.
                debug2('DNS recv from %r: %s\n' % (self.peer, e))
                self.try_send()
                return
            else:
                log('DNS recv from %r: %s\n' % (self.peer, e))
                return
        debug2('DNS response: %d bytes\n' % len(data))
        self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
        self.ok = False


class UdpProxy(Handler):
    def __init__(self, mux, chan, family):
        sock = socket.socket(family, socket.SOCK_DGRAM)
        Handler.__init__(self, [sock])
        self.timeout = time.time() + 30
        self.mux = mux
        self.chan = chan
        self.sock = sock
        if family == socket.AF_INET:
            self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
Example #39
0
 def dns_req(channel, data):
     debug2('Incoming DNS request channel=%d.\n' % channel)
     h = DnsProxy(mux, channel, data)
     handlers.append(h)
     dnshandlers[channel] = h
Example #40
0
    def callback(self):
        try:
            data = self.sock.recv(4096)
        except socket.error, e:
            if e.args[0] in ssnet.NET_ERRS:
                # might have been spurious; try again.
                # Note: these errors sometimes are reported by recv(),
                # and sometimes by send().  We have to catch both.
                debug2('DNS recv from %r: %s\n' % (self.peer, e))
                self.try_send()
                return
            else:
                log('DNS recv from %r: %s\n' % (self.peer, e))
                return
        debug2('DNS response: %d bytes\n' % len(data))
        self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
        self.ok = False


class UdpProxy(Handler):

    def __init__(self, mux, chan, family):
        sock = socket.socket(family, socket.SOCK_DGRAM)
        Handler.__init__(self, [sock])
        self.timeout = time.time() + 30
        self.mux = mux
        self.chan = chan
        self.sock = sock
        if family == socket.AF_INET:
            self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
Example #41
0
 def onhostlist(hostlist):
     debug2('got host list: %r\n' % hostlist)
     for line in hostlist.strip().split():
         if line:
             name, ip = line.split(',', 1)
             fw.sethostip(name, ip)
Example #42
0
        debug1("UDP support requires tproxy; disabling UDP.\n")
        udp = False

    if listenip_v6 and listenip_v6[1] and listenip_v4 and listenip_v4[1]:
        # if both ports given, no need to search for a spare port
        ports = [0, ]
    else:
        # if at least one port missing, we have to search
        ports = xrange(12300, 9000, -1)

    # search for free ports and try to bind
    last_e = None
    redirectport_v6 = 0
    redirectport_v4 = 0
    bound = False
    debug2('Binding redirector:')
    for port in ports:
        debug2(' %d' % port)
        tcp_listener = MultiListener()
        tcp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        if udp:
            udp_listener = MultiListener(socket.SOCK_DGRAM)
            udp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        else:
            udp_listener = None

        if listenip_v6 and listenip_v6[1]:
            lv6 = listenip_v6
            redirectport_v6 = lv6[1]
        elif listenip_v6:
Example #43
0
    if listenip_v6 and listenip_v6[1] and listenip_v4 and listenip_v4[1]:
        # if both ports given, no need to search for a spare port
        ports = [
            0,
        ]
    else:
        # if at least one port missing, we have to search
        ports = xrange(12300, 9000, -1)

    # search for free ports and try to bind
    last_e = None
    redirectport_v6 = 0
    redirectport_v4 = 0
    bound = False
    debug2('Binding redirector:')
    for port in ports:
        debug2(' %d' % port)
        tcp_listener = MultiListener()
        tcp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        if udp:
            udp_listener = MultiListener(socket.SOCK_DGRAM)
            udp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        else:
            udp_listener = None

        if listenip_v6 and listenip_v6[1]:
            lv6 = listenip_v6
            redirectport_v6 = lv6[1]
        elif listenip_v6:
Example #44
0
def add_dep(t, mode, dep):
    debug2("add-dep(%r)\n" % t)
    open(_sname("dep", t), "a").write("%s %s\n" % (mode, relpath(dep, vars.BASE)))
Example #45
0
 def onhostlist(hostlist):
     debug2('got host list: %r\n' % hostlist)
     for line in hostlist.strip().split():
         if line:
             name, ip = line.split(',', 1)
             fw.sethostip(name, ip)
Example #46
0
def connect(ssh_cmd, rhostport, python, stderr, options):
    portl = []

    if (rhostport or '').count(':') > 1:
        if rhostport.count(']') or rhostport.count('['):
            result = rhostport.split(']')
            rhost = result[0].strip('[')
            if len(result) > 1:
                result[1] = result[1].strip(':')
                if result[1] is not '':
                    portl = ['-p', str(int(result[1]))]
        # can't disambiguate IPv6 colons and a port number. pass the hostname
        # through.
        else:
            rhost = rhostport
    else:  # IPv4
        l = (rhostport or '').split(':', 1)
        rhost = l[0]
        if len(l) > 1:
            portl = ['-p', str(int(l[1]))]

    if rhost == '-':
        rhost = None

    z = zlib.compressobj(1)
    content = readfile('assembler.py')
    optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in options.items())
    content2 = (empackage(z, 'cmdline_options.py', optdata) +
                empackage(z, 'helpers.py') +
                empackage(z, 'compat/ssubprocess.py') +
                empackage(z, 'ssnet.py') +
                empackage(z, 'hostwatch.py') +
                empackage(z, 'server.py') +
                "\n")

    pyscript = r"""
                import sys;
                skip_imports=1;
                verbosity=%d;
                exec compile(sys.stdin.read(%d), "assembler.py", "exec")
                """ % (helpers.verbose or 0, len(content))
    pyscript = re.sub(r'\s+', ' ', pyscript.strip())

    if not rhost:
        # ignore the --python argument when running locally; we already know
        # which python version works.
        argv = [sys.argv[1], '-c', pyscript]
    else:
        if ssh_cmd:
            sshl = ssh_cmd.split(' ')
        else:
            sshl = ['ssh']
        if python:
            pycmd = "'%s' -c '%s'" % (python, pyscript)
        else:
            pycmd = ("P=python2; $P -V 2>/dev/null || P=python; "
                     "exec \"$P\" -c '%s'") % pyscript
        argv = (sshl +
                portl +
                [rhost, '--', pycmd])
    (s1, s2) = socket.socketpair()

    def setup():
        # runs in the child process
        s2.close()
    s1a, s1b = os.dup(s1.fileno()), os.dup(s1.fileno())
    s1.close()
    debug2('executing: %r\n' % argv)
    p = ssubprocess.Popen(argv, stdin=s1a, stdout=s1b, preexec_fn=setup,
                          close_fds=True, stderr=stderr)
    os.close(s1a)
    os.close(s1b)
    s2.sendall(content)
    s2.sendall(content2)
    return p, s2