From 78b98781e3c0c2a2d3b685b3ae74e481ab5f0613 Mon Sep 17 00:00:00 2001 From: HonigBij Date: Tue, 17 Mar 2015 23:00:35 +0100 Subject: [PATCH 1/9] Added auth_class and auth_class_parameters The auth_class and class_parameters options in kippo.cfg can be used to enable an alternative class (instead of UserDB) for checklogin() in auth.py --- kippo.cfg.dist | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kippo.cfg.dist b/kippo.cfg.dist index 7ed1b0d3..00cb518e 100644 --- a/kippo.cfg.dist +++ b/kippo.cfg.dist @@ -69,6 +69,24 @@ filesystem_file = fs.pickle # (default: data_path) data_path = data +# Class that implements the checklogin() method. +# +# Class must be defined in kippo/core/auth.py +# Default is the 'UserDB' class which uses the password database. +# +# Alternatively the 'AuthRandom' class can be used, which will let +# a user login after a random number of attempts. +# It will also cache username/password combinations that allow login. +# +auth_class = UserDB +# When AuthRandom is used also set the +# auth_class_parameters: , , +# for example: 2, 5, 10 = allows access after randint(2,5) attempts +# and cache 10 combinations. +# +#auth_class = AuthRandom +#auth_class_parameters = 2, 5, 10 + # Directory for creating simple commands that only output text. # # The command must be placed under this directory with the proper path, such From 0b25c86051a42605576c94cf9dfd0fa816e5e34f Mon Sep 17 00:00:00 2001 From: HonigBij Date: Tue, 17 Mar 2015 23:01:53 +0100 Subject: [PATCH 2/9] Added AuthRandom class The AuthRandom class is an alternative to the UserDB class and implements the checklogin() method. To enable the class use the auth_class and auth_class_parameters options in kippo.cfg. --- kippo/core/auth.py | 191 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 166 insertions(+), 25 deletions(-) diff --git a/kippo/core/auth.py b/kippo/core/auth.py index 7173b631..9fba5ca3 100644 --- a/kippo/core/auth.py +++ b/kippo/core/auth.py @@ -2,13 +2,17 @@ # See the COPYRIGHT file for more information import string +import json +from os import path +from random import randint from zope.interface import implementer import twisted from twisted.cred.checkers import ICredentialsChecker -from twisted.cred.credentials import IUsernamePassword, ISSHPrivateKey, IPluggableAuthenticationModules +from twisted.cred.credentials import IUsernamePassword, ISSHPrivateKey, \ + IPluggableAuthenticationModules, ICredentials from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials from twisted.internet import defer @@ -28,8 +32,7 @@ class UserDB(object): def load(self): '''load the user db''' - userdb_file = '%s/userdb.txt' % \ - (config().get('honeypot', 'data_path'),) + userdb_file = '%s/userdb.txt' % (config().get('honeypot', 'data_path'),) f = open(userdb_file, 'r') while True: @@ -41,7 +44,7 @@ class UserDB(object): if not line: continue - if line.startswith( '#' ): + if line.startswith('#'): continue (login, uid_str, passwd) = line.split(':', 2) @@ -59,8 +62,7 @@ class UserDB(object): def save(self): '''save the user db''' - userdb_file = '%s/userdb.txt' % \ - (config().get('honeypot', 'data_path'),) + userdb_file = '%s/userdb.txt' % (config().get('honeypot', 'data_path'),) # Note: this is subject to races between kippo instances, but hey ... f = open(userdb_file, 'w') @@ -68,14 +70,14 @@ class UserDB(object): f.write('%s:%d:%s\n' % (login, uid, passwd)) f.close() - def checklogin(self, thelogin, thepasswd): + def checklogin(self, thelogin, thepasswd, src_ip = '0.0.0.0'): '''check entered username/password against database''' '''note that it allows multiple passwords for a single username''' '''it also knows wildcard '*' for any password''' '''prepend password with ! to explicitly deny it. Denials must come before wildcards''' for (login, uid, passwd) in self.userdb: # explicitly fail on !password - if login == thelogin and passwd == '!'+thepasswd: + if login == thelogin and passwd == '!' + thepasswd: return False if login == thelogin and passwd in (thepasswd, '*'): return True @@ -114,6 +116,111 @@ class UserDB(object): self.userdb.append((login, uid, passwd)) self.save() +class AuthRandom(object): + """ + Alternative class that defines the checklogin() method. + Users will be authenticated after a random number of attempts. + """ + + def __init__(self, mintry = 2, maxtry = 5, maxcache = 10): + self.mintry, self.maxtry, self.maxcache = mintry, maxtry, maxcache + self.uservar = {} + self.loadvars() + + def loadvars(self): + # load user vars from json file + uservar_file = '%s/uservar.json' % (config().get('honeypot', 'data_path')) + if path.isfile(uservar_file): + with open(uservar_file, 'rb') as fp: + try: + self.uservar = json.load(fp) + except: + self.uservar = {} + + def savevars(self): + # save the user vars to json file + uservar_file = '%s/uservar.json' % (config().get('honeypot', 'data_path')) + data = self.uservar + # Note: this is subject to races between kippo logins + with open(uservar_file, 'wb') as fp: + json.dump(data, fp) + + def checklogin(self, thelogin, thepasswd, src_ip): + '''Every new source IP will have to try a random number of times between mintry''' + '''and maxtry before succeeding to login''' + '''All username/password combinations must be different''' + '''The successful login combination is stored with the IP address''' + '''Successful username/passwords combo's are also cached for maxcache times''' + '''This is to allow access for returns from different IP addresses''' + '''Variables are saved in the uservar.json in the data directory''' + auth = False + userpass = thelogin + ':' + thepasswd + + if not 'cache' in self.uservar: + self.uservar['cache'] = [] + cache = self.uservar['cache'] + + # Check if it is the first visit from src_ip + if src_ip not in self.uservar: + self.uservar[src_ip] = {} + ipinfo = self.uservar[src_ip] + ipinfo['try'] = 0 + if userpass in cache: + log.msg('First time for %s, found cached: %s' % (src_ip, userpass)) + ipinfo['max'] = 1 + ipinfo['user'] = thelogin + ipinfo['pw'] = thepasswd + auth = True + self.savevars() + return auth + else: + ipinfo['max'] = randint(self.mintry, self.maxtry) + log.msg('First time for %s, need: %d' % (src_ip, ipinfo['max'])) + + ipinfo = self.uservar[src_ip] + + # Fill in missing variables + if not 'max' in ipinfo: + ipinfo['max'] = randint(self.mintry, self.maxtry) + if not 'try' in ipinfo: + ipinfo['try'] = 0 + if not 'tried' in ipinfo: + ipinfo['tried'] = [] + + # Don't count repeated username/password combo's + if userpass in ipinfo['tried']: + log.msg('Already tried this combo') + self.savevars() + return auth + + ipinfo['try'] += 1 + attempts = ipinfo['try'] + need = ipinfo['max'] + log.msg('Login attempt: %d' % attempts) + + # Check if enough login attempts are tried + if attempts < need: + self.uservar[src_ip]['tried'].append(userpass) + elif attempts == need: + ipinfo['user'] = thelogin + ipinfo['pw'] = thepasswd + cache.append(userpass) + if len(cache) > self.maxcache: + cache.pop(0) + auth = True + # Returning after successful login + elif attempts > need: + if not 'user' in ipinfo or not 'pw' in ipinfo: + log.msg('Return, but username or password not set!!!') + ipinfo['tried'].append(userpass) + ipinfo['try'] = 1 + else: + log.msg('Login return, expect: [%s/%s]' % (ipinfo['user'], ipinfo['pw'])) + if thelogin == ipinfo['user'] and thepasswd == ipinfo['pw']: + auth = True + self.savevars() + return auth + @implementer(ICredentialsChecker) class HoneypotPublicKeyChecker: """ @@ -125,8 +232,27 @@ class HoneypotPublicKeyChecker: def requestAvatarId(self, credentials): _pubKey = keys.Key.fromString(credentials.blob) log.msg(format='public key attempt for user %(username)s with fingerprint %(fingerprint)s', - username=credentials.username, fingerprint=_pubKey.fingerprint()) - return failure.Failure(error.ConchError("Incorrect signature")) + username=credentials.username, + fingerprint=_pubKey.fingerprint()) + return failure.Failure(error.ConchError('Incorrect signature')) + +# This credential interface also provides an IP address +@implementer(IUsernamePassword) +class UsernamePasswordIP: + + def __init__(self, username, password, ip): + self.username = username + self.password = password + self.ip = ip + +# This credential interface also provides an IP address +@implementer(IPluggableAuthenticationModules) +class PluggableAuthenticationModulesIP: + + def __init__(self, username, pamConversion, ip): + self.username = username + self.pamConversion = pamConversion + self.ip = ip @implementer(ICredentialsChecker) class HoneypotPasswordChecker: @@ -138,37 +264,52 @@ class HoneypotPasswordChecker: def requestAvatarId(self, credentials): if hasattr(credentials, 'password'): - if self.checkUserPass(credentials.username, credentials.password): + if self.checkUserPass(credentials.username, credentials.password, + credentials.ip): return defer.succeed(credentials.username) else: return defer.fail(UnauthorizedLogin()) elif hasattr(credentials, 'pamConversion'): return self.checkPamUser(credentials.username, - credentials.pamConversion) + credentials.pamConversion, credentials.ip) return defer.fail(UnhandledCredentials()) - def checkPamUser(self, username, pamConversion): + def checkPamUser(self, username, pamConversion, ip): r = pamConversion((('Password:', 1),)) - return r.addCallback(self.cbCheckPamUser, username) + return r.addCallback(self.cbCheckPamUser, username, ip) - def cbCheckPamUser(self, responses, username): - for response, zero in responses: - if self.checkUserPass(username, response): + def cbCheckPamUser(self, responses, username, ip): + for (response, zero) in responses: + if self.checkUserPass(username, response, ip): return defer.succeed(username) return defer.fail(UnauthorizedLogin()) - def checkUserPass(self, theusername, thepassword): - if UserDB().checklogin(theusername, thepassword): - #log.msg( 'login attempt [%s/%s] succeeded' % (theusername, thepassword) ) - log.msg( eventid='KIPP0002', + def checkUserPass(self, theusername, thepassword, ip): + authname=UserDB + + if config().has_option('honeypot', 'auth_class'): + authclass = config().get('honeypot', 'auth_class') + if authclass == 'AuthRandom': + authname = AuthRandom + + if config().has_option('honeypot', 'auth_class_parameters'): + parameters = config().get('honeypot', 'auth_class_parameters') + mintry, maxtry, maxcache = parameters.split(',') + theauth = authname(int(mintry), int(maxtry), int(maxcache)) + else: + theauth = authname() + + if theauth.checklogin(theusername, thepassword, ip): + # log.msg( 'login attempt [%s/%s] succeeded' % (theusername, thepassword) ) + log.msg(eventid='KIPP0002', format='login attempt [%(username)s/%(password)s] succeeded', - username=theusername, password=thepassword ) + username=theusername, password=thepassword) return True else: - #log.msg( 'login attempt [%s/%s] failed' % (theusername, thepassword) ) - log.msg( eventid='KIPP0003', + # log.msg( 'login attempt [%s/%s] failed' % (theusername, thepassword) ) + log.msg(eventid='KIPP0003', format='login attempt [%(username)s/%(password)s] failed', - username=theusername, password=thepassword ) + username=theusername, password=thepassword) return False # vim: set sw=4 et: From 4c78039143b9ee3169458fd8f58ec2dc8cd89506 Mon Sep 17 00:00:00 2001 From: HonigBij Date: Tue, 17 Mar 2015 23:02:22 +0100 Subject: [PATCH 3/9] Additions for IP address in credentials --- kippo/core/ssh.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/kippo/core/ssh.py b/kippo/core/ssh.py index 1856d9e0..ee79545d 100644 --- a/kippo/core/ssh.py +++ b/kippo/core/ssh.py @@ -56,6 +56,23 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): self.sendBanner() return userauth.SSHUserAuthServer.ssh_USERAUTH_REQUEST(self, packet) + # Overridden to pass src_ip to auth.UsernamePasswordIP + def auth_password(self, packet): + password = getNS(packet[1:])[0] + c = auth.UsernamePasswordIP(self.user, password, self.transport.src_ip) + return self.portal.login(c, None, conchinterfaces.IConchUser).addErrback( + self._ebPassword) + + # Overridden to pass src_ip to auth.PlubbableAuthenticationModulesIP + def auth_keyboard_interactive(self, packet): + if self._pamDeferred is not None: + self.transport.sendDisconnect( + transport.DISCONNECT_PROTOCOL_ERROR, + "only one keyboard interactive attempt at a time") + return defer.fail(error.IgnoreAuthentication()) + c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, self.transport.src_ip) + return self.portal.login(c, None, conchinterfaces.IConchUser) + # As implemented by Kojoney class HoneyPotSSHFactory(factory.SSHFactory): services = { @@ -185,6 +202,8 @@ class HoneyPotTransport(sshserver.KippoSSHServerTransport): def connectionMade(self): self.transportId = uuid.uuid4().hex[:8] self.interactors = [] + # store src_ip to use in HoneyPotSSHUserAuthServer + self.src_ip=self.transport.getPeer().host log.msg( eventid='KIPP0001', format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(sessionno)s]', From dc0e183de30a0480c0777b3a57a53a249e8120e9 Mon Sep 17 00:00:00 2001 From: HonigBij Date: Wed, 18 Mar 2015 13:53:01 +0100 Subject: [PATCH 4/9] Auth_class more generic via dynamic lookup If auth_class is defined in the kippo.cfg config file it is looked up in the module. When it exists it is used, otherwise fall back to default UserDB class. Also auth_class_parameters are made more robust. --- kippo/core/auth.py | 58 ++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/kippo/core/auth.py b/kippo/core/auth.py index 9fba5ca3..52fd1820 100644 --- a/kippo/core/auth.py +++ b/kippo/core/auth.py @@ -4,6 +4,7 @@ import string import json from os import path +from sys import modules from random import randint from zope.interface import implementer @@ -122,13 +123,23 @@ class AuthRandom(object): Users will be authenticated after a random number of attempts. """ - def __init__(self, mintry = 2, maxtry = 5, maxcache = 10): - self.mintry, self.maxtry, self.maxcache = mintry, maxtry, maxcache + def __init__(self, parameters): + # Default values + self.mintry, self.maxtry, self.maxcache = 2, 5, 10 + parlist = parameters.split(',') + + if len(parlist) == 3: + self.mintry = int(parlist[0]) + self.maxtry = int(parlist[1]) + self.maxcache = int(parlist[2]) + if self.maxtry < self.mintry: + self.maxtry = self.mintry + 1 + log.msg('maxtry < mintry, adjusting maxtry to: %d' % self.maxtry) self.uservar = {} self.loadvars() def loadvars(self): - # load user vars from json file + # Load user vars from json file uservar_file = '%s/uservar.json' % (config().get('honeypot', 'data_path')) if path.isfile(uservar_file): with open(uservar_file, 'rb') as fp: @@ -138,7 +149,7 @@ class AuthRandom(object): self.uservar = {} def savevars(self): - # save the user vars to json file + # Save the user vars to json file uservar_file = '%s/uservar.json' % (config().get('honeypot', 'data_path')) data = self.uservar # Note: this is subject to races between kippo logins @@ -166,7 +177,7 @@ class AuthRandom(object): ipinfo = self.uservar[src_ip] ipinfo['try'] = 0 if userpass in cache: - log.msg('First time for %s, found cached: %s' % (src_ip, userpass)) + log.msg('first time for %s, found cached: %s' % (src_ip, userpass)) ipinfo['max'] = 1 ipinfo['user'] = thelogin ipinfo['pw'] = thepasswd @@ -175,7 +186,7 @@ class AuthRandom(object): return auth else: ipinfo['max'] = randint(self.mintry, self.maxtry) - log.msg('First time for %s, need: %d' % (src_ip, ipinfo['max'])) + log.msg('first time for %s, need: %d' % (src_ip, ipinfo['max'])) ipinfo = self.uservar[src_ip] @@ -187,16 +198,16 @@ class AuthRandom(object): if not 'tried' in ipinfo: ipinfo['tried'] = [] - # Don't count repeated username/password combo's + # Don't count repeated username/password combinations if userpass in ipinfo['tried']: - log.msg('Already tried this combo') + log.msg('already tried this combination') self.savevars() return auth ipinfo['try'] += 1 attempts = ipinfo['try'] need = ipinfo['max'] - log.msg('Login attempt: %d' % attempts) + log.msg('login attempt: %d' % attempts) # Check if enough login attempts are tried if attempts < need: @@ -211,11 +222,11 @@ class AuthRandom(object): # Returning after successful login elif attempts > need: if not 'user' in ipinfo or not 'pw' in ipinfo: - log.msg('Return, but username or password not set!!!') + log.msg('return, but username or password not set!!!') ipinfo['tried'].append(userpass) ipinfo['try'] = 1 else: - log.msg('Login return, expect: [%s/%s]' % (ipinfo['user'], ipinfo['pw'])) + log.msg('login return, expect: [%s/%s]' % (ipinfo['user'], ipinfo['pw'])) if thelogin == ipinfo['user'] and thepasswd == ipinfo['pw']: auth = True self.savevars() @@ -285,28 +296,35 @@ class HoneypotPasswordChecker: return defer.fail(UnauthorizedLogin()) def checkUserPass(self, theusername, thepassword, ip): - authname=UserDB + # UserDB is the default auth_class + authname = UserDB + parameters = None + # Is the auth_class defined in the config file? if config().has_option('honeypot', 'auth_class'): authclass = config().get('honeypot', 'auth_class') - if authclass == 'AuthRandom': - authname = AuthRandom - if config().has_option('honeypot', 'auth_class_parameters'): - parameters = config().get('honeypot', 'auth_class_parameters') - mintry, maxtry, maxcache = parameters.split(',') - theauth = authname(int(mintry), int(maxtry), int(maxcache)) + # Check if authclass exists in this module + if hasattr(modules[__name__], authclass): + authname = getattr(modules[__name__], authclass) + + # Are there auth_class parameters? + if config().has_option('honeypot', 'auth_class_parameters'): + parameters = config().get('honeypot', 'auth_class_parameters') + else: + log.msg('auth_class: %s not found in %s' % (authclass, __name__)) + + if parameters: + theauth = authname(parameters) else: theauth = authname() if theauth.checklogin(theusername, thepassword, ip): - # log.msg( 'login attempt [%s/%s] succeeded' % (theusername, thepassword) ) log.msg(eventid='KIPP0002', format='login attempt [%(username)s/%(password)s] succeeded', username=theusername, password=thepassword) return True else: - # log.msg( 'login attempt [%s/%s] failed' % (theusername, thepassword) ) log.msg(eventid='KIPP0003', format='login attempt [%(username)s/%(password)s] failed', username=theusername, password=thepassword) From 2957d00bd874d187798f32e9f73cf47595c4224a Mon Sep 17 00:00:00 2001 From: HonigBij Date: Wed, 18 Mar 2015 15:44:13 +0100 Subject: [PATCH 5/9] Retrieve client IP address (src_ip) directly in HoneyPotSSHUserAuthServer --- kippo/core/ssh.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kippo/core/ssh.py b/kippo/core/ssh.py index ee79545d..06c64643 100644 --- a/kippo/core/ssh.py +++ b/kippo/core/ssh.py @@ -70,7 +70,8 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): transport.DISCONNECT_PROTOCOL_ERROR, "only one keyboard interactive attempt at a time") return defer.fail(error.IgnoreAuthentication()) - c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, self.transport.src_ip) + src_ip=self.transport.getPeer().address.host + c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser) # As implemented by Kojoney @@ -202,8 +203,6 @@ class HoneyPotTransport(sshserver.KippoSSHServerTransport): def connectionMade(self): self.transportId = uuid.uuid4().hex[:8] self.interactors = [] - # store src_ip to use in HoneyPotSSHUserAuthServer - self.src_ip=self.transport.getPeer().host log.msg( eventid='KIPP0001', format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(sessionno)s]', From b2794b1aed2628b691b6d8eb30b420d24d046358 Mon Sep 17 00:00:00 2001 From: HonigBij Date: Wed, 18 Mar 2015 15:47:09 +0100 Subject: [PATCH 6/9] formatting --- kippo/core/ssh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kippo/core/ssh.py b/kippo/core/ssh.py index 06c64643..bac66e2f 100644 --- a/kippo/core/ssh.py +++ b/kippo/core/ssh.py @@ -70,7 +70,7 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): transport.DISCONNECT_PROTOCOL_ERROR, "only one keyboard interactive attempt at a time") return defer.fail(error.IgnoreAuthentication()) - src_ip=self.transport.getPeer().address.host + src_ip = self.transport.getPeer().address.host c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser) From 8f343662c010d2616858d838173452f4b40189d2 Mon Sep 17 00:00:00 2001 From: HonigBij Date: Wed, 18 Mar 2015 16:04:48 +0100 Subject: [PATCH 7/9] Formatting of AuthRandom checklogin comment --- kippo/core/auth.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kippo/core/auth.py b/kippo/core/auth.py index 52fd1820..ea17413f 100644 --- a/kippo/core/auth.py +++ b/kippo/core/auth.py @@ -157,13 +157,13 @@ class AuthRandom(object): json.dump(data, fp) def checklogin(self, thelogin, thepasswd, src_ip): - '''Every new source IP will have to try a random number of times between mintry''' - '''and maxtry before succeeding to login''' - '''All username/password combinations must be different''' - '''The successful login combination is stored with the IP address''' - '''Successful username/passwords combo's are also cached for maxcache times''' - '''This is to allow access for returns from different IP addresses''' - '''Variables are saved in the uservar.json in the data directory''' + '''Every new source IP will have to try a random number of times between''' + ''''mintry' and 'maxtry' before succeeding to login.''' + '''All username/password combinations must be different.''' + '''The successful login combination is stored with the IP address.''' + '''Successful username/passwords pairs are also cached for 'maxcache' times.''' + '''This is to allow access for returns from different IP addresses.''' + '''Variables are saved in 'uservar.json' in the data directory.''' auth = False userpass = thelogin + ':' + thepasswd From cb1ba514a6ce007fc8924f89188bf1372ec6fa26 Mon Sep 17 00:00:00 2001 From: honigbij Date: Wed, 18 Mar 2015 19:03:09 +0100 Subject: [PATCH 8/9] Also set src_ip directly in auth_password --- kippo/core/ssh.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kippo/core/ssh.py b/kippo/core/ssh.py index bac66e2f..e94c7e84 100644 --- a/kippo/core/ssh.py +++ b/kippo/core/ssh.py @@ -59,7 +59,8 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): # Overridden to pass src_ip to auth.UsernamePasswordIP def auth_password(self, packet): password = getNS(packet[1:])[0] - c = auth.UsernamePasswordIP(self.user, password, self.transport.src_ip) + src_ip = self.transport.getPeer().address.host + c = auth.UsernamePasswordIP(self.user, password, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser).addErrback( self._ebPassword) From db22e63bc38df7c85143aaca64184aeca93defc0 Mon Sep 17 00:00:00 2001 From: honigbij Date: Thu, 19 Mar 2015 10:24:48 +0100 Subject: [PATCH 9/9] Use self.transport.transport instead of self.transport --- kippo/core/ssh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kippo/core/ssh.py b/kippo/core/ssh.py index e94c7e84..cb38fc22 100644 --- a/kippo/core/ssh.py +++ b/kippo/core/ssh.py @@ -59,19 +59,19 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): # Overridden to pass src_ip to auth.UsernamePasswordIP def auth_password(self, packet): password = getNS(packet[1:])[0] - src_ip = self.transport.getPeer().address.host + src_ip = self.transport.transport.getPeer().host c = auth.UsernamePasswordIP(self.user, password, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser).addErrback( self._ebPassword) - # Overridden to pass src_ip to auth.PlubbableAuthenticationModulesIP + # Overridden to pass src_ip to auth.PluggableAuthenticationModulesIP def auth_keyboard_interactive(self, packet): if self._pamDeferred is not None: self.transport.sendDisconnect( transport.DISCONNECT_PROTOCOL_ERROR, "only one keyboard interactive attempt at a time") return defer.fail(error.IgnoreAuthentication()) - src_ip = self.transport.getPeer().address.host + src_ip = self.transport.transport.getPeer().host c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser)