[Windows, Linux, PHP, Active Directory, OpenLDAP] A Quick Authentication Programming Guide
PRODUCT: XAMPP Microsoft Active Directory LAMP OpenLDAP
OP/SYS: Microsoft Windows Server 2008 Linux Fedora 15
COMPONENT: PHP
SOURCE: Philippe Vouters Fontainebleau/France
LOW-COST HIGH-TECH: http://techno-star.fr
OVERVIEW: Refer to http://fr.wikipedia.org/wiki/WAMP for the XAMPP and LAMP acronyms meanings in the PRODUCT section. The PHP/HTML codes in the PROGRAMS section stem from a personal work porting a Microsoft Active Directory PHP authentication code running on a Windows server computer to Linux OpenLDAP based PHP authentication. The PHP code has to run indifferently on both operating systems each using its own authentication method. For the reader to fully understand the work context, the identical Linux/Windows PHP code is developed and tested on a Linux computer in a network completely independant from the target Windows computer network. Hence the OpenLDAP/PHP code on Linux has to emulate the Active Directory/PHP code on Windows. The target production system runs XAMPP on a Windows Server 2008.
*** CAUTION *** This sample PHP codes have been tested using XAMPP along with Active Directory and LAMP with OpenLDAP respective authentications. However, we cannot guarantee their effectiveness because of the possibility of error in transmitting or implementing them. It is meant to be used as a template for writing your own PHP code, and does require modification for use on your system.
PROGRAM NOTES: Refer to ../tima/Linux-OpenLDAP-A_quick_HOWTO_guide_part_1.html to setup OpenLDAP on the Linux computer.
PHP PROGRAMS: Configuration file: ********* * AD-OLDAP.config.php ********* <?php // Selection window title $phpAD["ldap_window_title"] = "Active Directory Users"; // Default empty string $phpAD["ldap_def_string"] = "<< Type names separated by semicolons or choose from list >>"; // Server running an LDAP service. if (PHP_OS != "Linux"){ $phpAD["ldap_server"] = "ldap://192.168.1.2"; } else { $phpAD["ldap_server"] = "ldap://127.0.0.1"; } // User & password to use for establishing the connection with the // Active Directory/OpenLDAP emulation. // On an Active Directory domain, you may use DOMAIN\<username> $phpAD["auth_user"] = "admin"; $phpAD["auth_pass"] = "Secret"; // Organisational Unit containing the list of all locations if (PHP_OS != "Linux"){ $phpAD["ldap_dn"] = "CN=Users,DC=mycompany,DC=com"; } else { $phpAD["ldap_dn"] = "OU=people,DC=vouters,DC=dyndns,DC=org"; } // Default OU to open $phpAD["ldap_default_ou"] = ""; // Active directory Domain name if (PHP_OS != "Linux"){ $phpAD["ad_domain_name"] = "DOMAIN"; } // Informations displayed in the authentication box $phpAD["auth_realm"] = "Active Directory login"; $phpAD["auth_description"] = "User Login"; // Name of the page where to redirect the user when authorisation is denied $phpAD["auth_error_page"] = "error.php"; ?> PHP authenticating code file: ********* * AD-OLDAP.code.php ********* <?php function Authenticate($Auth_Realm="",$Auth_Description="",$Auth_Redirect="",$Process_Security=TRUE) { global $phpAD; global $givenname; header('Cache-Control: no-store, no-cache, must-revalidate'); if ( $Auth_Realm == "" ) { $Auth_Realm = $phpAD["auth_realm"]; } if ( $Auth_Description == "" ) { $Auth_Description = $phpAD["auth_description"]; } if ( $Auth_Redirect == "" ) { $Auth_Redirect = $phpAD["auth_error_page"]; } // If not authenticated, challenge the user if ( isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) ) { $ldap_server = $phpAD["ldap_server"]; $auth_pass = $_SERVER['PHP_AUTH_PW']; $auth_user = $_SERVER['PHP_AUTH_USER']; if ( isset($phpAD["ad_domain_name"]) and strtoupper(left($auth_user,strlen($phpAD["ad_domain_name"]))) != strtoupper($phpAD["ad_domain_name"])){ // With Active Directory we look for for DOMAIN\login $auth_user = $phpAD["ad_domain_name"]."\\".$auth_user; $auth_user = str_replace("\\\\","\\",$auth_user); } elseif (!isset($phpAD["ad_domain_name"])) { // With OpenLDAP, we look for the string // "cn='login',ou=people,dc=vouters,dc=dyndns,dc=org" $auth_user = "cn=".$auth_user.",".$phpAD["ldap_dn"]; } // Check for empty login or password if ( $auth_user."" == "" || $auth_pass."" == "" ) SendAuthHeader($Auth_Realm,$Auth_Description); // Connect to either Active Directory or OpenLDAP using ldap://w.x.y.z if (!($connect=ldap_connect($ldap_server))) { header("Location: NotAllowed.php"); exit; } // Attempt to authenticate the user if (!($bind=ldap_bind($connect, $auth_user, $auth_pass))) SendAuthHeader($Auth_Realm,$Auth_Description); } else SendAuthHeader($Auth_Realm,$Auth_Description); if (isset($phpAD["ad_domain_name"]) and strlen($phpAD["ad_domain_name"])){ // Retrieve the original login string $auth_user = right($auth_user,strlen($auth_user)-(strlen($phpAD["ad_domain_name"])+1)); } // Do we have a security descriptor for this folder? if (isset($phpAD["ldap_auth_file"])) { // Now ldap search user informations using the sAMAccountName Active // Directory field information $filter = "(sAMAccountName=".$auth_user.")"; if (!($search=@ldap_search($connect, $phpAD["ldap_dn"], $filter))) die("Unable to search ldap server"); $info = ldap_get_entries($connect, $search); } else { // OpenLDAP ldap search on givenName. The preg_match is used to retrieve // the original login value. Note that the OpenLDAP givenName field has // been added to the OpenLDAP database and has been set to match the // Active Directory sAMAccountName field. $regex="/^cn=([A-Za-z ]+),".$phpAD["ldap_dn"]."/"; preg_match($regex,$auth_user,$matches); $filter = "(cn=".$matches[1].")"; $justthese = array("givenName"); $search=ldap_search($connect, $phpAD["ldap_dn"], $filter, $justthese) or die("Unable to search ldap server"); $info = ldap_get_entries($connect, $search); $givenname = $info[0]['givenname'][0]; } ldap_close($connect); } // End function Authenticate() /* Send authentication header to the web browser. The access to the page is denied and the user has to provide a UserName / Password. All parameters are optional. SendAuthHeader(string Real,string Description) */ function SendAuthHeader($Realm,$Description) { global $phpAD; header('WWW-Authenticate: Basic realm="'.$Realm.' '.$Description.'"'); header('HTTP/1.0 401 Unauthorized'); exit; } /* Send a page redirection header. New URL must be provided as first parameter. SendRedirectHeader(string URL) */ function SendRedirectHeader($URL) { header("Location: ".$URL); exit; } /* Various string functions. left(string Message,int Offset) right(string Message,int Offset) mid(string Message,int Start,int lenght) */ function left($value,$NbChar) { if ($NbChar <= 0) return ""; else return substr($value,0,$NbChar);} function right($value,$NbChar) { if ($NbChar > strlen($value)) return $value; else return substr($value,strlen($value)-$NbChar,$NbChar); } function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); } ?> PHP - HTML user code: ********* * index.php ********* <?php include("AD-OLDAP.config.php"); include("AD-OLDAP.code.php"); ?> <?php session_start(); // The PHP session starts Authenticate();// Authenticate using either Active Directory or OpenLDAP $login = $_SERVER['PHP_AUTH_USER']; if (PHP_OS == "Linux"){ if (isset($givenname)){ $_SESSION['login'] = $givenname; } else{ $_SESSION['login'] = $login; } } else { $_SESSION['login'] = $login; } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="EN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Active Directory or OpenLDAP authenticated</title> </head> <body> If you can read this Web page, this means you authenticated<br> using either Microsoft Active Diectory or Linux/Unix OpenLDAP.<br> </body> </html>
REFERENCE(S): PHP Manual and along with code examples available on the net. XAMPP home page can be found at: http://www.apachefriends.org/en/xampp.html OpenLDAP actual configuration for use with the code in this article: ../tima/Linux-OpenLDAP-A_quick_HOWTO_guide_part_1.html