📄 ldap.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Amitay Isaacs <amitay@w-o-i.com> | | Eric Warnke <ericw@albany.edu> | | Rasmus Lerdorf <rasmus@php.net> | | Gerrit Thomson <334647@swin.edu.au> | | Jani Taskinen <sniper@iki.fi> | | Stig Venaas <venaas@uninett.no> | | PHP 4.0 updates: Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ /* $Id: ldap.c,v 1.130.2.13.2.2 2007/01/01 09:46:44 sebastian Exp $ */#define IS_EXT_MODULE#ifdef HAVE_CONFIG_H#include "config.h"#endif/* Additional headers for NetWare */#if defined(NETWARE) && (NEW_LIBC)#include <sys/select.h>#include <sys/timeval.h>#endif#include "php.h"#include "php_ini.h"#include <stddef.h>#include "ext/standard/dl.h"#include "php_ldap.h"#ifdef PHP_WIN32#include <string.h>#if HAVE_NSLDAP#include <winsock.h>#endif#define strdup _strdup#undef WINDOWS#undef strcasecmp#undef strncasecmp#define WINSOCK 1#define __STDC__ 1#endif#include "ext/standard/php_string.h"#include "ext/standard/info.h"typedef struct { LDAP *link;#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) zval *rebindproc;#endif} ldap_linkdata;typedef struct { LDAPMessage *data; int id;} ldap_resultentry;ZEND_DECLARE_MODULE_GLOBALS(ldap)static unsigned char third_argument_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };static unsigned char arg3to6of6_force_ref[] = { 6, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE };static int le_link, le_result, le_result_entry, le_ber_entry;/* This is just a small subset of the functionality provided by the LDAP library. All the operations are synchronous. Referrals are not handled automatically.*//* {{{ ldap_functions[] */function_entry ldap_functions[] = { PHP_FE(ldap_connect, NULL) PHP_FALIAS(ldap_close, ldap_unbind, NULL) PHP_FE(ldap_bind, NULL) PHP_FE(ldap_unbind, NULL) PHP_FE(ldap_read, NULL) PHP_FE(ldap_list, NULL) PHP_FE(ldap_search, NULL) PHP_FE(ldap_free_result, NULL) PHP_FE(ldap_count_entries, NULL) PHP_FE(ldap_first_entry, NULL) PHP_FE(ldap_next_entry, NULL) PHP_FE(ldap_get_entries, NULL) PHP_FE(ldap_first_attribute, third_argument_force_ref) PHP_FE(ldap_next_attribute, third_argument_force_ref) PHP_FE(ldap_get_attributes, NULL) PHP_FE(ldap_get_values, NULL) PHP_FE(ldap_get_values_len, NULL) PHP_FE(ldap_get_dn, NULL) PHP_FE(ldap_explode_dn, NULL) PHP_FE(ldap_dn2ufn, NULL) PHP_FE(ldap_add, NULL) PHP_FE(ldap_delete, NULL) PHP_FALIAS(ldap_modify, ldap_mod_replace, NULL)/* additional functions for attribute based modifications, Gerrit Thomson */ PHP_FE(ldap_mod_add, NULL) PHP_FE(ldap_mod_replace, NULL) PHP_FE(ldap_mod_del, NULL)/* end gjt mod */ PHP_FE(ldap_errno, NULL) PHP_FE(ldap_err2str, NULL) PHP_FE(ldap_error, NULL) PHP_FE(ldap_compare, NULL) PHP_FE(ldap_sort, NULL)#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 PHP_FE(ldap_rename, NULL) PHP_FE(ldap_get_option, third_argument_force_ref) PHP_FE(ldap_set_option, NULL) PHP_FE(ldap_first_reference, NULL) PHP_FE(ldap_next_reference, NULL)#ifdef HAVE_LDAP_PARSE_REFERENCE PHP_FE(ldap_parse_reference, third_argument_force_ref)#endif#ifdef HAVE_LDAP_PARSE_RESULT PHP_FE(ldap_parse_result, arg3to6of6_force_ref)#endif#ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL)#endif#endif#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) PHP_FE(ldap_set_rebind_proc, NULL)#endif#ifdef STR_TRANSLATION PHP_FE(ldap_t61_to_8859, NULL) PHP_FE(ldap_8859_to_t61, NULL)#endif {NULL, NULL, NULL}};/* }}} */zend_module_entry ldap_module_entry = { STANDARD_MODULE_HEADER, "ldap", ldap_functions, PHP_MINIT(ldap), PHP_MSHUTDOWN(ldap), NULL, NULL, PHP_MINFO(ldap), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_LDAPZEND_GET_MODULE(ldap)#endifstatic void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC){ ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr; ldap_unbind_s(ld->link);#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) if (ld->rebindproc != NULL) { zval_dtor(ld->rebindproc); FREE_ZVAL(ld->rebindproc); }#endif efree(ld); LDAPG(num_links)--;}static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC){ LDAPMessage *result = (LDAPMessage *)rsrc->ptr; ldap_msgfree(result);}static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC){ ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr; zend_list_delete(entry->id); efree(entry);} /* {{{ PHP_INI_BEGIN */PHP_INI_BEGIN() STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)PHP_INI_END()/* }}} *//* {{{ php_ldap_init_globals */static void php_ldap_init_globals(zend_ldap_globals *ldap_globals){ ldap_globals->num_links = 0;}/* }}} *//* {{{ PHP_MINIT_FUNCTION */PHP_MINIT_FUNCTION(ldap){ ZEND_INIT_MODULE_GLOBALS(ldap, php_ldap_init_globals, NULL); REGISTER_INI_ENTRIES(); /* Constants to be used with deref-parameter in php_ldap_do_search() */ REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 /* LDAP options */ REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);#ifdef LDAP_OPT_RESTART REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);#endif#ifdef LDAP_OPT_HOST_NAME REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);#endif REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);#ifdef LDAP_OPT_MATCHED_DN REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);#endif REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);#endif#ifdef LDAP_OPT_DEBUG_LEVEL REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);#endif#ifdef ORALDAP REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);#endif le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number); le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number); le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number); le_ber_entry = zend_register_list_destructors_ex(NULL, NULL, "ldap ber entry", module_number); Z_TYPE(ldap_module_entry) = type; return SUCCESS;}/* }}} *//* {{{ PHP_MSHUTDOWN_FUNCTION */PHP_MSHUTDOWN_FUNCTION(ldap){ UNREGISTER_INI_ENTRIES(); return SUCCESS;}/* }}} *//* {{{ PHP_MINFO_FUNCTION */PHP_MINFO_FUNCTION(ldap){ char tmp[32];#if HAVE_NSLDAP LDAPVersion ver; double SDKVersion;#endif php_info_print_table_start(); php_info_print_table_row(2, "LDAP Support", "enabled"); php_info_print_table_row(2, "RCS Version", "$Id: ldap.c,v 1.130.2.13.2.2 2007/01/01 09:46:44 sebastian Exp $"); if (LDAPG(max_links) == -1) { snprintf(tmp, 31, "%ld/unlimited", LDAPG(num_links)); } else { snprintf(tmp, 31, "%ld/%ld", LDAPG(num_links), LDAPG(max_links)); } php_info_print_table_row(2, "Total Links", tmp);#ifdef LDAP_API_VERSION snprintf(tmp, 31, "%d", LDAP_API_VERSION); php_info_print_table_row(2, "API Version", tmp);#endif#ifdef LDAP_VENDOR_NAME php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);#endif#ifdef LDAP_VENDOR_VERSION snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION); php_info_print_table_row(2, "Vendor Version", tmp);#endif#if HAVE_NSLDAP SDKVersion = ldap_version(&ver); snprintf(tmp, 31, "%f", SDKVersion/100.0); php_info_print_table_row(2, "SDK Version", tmp); snprintf(tmp, 31, "%f", ver.protocol_version/100.0); php_info_print_table_row(2, "Highest LDAP Protocol Supported", tmp); snprintf(tmp, 31, "%f", ver.SSL_version/100.0); php_info_print_table_row(2, "SSL Level Supported", tmp); if (ver.security_level != LDAP_SECURITY_NONE) { snprintf(tmp, 31, "%d", ver.security_level); } else { strcpy(tmp, "SSL not enabled"); } php_info_print_table_row(2, "Level of Encryption", tmp);#endif php_info_print_table_end();}/* }}} *//* {{{ proto resource ldap_connect([string host [, int port]]) Connect to an LDAP server */PHP_FUNCTION(ldap_connect){ char *host = NULL; int hostlen; long port = 389; /* Default port */#ifdef HAVE_ORALDAP char *wallet, *walletpasswd; int walletlen, walletpasswdlen; long authmode; int ssl=0;#endif ldap_linkdata *ld; LDAP *ldap;#ifdef HAVE_ORALDAP if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|slssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) == FAILURE) { RETURN_FALSE; } if (ZEND_NUM_ARGS() == 5) { ssl = 1; }#else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &host, &hostlen, &port) == FAILURE) { RETURN_FALSE; }#endif if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", LDAPG(num_links)); RETURN_FALSE; } ld = ecalloc(1, sizeof(ldap_linkdata));#ifdef LDAP_API_FEATURE_X_OPENLDAP if (host != NULL && strchr(host, '/')) { int rc; rc = ldap_initialize(&ldap, host); if (rc != LDAP_SUCCESS) { efree(ld); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc)); RETURN_FALSE; } } else { ldap = ldap_init(host, port); }#else ldap = ldap_open(host, port);#endif if (ldap == NULL) { efree(ld); RETURN_FALSE; } else {#ifdef HAVE_ORALDAP if (ssl) { if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) { efree(ld); php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL init failed"); RETURN_FALSE; } } #endif LDAPG(num_links)++; ld->link = ldap; ZEND_REGISTER_RESOURCE(return_value, ld, le_link); }}/* }}} *//* {{{ _get_lderrno */static int _get_lderrno(LDAP *ldap){#if !HAVE_NSLDAP#if LDAP_API_VERSION > 2000 || HAVE_ORALDAP_10 int lderr; /* New versions of OpenLDAP do it this way */ ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr); return lderr;#else return ldap->ld_errno;#endif#else return ldap_get_lderrno(ldap, NULL, NULL);#endif}/* }}} *//* {{{ proto bool ldap_bind(resource link [, string dn, string password]) Bind to LDAP directory */PHP_FUNCTION(ldap_bind){ zval *link; char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL; int ldap_bind_dnlen, ldap_bind_pwlen; ldap_linkdata *ld; int rc; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ss", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); RETURN_FALSE; } else { RETURN_TRUE; }}/* }}} *//* {{{ proto bool ldap_unbind(resource link) Unbind from LDAP directory */PHP_FUNCTION(ldap_unbind){ zval *link; ldap_linkdata *ld; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); zend_list_delete(Z_LVAL_P(link)); RETURN_TRUE;}/* }}} *//* {{{ php_set_opts */static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref){ /* sizelimit */ if (sizelimit > -1) {#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);#else ldap->ld_sizelimit = sizelimit; #endif } /* timelimit */ if (timelimit > -1) {#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);#else ldap->ld_timelimit = timelimit; #endif } /* deref */ if (deref > -1) {#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);#else ldap->ld_deref = deref; #endif }}/* }}} *//* {{{ php_ldap_do_search */static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope){ zval **link, **base_dn, **filter, **attrs, **attr, **attrsonly, **sizelimit, **timelimit, **deref; char *ldap_base_dn = NULL; char *ldap_filter = NULL; char **ldap_attrs = NULL; ldap_linkdata *ld; LDAPMessage *ldap_res; int ldap_attrsonly = 0; int ldap_sizelimit = -1; int ldap_timelimit = -1; int ldap_deref = -1; int num_attribs = 0; int i, errno; int myargcount = ZEND_NUM_ARGS(); if (myargcount < 3 || myargcount > 8 || zend_get_parameters_ex(myargcount, &link, &base_dn, &filter, &attrs, &attrsonly, &sizelimit, &timelimit, &deref) == FAILURE) { WRONG_PARAM_COUNT; } /* Reverse -> fall through */ switch (myargcount) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -