Ticket #1411: sftp-auth-key-1411.patch

File sftp-auth-key-1411.patch, 3.8 KB (added by pyhedgehog, at 2012-12-09T23:48:09Z)
  • src/allmydata/frontends/auth.py

    diff --git a/src/allmydata/frontends/auth.py b/src/allmydata/frontends/auth.py
    index 82ef1c6..02c65a0 100644
    a b  
    11import os
    2 from zope.interface import implements
     2from zope.interface import implements, providedBy
    33from twisted.web.client import getPage
    44from twisted.internet import defer
    55from twisted.cred import error, checkers, credentials
     6from twisted.conch.ssh import keys
     7from twisted.conch import error as conch_error
     8from twisted.python import failure
    69from allmydata.util import base32
    710
    811class NeedRootcapLookupScheme(Exception):
    class FTPAvatarID: 
    1720
    1821class AccountFileChecker:
    1922    implements(checkers.ICredentialsChecker)
    20     credentialInterfaces = (credentials.IUsernamePassword,
     23    credentialInterfaces = (credentials.ISSHPrivateKey,
     24                            credentials.IUsernamePassword,
    2125                            credentials.IUsernameHashedPassword)
    2226    def __init__(self, client, accountfile):
    2327        self.client = client
    class AccountFileChecker: 
    3135            name, passwd, rest = line.split(None, 2)
    3236            if passwd in ("ssh-dss", "ssh-rsa"):
    3337                bits = rest.split()
    34                 keystring = " ".join(bits[-1])
     38                keystring = " ".join(bits[:-1])
    3539                rootcap = bits[-1]
    36                 self.pubkeys[name] = keystring
     40                if name not in self.pubkeys:
     41                  self.pubkeys[name] = {}
     42                self.pubkeys[name][keystring.decode('base64')] = rootcap
    3743            else:
    3844                self.passwords[name] = passwd
    3945                rootcap = rest
    40             self.rootcaps[name] = rootcap
     46                self.rootcaps[name] = rootcap
    4147
    4248    def _cbPasswordMatch(self, matched, username):
    4349        if matched:
    4450            return FTPAvatarID(username, self.rootcaps[username])
    4551        raise error.UnauthorizedLogin
    4652
    47     def requestAvatarId(self, credentials):
    48         if credentials.username in self.passwords:
    49             d = defer.maybeDeferred(credentials.checkPassword,
    50                                     self.passwords[credentials.username])
    51             d.addCallback(self._cbPasswordMatch, str(credentials.username))
     53    def _cbCheckKey(self, matched, credentials):
     54        if not credentials.signature:
     55            return failure.Failure(conch_error.ValidPublicKey())
     56        if matched:
     57            pubKey = keys.Key.fromString(credentials.blob)
     58            matched = pubKey.verify(credentials.signature, credentials.sigData)
     59        if matched:
     60            rootcap = self.pubkeys[credentials.username][credentials.blob]
     61            return FTPAvatarID(username, rootcap)
     62        raise error.UnauthorizedLogin
     63
     64    def checkKey(self, credentials):
     65        return credentials.blob in self.pubkeys[credentials.username]
     66
     67    def requestAvatarId(self, s_credentials):
     68        if (credentials.ISSHPrivateKey in providedBy(s_credentials)
     69                and s_credentials.username in self.pubkeys):
     70            d = defer.maybeDeferred(self.checkKey, s_credentials)
     71            d.addCallback(self._cbCheckKey, s_credentials)
     72            return d
     73        if ((credentials.IUsernamePassword in providedBy(s_credentials) or
     74             credentials.IUsernameHashedPassword in providedBy(s_credentials))
     75                and s_credentials.username in self.passwords):
     76            d = defer.maybeDeferred(s_credentials.checkPassword,
     77                                    self.passwords[s_credentials.username])
     78            d.addCallback(self._cbPasswordMatch, str(s_credentials.username))
    5279            return d
    5380        return defer.fail(error.UnauthorizedLogin())
    5481