Working support of scram-sha-256.

This commit is contained in:
Valentin Lorentz 2017-01-11 00:10:46 +01:00
parent 9be4db01f8
commit 8ce43110b6
3 changed files with 27 additions and 8 deletions

View File

@ -312,7 +312,8 @@ class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf):
return None return None
class ValidSaslMechanism(registry.OnlySomeStrings): class ValidSaslMechanism(registry.OnlySomeStrings):
validStrings = ('ecdsa-nist256p-challenge', 'external', 'plain') validStrings = ('ecdsa-nist256p-challenge', 'external', 'plain',
'scram-sha-256')
class SpaceSeparatedListOfSaslMechanisms(registry.SpaceSeparatedListOf): class SpaceSeparatedListOfSaslMechanisms(registry.SpaceSeparatedListOf):
Value = ValidSaslMechanism Value = ValidSaslMechanism

View File

@ -1116,10 +1116,16 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
step = self.sasl_scram_state['step'] step = self.sasl_scram_state['step']
try: try:
if step == 'uninitialized': if step == 'uninitialized':
self.doAuthenticateScramFirst() log.debug('%s: starting SCRAM.',
self.network)
self.doAuthenticateScramFirst(mechanism)
elif step == 'first-sent': elif step == 'first-sent':
log.debug('%s: received SCRAM challenge.',
self.network)
self.doAuthenticateScramChallenge(string) self.doAuthenticateScramChallenge(string)
elif step == 'final-sent': elif step == 'final-sent':
log.debug('%s: finishing SCRAM.',
self.network)
self.doAuthenticateScramFinish(string) self.doAuthenticateScramFinish(string)
else: else:
assert False assert False
@ -1149,11 +1155,17 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
args=('*',))) args=('*',)))
self.tryNextSaslMechanism() self.tryNextSaslMechanism()
def doAuthenticateScramFirst(self): def doAuthenticateScramFirst(self, mechanism):
"""Handle sending the client-first message of SCRAM auth.""" """Handle sending the client-first message of SCRAM auth."""
hash_name = mechanism[len('scram-'):] hash_name = mechanism[len('scram-'):]
if hash_name.endswith('-plus'): if hash_name.endswith('-plus'):
hash_name = hash_name[:-len('-plus')] hash_name = hash_name[:-len('-plus')]
hash_name = hash_name.upper()
if hash_name not in scram.HASH_FACTORIES:
log.debug('%s: SCRAM hash %r not supported, aborting.',
self.network, hash_name)
self.tryNextSaslMechanism()
return
authenticator = scram.SCRAMClientAuthenticator(hash_name, authenticator = scram.SCRAMClientAuthenticator(hash_name,
channel_binding=False) channel_binding=False)
self.sasl_scram_state['authenticator'] = authenticator self.sasl_scram_state['authenticator'] = authenticator
@ -1167,13 +1179,19 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
def doAuthenticateScramChallenge(self, challenge): def doAuthenticateScramChallenge(self, challenge):
client_final = self.sasl_scram_state['authenticator'] \ client_final = self.sasl_scram_state['authenticator'] \
.challenge(challenge) .challenge(challenge)
self.sendSaslString(client_final)
self.sasl_scram_state['step'] = 'final-sent' self.sasl_scram_state['step'] = 'final-sent'
def doAuthenticateScramFinish(self, data): def doAuthenticateScramFinish(self, data):
# TODO: do something with BadSuccessException try:
res = self.sasl_scram_state['authenticator'] \ res = self.sasl_scram_state['authenticator'] \
.finish(data) .finish(data)
self.sasl_scram_state['step'] = 'authenticated' except scram.BadSuccessException as e:
log.warning('%s: SASL authentication failed with SCRAM error: %e',
self.network, e)
self.tryNextSaslMechanism()
else:
self.sasl_scram_state['step'] = 'authenticated'
def do903(self, msg): def do903(self, msg):
log.info('%s: SASL authentication successful', self.network) log.info('%s: SASL authentication successful', self.network)

View File

@ -508,7 +508,7 @@ class Probability(Float):
class String(Value): class String(Value):
"""Value is not a valid Python string.""" """Value is not a valid Python string."""
errormsg = _('Value is not a valid Python string, not %r.') errormsg = _('Value should be a valid Python string, not %r.')
def set(self, s): def set(self, s):
v = s v = s
if not v: if not v: