2012-05-23 110 views
12

this question类似,我试图使用python ldap(CentOS 6.2 x86_64,Python 2.6.6,python- ldap 2.3.10)。使用python-ldap验证Active Directory始终返回(97,[])

尽管之后在init所有常见的步骤,包括

conn.set_option(ldap.OPT_REFERRALS, 0) 

如果我通过正确的凭据我总是得到(97, [])返回:

>>> import ldap 
>>> conn = ldap.initialize('ldap://ad.server.domain.com') 
>>> conn.protocol_version = 3 
>>> conn.set_option(ldap.OPT_REFERRALS, 0) 
>>> conn.simple_bind_s('[email protected]', 'WrongPassword') 
ldap.INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece', 'desc': 'Invalid credentials'} 
>>> conn.simple_bind_s('[email protected]', 'CorrectPassword') 
(97, []) 

错误代码97是不是成功;它是从AD返回的LDAP_REFERRAL_LIMIT_EXCEEDED错误。我也可以把它作为一个事实上成功的指标,因为:

>>> conn.simple_bind_s('', 'CorrectPassword') 
(97, []) 
>>> conn.simple_bind_s('', '') 
(97, []) 

更令人沮丧的是,这个脚本是使用网:: LDAP的老Perl脚本,这确实返回0迁移用于成功验证绑定到同一个AD和服务器。

我可以在python-ldap上找到的所有信息表明我正在做的事情应该只是工作;我倾向于认为AD服务器有问题,但Perl脚本确实会在成功绑定时返回正确的LDAP代码。

我已经测试了python-ldap 2.2.0和python 2.4.4,在一个旧的CentOS 5.5盒子上,我躺在那里,它以“完全相同的方式失败”。

有人知道我失踪了吗?

编辑:每个请求,这是Perl脚本的作品。 Net::LDAP返回来自LDAP服务器的返回码,AD服务器返回0x00,“成功请求”,AFAICT。

#!/usr/bin/perl -w 
use strict; 
use Net::LDAP; 

## Corporate subdomains 
my @domains = ("americas", "asia", "europe"); 

# AD connect timeout 
my $timeout = 10; 
# Set AD server info. 
my $port = "389"; 
my $host = "server.domain.com"; 

my $user = shift @ARGV; 
chomp $user; 

my $password = <STDIN>; 
$password =~ s/\r\n//; 
chomp $password; 

my $ldap = Net::LDAP->new($host, port => $port, timeout => $timeout) || 
     die "Unable to connect to LDAP server"; 

my $bind_return = 1; 
foreach (@domains) { 
     my $result = $ldap->bind("$user\@$_.domain.com", password => $password); 
     if($result->code == 0) { 
       $bind_return = 0; 
       last; 
     } 
} 

## Unbind and return 
$ldap->unbind; 

if ($bind_return) { print "Authentication Failed. Access Denied\n" } 
exit $bind_return; 
+0

您可以发布相关Perl代码? – stark

+0

我认为对于server.domain.com,你的意思是ad.server.domain.com与python相匹配?另外,默认端口是389,但是可以明确地向该URL添加“:389”。 – stark

回答

14

迈克尔Ströder,蟒蛇,LDAP库的作者,使我明白这样的:

的97不是LDAP结果代码。这是结果类型 ldap.RES_BIND。通常,您不必查看LDAPObject.simple_bind_s()返回的结果 (除非您想提取绑定 响应控件)。

如果LDAP结果代码不是0,则伴随的异常会在您的示例中引发 ,如ldap.INVALID_CREDENTIALS。

所以,你的代码应该是这样的:

try: 
    conn.simple_bind_s('[email protected]', 'WrongPassword') 
except ldap.INVALID_CREDENTIALS: 
    user_error_msg('wrong password provided') 

之所以这些结果:

>>> conn.simple_bind_s('', 'CorrectPassword') 
(97, []) 
>>> conn.simple_bind_s('', '') 
(97, []) 

是从2003 Active Directory的allows anonymous binds盒子。因此,如果唯一被测试的是simple_bind_s()是否引发错误,那么根本不提供用户标识仍然会通过简单的绑定检查。

2003的Active Directory 确实要求对不属于RootDSE的属性的任何搜索验证,所以我们内部的目的,我们添加一个简单的搜索到的try:块:

try: 
    conn.simple_bind_s('[email protected]', 'SubmittedPassword') 
    conn.search_st('DC=domain,DC=com', ldap.SCOPE_SUBTREE, '(objectClass=container)', 'name', 0, 30) 
except ldap.INVALID_CREDENTIALS: 
    user_error_msg('wrong password provided') 
0

此错误表示您的conn.set_option(ldap.OPT_REFERRALS, 0)未受影响。

因此,试试这个:

import ldap 

ldap.set_option(ldap.OPT_REFERRALS,0) 
ldap.protocol_version = 3 
conn = ldap.initialize('ldap://....') 
conn.simple_bind_s('[email protected]', 'RightPassword') 
+0

没有快乐,我很害怕。仍然返回'(97,[])'。我用conn.get_option()验证了这些选项正在为conn SimpleLDAPObject实例正确设置。 –

+0

我可能是错的,但我认为在Perl脚本中,它使用'user @ europe.domain.com'? –