<?php
/*
 * Author: Pierangelo Masarati <ando@OpenLDAP.org>
 *
 * Tests PHP support for LDAP extended operations (WhoAmI, passwd)
 *
 * Suggested usage:
 * 
 * 1) run test003 of OpenLDAP 2.3 test suite
 *
 * 2) edit testrun/slapd.1.conf: add

access to attrs=userPassword
	by self =xw
	by * =x

access to *
	by * read

 *    before any "database" statement
 *
 * 3) run ../servers/slapd/slapd -f testrun/slapd.1.conf -h ldap://:9011 -d 0
 *
 * 4) run this script and view the output in a HTML browser.
 */

echo "<h3>LDAP extended operations test</h3>";
echo "Connecting... ";
// support for URI form
$ds = ldap_connect("ldap://:9011");  // must be a valid LDAP server!
//$ds = ldap_connect("localhost", "9011");  // must be a valid LDAP server!
echo "connect result is [" . $ds . "]<br />";

if (!$ds) {
	echo "<h4>Unable to connect to LDAP server</h4>";

} else {
	if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
		echo "Failed to set protocol version to 3<br />";

	} else {
		echo "Using LDAPv3<br />";

		// This data should be present in the DSA
		$binddn = "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com";
		$bindpw = "bjorn";
		// The new password that will be changed via passwd exop
		$newpw = "nrojb";

		echo "Binding... ";
		$r = ldap_bind($ds, $binddn, $bindpw);
		echo "bind result is [" . $r . "]<br />";
		if ($r) {
			echo "WhoAmI via low-level API... ";
			// ldap_exop() takes the OID and the value of the operation,
			// and returns the OID and the value of the response.
			// For WhoAmI, no response OID is expected, and the
			// value is the string containing "dn:" and the DN
			// of the identity assumed by the client during the operation
			$r = ldap_exop($ds, "1.3.6.1.4.1.4203.1.11.3", NULL, $retoid, $retdata);
			if (!$r) {
				echo "failed<br />";

			} else {
				echo $retdata . " (retoid=" . $retoid . ")<br />";

				echo "WhoAmI via high-level API... ";
				// ldap_exop_whoami() sends the operation and
				// returns the string
				$r = ldap_exop_whoami($ds, $authzid);
				if (!$r) {
					echo "failed<br />";

				} else {
					echo $authzid . "<br />";
	
					echo "Changing password via low-level API... ";
					$reqdata = "0\011\200\000\202\005";
					// For passwd, the value is composed 
					// of an optional ID, an optional OLD
					// value and an optional NEW value,
					// BER-encoded.  The optional return 
					// value contains the generated NEW
					// password if none was provided.
					$r = ldap_exop($ds, "1.3.6.1.4.1.4203.1.11.1", $reqdata . $newpw, $retoid, $retdata);
					if (!$r) {
						echo "failed<br />";

					} else {
						echo "retoid=" . $retoid . " retdata=" . bin2hex($retdata) . "<br />";

						echo "Binding with old password (should fail)... ";
						$r = ldap_bind($ds, $binddn, $bindpw);
						echo "bind result is [" . $r . "]<br />";

						echo "Binding with new password (should succeed)... ";
						$r = ldap_bind($ds, $binddn, $newpw);
						echo "bind result is [" . $r . "]<br />";

						echo "Re-changing password via high-level API, checking old... ";
						// ldap_exop_passwd() allows
						// to pass the ID, OLD and NEW
						// values, and optionally
						// returns the NEW value if 
						// none was passed.
						$r = ldap_exop_passwd($ds, "", $newpw, "", $genpw);
						if (!$r) {
							echo "failed<br />";

						} else {
							echo "succeeded (generated password: \"" . $genpw . "\")<br />";

							echo "Binding with new generated password (should succeed)... ";
							$r = ldap_bind($ds, $binddn, $genpw);
							echo "bind result is [" . $r . "]<br />";

							echo "Re-setting password to original value via high-level API... ";
							$r = ldap_exop_passwd($ds, "", "", $bindpw);
							if (!$r) {
								echo "failed<br />";

							} else {
								echo "succeeded<br />";
							}
						}
					}
				}
			}
		}
	}

	echo "Closing connection...<br />";
	ldap_close($ds);
}
?> 
