[Twisted-Python] Telnet server using Twisted and AuthenticatingTelnetProtocol
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Hello, I have created a telnet server in python. Maybe you wonder why to create a telnet server while Windows has one? Because the windows telnet server does not allow to interract with the desktop. If you try to start a GUI app, it will start and run but will not be displayed on the server desktop. My telnet server will allow to start a GUI application interracting with the windows desktop of the server. Ex. : typing "notepad" in the telnet console will pop up the notepad on the Windows desktop of the server. At the time this server works but has no authentication feature implemented. I would like to implement the authentication using AuthenticatingTelnetProtocol and credential. I found the "cred.py" example on the twistedmatrix website (in the example section) and looked fine as starting point. I quite well understand this expample. I modified the code as follow but always got the same error message when a connectiion is attempted. I have been trying since two weeks but I cannot get it work. Is there a problem with "AuthenticatingTelnetProtocol" The error message: ************************************************************ D:\workspace\twisted>telnet_cred.py 2009-08-20 08:57:11+0200 [-] Log opened. 2009-08-20 08:57:11+0200 [-] __main__.ServerFactory starting on 4738 2009-08-20 08:57:11+0200 [-] Starting factory <__main__.ServerFactory instance at 0x00D79C60> 2009-08-20 08:57:15+0200 [__main__.ServerFactory] DEBUG: buildProtocol - addr IPv4Address(TCP, '127.0.0.1', 4978) 2009-08-20 08:57:15+0200 [__main__.ServerFactory] Unhandled Error Traceback (most recent call last): File "C:\Python25\lib\site-packages\twisted\python\log.py", line 69, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "C:\Python25\lib\site-packages\twisted\python\context.py", line 59, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "C:\Python25\lib\site-packages\twisted\python\context.py", line 37, in callWithContext return func(*args,**kw) File "C:\Python25\lib\site-packages\twisted\internet\selectreactor.py", line 146, in _doReadOrWrite why = getattr(selectable, method)() --- <exception caught here> --- File "C:\Python25\lib\site-packages\twisted\internet\tcp.py", line 932, in doRead protocol = self.factory.buildProtocol(self._buildAddr(addr)) File "D:\workspace\twisted\telnet_cred.py", line 130, in buildProtocol p = protocol.ServerFactory.buildProtocol(self, addr) File "C:\Python25\lib\site-packages\twisted\internet\protocol.py", line 98, in buildProtocol p = self.protocol() exceptions.TypeError: __init__() takes exactly 2 arguments (1 given) ************************************************************ The modified code: ************************************************************ # Copyright (c) 2001-2004 Twisted Matrix Laboratories. # See LICENSE for details. import sys from zope.interface import implements, Interface from twisted.protocols import basic from twisted.internet import protocol from twisted.python import log from twisted.cred import error from twisted.cred import portal from twisted.cred import checkers from twisted.cred import credentials from twisted.conch.telnet import AuthenticatingTelnetProtocol, ITelnetProtocol, TelnetProtocol class IProtocolUser(Interface): def getPrivileges(): """Return a list of privileges this user has.""" def logout(): """Cleanup per-login resources allocated to this avatar""" class AnonymousUser: implements(IProtocolUser) def getPrivileges(self): return [1, 2, 3] def logout(self): print "Cleaning up anonymous user resources" class RegularUser: implements(IProtocolUser) def getPrivileges(self): return [1, 2, 3, 5, 6] def logout(self): print "Cleaning up regular user resources" class Administrator: implements(IProtocolUser) def getPrivileges(self): return range(50) def logout(self): print "Cleaning up administrator resources" class Protocol(basic.LineReceiver): user = None portal = None avatar = None logout = None def connectionMade(self): self.sendLine("Login with USER <name> followed by PASS <password> or ANON") self.sendLine("Check privileges with PRIVS") def connectionLost(self, reason): if self.logout: self.logout() self.avatar = None self.logout = None def lineReceived(self, line): f = getattr(self, 'cmd_' + line.upper().split()[0]) if f: try: f(*line.split()[1:]) except TypeError: self.sendLine("Wrong number of arguments.") except: self.sendLine("Server error (probably your fault)") def cmd_ANON(self): if self.portal: self.portal.login(credentials.Anonymous(), None, IProtocolUser ).addCallbacks(self._cbLogin, self._ebLogin ) else: self.sendLine("DENIED") def cmd_USER(self, name): self.user = name self.sendLine("Alright. Now PASS?") def cmd_PASS(self, password): if not self.user: self.sendLine("USER required before PASS") else: if self.portal: self.portal.login( credentials.UsernamePassword(self.user, password), None, IProtocolUser ).addCallbacks(self._cbLogin, self._ebLogin ) else: self.sendLine("DENIED") def cmd_PRIVS(self): self.sendLine("You have the following privileges: ") self.sendLine(" ".join(map(str, self.avatar.getPrivileges()))) def _cbLogin(self, (interface, avatar, logout)): assert interface is IProtocolUser self.avatar = avatar self.logout = logout self.sendLine("Login successful. Available commands: PRIVS") def _ebLogin(self, failure): failure.trap(error.UnauthorizedLogin) self.sendLine("Login denied! Go away.") class ServerFactory(protocol.ServerFactory): ## protocol = Protocol protocol = AuthenticatingTelnetProtocol def __init__(self, portal): self.portal = portal def buildProtocol(self, addr): print "DEBUG: buildProtocol - addr", addr p = protocol.ServerFactory.buildProtocol(self, addr) print "DEBUG2: buildProtocol - addr", addr p.portal = self.portal return p class Realm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if IProtocolUser in interfaces: if avatarId == checkers.ANONYMOUS: av = AnonymousUser() elif avatarId.isupper(): # Capitalized usernames are administrators. av = Administrator() else: av = RegularUser() return IProtocolUser, av, av.logout elif ITelnetProtocol in interfaces: print "BEGUG: aaaa" if avatarId.isupper(): av = TelnetProtocol() return ITelnetProtocol, av, None raise NotImplementedError("Only IProtocolUser interface is supported by this realm") def main(): r = Realm() p = portal.Portal(r) c = checkers.InMemoryUsernamePasswordDatabaseDontUse() c.addUser("auser", "thepass") c.addUser("SECONDUSER", "secret") p.registerChecker(c) p.registerChecker(checkers.AllowAnonymousAccess()) f = ServerFactory(p) log.startLogging(sys.stdout) from twisted.internet import reactor reactor.listenTCP(4738, f) reactor.run() if __name__ == '__main__': main() ************************************************************ If someone could help me. Philippe
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 07:07 am, filoufake-python@yahoo.fr wrote:
AuthenticatingTelnetProtocol requires an argument to its constructor - the cred portal to use to do the authentication and authorization with. However, ServerFactory.buildProtocol doesn't invoke it with any arguments, so you get a TypeError. You can fix this by making your factory's protocol be a no-argument callable instead - eg, by making it a lambda that closes over the portal or the factory: def __init__(self, portal): self.protocol = lambda: AuthenticatingTelnetProtocol(portal) However, this won't completely fix your problems. AuthenticatingTelnetProtocol expects to be connected to an ITelnetTransport, not an ITCPTransport. http://twistedmatrix.com/trac/browser/branches/telnet-server- example-3940/doc/conch/examples/telnet_echo.tac might help illuminate the way telnet transports and telnet protocols are intended to be assembled. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Thank you Jean-Paul for replying, I still have some things that I don't understand: If I put your piece of code in my factory's protocol, I can connect to the server but as soon as I enter the username, I got the an error message telling that Server doesn't support "will" ('Server' object has no attribute 'will'). 2009-08-25 00:32:40+0200 [-] Log opened. 2009-08-25 00:32:40+0200 [-] twisted.internet.protocol.ServerFactory starting on 4738 2009-08-25 00:32:40+0200 [-] Starting factory <twisted.internet.protocol.ServerFactory instance at 0x00D828F0> 2009-08-25 00:32:45+0200 [AuthenticatingTelnetProtocol,0,127.0.0.1] Unhandled Error Traceback (most recent call last): File "C:\Python26\lib\site-packages\twisted\python\log.py", line 84, in callWithLogger return callWithContext({"system": lp}, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\log.py", line 69, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\context.py", line 59, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\context.py", line 37, in callWithContext return func(*args,**kw) --- <exception caught here> --- File "C:\Python26\lib\site-packages\twisted\internet\selectreactor.py", line 146, in _doReadOrWrite why = getattr(selectable, method)() File "C:\Python26\lib\site-packages\twisted\internet\tcp.py", line 463, in doRead return self.protocol.dataReceived(data) File "C:\Python26\lib\site-packages\twisted\protocols\basic.py", line 231, in dataReceived why = self.lineReceived(line) File "C:\Python26\lib\site-packages\twisted\conch\telnet.py", line 925, in lineReceived newState = getattr(self, "telnet_" + oldState)(line) File "C:\Python26\lib\site-packages\twisted\conch\telnet.py", line 967, in telnet_User self.transport.will(ECHO) exceptions.AttributeError: 'Server' object has no attribute 'will' I understand that this has something to do with TelnetTranport but how to implement it? I read the telnet_echo.tac but in my case I have to manage the portal also and that is a litle bit too complex for me. You say also that AuthenticatingTelnetProtocol expects to be connected to an ITelnetTransport, but the documentation says "When the information is collected, it is passed to a portal and an avatar implementing ITelnetProtocol is requested". I'm lost. May I abuse to ask you to tell how to do? Many thanks Philippe
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 24 Aug, 11:07 pm, filoufake-python@yahoo.fr wrote:
That means you've hooked up a telnet protocol to a tcp transport, rather than a telnet transport. The telnet transport sits between these two things and adds features like "will" negotiation; it also is in charge of actually interpreting telnet command sequences received from the network and turning them into calls onto your telnet protocol instance. Without the telnet transport, the telnet protocol just gets raw data.
If necessary, you can pass arguments to your telnet protocol. telnet_echo.tac uses "lambda: TelnetTransport(TelnetEcho)" as its protocol. If TelnetEcho took an argument to __init__, though, you could supply it by using this as your protocol instead: "lambda: TelnetTransport(TelnetEcho, foo)". Does that help?
AuthenticatingTelnetProtocol is an ITelnetProtocol implementation. So, it needs to be hooked up to an ITelnetTransport implementation, as all ITelnetProtocol implementations need to. However, since the only thing it knows how to do is handle authentication, it also wants to get /another/ ITelnetProtocol implementation out of the portal you give it. After authentication succeeds, that new ITelnetProtocol implementation will be given control of the connection and the AuthenticatingTelnetProtocol will get out of the way. So you end up with one telnet transport and two telnet protocols. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Hello, Thanks to your help, the server now requests a username and password for the authentication. Once the password has been enterred, nothing happened on the client side. I'm even not able to escape from the client. I have to ctrl-c in the server console. If I well understood the doc, for each state of the connection a method is called: telnet_User called when state = 'User', telnet_Password called when state = 'Password' and at the end telnet_Command (to be written by me). I have added my "telnet_Command" method into my ITelnetProtocol implementation return by requestAvatar, but it is never called. In the telnet_Password method, the deferred calls _cbLogin in case of good authentication or _ebLogin. I could verify that _cbLogin is well called but it seems the application blocks in. The method looks like this: def _cbLogin(self, ial): interface, protocol, logout = ial assert interface is ITelnetProtocol self.protocol = protocol self.logout = logout self.state = 'Command' protocol.makeConnection(self.transport) self.transport.protocol = protocol I almost sure this has to do with what requestAvatar returns in my Realm class: class Realm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if ITelnetProtocol in interfaces: av = MyTelnet() return ITelnetProtocol, av, lambda:None raise NotImplementedError("Only IProtocolUser interface is supported by this realm") MyTelnet being a derived class of StatefulTelnetProtocol. Is it what you explained in your previous reply?
I think I did all you said but I'm not able to get it work. Do you have another idea? Thanks in advance. Here is the log on the server: 2009-09-01 22:37:35+0200 [-] Log opened. 2009-09-01 22:37:35+0200 [-] twisted.internet.protocol.ServerFactory starting on 4738 2009-09-01 22:37:35+0200 [-] Starting factory <twisted.internet.protocol.ServerFactory instance at 0x00D82DA0> 2009-09-01 22:37:57+0200 [twisted.internet.protocol.ServerFactory] state User 2009-09-01 22:38:01+0200 [TelnetTransport,0,127.0.0.1] state User 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] state Password 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in requestAvatar: av = <__main__.MyTelnet instance at 0x00E757D8> 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in _cbLogin: ial = (<InterfaceClass twisted.conch.telnet.ITelnetProtocol>, <__main__.MyTelnet instance at 0x00E757D8>, None) 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in _cbLogin: state = Command 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in telnet_Password: deferred d = <Deferred at 0xe75b48 current result: None> Regards, Philippe
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 08:49 pm, filoufake-python@yahoo.fr wrote:
It's hard to say what's going wrong without being able to see all of the code. A short, self contained, correct example (<http://sscce.org/>) would help a lot. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Hello,
Hereafter is the simplest code that generates the problem. If you run it, you will see that after entering the password nothing happened. The "telnet_Command" method of MyTelnet is never called. I think the problem is what requestAvatar returns. Thanks again for your support import sys from zope.interface import implements from twisted.internet import protocol from twisted.python import log from twisted.cred import error from twisted.cred import portal from twisted.cred import checkers from twisted.cred import credentials from twisted.conch.telnet import AuthenticatingTelnetProtocol from twisted.conch.telnet import StatefulTelnetProtocol from twisted.conch.telnet import ITelnetProtocol from twisted.conch.telnet import TelnetTransport class Realm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if ITelnetProtocol in interfaces: av = MyTelnet() return ITelnetProtocol, av, lambda:None raise NotImplementedError("Not supported by this realm") class MyTelnet(StatefulTelnetProtocol): def telnet_Command(self, line): print "line received via telnet", line def main(): r = Realm() p = portal.Portal(r) c = checkers.InMemoryUsernamePasswordDatabaseDontUse() c.addUser("AA", "aa") p.registerChecker(c) p.registerChecker(checkers.AllowAnonymousAccess()) f = protocol.ServerFactory() f.protocol = lambda: TelnetTransport(AuthenticatingTelnetProtocol, p) log.startLogging(sys.stdout) from twisted.internet import reactor reactor.listenTCP(4738, f) reactor.run() if __name__ == '__main__': main()
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 11:44 am, filoufake-python@yahoo.fr wrote:
The default state of StatefulTelnetProtocol is "Discard". If you change the avatar's state to "Command" before returning it from requestAvatar, I think you'll see the behavior you want. Jean-Paul
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 07:07 am, filoufake-python@yahoo.fr wrote:
AuthenticatingTelnetProtocol requires an argument to its constructor - the cred portal to use to do the authentication and authorization with. However, ServerFactory.buildProtocol doesn't invoke it with any arguments, so you get a TypeError. You can fix this by making your factory's protocol be a no-argument callable instead - eg, by making it a lambda that closes over the portal or the factory: def __init__(self, portal): self.protocol = lambda: AuthenticatingTelnetProtocol(portal) However, this won't completely fix your problems. AuthenticatingTelnetProtocol expects to be connected to an ITelnetTransport, not an ITCPTransport. http://twistedmatrix.com/trac/browser/branches/telnet-server- example-3940/doc/conch/examples/telnet_echo.tac might help illuminate the way telnet transports and telnet protocols are intended to be assembled. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Thank you Jean-Paul for replying, I still have some things that I don't understand: If I put your piece of code in my factory's protocol, I can connect to the server but as soon as I enter the username, I got the an error message telling that Server doesn't support "will" ('Server' object has no attribute 'will'). 2009-08-25 00:32:40+0200 [-] Log opened. 2009-08-25 00:32:40+0200 [-] twisted.internet.protocol.ServerFactory starting on 4738 2009-08-25 00:32:40+0200 [-] Starting factory <twisted.internet.protocol.ServerFactory instance at 0x00D828F0> 2009-08-25 00:32:45+0200 [AuthenticatingTelnetProtocol,0,127.0.0.1] Unhandled Error Traceback (most recent call last): File "C:\Python26\lib\site-packages\twisted\python\log.py", line 84, in callWithLogger return callWithContext({"system": lp}, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\log.py", line 69, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\context.py", line 59, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "C:\Python26\lib\site-packages\twisted\python\context.py", line 37, in callWithContext return func(*args,**kw) --- <exception caught here> --- File "C:\Python26\lib\site-packages\twisted\internet\selectreactor.py", line 146, in _doReadOrWrite why = getattr(selectable, method)() File "C:\Python26\lib\site-packages\twisted\internet\tcp.py", line 463, in doRead return self.protocol.dataReceived(data) File "C:\Python26\lib\site-packages\twisted\protocols\basic.py", line 231, in dataReceived why = self.lineReceived(line) File "C:\Python26\lib\site-packages\twisted\conch\telnet.py", line 925, in lineReceived newState = getattr(self, "telnet_" + oldState)(line) File "C:\Python26\lib\site-packages\twisted\conch\telnet.py", line 967, in telnet_User self.transport.will(ECHO) exceptions.AttributeError: 'Server' object has no attribute 'will' I understand that this has something to do with TelnetTranport but how to implement it? I read the telnet_echo.tac but in my case I have to manage the portal also and that is a litle bit too complex for me. You say also that AuthenticatingTelnetProtocol expects to be connected to an ITelnetTransport, but the documentation says "When the information is collected, it is passed to a portal and an avatar implementing ITelnetProtocol is requested". I'm lost. May I abuse to ask you to tell how to do? Many thanks Philippe
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 24 Aug, 11:07 pm, filoufake-python@yahoo.fr wrote:
That means you've hooked up a telnet protocol to a tcp transport, rather than a telnet transport. The telnet transport sits between these two things and adds features like "will" negotiation; it also is in charge of actually interpreting telnet command sequences received from the network and turning them into calls onto your telnet protocol instance. Without the telnet transport, the telnet protocol just gets raw data.
If necessary, you can pass arguments to your telnet protocol. telnet_echo.tac uses "lambda: TelnetTransport(TelnetEcho)" as its protocol. If TelnetEcho took an argument to __init__, though, you could supply it by using this as your protocol instead: "lambda: TelnetTransport(TelnetEcho, foo)". Does that help?
AuthenticatingTelnetProtocol is an ITelnetProtocol implementation. So, it needs to be hooked up to an ITelnetTransport implementation, as all ITelnetProtocol implementations need to. However, since the only thing it knows how to do is handle authentication, it also wants to get /another/ ITelnetProtocol implementation out of the portal you give it. After authentication succeeds, that new ITelnetProtocol implementation will be given control of the connection and the AuthenticatingTelnetProtocol will get out of the way. So you end up with one telnet transport and two telnet protocols. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Hello, Thanks to your help, the server now requests a username and password for the authentication. Once the password has been enterred, nothing happened on the client side. I'm even not able to escape from the client. I have to ctrl-c in the server console. If I well understood the doc, for each state of the connection a method is called: telnet_User called when state = 'User', telnet_Password called when state = 'Password' and at the end telnet_Command (to be written by me). I have added my "telnet_Command" method into my ITelnetProtocol implementation return by requestAvatar, but it is never called. In the telnet_Password method, the deferred calls _cbLogin in case of good authentication or _ebLogin. I could verify that _cbLogin is well called but it seems the application blocks in. The method looks like this: def _cbLogin(self, ial): interface, protocol, logout = ial assert interface is ITelnetProtocol self.protocol = protocol self.logout = logout self.state = 'Command' protocol.makeConnection(self.transport) self.transport.protocol = protocol I almost sure this has to do with what requestAvatar returns in my Realm class: class Realm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if ITelnetProtocol in interfaces: av = MyTelnet() return ITelnetProtocol, av, lambda:None raise NotImplementedError("Only IProtocolUser interface is supported by this realm") MyTelnet being a derived class of StatefulTelnetProtocol. Is it what you explained in your previous reply?
I think I did all you said but I'm not able to get it work. Do you have another idea? Thanks in advance. Here is the log on the server: 2009-09-01 22:37:35+0200 [-] Log opened. 2009-09-01 22:37:35+0200 [-] twisted.internet.protocol.ServerFactory starting on 4738 2009-09-01 22:37:35+0200 [-] Starting factory <twisted.internet.protocol.ServerFactory instance at 0x00D82DA0> 2009-09-01 22:37:57+0200 [twisted.internet.protocol.ServerFactory] state User 2009-09-01 22:38:01+0200 [TelnetTransport,0,127.0.0.1] state User 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] state Password 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in requestAvatar: av = <__main__.MyTelnet instance at 0x00E757D8> 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in _cbLogin: ial = (<InterfaceClass twisted.conch.telnet.ITelnetProtocol>, <__main__.MyTelnet instance at 0x00E757D8>, None) 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in _cbLogin: state = Command 2009-09-01 22:38:02+0200 [TelnetTransport,0,127.0.0.1] BEGUG in telnet_Password: deferred d = <Deferred at 0xe75b48 current result: None> Regards, Philippe
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 08:49 pm, filoufake-python@yahoo.fr wrote:
It's hard to say what's going wrong without being able to see all of the code. A short, self contained, correct example (<http://sscce.org/>) would help a lot. Jean-Paul
![](https://secure.gravatar.com/avatar/c71423fe5c5b4270caa47298a96676b1.jpg?s=120&d=mm&r=g)
Hello,
Hereafter is the simplest code that generates the problem. If you run it, you will see that after entering the password nothing happened. The "telnet_Command" method of MyTelnet is never called. I think the problem is what requestAvatar returns. Thanks again for your support import sys from zope.interface import implements from twisted.internet import protocol from twisted.python import log from twisted.cred import error from twisted.cred import portal from twisted.cred import checkers from twisted.cred import credentials from twisted.conch.telnet import AuthenticatingTelnetProtocol from twisted.conch.telnet import StatefulTelnetProtocol from twisted.conch.telnet import ITelnetProtocol from twisted.conch.telnet import TelnetTransport class Realm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if ITelnetProtocol in interfaces: av = MyTelnet() return ITelnetProtocol, av, lambda:None raise NotImplementedError("Not supported by this realm") class MyTelnet(StatefulTelnetProtocol): def telnet_Command(self, line): print "line received via telnet", line def main(): r = Realm() p = portal.Portal(r) c = checkers.InMemoryUsernamePasswordDatabaseDontUse() c.addUser("AA", "aa") p.registerChecker(c) p.registerChecker(checkers.AllowAnonymousAccess()) f = protocol.ServerFactory() f.protocol = lambda: TelnetTransport(AuthenticatingTelnetProtocol, p) log.startLogging(sys.stdout) from twisted.internet import reactor reactor.listenTCP(4738, f) reactor.run() if __name__ == '__main__': main()
![](https://secure.gravatar.com/avatar/607cfd4a5b41fe6c886c978128b9c03e.jpg?s=120&d=mm&r=g)
On 11:44 am, filoufake-python@yahoo.fr wrote:
The default state of StatefulTelnetProtocol is "Discard". If you change the avatar's state to "Command" before returning it from requestAvatar, I think you'll see the behavior you want. Jean-Paul
participants (2)
-
exarkun@twistedmatrix.com
-
filoufake-python@yahoo.fr