Using LDIF to simulate LDAP transactions with PHP

Avatar von Stephanie Ehrling

LDIF is the acronym for LDAP Data Interchange Format and a text format to represent LDAP information (http://tools.ietf.org/html/rfc2849). Respectively an LDIF file is a simple text file that can contain those LDAP information, which can be separated into two groups. On the one hand, it can hold exported LDAP data in a text format. The other purpose of LDIF is to use it for importing data into an LDAP based system. So it can contain data to be imported or just commands that shall be processed. This is an important fact, because that opens the door to an interesting workaround. Though LDAP does not support transactions, which can be a real problem, LDIF can do the job for you. Transactions are important whenever some instructions have to be performed atomically. That means that a set of instructions can not be disturbed by any other commands of another client. A good example would be a scenario where you first read a record and then perform actions (like update or delete) on that record. Without transactions it is not possible to make sure the record still exists after you read it.

Using LDIF requires ldap client binaries. You can chose between the following client programs.

  • ldapsearch
  • ldapcompare
  • ldapcmp
  • ldapdelete
  • ldapmodify

Those binaries can be found in the Open Ldap distribution or in the Sun ONE Directory SDK for C 5.08 (http://www.sun.com/download/products.xml?id=3ec28dbd).
To import data ldapmodify is the best choice. It is necessary to call that binary with the right connect parameters which are host name, user name, password and of course the file to import. The php code snippet would look like the following (the call itself is done by the PHP function proc_open):

        //  Using ldapmodify with pipes to ensure safe transactions
	$descriptorspec = array(
		0 => array("pipe", "r"),  	// stdin is a pipe that the child will read from
		1 => array("pipe", "w"),  	// stdout is a pipe that the child will write to
		2 => array("pipe", "w") 	// stderr is a pipe that the child will write to
	);
	$pipes = array();
	
	//  build LDAP-Command								
	$comm = $ldapPath.'ldapmodify -h "'.$host.'" -D "'. $user.'" -w "'. $pwd .'"  -f '.$filename;
			
	// call ldapmodify
	$process = proc_open($comm, $descriptorspec, $pipes);

	if (is_resource($process)) {
		// $pipes now looks like this:
		// 0 => writeable handle connected to child stdin
		// 1 => readable handle connected to child stdout

		fwrite($pipes[0], '');
		fclose($pipes[0]);

		// check for output
		$out = "";
		while (!feof($pipes[1])) {
			$out .= fgets($pipes[1], 1024);
		}
		fclose($pipes[1]);

		// check for errors
		$err = '';
		while (!feof($pipes[2])) {
			$err .= fgets($pipes[2], 1024);
		}
		fclose($pipes[2]);

		// It is important that you close any pipes before calling
		// proc_close in order to avoid a deadlock
		$return_value = proc_close($process);

		if ($err != '') {
			// TODO: Handle error
		} else {
			// TODO: Handle result
		}
	}

The Code creates a command string with the needed connection parameters and the filename. This string is used as a parameter of the proc_open function which executes the command. That has the effect that the LDIF file is imported and cannot be disturbed by any other client, in other words it is executed atomically which leads to the concept of transactions.

Avatar von Stephanie Ehrling

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.