Exemple #1
0
 def succeedAuth(self):
     """
     Sends a Userauth Success packet to the client, then switches the transport
     to the client's desired service.
     """
     # Authentication has succeeded fully.
     # Obtain the service desired by the end user
     service = self.transport.factory.getService(self.transport,
             self.state.desired_service)
     self.transport.sendPacket(userauth.MSG_USERAUTH_SUCCESS, b'')
     self.transport.setService(service())
 def _cbFinishedAuth(self, result):
     """
     The callback when user has successfully been authenticated.  For a
     description of the arguments, see L{twisted.cred.portal.Portal.login}.
     We start the service requested by the user.
     """
     (interface, avatar, logout) = result
     self.transport.avatar = avatar
     self.transport.logoutFunction = logout
     service = self.transport.factory.getService(self.transport,
             self.nextService)
     if not service:
         raise error.ConchError('could not get next service: %s'
                               % self.nextService)
     log.msg('%s authenticated with %s' % (self.user, self.method))
     self.transport.sendPacket(MSG_USERAUTH_SUCCESS, b'')
     self.transport.setService(service())
Exemple #3
0
 def _cbFinishedAuth(self, result):
     """
     The callback when user has successfully been authenticated.  For a
     description of the arguments, see L{twisted.cred.portal.Portal.login}.
     We start the service requested by the user.
     """
     (interface, avatar, logout) = result
     self.transport.avatar = avatar
     self.transport.logoutFunction = logout
     service = self.transport.factory.getService(self.transport,
                                                 self.nextService)
     if not service:
         raise error.ConchError('could not get next service: %s' %
                                self.nextService)
     log.msg('%s authenticated with %s' % (self.user, self.method))
     self.transport.sendPacket(MSG_USERAUTH_SUCCESS, b'')
     self.transport.setService(service())
