Diff for /embedaddon/php/ext/ldap/ldap.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2013/07/22 01:31:52 version 1.1.1.4, 2014/06/15 20:03:49
Line 2 Line 2
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | PHP Version 5                                                        |     | PHP Version 5                                                        |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
   | Copyright (c) 1997-2013 The PHP Group                                |   | Copyright (c) 1997-2014 The PHP Group                                |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | This source file is subject to version 3.01 of the PHP license,      |     | 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        |     | that is bundled with this package in the file LICENSE, and is        |
Line 152  PHP_MINIT_FUNCTION(ldap) Line 152  PHP_MINIT_FUNCTION(ldap)
         REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, 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);          REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
   
           /* Constants to be used with ldap_modify_batch() */
           REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_ADD", LDAP_MODIFY_BATCH_ADD, CONST_PERSISTENT | CONST_CS);
           REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE", LDAP_MODIFY_BATCH_REMOVE, CONST_PERSISTENT | CONST_CS);
           REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE_ALL", LDAP_MODIFY_BATCH_REMOVE_ALL, CONST_PERSISTENT | CONST_CS);
           REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REPLACE", LDAP_MODIFY_BATCH_REPLACE, CONST_PERSISTENT | CONST_CS);
           REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_ATTRIB", LDAP_MODIFY_BATCH_ATTRIB, CONST_PERSISTENT | CONST_CS);
           REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_MODTYPE", LDAP_MODIFY_BATCH_MODTYPE, CONST_PERSISTENT | CONST_CS);
           REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_VALUES", LDAP_MODIFY_BATCH_VALUES, CONST_PERSISTENT | CONST_CS);
   
 #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10  #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
         /* LDAP options */          /* LDAP options */
         REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);          REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
