From 9e5f8cfc0efc55e840544bafa188597dba2638f7 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 19 Sep 2011 14:41:38 -0500 Subject: [PATCH] it works! --- sshit/sshsimpleserver.py | 119 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 sshit/sshsimpleserver.py diff --git a/sshit/sshsimpleserver.py b/sshit/sshsimpleserver.py new file mode 100644 index 0000000..c8ed4df --- /dev/null +++ b/sshit/sshsimpleserver.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +from twisted.cred import portal, checkers +from twisted.conch import error, avatar +from twisted.conch.checkers import SSHPublicKeyDatabase +from twisted.conch.ssh import factory, userauth, connection, keys, session +from twisted.internet import reactor, protocol, defer +from twisted.python import log +from zope.interface import implements +import sys +log.startLogging(sys.stderr) + +""" +Example of running another protocol over an SSH channel. +log in with username "user" and password "password". +""" + +class ExampleAvatar(avatar.ConchUser): + + def __init__(self, username): + avatar.ConchUser.__init__(self) + self.username = username + self.channelLookup.update({'session':session.SSHSession}) + +class ExampleRealm: + implements(portal.IRealm) + + def requestAvatar(self, avatarId, mind, *interfaces): + return interfaces[0], ExampleAvatar(avatarId), lambda: None + +class EchoProtocol(protocol.Protocol): + """this is our example protocol that we will run over SSH + """ + def dataReceived(self, data): + if data == '\r': + data = '\r\n' + elif data == '\x03': #^C + self.transport.loseConnection() + return + self.transport.write(data) + +publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEArzJx8OYOnJmzf4tfBEvLi8DVPrJ3/c9k2I/Az64fxjHf9imyRJbixtQhlH9lfNjUIx+4LmrJH5QNRsFporcHDKOTwTTYLh5KmRpslkYHRivcJSkbh/C+BR3utDS555mV' + +privateKey = """-----BEGIN RSA PRIVATE KEY----- +MIIByAIBAAJhAK8ycfDmDpyZs3+LXwRLy4vA1T6yd/3PZNiPwM+uH8Yx3/YpskSW +4sbUIZR/ZXzY1CMfuC5qyR+UDUbBaaK3Bwyjk8E02C4eSpkabJZGB0Yr3CUpG4fw +vgUd7rQ0ueeZlQIBIwJgbh+1VZfr7WftK5lu7MHtqE1S1vPWZQYE3+VUn8yJADyb +Z4fsZaCrzW9lkIqXkE3GIY+ojdhZhkO1gbG0118sIgphwSWKRxK0mvh6ERxKqIt1 +xJEJO74EykXZV4oNJ8sjAjEA3J9r2ZghVhGN6V8DnQrTk24Td0E8hU8AcP0FVP+8 +PQm/g/aXf2QQkQT+omdHVEJrAjEAy0pL0EBH6EVS98evDCBtQw22OZT52qXlAwZ2 +gyTriKFVoqjeEjt3SZKKqXHSApP/AjBLpF99zcJJZRq2abgYlf9lv1chkrWqDHUu +DZttmYJeEfiFBBavVYIF1dOlZT0G8jMCMBc7sOSZodFnAiryP+Qg9otSBjJ3bQML +pSTqy7c3a2AScC/YyOwkDaICHnnD3XyjMwIxALRzl0tQEKMXs6hH8ToUdlLROCrP +EhQ0wahUTCk1gKA4uPD6TMTChavbh4K63OvbKg== +-----END RSA PRIVATE KEY-----""" + + +class InMemoryPublicKeyChecker(SSHPublicKeyDatabase): + + def checkKey(self, credentials): + return credentials.username == 'user' and \ + keys.Key.fromString(data=publicKey).blob() == credentials.blob + +class ExampleSession: + + def __init__(self, avatar): + """ + We don't use it, but the adapter is passed the avatar as its first + argument. + """ + + def getPty(self, term, windowSize, attrs): + pass + + def execCommand(self, proto, cmd): + raise Exception("no executing commands") + + def openShell(self, trans): + ep = EchoProtocol() + ep.makeConnection(trans) + trans.makeConnection(session.wrapProtocol(ep)) + + def eofReceived(self): + pass + + def closed(self): + pass + +from twisted.python import components +components.registerAdapter(ExampleSession, ExampleAvatar, session.ISession) + +class ExampleFactory(factory.SSHFactory): + publicKeys = { + 'ssh-rsa': keys.Key.fromString(data=publicKey) + } + privateKeys = { + 'ssh-rsa': keys.Key.fromString(data=privateKey) + } + services = { + 'ssh-userauth': userauth.SSHUserAuthServer, + 'ssh-connection': connection.SSHConnection + } + + +# portal = portal.Portal(ExampleRealm()) +from twisted.conch.unix import UnixSSHRealm +portal = portal.Portal(UnixSSHRealm()) +passwdDB = checkers.InMemoryUsernamePasswordDatabaseDontUse() +passwdDB.addUser('kreitz', 'password') +portal.registerChecker(passwdDB) +portal.registerChecker(InMemoryPublicKeyChecker()) +ExampleFactory.portal = portal + +if __name__ == '__main__': + reactor.listenTCP(5022, ExampleFactory()) + reactor.run()