From a572c4fd15dd9f82784d9cacd505d39f08e5f702 Mon Sep 17 00:00:00 2001 From: Michel Oosterhof Date: Fri, 28 Aug 2015 11:48:36 +0000 Subject: [PATCH] split out credentials to credentials.py --- cowrie/core/auth.py | 34 +++-------------- cowrie/core/credentials.py | 75 ++++++++++++++++++++++++++++++++++++++ cowrie/core/ssh.py | 14 ++++--- 3 files changed, 88 insertions(+), 35 deletions(-) create mode 100644 cowrie/core/credentials.py diff --git a/cowrie/core/auth.py b/cowrie/core/auth.py index 5407c91a..204f1505 100644 --- a/cowrie/core/auth.py +++ b/cowrie/core/auth.py @@ -10,8 +10,7 @@ from random import randint from zope.interface import implementer from twisted.cred.checkers import ICredentialsChecker -from twisted.cred.credentials import IUsernamePassword, ISSHPrivateKey, \ - ICredentials +from twisted.cred.credentials import ISSHPrivateKey from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials from twisted.internet import defer @@ -19,6 +18,8 @@ from twisted.python import log, failure from twisted.conch import error from twisted.conch.ssh import keys +import credentials + # by Walter de Jong class UserDB(object): @@ -257,38 +258,13 @@ class HoneypotPublicKeyChecker: fingerprint=_pubKey.fingerprint()) return failure.Failure(error.ConchError('Incorrect signature')) -class IUsername(ICredentials): - """ - Encapsulate username only - - @type username: C{str} - @ivar username: The username associated with these credentials. - """ - - -@implementer(IUsername) -class Username: - - def __init__(self, username): - self.username = username - - -# 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 - @implementer(ICredentialsChecker) class HoneypotNoneChecker: """ Checker that does no authentication check """ - credentialInterfaces = (IUsername,) + credentialInterfaces = (credentials.IUsername,) def __init__(self): pass @@ -302,7 +278,7 @@ class HoneypotPasswordChecker: Checker that accepts "keyboard-interactive" and "password" """ - credentialInterfaces = (IUsernamePassword,) + credentialInterfaces = (credentials.IUsernamePasswordIP,) def __init__(self, cfg): self.cfg = cfg diff --git a/cowrie/core/credentials.py b/cowrie/core/credentials.py new file mode 100644 index 00000000..d969d597 --- /dev/null +++ b/cowrie/core/credentials.py @@ -0,0 +1,75 @@ +# Copyright (c) 2015 Michel Oosterhof +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The names of the author(s) may not be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +from zope.interface import implementer + +from twisted.cred.credentials import IUsernamePassword, \ + ICredentials + +class IUsername(ICredentials): + """ + Encapsulate username only + + @type username: C{str} + @ivar username: The username associated with these credentials. + """ + +class IUsernamePasswordIP(IUsernamePassword): + """ + I encapsulate a username, a plaintext password and a source IP + + @type username: C{str} + @ivar username: The username associated with these credentials. + + @type password: C{str} + @ivar password: The password associated with these credentials. + + @type ip: C{str} + @ivar ip: The source ip address associated with these credentials. + """ + +@implementer(IUsername) +class Username: + """ + + """ + def __init__(self, username): + self.username = username + +# This credential interface also provides an IP address +@implementer(IUsernamePasswordIP) +class UsernamePasswordIP: + """ + + """ + def __init__(self, username, password, ip): + self.username = username + self.password = password + self.ip = ip + +# vim: set sw=4 et: diff --git a/cowrie/core/ssh.py b/cowrie/core/ssh.py index bce0228e..7a34c166 100644 --- a/cowrie/core/ssh.py +++ b/cowrie/core/ssh.py @@ -20,6 +20,7 @@ from twisted.internet import defer import ConfigParser +import credentials import fs import auth import connection @@ -29,7 +30,8 @@ import protocol class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): def serviceStarted(self): - self.interfaceToMethod[auth.IUsername] = 'none' + self.interfaceToMethod[credentials.IUsername] = 'none' + self.interfaceToMethod[credentials.IUsernamePasswordIP] = 'password' userauth.SSHUserAuthServer.serviceStarted(self) self.bannerSent = False @@ -54,18 +56,18 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): return userauth.SSHUserAuthServer.ssh_USERAUTH_REQUEST(self, packet) def auth_none(self, packet): - c = auth.Username(self.user) + c = credentials.Username(self.user) return self.portal.login(c, None, conchinterfaces.IConchUser) - # Overridden to pass src_ip to auth.UsernamePasswordIP + # Overridden to pass src_ip to credentials.UsernamePasswordIP def auth_password(self, packet): password = getNS(packet[1:])[0] src_ip = self.transport.transport.getPeer().host - c = auth.UsernamePasswordIP(self.user, password, src_ip) + c = credentials.UsernamePasswordIP(self.user, password, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser).addErrback(self._ebPassword) - # Overridden to pass src_ip to auth.PluggableAuthenticationModulesIP + # Overridden to pass src_ip to credentials.PluggableAuthenticationModulesIP def auth_keyboard_interactive(self, packet): if self._pamDeferred is not None: self.transport.sendDisconnect( @@ -73,7 +75,7 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer): "only one keyboard interactive attempt at a time") return defer.fail(error.IgnoreAuthentication()) src_ip = self.transport.transport.getPeer().host - c = auth.PluggableAuthenticationModulesIP(self.user, self._pamConv, src_ip) + c = credentials.PluggableAuthenticationModulesIP(self.user, self._pamConv, src_ip) return self.portal.login(c, None, conchinterfaces.IConchUser).addErrback(self._ebPassword)