Created
July 7, 2011 17:14
-
-
Save gorsuch/1070018 to your computer and use it in GitHub Desktop.
simple twisted ssh server w/o keys
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from twisted.cred import portal, checkers, credentials | |
from twisted.conch import error, avatar, recvline, interfaces as conchinterfaces | |
from twisted.conch.ssh import factory, userauth, connection, keys, session, common | |
from twisted.conch.insults import insults | |
from twisted.application import service, internet | |
from zope.interface import implements | |
import os | |
class SSHDemoProtocol(recvline.HistoricRecvLine): | |
def __init__(self, user): | |
self.user = user | |
def connectionMade(self): | |
recvline.HistoricRecvLine.connectionMade(self) | |
self.terminal.write("Welcome to my test SSH server.") | |
self.terminal.nextLine( ) | |
self.showPrompt( ) | |
def showPrompt(self): | |
self.terminal.write("$ ") | |
def lineReceived(self, line): | |
self.terminal.write(line) | |
self.terminal.nextLine() | |
self.showPrompt( ) | |
class SSHDemoAvatar(avatar.ConchUser): | |
implements(conchinterfaces.ISession) | |
def __init__(self, username): | |
avatar.ConchUser.__init__(self) | |
self.username = username | |
self.channelLookup.update({'session':session.SSHSession}) | |
def openShell(self, protocol): | |
serverProtocol = insults.ServerProtocol(SSHDemoProtocol, self) | |
serverProtocol.makeConnection(protocol) | |
protocol.makeConnection(session.wrapProtocol(serverProtocol)) | |
def getPty(self, terminal, windowSize, attrs): | |
return None | |
def execCommand(self, protocol, cmd): | |
raise NotImplementedError | |
def closed(self): | |
pass | |
class SSHDemoRealm: | |
implements(portal.IRealm) | |
def requestAvatar(self, avatarId, mind, *interfaces): | |
if conchinterfaces.IConchUser in interfaces: | |
return interfaces[0], SSHDemoAvatar(avatarId), lambda: None | |
else: | |
raise Exception, "No supported interfaces found." | |
def getRSAKeys(): | |
if not (os.path.exists('public.key') and os.path.exists('private.key')): | |
# generate a RSA keypair | |
print "Generating RSA keypair..." | |
from Crypto.PublicKey import RSA | |
KEY_LENGTH = 1024 | |
rsaKey = RSA.generate(KEY_LENGTH, common.entropy.get_bytes) | |
publicKeyString = keys.makePublicKeyString(rsaKey) | |
privateKeyString = keys.makePrivateKeyString(rsaKey) | |
# save keys for next time | |
file('public.key', 'w+b').write(publicKeyString) | |
file('private.key', 'w+b').write(privateKeyString) | |
print "done." | |
else: | |
publicKeyString = file('public.key').read() | |
privateKeyString = file('private.key').read() | |
return publicKeyString, privateKeyString | |
if __name__ == "__main__": | |
sshFactory = factory.SSHFactory() | |
sshFactory.portal = portal.Portal(SSHDemoRealm()) | |
users = {'admin': 'aaa', 'guest': 'bbb'} | |
sshFactory.portal.registerChecker(checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) | |
pubKeyString, privKeyString = getRSAKeys() | |
sshFactory.publicKeys = { | |
'ssh-rsa': keys.getPublicKeyString(data=pubKeyString)} | |
sshFactory.privateKeys = { | |
'ssh-rsa': keys.getPrivateKeyObject(data=privKeyString)} | |
from twisted.internet import reactor | |
reactor.listenTCP(2222, sshFactory) | |
reactor.run( ) |
why name this "without keys" when it literally either requires or will generate a key...
@CDWimmer great question -- honestly, this gist was written 11 years ago, and I barely remember it. I'm not sure why I named it that way.
I’ve learned from an IRC chat with Twisted users that these are just server-side keys and aren’t required by a client, which I was misunderstanding! All’s well and the name does make sense from a client perspective! 😊
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
why name this "without keys" when it literally either requires or will generate a key...