We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
^M for carriage return in telnet
Trying to log in via telnet to cowrie results in the following:

$telnet xx.yy.zz.aa
Trying xx.yy.zz.aa
Connected to xx.yy.zz.aa.
Escape character is '^]'.
login: icantpressenter^M^M^M^M^M^M^M^M^M^M^M^]
telnet> q
Connection closed.

It looks like some kind of control character thing. Telnet on windows "kind of works", and telnet on OS X and Linux (Debian 8.6) produce the above ^M issue.

oddly, specifying the destination port in the telnet client  (e.g "telnet host 23" ) removes this issue. Probably because control messages aren't sent.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cowrie/telnet/transport.py`
Content:
```
1 # Copyright (C) 2015, 2016 GoSecure Inc.
2 """
3 Telnet Transport and Authentication for the Honeypot
4 
5 @author: Olivier Bilodeau <obilodeau@gosecure.ca>
6 """
7 
8 import struct
9 import time
10 import uuid
11 import inspect
12 import random
13 
14 from twisted.python import log
15 from twisted.internet import protocol
16 from twisted.conch.telnet import AuthenticatingTelnetProtocol, ECHO, TRAPSIG, \
17                                  ITelnetProtocol, ProtocolTransportMixin, \
18                                  SGA, NAWS, MODE, LINEMODE, TelnetTransport, AlreadyNegotiating
19 from twisted.protocols.policies import TimeoutMixin
20 
21 from cowrie.core.credentials import UsernamePasswordIP
22 
23 class HoneyPotTelnetFactory(protocol.ServerFactory):
24     """
25     This factory creates HoneyPotTelnetAuthProtocol instances
26     They listen directly to the TCP port
27     """
28     tac = None # gets set later
29 
30     def __init__(self, cfg):
31         self.cfg = cfg
32 
33 
34     # TODO logging clarity can be improved: see what SSH does
35     def logDispatch(self, *msg, **args):
36         """
37         Special delivery to the loggers to avoid scope problems
38         """
39         args['sessionno'] = 'T'+str(args['sessionno'])
40         for dblog in self.tac.dbloggers:
41             dblog.logDispatch(*msg, **args)
42         for output in self.tac.output_plugins:
43             output.logDispatch(*msg, **args)
44 
45 
46     def startFactory(self):
47         """
48         """
49         try:
50             honeyfs = self.portal.realm.cfg.get('honeypot', 'contents_path')
51             issuefile = honeyfs + "/etc/issue.net"
52             self.banner = open(issuefile).read()
53         except IOError:
54             self.banner = ""
55 
56         # For use by the uptime command
57         self.starttime = time.time()
58 
59         # hook protocol
60         self.protocol = lambda: CowrieTelnetTransport(HoneyPotTelnetAuthProtocol,
61                                          self.portal)
62         protocol.ServerFactory.startFactory(self)
63         log.msg("Ready to accept Telnet connections")
64 
65 
66     def stopFactory(self):
67         """
68         Stop output plugins
69         """
70         protocol.ServerFactory.stopFactory(self)
71 
72 
73 class HoneyPotTelnetAuthProtocol(AuthenticatingTelnetProtocol):
74     """
75     TelnetAuthProtocol that takes care of Authentication. Once authenticated this
76     protocol is replaced with HoneyPotTelnetSession.
77     """
78 
79     loginPrompt = 'login: '
80     passwordPrompt = 'Password: '
81     windowSize = [40, 80]
82 
83     def connectionMade(self):
84         """
85         """
86         self.transport.negotiationMap[NAWS] = self.telnet_NAWS
87         # Initial option negotation. Want something at least for Mirai
88         for opt in (NAWS,):
89             self.transport.doChain(opt).addErrback(log.err)
90 
91         # I need to doubly escape here since my underlying
92         # CowrieTelnetTransport hack would remove it and leave just \n
93         self.transport.write(self.factory.banner.replace('\n', '\r\r\n'))
94         self.transport.write(self.loginPrompt)
95 
96 
97     def connectionLost(self, reason):
98         """
99         Fires on pre-authentication disconnects
100         """
101         AuthenticatingTelnetProtocol.connectionLost(self, reason)
102 
103 
104     def telnet_User(self, line):
105         """
106         Overridden to conditionally kill 'WILL ECHO' which confuses clients
107         that don't implement a proper Telnet protocol (most malware)
108         """
109         self.username = line
110         # only send ECHO option if we are chatting with a real Telnet client
111         #if self.transport.options: <-- doesn't work
112         self.transport.willChain(ECHO)
113         # FIXME: this should be configurable or provided via filesystem
114         self.transport.write(self.passwordPrompt)
115         return 'Password'
116 
117 
118     def telnet_Password(self, line):
119         username, password = self.username, line
120         del self.username
121         def login(ignored):
122             self.src_ip = self.transport.getPeer().host
123             creds = UsernamePasswordIP(username, password, self.src_ip)
124             d = self.portal.login(creds, self.src_ip, ITelnetProtocol)
125             d.addCallback(self._cbLogin)
126             d.addErrback(self._ebLogin)
127 
128         # are we dealing with a real Telnet client?
129         if self.transport.options:
130             # stop ECHO
131             # even if ECHO negotiation fails we still want to attempt a login
132             # this allows us to support dumb clients which is common in malware
133             # thus the addBoth: on success and on exception (AlreadyNegotiating)
134             self.transport.wontChain(ECHO).addBoth(login)
135         else:
136             # process login
137             login('')
138 
139         return 'Discard'
140 
141     def telnet_Command(self, command):
142         self.transport.protocol.dataReceived(command+'\r')
143         return "Command"
144 
145     def _cbLogin(self, ial):
146         """
147         Fired on a successful login
148         """
149         interface, protocol, logout = ial
150         protocol.windowSize = self.windowSize
151         self.protocol = protocol
152         self.logout = logout
153         self.state = 'Command'
154 
155         # Remove the short timeout of the login prompt. Timeout will be
156         # provided later by the HoneyPotBaseProtocol class.
157         self.transport.setTimeout(None)
158 
159         # replace myself with avatar protocol
160         protocol.makeConnection(self.transport)
161         self.transport.protocol = protocol
162 
163 
164     def _ebLogin(self, failure):
165     # TODO: provide a way to have user configurable strings for wrong password
166         self.transport.wontChain(ECHO)
167         self.transport.write("\nLogin incorrect\n")
168         self.transport.write(self.loginPrompt)
169         self.state = "User"
170 
171     # From TelnetBootstrapProtocol in twisted/conch/telnet.py
172     def telnet_NAWS(self, data):
173         if len(data) == 4:
174             width, height = struct.unpack('!HH', b''.join(data))
175             self.windowSize = [height, width]
176         else:
177             log.msg("Wrong number of NAWS bytes")
178 
179     def enableLocal(self, opt):
180         if opt == ECHO:
181             return True
182         elif opt == SGA:
183             return True
184         else:
185             return False
186 
187 
188     def enableRemote(self, opt):
189         if opt == LINEMODE:
190             self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))
191             return True
192         elif opt == NAWS:
193             return True
194         elif opt == SGA:
195             return True
196         else:
197             return False
198 
199 
200 
201 class CowrieTelnetTransport(TelnetTransport, TimeoutMixin):
202     """
203     """
204     def connectionMade(self):
205         self.transportId = uuid.uuid4().hex[:8]
206         sessionno = self.transport.sessionno
207         self.startTime = time.time()
208         self.setTimeout(300)
209 
210         log.msg(eventid='cowrie.session.connect',
211            format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: T%(sessionno)s]',
212            src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,
213            dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
214            session=self.transportId, sessionno='T'+str(sessionno))
215         TelnetTransport.connectionMade(self)
216 
217 
218     def write(self, bytes):
219         """
220         Because of the presence of two ProtocolTransportMixin in the protocol
221         stack once authenticated, I need to override write() and remove a \r
222         otherwise we end up with \r\r\n on the wire.
223 
224         It is kind of a hack. I asked for a better solution here:
225         http://stackoverflow.com/questions/35087250/twisted-telnet-server-how-to-avoid-nested-crlf
226         """
227         self.transport.write(bytes.replace('\r\n', '\n'))
228 
229 
230     def connectionLost(self, reason):
231         """
232         Fires on pre-authentication disconnects
233         """
234         self.setTimeout(None)
235         TelnetTransport.connectionLost(self, reason)
236         duration = time.time() - self.startTime
237         log.msg(eventid='cowrie.session.closed',
238             format='Connection lost after %(duration)d seconds',
239             duration=duration)
240 
241     def willChain(self, option):
242         return self._chainNegotiation(None, self.will, option)
243 
244     def wontChain(self, option):
245         return self._chainNegotiation(None, self.wont, option)
246 
247     def doChain(self, option):
248         return self._chainNegotiation(None, self.do, option)
249 
250     def dontChain(self, option):
251         return self._chainNegotiation(None, self.dont, option)
252 
253     def _handleNegotiationError(self, f, func, option):
254         if f.type is AlreadyNegotiating:
255             s = self.getOptionState(option)
256             if func in (self.do, self.dont):
257                 s.him.onResult.addCallback(self._chainNegotiation, func, option)
258                 s.him.onResult.addErrback(self._handleNegotiationError, func, option)
259             if func in (self.will, self.wont):
260                 s.us.onResult.addCallback(self._chainNegotiation, func, option)
261                 s.us.onResult.addErrback(self._handleNegotiationError, func, option)
262         # We only care about AlreadyNegotiating, everything else can be ignored
263         # Possible other types include OptionRefused, AlreadyDisabled, AlreadyEnabled, ConnectionDone, ConnectionLost
264         elif f.type is AssertionError:
265             log.err('Client tried to illegally refuse to disable an option; ignoring, but undefined behavior may result')
266             # TODO: Is ignoring this violation of the protocol the proper behavior?
267             # Should the connection be terminated instead?
268             # The telnetd package on Ubuntu (netkit-telnet) does all negotiation before sending the login prompt,
269             # but does handle client-initiated negotiation at any time.
270         return None  # This Failure has been handled, no need to continue processing errbacks
271 
272     def _chainNegotiation(self, res, func, option):
273         return func(option).addErrback(self._handleNegotiationError, func, option)
274
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cowrie/telnet/transport.py b/cowrie/telnet/transport.py
--- a/cowrie/telnet/transport.py
+++ b/cowrie/telnet/transport.py
@@ -180,15 +180,17 @@
         if opt == ECHO:
             return True
         elif opt == SGA:
-            return True
+            return False
+            #return True
         else:
             return False
 
 
     def enableRemote(self, opt):
         if opt == LINEMODE:
-            self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))
-            return True
+            return False
+            #self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))
+            #return True
         elif opt == NAWS:
             return True
         elif opt == SGA:

{"golden_diff": "diff --git a/cowrie/telnet/transport.py b/cowrie/telnet/transport.py\n--- a/cowrie/telnet/transport.py\n+++ b/cowrie/telnet/transport.py\n@@ -180,15 +180,17 @@\n         if opt == ECHO:\n             return True\n         elif opt == SGA:\n-            return True\n+            return False\n+            #return True\n         else:\n             return False\n \n \n     def enableRemote(self, opt):\n         if opt == LINEMODE:\n-            self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))\n-            return True\n+            return False\n+            #self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))\n+            #return True\n         elif opt == NAWS:\n             return True\n         elif opt == SGA:\n", "issue": "^M for carriage return in telnet\nTrying to log in via telnet to cowrie results in the following:\r\n\r\n$telnet xx.yy.zz.aa\r\nTrying xx.yy.zz.aa\r\nConnected to xx.yy.zz.aa.\r\nEscape character is '^]'.\r\nlogin: icantpressenter^M^M^M^M^M^M^M^M^M^M^M^]\r\ntelnet> q\r\nConnection closed.\r\n\r\nIt looks like some kind of control character thing. Telnet on windows \"kind of works\", and telnet on OS X and Linux (Debian 8.6) produce the above ^M issue.\r\n\r\noddly, specifying the destination port in the telnet client  (e.g \"telnet host 23\" ) removes this issue. Probably because control messages aren't sent.\n", "before_files": [{"content": "# Copyright (C) 2015, 2016 GoSecure Inc.\n\"\"\"\nTelnet Transport and Authentication for the Honeypot\n\n@author: Olivier Bilodeau <obilodeau@gosecure.ca>\n\"\"\"\n\nimport struct\nimport time\nimport uuid\nimport inspect\nimport random\n\nfrom twisted.python import log\nfrom twisted.internet import protocol\nfrom twisted.conch.telnet import AuthenticatingTelnetProtocol, ECHO, TRAPSIG, \\\n                                 ITelnetProtocol, ProtocolTransportMixin, \\\n                                 SGA, NAWS, MODE, LINEMODE, TelnetTransport, AlreadyNegotiating\nfrom twisted.protocols.policies import TimeoutMixin\n\nfrom cowrie.core.credentials import UsernamePasswordIP\n\nclass HoneyPotTelnetFactory(protocol.ServerFactory):\n    \"\"\"\n    This factory creates HoneyPotTelnetAuthProtocol instances\n    They listen directly to the TCP port\n    \"\"\"\n    tac = None # gets set later\n\n    def __init__(self, cfg):\n        self.cfg = cfg\n\n\n    # TODO logging clarity can be improved: see what SSH does\n    def logDispatch(self, *msg, **args):\n        \"\"\"\n        Special delivery to the loggers to avoid scope problems\n        \"\"\"\n        args['sessionno'] = 'T'+str(args['sessionno'])\n        for dblog in self.tac.dbloggers:\n            dblog.logDispatch(*msg, **args)\n        for output in self.tac.output_plugins:\n            output.logDispatch(*msg, **args)\n\n\n    def startFactory(self):\n        \"\"\"\n        \"\"\"\n        try:\n            honeyfs = self.portal.realm.cfg.get('honeypot', 'contents_path')\n            issuefile = honeyfs + \"/etc/issue.net\"\n            self.banner = open(issuefile).read()\n        except IOError:\n            self.banner = \"\"\n\n        # For use by the uptime command\n        self.starttime = time.time()\n\n        # hook protocol\n        self.protocol = lambda: CowrieTelnetTransport(HoneyPotTelnetAuthProtocol,\n                                         self.portal)\n        protocol.ServerFactory.startFactory(self)\n        log.msg(\"Ready to accept Telnet connections\")\n\n\n    def stopFactory(self):\n        \"\"\"\n        Stop output plugins\n        \"\"\"\n        protocol.ServerFactory.stopFactory(self)\n\n\nclass HoneyPotTelnetAuthProtocol(AuthenticatingTelnetProtocol):\n    \"\"\"\n    TelnetAuthProtocol that takes care of Authentication. Once authenticated this\n    protocol is replaced with HoneyPotTelnetSession.\n    \"\"\"\n\n    loginPrompt = 'login: '\n    passwordPrompt = 'Password: '\n    windowSize = [40, 80]\n\n    def connectionMade(self):\n        \"\"\"\n        \"\"\"\n        self.transport.negotiationMap[NAWS] = self.telnet_NAWS\n        # Initial option negotation. Want something at least for Mirai\n        for opt in (NAWS,):\n            self.transport.doChain(opt).addErrback(log.err)\n\n        # I need to doubly escape here since my underlying\n        # CowrieTelnetTransport hack would remove it and leave just \\n\n        self.transport.write(self.factory.banner.replace('\\n', '\\r\\r\\n'))\n        self.transport.write(self.loginPrompt)\n\n\n    def connectionLost(self, reason):\n        \"\"\"\n        Fires on pre-authentication disconnects\n        \"\"\"\n        AuthenticatingTelnetProtocol.connectionLost(self, reason)\n\n\n    def telnet_User(self, line):\n        \"\"\"\n        Overridden to conditionally kill 'WILL ECHO' which confuses clients\n        that don't implement a proper Telnet protocol (most malware)\n        \"\"\"\n        self.username = line\n        # only send ECHO option if we are chatting with a real Telnet client\n        #if self.transport.options: <-- doesn't work\n        self.transport.willChain(ECHO)\n        # FIXME: this should be configurable or provided via filesystem\n        self.transport.write(self.passwordPrompt)\n        return 'Password'\n\n\n    def telnet_Password(self, line):\n        username, password = self.username, line\n        del self.username\n        def login(ignored):\n            self.src_ip = self.transport.getPeer().host\n            creds = UsernamePasswordIP(username, password, self.src_ip)\n            d = self.portal.login(creds, self.src_ip, ITelnetProtocol)\n            d.addCallback(self._cbLogin)\n            d.addErrback(self._ebLogin)\n\n        # are we dealing with a real Telnet client?\n        if self.transport.options:\n            # stop ECHO\n            # even if ECHO negotiation fails we still want to attempt a login\n            # this allows us to support dumb clients which is common in malware\n            # thus the addBoth: on success and on exception (AlreadyNegotiating)\n            self.transport.wontChain(ECHO).addBoth(login)\n        else:\n            # process login\n            login('')\n\n        return 'Discard'\n\n    def telnet_Command(self, command):\n        self.transport.protocol.dataReceived(command+'\\r')\n        return \"Command\"\n\n    def _cbLogin(self, ial):\n        \"\"\"\n        Fired on a successful login\n        \"\"\"\n        interface, protocol, logout = ial\n        protocol.windowSize = self.windowSize\n        self.protocol = protocol\n        self.logout = logout\n        self.state = 'Command'\n\n        # Remove the short timeout of the login prompt. Timeout will be\n        # provided later by the HoneyPotBaseProtocol class.\n        self.transport.setTimeout(None)\n\n        # replace myself with avatar protocol\n        protocol.makeConnection(self.transport)\n        self.transport.protocol = protocol\n\n\n    def _ebLogin(self, failure):\n    # TODO: provide a way to have user configurable strings for wrong password\n        self.transport.wontChain(ECHO)\n        self.transport.write(\"\\nLogin incorrect\\n\")\n        self.transport.write(self.loginPrompt)\n        self.state = \"User\"\n\n    # From TelnetBootstrapProtocol in twisted/conch/telnet.py\n    def telnet_NAWS(self, data):\n        if len(data) == 4:\n            width, height = struct.unpack('!HH', b''.join(data))\n            self.windowSize = [height, width]\n        else:\n            log.msg(\"Wrong number of NAWS bytes\")\n\n    def enableLocal(self, opt):\n        if opt == ECHO:\n            return True\n        elif opt == SGA:\n            return True\n        else:\n            return False\n\n\n    def enableRemote(self, opt):\n        if opt == LINEMODE:\n            self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))\n            return True\n        elif opt == NAWS:\n            return True\n        elif opt == SGA:\n            return True\n        else:\n            return False\n\n\n\nclass CowrieTelnetTransport(TelnetTransport, TimeoutMixin):\n    \"\"\"\n    \"\"\"\n    def connectionMade(self):\n        self.transportId = uuid.uuid4().hex[:8]\n        sessionno = self.transport.sessionno\n        self.startTime = time.time()\n        self.setTimeout(300)\n\n        log.msg(eventid='cowrie.session.connect',\n           format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: T%(sessionno)s]',\n           src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,\n           dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,\n           session=self.transportId, sessionno='T'+str(sessionno))\n        TelnetTransport.connectionMade(self)\n\n\n    def write(self, bytes):\n        \"\"\"\n        Because of the presence of two ProtocolTransportMixin in the protocol\n        stack once authenticated, I need to override write() and remove a \\r\n        otherwise we end up with \\r\\r\\n on the wire.\n\n        It is kind of a hack. I asked for a better solution here:\n        http://stackoverflow.com/questions/35087250/twisted-telnet-server-how-to-avoid-nested-crlf\n        \"\"\"\n        self.transport.write(bytes.replace('\\r\\n', '\\n'))\n\n\n    def connectionLost(self, reason):\n        \"\"\"\n        Fires on pre-authentication disconnects\n        \"\"\"\n        self.setTimeout(None)\n        TelnetTransport.connectionLost(self, reason)\n        duration = time.time() - self.startTime\n        log.msg(eventid='cowrie.session.closed',\n            format='Connection lost after %(duration)d seconds',\n            duration=duration)\n\n    def willChain(self, option):\n        return self._chainNegotiation(None, self.will, option)\n\n    def wontChain(self, option):\n        return self._chainNegotiation(None, self.wont, option)\n\n    def doChain(self, option):\n        return self._chainNegotiation(None, self.do, option)\n\n    def dontChain(self, option):\n        return self._chainNegotiation(None, self.dont, option)\n\n    def _handleNegotiationError(self, f, func, option):\n        if f.type is AlreadyNegotiating:\n            s = self.getOptionState(option)\n            if func in (self.do, self.dont):\n                s.him.onResult.addCallback(self._chainNegotiation, func, option)\n                s.him.onResult.addErrback(self._handleNegotiationError, func, option)\n            if func in (self.will, self.wont):\n                s.us.onResult.addCallback(self._chainNegotiation, func, option)\n                s.us.onResult.addErrback(self._handleNegotiationError, func, option)\n        # We only care about AlreadyNegotiating, everything else can be ignored\n        # Possible other types include OptionRefused, AlreadyDisabled, AlreadyEnabled, ConnectionDone, ConnectionLost\n        elif f.type is AssertionError:\n            log.err('Client tried to illegally refuse to disable an option; ignoring, but undefined behavior may result')\n            # TODO: Is ignoring this violation of the protocol the proper behavior?\n            # Should the connection be terminated instead?\n            # The telnetd package on Ubuntu (netkit-telnet) does all negotiation before sending the login prompt,\n            # but does handle client-initiated negotiation at any time.\n        return None  # This Failure has been handled, no need to continue processing errbacks\n\n    def _chainNegotiation(self, res, func, option):\n        return func(option).addErrback(self._handleNegotiationError, func, option)\n", "path": "cowrie/telnet/transport.py"}], "after_files": [{"content": "# Copyright (C) 2015, 2016 GoSecure Inc.\n\"\"\"\nTelnet Transport and Authentication for the Honeypot\n\n@author: Olivier Bilodeau <obilodeau@gosecure.ca>\n\"\"\"\n\nimport struct\nimport time\nimport uuid\nimport inspect\nimport random\n\nfrom twisted.python import log\nfrom twisted.internet import protocol\nfrom twisted.conch.telnet import AuthenticatingTelnetProtocol, ECHO, TRAPSIG, \\\n                                 ITelnetProtocol, ProtocolTransportMixin, \\\n                                 SGA, NAWS, MODE, LINEMODE, TelnetTransport, AlreadyNegotiating\nfrom twisted.protocols.policies import TimeoutMixin\n\nfrom cowrie.core.credentials import UsernamePasswordIP\n\nclass HoneyPotTelnetFactory(protocol.ServerFactory):\n    \"\"\"\n    This factory creates HoneyPotTelnetAuthProtocol instances\n    They listen directly to the TCP port\n    \"\"\"\n    tac = None # gets set later\n\n    def __init__(self, cfg):\n        self.cfg = cfg\n\n\n    # TODO logging clarity can be improved: see what SSH does\n    def logDispatch(self, *msg, **args):\n        \"\"\"\n        Special delivery to the loggers to avoid scope problems\n        \"\"\"\n        args['sessionno'] = 'T'+str(args['sessionno'])\n        for dblog in self.tac.dbloggers:\n            dblog.logDispatch(*msg, **args)\n        for output in self.tac.output_plugins:\n            output.logDispatch(*msg, **args)\n\n\n    def startFactory(self):\n        \"\"\"\n        \"\"\"\n        try:\n            honeyfs = self.portal.realm.cfg.get('honeypot', 'contents_path')\n            issuefile = honeyfs + \"/etc/issue.net\"\n            self.banner = open(issuefile).read()\n        except IOError:\n            self.banner = \"\"\n\n        # For use by the uptime command\n        self.starttime = time.time()\n\n        # hook protocol\n        self.protocol = lambda: CowrieTelnetTransport(HoneyPotTelnetAuthProtocol,\n                                         self.portal)\n        protocol.ServerFactory.startFactory(self)\n        log.msg(\"Ready to accept Telnet connections\")\n\n\n    def stopFactory(self):\n        \"\"\"\n        Stop output plugins\n        \"\"\"\n        protocol.ServerFactory.stopFactory(self)\n\n\nclass HoneyPotTelnetAuthProtocol(AuthenticatingTelnetProtocol):\n    \"\"\"\n    TelnetAuthProtocol that takes care of Authentication. Once authenticated this\n    protocol is replaced with HoneyPotTelnetSession.\n    \"\"\"\n\n    loginPrompt = 'login: '\n    passwordPrompt = 'Password: '\n    windowSize = [40, 80]\n\n    def connectionMade(self):\n        \"\"\"\n        \"\"\"\n        self.transport.negotiationMap[NAWS] = self.telnet_NAWS\n        # Initial option negotation. Want something at least for Mirai\n        for opt in (NAWS,):\n            self.transport.doChain(opt).addErrback(log.err)\n\n        # I need to doubly escape here since my underlying\n        # CowrieTelnetTransport hack would remove it and leave just \\n\n        self.transport.write(self.factory.banner.replace('\\n', '\\r\\r\\n'))\n        self.transport.write(self.loginPrompt)\n\n\n    def connectionLost(self, reason):\n        \"\"\"\n        Fires on pre-authentication disconnects\n        \"\"\"\n        AuthenticatingTelnetProtocol.connectionLost(self, reason)\n\n\n    def telnet_User(self, line):\n        \"\"\"\n        Overridden to conditionally kill 'WILL ECHO' which confuses clients\n        that don't implement a proper Telnet protocol (most malware)\n        \"\"\"\n        self.username = line\n        # only send ECHO option if we are chatting with a real Telnet client\n        #if self.transport.options: <-- doesn't work\n        self.transport.willChain(ECHO)\n        # FIXME: this should be configurable or provided via filesystem\n        self.transport.write(self.passwordPrompt)\n        return 'Password'\n\n\n    def telnet_Password(self, line):\n        username, password = self.username, line\n        del self.username\n        def login(ignored):\n            self.src_ip = self.transport.getPeer().host\n            creds = UsernamePasswordIP(username, password, self.src_ip)\n            d = self.portal.login(creds, self.src_ip, ITelnetProtocol)\n            d.addCallback(self._cbLogin)\n            d.addErrback(self._ebLogin)\n\n        # are we dealing with a real Telnet client?\n        if self.transport.options:\n            # stop ECHO\n            # even if ECHO negotiation fails we still want to attempt a login\n            # this allows us to support dumb clients which is common in malware\n            # thus the addBoth: on success and on exception (AlreadyNegotiating)\n            self.transport.wontChain(ECHO).addBoth(login)\n        else:\n            # process login\n            login('')\n\n        return 'Discard'\n\n    def telnet_Command(self, command):\n        self.transport.protocol.dataReceived(command+'\\r')\n        return \"Command\"\n\n    def _cbLogin(self, ial):\n        \"\"\"\n        Fired on a successful login\n        \"\"\"\n        interface, protocol, logout = ial\n        protocol.windowSize = self.windowSize\n        self.protocol = protocol\n        self.logout = logout\n        self.state = 'Command'\n\n        # Remove the short timeout of the login prompt. Timeout will be\n        # provided later by the HoneyPotBaseProtocol class.\n        self.transport.setTimeout(None)\n\n        # replace myself with avatar protocol\n        protocol.makeConnection(self.transport)\n        self.transport.protocol = protocol\n\n\n    def _ebLogin(self, failure):\n    # TODO: provide a way to have user configurable strings for wrong password\n        self.transport.wontChain(ECHO)\n        self.transport.write(\"\\nLogin incorrect\\n\")\n        self.transport.write(self.loginPrompt)\n        self.state = \"User\"\n\n    # From TelnetBootstrapProtocol in twisted/conch/telnet.py\n    def telnet_NAWS(self, data):\n        if len(data) == 4:\n            width, height = struct.unpack('!HH', b''.join(data))\n            self.windowSize = [height, width]\n        else:\n            log.msg(\"Wrong number of NAWS bytes\")\n\n    def enableLocal(self, opt):\n        if opt == ECHO:\n            return True\n        elif opt == SGA:\n            return False\n            #return True\n        else:\n            return False\n\n\n    def enableRemote(self, opt):\n        if opt == LINEMODE:\n            return False\n            #self.transport.requestNegotiation(LINEMODE, MODE + chr(TRAPSIG))\n            #return True\n        elif opt == NAWS:\n            return True\n        elif opt == SGA:\n            return True\n        else:\n            return False\n\n\n\nclass CowrieTelnetTransport(TelnetTransport, TimeoutMixin):\n    \"\"\"\n    \"\"\"\n    def connectionMade(self):\n        self.transportId = uuid.uuid4().hex[:8]\n        sessionno = self.transport.sessionno\n        self.startTime = time.time()\n        self.setTimeout(300)\n\n        log.msg(eventid='cowrie.session.connect',\n           format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: T%(sessionno)s]',\n           src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,\n           dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,\n           session=self.transportId, sessionno='T'+str(sessionno))\n        TelnetTransport.connectionMade(self)\n\n\n    def write(self, bytes):\n        \"\"\"\n        Because of the presence of two ProtocolTransportMixin in the protocol\n        stack once authenticated, I need to override write() and remove a \\r\n        otherwise we end up with \\r\\r\\n on the wire.\n\n        It is kind of a hack. I asked for a better solution here:\n        http://stackoverflow.com/questions/35087250/twisted-telnet-server-how-to-avoid-nested-crlf\n        \"\"\"\n        self.transport.write(bytes.replace('\\r\\n', '\\n'))\n\n\n    def connectionLost(self, reason):\n        \"\"\"\n        Fires on pre-authentication disconnects\n        \"\"\"\n        self.setTimeout(None)\n        TelnetTransport.connectionLost(self, reason)\n        duration = time.time() - self.startTime\n        log.msg(eventid='cowrie.session.closed',\n            format='Connection lost after %(duration)d seconds',\n            duration=duration)\n\n    def willChain(self, option):\n        return self._chainNegotiation(None, self.will, option)\n\n    def wontChain(self, option):\n        return self._chainNegotiation(None, self.wont, option)\n\n    def doChain(self, option):\n        return self._chainNegotiation(None, self.do, option)\n\n    def dontChain(self, option):\n        return self._chainNegotiation(None, self.dont, option)\n\n    def _handleNegotiationError(self, f, func, option):\n        if f.type is AlreadyNegotiating:\n            s = self.getOptionState(option)\n            if func in (self.do, self.dont):\n                s.him.onResult.addCallback(self._chainNegotiation, func, option)\n                s.him.onResult.addErrback(self._handleNegotiationError, func, option)\n            if func in (self.will, self.wont):\n                s.us.onResult.addCallback(self._chainNegotiation, func, option)\n                s.us.onResult.addErrback(self._handleNegotiationError, func, option)\n        # We only care about AlreadyNegotiating, everything else can be ignored\n        # Possible other types include OptionRefused, AlreadyDisabled, AlreadyEnabled, ConnectionDone, ConnectionLost\n        elif f.type is AssertionError:\n            log.err('Client tried to illegally refuse to disable an option; ignoring, but undefined behavior may result')\n            # TODO: Is ignoring this violation of the protocol the proper behavior?\n            # Should the connection be terminated instead?\n            # The telnetd package on Ubuntu (netkit-telnet) does all negotiation before sending the login prompt,\n            # but does handle client-initiated negotiation at any time.\n        return None  # This Failure has been handled, no need to continue processing errbacks\n\n    def _chainNegotiation(self, res, func, option):\n        return func(option).addErrback(self._handleNegotiationError, func, option)\n", "path": "cowrie/telnet/transport.py"}]}