微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用PHP安全绑定到Active Directory的问题

我似乎无法使用PHP安全地绑定到Active Directory.未加密的连接工作正常.使用其他客户端能够牢固地绑定,例如通过SSL连接使用LDAPAdmin.这里有什么问题?有没有我缺少的LDAP SSL模块?如何使用 PHP安全地绑定到服务器?

我注意到PHPinfo(),cURL支持ldap / ldaps – 一个很好的例子,利用它来执行安全绑定在PHP中?这是一个可行的解决方法吗?

PHPinfo();

ldap
LDAP Support    enabled
RCS Version     $Id: ldap.c 293036 2010-01-03 09:23:27Z sebastian $
Total Links     0/unlimited
API Version     3001
vendor Name     OpenLDAP
vendor Version  20421
SASL Support    Enabled

尝试使用Ubuntu 10.04 repo中的PHP 5.3.2-1ubuntu4.7绑定到Active Directory服务器

$username = 'user';
$password = 'passwd';
$account_suffix = '@example.com';
$hostnameSSL = 'ldaps://ldap.example.com:636';
$hostnameTLS = 'ldap.example.com';
$portTLS = 389;

ldap_set_option(NULL,LDAP_OPT_DEBUG_LEVEL,7);

// Attempting fix from http://www.PHP.net/manual/en/ref.ldap.PHP#77553
putenv('LDAPTLS_REQCERT=never');

####################
# SSL bind attempt #
####################
// Attempting Syntax from http://www.PHP.net/manual/en/function.ldap-bind.PHP#101445
$con =  ldap_connect($hostnameSSL);
if (!is_resource($con)) trigger_error("Unable to connect to $hostnameSSL",E_USER_WARNING);

// Options from http://www.PHP.net/manual/en/ref.ldap.PHP#73191
if (!ldap_set_option($con,LDAP_OPT_PROTOCOL_VERSION,3))
{
    trigger_error("Failed to set LDAP Protocol version to 3,TLS not supported",E_USER_WARNING);
}
ldap_set_option($con,LDAP_OPT_REFERRALS,0);

if (ldap_bind($con,$username . $account_suffix,$password)) die('All went well using SSL');
ldap_close($con);

####################
# TLS bind attempt #
####################
$con =  ldap_connect($hostnameTLS,$portTLS);
ldap_set_option($con,3);
ldap_set_option($con,0);
$encrypted = (ldap_start_tls($con));
if ($encrypted) ldap_bind($con,$password); // Unecrypted works,but don't want logins sent in cleartext
ldap_close($con);

#####################
# SASL bind attempt #
#####################
$con =  ldap_connect($hostnameTLS,0);
ldap_sasl_bind($con,NULL,$password,'DIGEST-MD5',$username. $account_suffix);
ldap_close($con);

以上所有失败.日志错误