Exemple #4
0
class SSHUserAuthServer(service.SSHService):
    """
    A service implementing the server side of the 'ssh-userauth' service.  It
    is used to authenticate the user on the other side as being able to access
    this server.

    @ivar name: the name of this service: 'ssh-userauth'
    @type name: C{str}
    @ivar authenticatedWith: a list of authentication methods that have
        already been used.
    @type authenticatedWith: C{list}
    @ivar loginTimeout: the number of seconds we wait before disconnecting
        the user for taking too long to authenticate
    @type loginTimeout: C{int}
    @ivar attemptsBeforeDisconnect: the number of failed login attempts we
        allow before disconnecting.
    @type attemptsBeforeDisconnect: C{int}
    @ivar loginAttempts: the number of login attempts that have been made
    @type loginAttempts: C{int}
    @ivar passwordDelay: the number of seconds to delay when the user gives
        an incorrect password
    @type passwordDelay: C{int}
    @ivar interfaceToMethod: a C{dict} mapping credential interfaces to
        authentication methods.  The server checks to see which of the
        cred interfaces have checkers and tells the client that those methods
        are valid for authentication.
    @type interfaceToMethod: C{dict}
    @ivar supportedAuthentications: A list of the supported authentication
        methods.
    @type supportedAuthentications: C{list} of C{str}
    @ivar user: the last username the client tried to authenticate with
    @type user: C{str}
    @ivar method: the current authentication method
    @type method: C{str}
    @ivar nextService: the service the user wants started after authentication
        has been completed.
    @type nextService: C{str}
    @ivar portal: the L{twisted.cred.portal.Portal} we are using for
        authentication
    @type portal: L{twisted.cred.portal.Portal}
    @ivar clock: an object with a callLater method.  Stubbed out for testing.
    """


    name = 'ssh-userauth'
    loginTimeout = 10 * 60 * 60
    # 10 minutes before we disconnect them
    attemptsBeforeDisconnect = 20
    # 20 login attempts before a disconnect
    passwordDelay = 1 # number of seconds to delay on a failed password
    clock = reactor
    interfaceToMethod = {
        credentials.ISSHPrivateKey : 'publickey',
        credentials.IUsernamePassword : '******',
        credentials.IPluggableAuthenticationModules : 'keyboard-interactive',
    }


    def serviceStarted(self):
        """
        Called when the userauth service is started.  Set up instance
        variables, check if we should allow password/keyboard-interactive
        authentication (only allow if the outgoing connection is encrypted) and
        set up a login timeout.
        """
        self.authenticatedWith = []
        self.loginAttempts = 0
        self.user = None
        self.nextService = None
        self._pamDeferred = None
        self.portal = self.transport.factory.portal

        self.supportedAuthentications = []
        for i in self.portal.listCredentialsInterfaces():
            if i in self.interfaceToMethod:
                self.supportedAuthentications.append(self.interfaceToMethod[i])

        if not self.transport.isEncrypted('in'):
            # don't let us transport password in plaintext
            if 'password' in self.supportedAuthentications:
                self.supportedAuthentications.remove('password')
            if 'keyboard-interactive' in self.supportedAuthentications:
                self.supportedAuthentications.remove('keyboard-interactive')
        self._cancelLoginTimeout = self.clock.callLater(
            self.loginTimeout,
            self.timeoutAuthentication)


    def serviceStopped(self):
        """
        Called when the userauth service is stopped.  Cancel the login timeout
        if it's still going.
        """
        if self._cancelLoginTimeout:
            self._cancelLoginTimeout.cancel()
            self._cancelLoginTimeout = None


    def timeoutAuthentication(self):
        """
        Called when the user has timed out on authentication.  Disconnect
        with a DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE message.
        """
        self._cancelLoginTimeout = None
        self.transport.sendDisconnect(
            transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
            'you took too long')


    def tryAuth(self, kind, user, data):
        """
        Try to authenticate the user with the given method.  Dispatches to a
        auth_* method.

        @param kind: the authentication method to try.
        @type kind: C{str}
        @param user: the username the client is authenticating with.
        @type user: C{str}
        @param data: authentication specific data sent by the client.
        @type data: C{str}
        @return: A Deferred called back if the method succeeded, or erred back
            if it failed.
        @rtype: C{defer.Deferred}
        """
        log.msg('%s trying auth %s' % (user, kind))
        if kind not in self.supportedAuthentications:
            return defer.fail(
                    error.ConchError('unsupported authentication, failing'))
        kind = kind.replace('-', '_')
        f = getattr(self,'auth_%s'%kind, None)
        if f:
            ret = f(data)
            if not ret:
                return defer.fail(
                        error.ConchError('%s return None instead of a Deferred'
                            % kind))
            else:
                return ret
        return defer.fail(error.ConchError('bad auth type: %s' % kind))


    def ssh_USERAUTH_REQUEST(self, packet):
        """
        The client has requested authentication.  Payload::
            string user
            string next service
            string method
            <authentication specific data>

        @type packet: C{str}
        """
        user, nextService, method, rest = getNS(packet, 3)
        if user != self.user or nextService != self.nextService:
            self.authenticatedWith = [] # clear auth state
        self.user = user
        self.nextService = nextService
        self.method = method
        d = self.tryAuth(method, user, rest)
        if not d:
            self._ebBadAuth(
                failure.Failure(error.ConchError('auth returned none')))
            return
        d.addCallback(self._cbFinishedAuth)
        d.addErrback(self._ebMaybeBadAuth)
        d.addErrback(self._ebBadAuth)
        return d


    def _cbFinishedAuth(self, (interface, avatar, logout)):
        """
        The callback when user has successfully been authenticated.  For a
        description of the arguments, see L{twisted.cred.portal.Portal.login}.
        We start the service requested by the user.
        """
        self.transport.avatar = avatar
        self.transport.logoutFunction = logout
        service = self.transport.factory.getService(self.transport,
                self.nextService)
        if not service:
            raise error.ConchError('could not get next service: %s'
                                  % self.nextService)
        log.msg('%s authenticated with %s' % (self.user, self.method))
        self.transport.sendPacket(MSG_USERAUTH_SUCCESS, '')
        self.transport.setService(service())