Ticket #4350: gitconnbug.py

File gitconnbug.py, 5.3 KB (added by bshi, 8 years ago)

ssh server reproducing issue (port 2222)

Line 
1#!/usr/bin/env python
2import os
3import struct
4import sys
5from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse
6from twisted.conch.avatar import ConchUser
7from twisted.conch.ssh import common
8from twisted.conch.ssh.session import SSHSession, ISession, SSHSessionProcessProtocol
9from twisted.conch.ssh.factory import SSHFactory
10from twisted.conch.ssh.keys import Key
11from twisted.cred.portal import IRealm, Portal
12from twisted.internet import reactor
13from twisted.python import components, log
14from zope import interface
15log.startLogging(sys.stderr)
16
17
18class TraceSession(SSHSession):
19    def __init__(self, *args, **kw):
20        SSHSession.__init__(self, *args, **kw)
21
22    def request_exec(self, data):
23        if not self.session:
24            self.session = ISession(self.avatar)
25        f,data = common.getNS(data)
26        log.msg('executing command "%s"' % f)
27        try:
28            #pp = SSHSessionProcessProtocol(self)
29            pp = TraceProcessProtocol(self)
30            self.session.execCommand(pp, f)
31        except:
32            log.deferr()
33            return 0
34        else:
35            self.client = pp
36            return 1
37
38class TraceProcessProtocol(SSHSessionProcessProtocol):
39    def __init__(self, session):
40        self.session = session
41
42    def outReceived(self, data):
43        log.msg('TPP.outReceived(...) %d bytes' % len(data))
44        SSHSessionProcessProtocol.outReceived(self, data)
45
46    def inConnectionLost(self):
47        log.msg('TPP.inConnectionLost()')
48        SSHSessionProcessProtocol.inConnectionLost(self)
49
50
51class GitConchUser(ConchUser):
52    def __init__(self, username):
53        ConchUser.__init__(self)
54        self.username = username
55        #self.channelLookup.update({"session": SSHSession})
56        self.channelLookup.update({"session": TraceSession})
57
58        # Find git-shell path.
59        # Adapted from http://bugs.python.org/file15381/shutil_which.patch
60        path = os.environ.get("PATH", os.defpath)
61        for dir in path.split(os.pathsep):
62            full_path = os.path.join(dir, 'git-shell')
63            if (os.path.exists(full_path) and 
64                    os.access(full_path, (os.F_OK | os.X_OK))):
65                self.shell = full_path
66                break
67
68    def logout(self): pass
69
70
71class SimpleGitSession(object):
72    interface.implements(ISession)
73
74    def __init__(self, user):
75        self.user = user
76
77    def execCommand(self, proto, cmd):
78        command = (self.user.shell, '-c', cmd)
79        reactor.spawnProcess(proto, self.user.shell, command)
80
81    def eofReceived(self): pass
82
83    def closed(self): pass
84
85
86class GitRealm(object):
87    interface.implements(IRealm)
88
89    def requestAvatar(self, username, mind, *interfaces):
90        user = GitConchUser(username)
91        return interfaces[0], user, user.logout
92
93
94
95
96TEST_PRIV_KEY = '''-----BEGIN RSA PRIVATE KEY-----
97MIIEogIBAAKCAQEA1ZIkA7Z735yOLh0Es+gUPjwBa0BBx++lf/PwbNisl+YUc9sm
98ve0oGJRUnS9v3EQLEoffDklH7DS2bIZm9K17LEGllLKF6D9i/WR4/7ruS2oZl54c
99SuwnbzAPLxxFJuJW7dF6nUo0iAjD/su2jPL3WGpvRHxOnDA6QVag0lbqzznZMdtg
100qUSmM3ErNEN0S+IydFXuoZYgdKte0qEoD6stk9d4HPJpvlc5Dfw2kA07SQ4lnlEp
101HPoPSsRxAvkdDpEnG8QB1Q2J1etxB6xlOVe/K1e6j+08pBpqeC1mwPHGgCneIdwA
102Sh+J1e1rMkLYZs0ZdJGuxQHlyYBqYetDTmw/NQIBIwKCAQBnvALdO2C9EYbjMqqD
103RNah4qGafkvWI/FMxvEe7OYd5MgbBAuA0kas2lT749c/Gbw8M122e11yuoR92uGM
104yUp0lOoGZVb7xwQx7vjxPYmvme8sYr1I9lxL8sWL6SjnADjZ6Wdw+Cgk0Q69liV3
105qTZPhCdqaENwbzI8/jDbMYf+P8gc6bN1puvQvoGImBf1WFVrKX5vwi/3BOq1YSIP
106OWn17UPxINMzJRcB2IpLsE7ukJPmTlC/4fcthj4KixHIvLpBi9qVlKBjhuSqNgzr
107oPv+GxGmwqzU/CqbQOdzXYAbmF4oZIqmJUytyftIGai8Awfk87Ghug4DtZyK4c23
108ToGvAoGBAO+GytOzodcgsfeMyEYxlUY1UPUbGNYLXJWmsc/d58I7yRky+9GTp2Pt
109s9HW2MW23Iq7865fB1IQdTN5TDMV45Pq6p+5uO14zl96iR+F7/1+ivlQ63o2z1TN
110tLFKFdgmCX3+bQwfuZHbYM2l8M1SLOElzz8iK2KDVVZQjgWWVcnvAoGBAORCXJP0
111WjTdczgGuoROWtL4+tcY3m8wgOXyvfP0TTbWNPEmswN2GC1JqLFoq1qX+OLbB4ky
1125UfclTZGytRqdE/1Metf11ImyxynLHZk4BU4Oqv2vEB6jzZq1PcQ3zHlE9qE+k8u
113r8OFsIklDigoIYJoVD4osc/VHpWKBNJr3j0bAoGBALjHEX69xf26IuOJ3FNoFBGW
1142A2J7pZ9yxRcBYMY5fw8v7Rah77uP00WdMZyifebsXJWeidt4RNryCBk4wLWXxpW
115IrW7KEIp/kmnq5v5m+DPVUP8mGWX/wbn1IjEH3rbg6pWjqLz5uzcbz+Oo9GXKe+D
116kT9U36PEZmcoMwuf28epAoGBAJyFRsvawYNWBd1GcUTIA8Pd7dVS4atUdaT+ORxP
117v+sWirP9R41YSxe9ev1PFmoBzzx47zmB/E6IoNTC1DnimOZe/ai2v4jKJOByoiVM
118fGZScV/5paiOjhavp/nfrv2kZWKkU96GaeUoeQ2VwJCQjAGmoCqfj974igAkIJBJ
11993pbAoGAOqVdfaUTSvHuBPhpyAInVqS8j4C/T/tdvMxsn8fQHC01kE6OOqrxPV5R
120PrAtME9H1kKmRf0RUzXWrkbnmd+qfvm91uUwVL0cxC+7eMqe7uQQbpOiAPouhiYj
121gGr4rmFN9PX9DHGzMhmEBjhP6YycXAsIYPumkqJCVrEMetxuhns=
122-----END RSA PRIVATE KEY-----'''
123
124TEST_PUB_KEY = ('ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1ZIkA7Z735y'
125'OLh0Es+gUPjwBa0BBx++lf/PwbNisl+YUc9smve0oGJRUnS9v3EQLEoffDklH7D'
126'S2bIZm9K17LEGllLKF6D9i/WR4/7ruS2oZl54cSuwnbzAPLxxFJuJW7dF6nUo0i'
127'AjD/su2jPL3WGpvRHxOnDA6QVag0lbqzznZMdtgqUSmM3ErNEN0S+IydFXuoZYg'
128'dKte0qEoD6stk9d4HPJpvlc5Dfw2kA07SQ4lnlEpHPoPSsRxAvkdDpEnG8QB1Q2'
129'J1etxB6xlOVe/K1e6j+08pBpqeC1mwPHGgCneIdwASh+J1e1rMkLYZs0ZdJGuxQ'
130'HlyYBqYetDTmw/NQ==')
131
132
133class SimpleGitServer(SSHFactory):
134    portal = Portal(GitRealm())
135
136    mockpasswd = InMemoryUsernamePasswordDatabaseDontUse()
137    mockpasswd.addUser('user', 'user')
138    portal.registerChecker(mockpasswd)
139
140    def __init__(self):
141        self.privateKeys = {'ssh-rsa': Key.fromString(TEST_PRIV_KEY)}
142        self.publicKeys = {'ssh-rsa': Key.fromString(TEST_PUB_KEY)}
143
144
145if __name__ == '__main__':
146    components.registerAdapter(SimpleGitSession, GitConchUser, ISession)
147    reactor.listenTCP(2222, SimpleGitServer())
148    reactor.run()