ldap_create
ldap_url_parse_ext(ldaps://ldap.example.com:636)
ldap_bind_s
ldap_simple_bind_s
ldap_sasl_bind_s
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP ldap.example.com:636
ldap_new_socket: 27
ldap_prepare_socket: 27
ldap_connect_to_host: Trying 1.1.1.1:636
ldap_pvt_connect: fd: 27 tm: -1 async: 0
ldap_open_defconn: successful
ldap_send_server_request
ldap_result ld 0x215380c0 msgid 1
wait4msg ld 0x215380c0 msgid 1 (infinite timeout)
wait4msg continue ld 0x215380c0 msgid 1 all 1
** ld 0x215380c0 Connections:
* host: ldap.example.com  port: 636  (default)
  refcnt: 2  status: Connected
  last used: Thu Mar 10 11:15:53 2011


** ld 0x215380c0 Outstanding Requests:
 * msgid 1,origid 1,status InProgress
   outstanding referrals 0,parent count 0
  ld 0x215380c0 request count 1 (abandoned 0)
** ld 0x215380c0 Response Queue:
   Empty
  ld 0x215380c0 response count 0
ldap_chkResponseList ld 0x215380c0 msgid 1 all 1
ldap_chkResponseList returns ld 0x215380c0 NULL
ldap_int_select
read1msg: ld 0x215380c0 msgid 1 all 1
ldap_err2string
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Warning:  ldap_bind() [<a href='function.ldap-bind'>function.ldap-bind</a>]: Unable to bind to server: Can't contact LDAP server in /..test.PHP on line 28
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Stack trace:
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   1. {main}() /..test.PHP:0
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   2. ldap_bind() /..test.PHP:28
ldap_free_request (origid 1,msgid 1)
ldap_free_connection 1 1
ldap_free_connection: actually freed
ldap_create
ldap_err2string
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Warning:  ldap_start_tls() [<a href='function.ldap-start-tls'>function.ldap-start-tls</a>]: Unable to start TLS: Not Supported in /..test.PHP on line 37
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Stack trace:
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   1. {main}() /..test.PHP:0
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   2. ldap_start_tls() /..test.PHP:37
ldap_create
ldap_sasl_interactive_bind_s: user selected: DIGEST-MD5
ldap_err2string
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Warning:  ldap_sasl_bind() [<a href='function.ldap-sasl-bind'>function.ldap-sasl-bind</a>]: Unable to bind to server: Not Supported in /..test.PHP on line 47
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP Stack trace:
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   1. {main}() /..test.PHP:0
[Thu Mar 10 11:15:53 2011] [error] [client ::1] PHP   2. ldap_sasl_bind() /..test.PHP:47

查看ssl响应:

>> openssl s_client -connect my.example.com:636 -prexit

(...)
SSL handshake has read 5732 bytes and written 443 bytes
---
New,TLSv1/SSLv3,Cipher is RC4-MD5
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5
    Session-ID: 111111111111111111111111
    Session-ID-ctx: 
    Master-Key: AAAAAAAAAAAAAAAAAAAAA
    Key-Arg   : None
    Start Time: 1299071105
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)

“strace PHP test.PHP”的结果:

write(2,"  refcnt: 2  status: Connected\n",31  refcnt: 2  status: Connected
    ) = 31
    write(2,"  last used: Tue Mar 15 10:59:19"...,39  last used: Tue Mar 15 10:59:19 2011

    ) = 39
    write(2,"\n",1
    )                       = 1
    write(2,"** ld 0x954e0b8 Outstanding Requ"...,38** ld 0x954e0b8 Outstanding Requests:
    ) = 38
    write(2," * msgid 1,status In"...,41 * msgid 1,status InProgress
    ) = 41
    write(2,"   outstanding referrals 0,pare"...,43   outstanding referrals 0,parent count 0
    ) = 43
    write(2,"  ld 0x954e0b8 request count 1 ("...,45  ld 0x954e0b8 request count 1 (abandoned 0)
    ) = 45
    write(2,"** ld 0x954e0b8 Response Queue:\n",32** ld 0x954e0b8 Response Queue:
    ) = 32
    write(2,"   Empty\n",9   Empty
    )               = 9
    write(2,"  ld 0x954e0b8 response count 0\n",32  ld 0x954e0b8 response count 0
    ) = 32
    write(2,"ldap_chkResponseList ld 0x954e0b"...,48ldap_chkResponseList ld 0x954e0b8 msgid 1 all 1
    ) = 48
    write(2,"ldap_chkResponseList returns ld "...,47ldap_chkResponseList returns ld 0x954e0b8 NULL
    ) = 47
    write(2,"ldap_int_select\n",16ldap_int_select
    )       = 16
    poll([{fd=3,events=POLLIN|POLLPRI|POLLERR|POLLHUP}],1,-1) = 1 ([{fd=3,revents=POLLIN}])
    write(2,"read1msg: ld 0x954e0b8 msgid 1 a"...,37read1msg: ld 0x954e0b8 msgid 1 all 1
    ) = 37
    read(3,"",8)                          = 0
    write(2,"ldap_err2string\n",16ldap_err2string
    )       = 16
    write(2,"PHP Warning:  ldap_bind(): Unabl"...,158PHP Warning:  ldap_bind(): Unable to bind to server: Can't contact LDAP server in

我确实有/etc/ldap.conf修复’TLS_REQCERT从不’ – 即使这个修复是针对不同的错误,这给出了一个相当明确的错误消息.

这是我如何做到的:
<?PHP
    $username = ''; // username to check
    $password = ''; // password to check

/**
 * Is it an Active Directory?
 *
 * <pre>
 * true = yes
 *        set the following values:
 *        SDB_AUTH_LDAP_HOST
 *        SDB_AUTH_LDAP_SSL
 *        SDB_AUTH_LDAP_BASE
 *        SDB_AUTH_LDAP_SEARCH
 *        SDB_AUTH_LDAP_USERDOMAIN
 * false = no,you have to supply an hostname
 *         and configure the following values:
 *         SDB_AUTH_LDAP_HOST
 *         SDB_AUTH_LDAP_PORT
 *         SDB_AUTH_LDAP_SSL
 *         SDB_AUTH_LDAP_BASE
 *         SDB_AUTH_LDAP_SEARCH
 *         SDB_AUTH_LDAP_USERDOMAIN
 * </pre>
 * @see SDB_AUTH_LDAP_HOST
 */
define('SDB_AUTH_IS_AD',true);
/**
 * Domain name of the LDAP Host or of the AD-Domain
 */
define('SDB_AUTH_LDAP_HOST','your-domain.tld');
/**
 * LDAP Port?
 *
 * if {@link SDB_AUTH_IS_AD} = true,then the port will be read form DNS.
 */
define('SDB_AUTH_LDAP_PORT','389');
/**
 * Use LDAPS (true) oder LDAP (false) connection?
 */
define('SDB_AUTH_LDAP_SSL',false);
/**
 * LDAP Base
 */
define('SDB_AUTH_LDAP_BASE','CN=Users,DC=your-domain.tld,DC=de');
/**
 * LDAP Search,to find a user
 *
 * %s will be replaced by the username.<br>
 * z.B. CN=%s
 */
define('SDB_AUTH_LDAP_SEARCH','(&(sAMAccountName=%s)(objectclass=user)(objectcategory=person))');
/**
 * Die LDAP Domain des Benutzers
 *
 * if the username doesnt contain a domain append this domain to it.<br>
 * in case this is empty,nothing will be appended.
 */
define('SDB_AUTH_LDAP_USERDOMAIN','your-domain.tld');
/**
 * Path to LDAP Search
 *
 * Will give back better error messages
 * ( leave empty in case you don't want to have it. )
 */
define('SDB_AUTH_LDAP_SEARCHBIN','/usr/bin/ldapsearch');




        $ldap_error_codes=array(
        '525' => 'Username doesnt exist.','52e' => 'Wrong password.','530' => 'You cannot login at this time.','531' => 'You cannot login from this host.','532' => 'Your password was expired.','533' => 'Your account has been deactivated.','701' => 'Your account was expired.','773' => 'Please set another password (at your workstation) before you login.','775' => 'Your account has been locked.',);


  if(SDB_AUTH_LDAP_SSL) $dcs=dns_get_record("_ldaps._tcp.".SDB_AUTH_LDAP_HOST,DNS_SRV); else $dcs=dns_get_record("_ldap._tcp.".SDB_AUTH_LDAP_HOST,DNS_SRV);
  shuffle($dcs);

  $_LDAP_ATTRS=array('cn','sn','description','givenname','distinguishedname','displayName','memberOf','name','sAMAccountName','sAMAccountType','objectClass','objectCategory');
  if(SDB_AUTH_LDAP_USERDOMAIN!='' && strstr($username,'@')===false) {
        $username=$username.'@'.SDB_AUTH_LDAP_USERDOMAIN;
  }
  $status=array();
  $status['CN']='';
  $status['displayName']='';
  $status['description']='';
  $status['distinguishedname']='';
  $status['groups']=array();
  $status['RC']=array();
  $status['connected']=false;
  $status['user_exists']=false;
  $status['is_in_team']=false;

foreach($dcs as $_LDAP_HOST) {
$_LDAP_PORT=$_LDAP_HOST['port'];
$_LDAP_HOST=$_LDAP_HOST['target'];
// check connection first ( http://bugs.PHP.net/bug.PHP?id=15637 )
$sock=@fsockopen($_LDAP_HOST,$_LDAP_PORT,$errno,$errstr,1);
@fclose($sock);
if($errno!=0) continue;

// then do a "connect"... ( the real connect happens with bind )
$ds=@ldap_connect(( SDB_AUTH_LDAP_SSL ? "ldaps://" : "ldap://" ).$_LDAP_HOST.":".$_LDAP_PORT."/");
ldap_set_option($ds,3);
// are we connected? actually,this will always return true
if(is_resource($ds)) {
    $status['connected']=true;
    // login sucessful? actually also connection test
    if(@ldap_bind($ds,$username,$password)) {
        // search
        $sr=ldap_search($ds,SDB_AUTH_LDAP_BASE,sprintf(SDB_AUTH_LDAP_SEARCH,$usernode),$_LDAP_ATTRS);
        // suche successful?
        if(is_resource($sr)) {

            // fetch entries
            $info = ldap_get_entries($ds,$sr);
            if(isset($info['count']) && $info['count']>0) {
                $status['user_exists']=true;
            }
            // close search result
            ldap_free_result($sr);
            $status['CN']=$info[0]['cn'][0];
            $status['description']=$info[0]['description'][0];
            $status['displayName']=$info[0]['displayname'][0];
            $status['distinguishedname']=$info[0]['distinguishedname'][0];
            // is the user in the dexteam?
            for($i=0; $i<$info[0]['memberof']['count']; $i++) {
                $status['groups'][]=$info[0]['memberof'][$i];
                // IS IN TEAM CHECK 
                if(substr($info[0]['memberof'][$i],strlen('CN=DexTeam,'))=='CN=DexTeam,') $status['is_in_team']=true; 
            }

            $status['RC']['code']=ldap_errno($ds);
            $status['RC']['string']=ldap_error($ds);
            ldap_close($ds);
            break;
        }
        else {
            $status['RC']['code']=ldap_errno($ds);
            $status['RC']['string']=ldap_error($ds);
            ldap_close($ds);
            break;
        }
    }
    else {
        $status['RC']['code']=ldap_errno($ds);
        $status['RC']['string']=ldap_error($ds);
        // do we want better error messages?
        if(SDB_AUTH_LDAP_SEARCHBIN!='' && is_executable(SDB_AUTH_LDAP_SEARCHBIN)) {
            $status['RC']['ldapsearchrc']='';
            $status['RC']['ldapsearchtxt']=array();
            exec(SDB_AUTH_LDAP_SEARCHBIN.' -x -H '.escapeshellarg(( SDB_AUTH_LDAP_SSL ? "ldaps://" : "ldap://" ).$_LDAP_HOST.":".$_LDAP_PORT."/").' -D '.escapeshellarg($username).' -w '.escapeshellarg($password).' 2>&1',$status['RC']['ldapsearchtxt'],$status['RC']['ldapsearchrc']);
            if($status['RC']['ldapsearchrc']!=0) {
                if(preg_match("/data ([^,]+),/",$status['RC']['ldapsearchtxt'][1],$matches)) {
                    if(isset($ldap_error_codes[$matches[1]])) {
                        $status['RC']['code']=$matches[1];
                        $status['RC']['string']=$ldap_error_codes[$matches[1]];
                    }
                }
                unset($status['RC']['ldapsearchrc']);
                unset($status['RC']['ldapsearchtxt']);
            }
        }
        ldap_close($ds);
        break;
    }
}
else {
    continue;
}
}

你启用了证书吗?我知道有一个问题,当证书被拒绝.编辑“/etc/ldap/ldap.conf”并添加“TLS_REQCERT never”

#
# LDAP Defaults
#
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
#BASE   dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-master.example.com:666
#SIZELIMIT      12
#TIMELIMIT      15
#DEREF          never
TLS_REQCERT never

然而,对我来说,它适用于ldap和ldaps:

>这可能是广告配置的配置问题.可能降低某些安全限制>或者它也可能是一个PHP / ldap lib问题.尝试更新到更新版本:)

原文地址:https://www.jb51.cc/php/132283.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