|
You are right, Cyrus SASL's SCRAM implementation is using three steps. The sasl_server_step function returns SASL_CONTINUE on the second step even though the conversation is finished. It returns SASL_OK on the third call.
Not sure if this is a bug in the library or intentional, investigating.
|
|
I figured it out. The problem is the server expects a 3rd challenge. After comparing v, if I send an empty challenge back to the server the conversation completes and authorization for subsequent ops works.
So, the server should only require two challenges according to the RFC. The third empty challenge makes no sense.
Here's the new conversation with the extra challenge:
>>> import pymongo
|
>>> c = pymongo.MongoClient()
|
>>> c.admin.authenticate('admin', 'pass', mechanism='SCRAM-SHA-1')
|
|
C: SON([(u'saslStart', 1), (u'mechanism', u'SCRAM-SHA-1'), (u'payload', Binary('n,,n=admin,r=MDc1NzQ3NDA2MTU5Nw==', 0)), (u'autoAuthorize', 1)])
|
S: {u'conversationId': 1, u'ok': 1.0, u'done': False, u'payload': Binary('r=MDc1NzQ3NDA2MTU5Nw==ifU50J2lPcglfCKeAgZmB6o13b+lQiO+,s=qO2AOxr9U3bw+2Y4UjKbIg==,i=10000', 0)}
|
|
server provided salt: 'qO2AOxr9U3bw+2Y4UjKbIg=='
|
client generated storedKey: '/sTbSy4VONe2FxB6Qc+c4+OuvBo='
|
client generated serverKey: 'Xjs3eTp4NIXaQvIyrOfFYMGm0/A='
|
client generated v: 'ms733XGZwzyibxPdvST8ibsu/Gc='
|
|
C: SON([(u'saslContinue', 1), (u'conversationId', 1), (u'payload', Binary('c=biws,r=MDc1NzQ3NDA2MTU5Nw==ifU50J2lPcglfCKeAgZmB6o13b+lQiO+,p=7yX5Hi7B2J0ba5CVUnpk8iFKFAo=', 0))])
|
S: {u'conversationId': 1, u'ok': 1.0, u'done': False, u'payload': Binary('v=ms733XGZwzyibxPdvST8ibsu/Gc=', 0)}
|
|
|
C: SON([(u'saslContinue', 1), (u'conversationId', 1), (u'payload', Binary('', 0))])
|
S: {u'conversationId': 1, u'ok': 1.0, u'done': True, u'payload': Binary('', 0)}
|
|
True
|
>>> c.admin.system.users.count()
|
1
|
|