Line 390  PHP_FUNCTION(ldap_bind) Line 399  PHP_FUNCTION(ldap_bind)
                 RETURN_FALSE;                  RETURN_FALSE;
         }          }
   
           if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN contains a null byte");
                   RETURN_FALSE;
           }
   
           if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte");
                   RETURN_FALSE;
           }
   
         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);          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) {          if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
Line 1432  PHP_FUNCTION(ldap_delete) Line 1451  PHP_FUNCTION(ldap_delete)
 }  }
 /* }}} */  /* }}} */
   
   /* {{{ _ldap_str_equal_to_const
    */
   static int _ldap_str_equal_to_const(const char *str, uint str_len, const char *cstr)
   {
           int i;
   
           if (strlen(cstr) != str_len)
                   return 0;
   
           for (i = 0; i < str_len; ++i) {
                   if (str[i] != cstr[i]) {
                           return 0;
                   }
           }
   
           return 1;
   }
   /* }}} */
   
   /* {{{ _ldap_strlen_max
    */
   static int _ldap_strlen_max(const char *str, uint max_len)
   {
           int i;
   
           for (i = 0; i < max_len; ++i) {
                   if (str[i] == '\0') {
                           return i;
                   }
           }
   
           return max_len;
   }
   /* }}} */
   
   /* {{{ _ldap_hash_fetch
    */
   static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
   {
           zval **fetched;
           if (zend_hash_find(Z_ARRVAL_P(hashTbl), key, strlen(key)+1, (void **) &fetched) == SUCCESS) {
                   *out = *fetched;
           }
           else {
                   *out = NULL;
           }
   }
   /* }}} */
   
   /* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs)
      Perform multiple modifications as part of one operation */
   PHP_FUNCTION(ldap_modify_batch)
   {
           ldap_linkdata *ld;
           zval *link, *mods, *mod, *modinfo, *modval;
           zval *attrib, *modtype, *vals;
           zval **fetched;
           char *dn;
           int dn_len;
           int i, j, k;
           int num_mods, num_modprops, num_modvals;
           LDAPMod **ldap_mods;
           uint oper;
   
           /*
           $mods = array(
                   array(
                           "attrib" => "unicodePwd",
                           "modtype" => LDAP_MODIFY_BATCH_REMOVE,
                           "values" => array($oldpw)
                   ),
                   array(
                           "attrib" => "unicodePwd",
                           "modtype" => LDAP_MODIFY_BATCH_ADD,
                           "values" => array($newpw)
                   ),
                   array(
                           "attrib" => "userPrincipalName",
                           "modtype" => LDAP_MODIFY_BATCH_REPLACE,
                           "values" => array("janitor@corp.contoso.com")
                   ),
                   array(
                           "attrib" => "userCert",
                           "modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
                   )
           );
           */
   
           if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &mods) != SUCCESS) {
                   return;
           }
   
           ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
   
           /* perform validation */
           {
                   char *modkey;
                   uint modkeylen;
                   long modtype;
   
                   /* to store the wrongly-typed keys */
                   ulong tmpUlong;
   
                   /* make sure the DN contains no NUL bytes */
                   if (_ldap_strlen_max(dn, dn_len) != dn_len) {
                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN must not contain NUL bytes");
                           RETURN_FALSE;
                   }
   
                   /* make sure the top level is a normal array */
                   zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
                   if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must not be string-indexed");
                           RETURN_FALSE;
                   }
   
                   num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
   
                   for (i = 0; i < num_mods; i++) {
                           /* is the numbering consecutive? */
                           if (zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched) != SUCCESS) {
                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must have consecutive indices 0, 1, ...");
                                   RETURN_FALSE;
                           }
                           mod = *fetched;
   
                           /* is it an array? */
                           if (Z_TYPE_P(mod) != IS_ARRAY) {
                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be an array itself");
                                   RETURN_FALSE;
                           }
   
                           /* for the modification hashtable... */
                           zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
                           num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
   
                           for (j = 0; j < num_modprops; j++) {
                                   /* are the keys strings? */
                                   if (zend_hash_get_current_key_ex(Z_ARRVAL_P(mod), &modkey, &modkeylen, &tmpUlong, 0, NULL) != HASH_KEY_IS_STRING) {
                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be string-indexed");
                                           RETURN_FALSE;
                                   }
   
                                   /* modkeylen includes the terminating NUL byte; remove that */
                                   --modkeylen;
   
                                   /* is this a valid entry? */
                                   if (
                                           !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB) &&
                                           !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE) &&
                                           !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)
                                   ) {
                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "The only allowed keys in entries of the modifications array are '" LDAP_MODIFY_BATCH_ATTRIB "', '" LDAP_MODIFY_BATCH_MODTYPE "' and '" LDAP_MODIFY_BATCH_VALUES "'");
                                           RETURN_FALSE;
                                   }
   
                                   zend_hash_get_current_data(Z_ARRVAL_P(mod), (void **) &fetched);
                                   modinfo = *fetched;
   
                                   /* does the value type match the key? */
                                   if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB)) {
                                           if (Z_TYPE_P(modinfo) != IS_STRING) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must be a string");
                                                   RETURN_FALSE;
                                           }
   
                                           if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must not contain NUL bytes");
                                                   RETURN_FALSE;
                                           }
                                   }
                                   else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE)) {
                                           if (Z_TYPE_P(modinfo) != IS_LONG) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_MODTYPE "' value must be a long");
                                                   RETURN_FALSE;
                                           }
   
                                           /* is the value in range? */
                                           modtype = Z_LVAL_P(modinfo);
                                           if (
                                                   modtype != LDAP_MODIFY_BATCH_ADD &&
                                                   modtype != LDAP_MODIFY_BATCH_REMOVE &&
                                                   modtype != LDAP_MODIFY_BATCH_REPLACE &&
                                                   modtype != LDAP_MODIFY_BATCH_REMOVE_ALL
                                           ) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "The '" LDAP_MODIFY_BATCH_MODTYPE "' value must match one of the LDAP_MODIFY_BATCH_* constants");
                                                   RETURN_FALSE;
                                           }
   
                                           /* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
                                           if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
                                                   if (zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
                                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must not be provided");
                                                           RETURN_FALSE;
                                                   }
                                           }
                                           else {
                                                   if (!zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
                                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is not LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must be provided");
                                                           RETURN_FALSE;
                                                   }
                                           }
                                   }
                                   else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)) {
                                           if (Z_TYPE_P(modinfo) != IS_ARRAY) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' value must be an array");
                                                   RETURN_FALSE;
                                           }
   
                                           /* is the array not empty? */
                                           zend_hash_internal_pointer_reset(Z_ARRVAL_P(modinfo));
                                           num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
                                           if (num_modvals == 0) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have at least one element");
                                                   RETURN_FALSE;
                                           }
   
                                           /* are its keys integers? */
                                           if (zend_hash_get_current_key_type(Z_ARRVAL_P(modinfo)) != HASH_KEY_IS_LONG) {
                                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must not be string-indexed");
                                                   RETURN_FALSE;
                                           }
   
                                           /* are the keys consecutive? */
                                           for (k = 0; k < num_modvals; k++) {
                                                   if (zend_hash_index_find(Z_ARRVAL_P(modinfo), k, (void **) &fetched) != SUCCESS) {
                                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have consecutive indices 0, 1, ...");
                                                           RETURN_FALSE;
                                                   }
                                                   modval = *fetched;
   
                                                   /* is the data element a string? */
                                                   if (Z_TYPE_P(modval) != IS_STRING) {
                                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each element of a '" LDAP_MODIFY_BATCH_VALUES "' array must be a string");
                                                           RETURN_FALSE;
                                                   }
                                           }
                                   }
   
                                   zend_hash_move_forward(Z_ARRVAL_P(mod));
                           }
                   }
           }
           /* validation was successful */
   
           /* allocate array of modifications */
           ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
   
           /* for each modification */
           for (i = 0; i < num_mods; i++) {
                   /* allocate the modification struct */
                   ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0);
   
                   /* fetch the relevant data */
                   zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched);
                   mod = *fetched;
   
                   _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
                   _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
                   _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
   
                   /* map the modification type */
                   switch (Z_LVAL_P(modtype)) {
                           case LDAP_MODIFY_BATCH_ADD:
                                   oper = LDAP_MOD_ADD;
                                   break;
                           case LDAP_MODIFY_BATCH_REMOVE:
                           case LDAP_MODIFY_BATCH_REMOVE_ALL:
                                   oper = LDAP_MOD_DELETE;
                                   break;
                           case LDAP_MODIFY_BATCH_REPLACE:
                                   oper = LDAP_MOD_REPLACE;
                                   break;
                           default:
                                   php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown and uncaught modification type.");
                                   RETURN_FALSE;
                   }
   
                   /* fill in the basic info */
                   ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
                   ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
   
                   if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
                           /* no values */
                           ldap_mods[i]->mod_bvalues = NULL;
                   }
                   else {
                           /* allocate space for the values as part of this modification */
                           num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
                           ldap_mods[i]->mod_bvalues = safe_emalloc((num_modvals+1), sizeof(struct berval *), 0);
   
                           /* for each value */
                           for (j = 0; j < num_modvals; j++) {
                                   /* fetch it */
                                   zend_hash_index_find(Z_ARRVAL_P(vals), j, (void **) &fetched);
                                   modval = *fetched;
   
                                   /* allocate the data struct */
                                   ldap_mods[i]->mod_bvalues[j] = safe_emalloc(1, sizeof(struct berval), 0);
   
                                   /* fill it */
                                   ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(modval);
                                   ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(Z_STRVAL_P(modval), Z_STRLEN_P(modval));
                           }
   
                           /* NULL-terminate values */
                           ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
                   }
           }
   
           /* NULL-terminate modifications */
           ldap_mods[num_mods] = NULL;
   
           /* perform (finally) */
           if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
                   RETVAL_FALSE;
           } else RETVAL_TRUE;
   
           /* clean up */
           {
                   for (i = 0; i < num_mods; i++) {
                           /* attribute */
                           efree(ldap_mods[i]->mod_type);
   
                           if (ldap_mods[i]->mod_bvalues != NULL) {
                                   /* each BER value */
                                   for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
                                           /* free the data bytes */
                                           efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
   
                                           /* free the bvalue struct */
                                           efree(ldap_mods[i]->mod_bvalues[j]);
                                   }
   
                                   /* the BER value array */
                                   efree(ldap_mods[i]->mod_bvalues);
                           }
   
                           /* the modification */
                           efree(ldap_mods[i]);
                   }
   
                   /* the modifications array */
                   efree(ldap_mods);
           }
   }
   /* }}} */
   
 /* {{{ proto int ldap_errno(resource link)  /* {{{ proto int ldap_errno(resource link)
    Get the current ldap error number */     Get the current ldap error number */
 PHP_FUNCTION(ldap_errno)  PHP_FUNCTION(ldap_errno)
Line 2107  PHP_FUNCTION(ldap_set_rebind_proc) Line 2475  PHP_FUNCTION(ldap_set_rebind_proc)
                 /* unregister rebind procedure */                  /* unregister rebind procedure */
                 if (ld->rebindproc != NULL) {                  if (ld->rebindproc != NULL) {
                         zval_dtor(ld->rebindproc);                          zval_dtor(ld->rebindproc);
                           FREE_ZVAL(ld->rebindproc);
                         ld->rebindproc = NULL;                          ld->rebindproc = NULL;
                         ldap_set_rebind_proc(ld->link, NULL, NULL);                          ldap_set_rebind_proc(ld->link, NULL, NULL);
                 }                  }
Line 2515  ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) Line 2884  ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3)
         ZEND_ARG_INFO(0, entry)          ZEND_ARG_INFO(0, entry)
 ZEND_END_ARG_INFO()  ZEND_END_ARG_INFO()
   
   ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3)
           ZEND_ARG_INFO(0, link_identifier)
           ZEND_ARG_INFO(0, dn)
           ZEND_ARG_ARRAY_INFO(0, modifications_info, 0)
   ZEND_END_ARG_INFO()
   
 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3)  ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3)
         ZEND_ARG_INFO(0, link_identifier)          ZEND_ARG_INFO(0, link_identifier)
         ZEND_ARG_INFO(0, dn)          ZEND_ARG_INFO(0, dn)
Line 2668  const zend_function_entry ldap_functions[] = { Line 3043  const zend_function_entry ldap_functions[] = {
         PHP_FE(ldap_dn2ufn,                                                                     arginfo_ldap_dn2ufn)          PHP_FE(ldap_dn2ufn,                                                                     arginfo_ldap_dn2ufn)
         PHP_FE(ldap_add,                                                                        arginfo_ldap_add)          PHP_FE(ldap_add,                                                                        arginfo_ldap_add)
         PHP_FE(ldap_delete,                                                                     arginfo_ldap_delete)          PHP_FE(ldap_delete,                                                                     arginfo_ldap_delete)
           PHP_FE(ldap_modify_batch,                                                       arginfo_ldap_modify_batch)
         PHP_FALIAS(ldap_modify,         ldap_mod_replace,               arginfo_ldap_modify)          PHP_FALIAS(ldap_modify,         ldap_mod_replace,               arginfo_ldap_modify)
   
 /* additional functions for attribute based modifications, Gerrit Thomson */  /* additional functions for attribute based modifications, Gerrit Thomson */

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>