How can I do two-stage authentication to an Active Directory server in Python?
I'm running Python 2.6 on a FreeBSD machine, and I would like to do (and I don't know the correct term for this) two-stage authentication against an active directory.
Basically, the process to log in user 'myuserid' is:
- Bind to the AD LDAP server using a system account created for this purpose (call it
DOMAIN\gatekeeper
) - Verify
myuserid
's password against the credentials stored in the AD for that user.
I have the following code, which looks a lot like the code in this question.
l = ldap.initialize(Server)
l.protoco_version = 3
l.set_option(ldap.OPT_REFERRALS, 0)
l.simple_bind_s('cn=gatekeeper,dc=DOMAIN,dc=COMPANY,dc=TLD', 'gatekeeper_password')
This last results in this error:
=> LDAPError - INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece', 'desc': 'Invalid credentials'}
---------------------------------------------------------------------------
INVALID_CREDENTIALS Traceback (most recent call last)
/Users/crose/projects/ldap-auth/9163_saas/webservices/aws/model/aw_registry/<ipython console> in <module>()
/Users/crose/virtualenv/ldap-auth/lib/python2.6/site-packages/ldap/ldapobject.pyc in simple_bind_s(self, who, cred, serverctrls, clientctrls)
205 """
206 msgid = self.simple_bind(who,cred,serverctrls,clientctrls)
--> 207 return self.result(msgid,all=1,timeout=self.timeout)
208
209 def bind(self,who,cred,method=ldap.AUTH_SIMPLE):
/Users/crose/virtualenv/ldap-auth/lib/python2.6/site-packages/ldap/ldapobject.pyc in result(self, msgid, all, timeout)
420 polling (timeout = 0), in which case (None, None) is returned.
421 """
--> 422 res_type,res_data,res_msgid = self.result2(msgid,all,timeout)
423 return res_type,res_data
424
/Users/crose/virtualenv/ldap-auth/lib/python2.6/site-packages/ldap/ldapobject.pyc in result2(self, msgid, all, timeout)
424
425 def result2(self,msgid=ldap.RES_ANY,all=1,timeout=None):
--> 426 res_type, res_data, res_msgid, srv_ctrls = self.result3(msgid,all,timeout)
427 return res_type, res_data, res_msgid
428
/Users/crose/virtualenv/ldap-开发者_高级运维auth/lib/python2.6/site-packages/ldap/ldapobject.pyc in result3(self, msgid, all, timeout)
430 if timeout is None:
431 timeout = self.timeout
--> 432 ldap_result = self._ldap_call(self._l.result3,msgid,all,timeout)
433 if ldap_result is None:
434 rtype, rdata, rmsgid, decoded_serverctrls = (None,None,None,None)
/Users/crose/virtualenv/ldap-auth/lib/python2.6/site-packages/ldap/ldapobject.pyc in _ldap_call(self, func, *args, **kwargs)
94 try:
95 try:
---> 96 result = func(*args,**kwargs)
97 if __debug__ and self._trace_level>=2:
98 if func.__name__!="unbind_ext":
INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece', 'desc': 'Invalid credentials'}
Every tutorial I see seems to presuppose that I'm running on Windows, which is not the case. How do I do this from Unix?
Your in multiple troubles there:
- SIMPLE Auth without SSL is usually disable on AD (and even the SSL version is often off)
- SIMPLE Auth does not really specify the password encoding (usually utf-8 works though)
- SIMPLE Auth might bring troubles with referrals
- Your AD user probably has a different CN when its Gatekeeper\DOMAIN, typically its something like cn=Gatekeeper,dc=Users,dc=DOMAIN,dc=COMPANY,dc=TLD or so (the Gatekeeper name is from the sAMAccountName property, the cn might be totally unrelated...)
So typically you need to do at least these things to get it to work:
- Make sure your AD accepts SIMPLE auth at all
- Bind with your gatekeeper account and find the DN to the username in AD (typically by searching for something like sAMAccountName or userPrincipalName)
- Try to BIND to the DN you found with the password the user provided
- If the bind succeeds you can treat the user as authenticated...
But if your that far its not much more work to use PAM or Kerberos instead.
LDAP returning error 49 with the subcode of 525 is not a bad password, but rather a bad bind DN. 52e is bad credentials. Check that you have the correct DN of the gatekeeper user.
精彩评论