* @copyright 2009 - CentOS Artwork SIG. * @license GPL */ class LDAP { var $ldapconn; var $ldapbind; // LDAP Filter Attributes var $filter_attrb = array(); var $filter_type = array(); var $filter_clean = array(); //-----------/* Class initializations function __construct() { // Open connection against ldap server $this->ldapconn = ldap_connect(LDAP_HOST,LDAP_PORT) or die("Could not connect to " . LDAP_HOST . "."); // Set protocol version to use ldap_set_option($this->ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3) or die("Could not connect to server through LDAPv3."); // Bind $this->ldapbind = ldap_bind( $this->ldapconn, LDAP_ROOTDN, LDAP_ROOTPW ); // Initialize ldap filter attributes $this->filter_attrb['cn'] = 'cn'; $this->filter_attrb['uid'] = 'uid'; $this->filter_attrb['employeetype'] = ucfirst(translate('employeetype')); $this->filter_attrb['preferredlanguage'] = ucfirst(translate('language')); // Initialize ldap filter Types $this->filter_type['='] = '='; $this->filter_type['~='] = '~='; // Initialize ldap filter default $this->filter_clean['attrb'] = 'preferredlanguage'; $this->filter_clean['type'] = '='; $this->filter_clean['value'] = LANGUAGE; } //----------- Get entries from ldap server function get_entries( $filter ) { // Return entries just if filter valid $search = ldap_search($this->ldapconn,LDAP_DN,$filter); $entries = ldap_get_entries($this->ldapconn,$search); return $entries; } //----------// Validate filter value input // Sanitize filter pattern - Attributes function is_valid( $name , $value ) { switch ( $name ) { case 'uid': $pattern = '/^([a-z0-9_]|\-|\.)+@(([a-z0-9_]|\-)+\.)+([a-z]{2,6})?$/'; break; case 'preferredlanguage': $pattern = '/^[a-zA-Z]{2}$/'; break; case 'filtertype': $pattern = '/^(=|~=)$/'; break; case 'employeetype': $pattern = '/^(writer|administrator)$/'; break; default: $pattern = '/^[a-zA-Z0-9_áéíóñúàçèé ]+$/'; break; } if ( isset( $pattern ) && preg_match( $pattern , $value )) { return true; } else { return false; } } //---------- Check filter attributes */ function sanitize_filter_attribute() { $dirty = array(); $clean = array(); // Initialize dirty attribute $dirty['attrb'] = $this->filter_clean['attrb']; // Initialize clean attribute $clean['attrb'] = $this->filter_clean['attrb']; // Recover dirty attribute values from filter form if ( isset( $_POST['attribute'] ) ) { $dirty['attrb'] = $_POST['attribute']; } // Check dirty attribute if ( array_key_exists( $dirty['attrb'], $this->filter_attrb ) ) { // Attribute is not dirty any more. It passed validation. $clean['attrb'] = $dirty['attrb']; } return $clean['attrb']; } //---------- Check filter types function sanitize_filter_type() { $dirty = array(); $clean = array(); $dirty['type'] = $this->filter_clean['type']; $clear['type'] = $this->filter_clean['type']; // Recover dirty type values from filter form if ( isset( $_POST['type'] ) ) { $dirty['type'] = $_POST['type']; } else { $dirty['type'] = $this->filter_clean['type']; } // Check dirty types if ( array_key_exists( $dirty['type'], $this->filter_type ) ) { // Type is not dirty any more. It passed validation. $clean['type'] = $dirty['type']; } return $clean['type']; } //---------- Sanitize filter value function sanitize_filter_value() { $dirty = array(); $clean = array(); $dirty['value'] = $this->filter_clean['value']; $clean['value'] = $this->filter_clean['value']; // Recover dirty value from filter form if ( isset( $_POST['value'] ) ) { $dirty['value'] = $_POST['value']; } // Sanitize dirty value, based on supplied attribe $name = $this->sanitize_filter_attribute(); $value = $dirty['value']; if ( $this->is_valid( $name, $value ) ) { // Value is not dirty any more. It passed validation. $clean['value'] = $value; } return $clean['value']; } //---------- Build ldap form filter function show_filter() { $clean = array(); $clean['attrb'] = $this->sanitize_filter_attribute(); $clean['type'] = $this->sanitize_filter_type(); $clean['value'] = $this->sanitize_filter_value(); // Start html form $html = '
'; $html .= '
'; // Build html form fileds. Start with some text $html .= ucfirst(translate('filtering by')) . ': '; // Build attributes' select form field $html .= get_user_attrSelector(); // Build types' select form field $html .= ''; // Build value's text form field $html .= ''; // Build submit form button $html .= ''; // End html form $html .= '
'; $html .= '
'; return $html; } //---------- Build ldap filter string function build_filter_string() { $clean['attrb'] = $this->sanitize_filter_attribute(); $clean['type'] = $this->sanitize_filter_type(); $clean['value'] = $this->sanitize_filter_value(); return $clean['attrb'] . $clean['type'] . $clean['value']; } //----------- Check uniqueness of uid attribute */ function is_uid_present( $uid ) { // Verify that uid entry's value be unique $filter = 'uid=' . $uid; $entry = $this->get_entries($filter); if ( $uid != '' && $entry['count'] == 1 ) { return true; } else { return false; } } //---------- Prepare userPassword function prepare_userpassword( $userpassword ) { $dirty['userpassword'] = $userpassword; switch ( LDAP_PASSHASH ) { case '{MD5}': $clean['userpassword'] = LDAP_PASSHASH . base64_encode( pack( 'H*', md5( $dirty['userpassword'] ) ) ); break; case '{SHA}': $clean['userpassword'] = LDAP_PASSHASH . base64_encode( pack( 'H*', sha1( $dirty['userpassword'] ) ) ); break; } return $clean['userpassword']; } //-----------/* Verify modifiable attributes /* Description : Generally used to redifine entry's input keys and values, /* based on is_valid() */ /* $entry : is an array with entry's keys and values. */ function sanitize_entry( $entry ) { // Define attributes that can be modified $fields = array('uid', 'cn','userpassword','displayname','preferredlanguage','employeetype'); // Verify and validate entry's attributes foreach ( $fields as $key ) { if ( isset( $entry[$key] ) && $this->is_valid( $key, $entry[$key] ) ) { // Values that reach this point may be concider "clean". $clean['entry'][$key] = $entry[$key]; } } // Return clean entry array or false if ( isset( $clean['entry'] ) && is_array( $clean['entry'] ) ) { return $clean['entry']; } else { return false; } } //----------/* Initialize useradd values. /* Description: Used in the useradd form page to initiate form values. /* $attribute : is an array with the related attributes to check. */ function init_useradd_values( $attributes ) { foreach ( $attributes as $key ) { if ( ! isset( $_POST[$key] ) ) { $entry[$key] = ''; } else { if ( isset( $_POST[$key] ) && $this->is_valid($key, $_POST[$key]) ) { $entry[$key] = $_POST[$key]; } else { $entry[$key] = ''; } } } return $entry; } //----------/* Initialize useradmin values and do action if submited /* values are different from the actual one. /* Description: used in the p_users.php to initiate form values. /* $id : is the name of the form identification. /* $attribute : is an array with the related attributes to check. */ function init_useradmin_values( $entry, $attributes, $action ) { // First loop to match b in x[b] for ($i = 0; $i < $entry['count']; $i++) { if ( isset( $_POST['uid'][$i] )) { // Define entry id $entry_new['uid'] = $entry[$i]['uid'][0]; // Initialize entry cn // Needed to update sn in the background. $entry_new['cn'] = $entry[$i]['cn'][0]; // Second loop to match x in x[b] foreach ( $attributes as $key ) { // Reset entry value based on input if ( isset( $_POST[$key][$i] ) ) { // Check it is a valid value if ( $this->is_valid( $key, $_POST[$key][$i] ) ) { // ... and that it is different from the actual one if ( $_POST[$key][$i] != $entry[$i][$key][0] ) { $entry_new[$key] = $_POST[$key][$i]; // Prepare userPassword. // SECURITY: this attribute value should never // be verified with the previous one. If // verification is done you are providing a // way to "guess" the user password by trying // passwords until someone reject to update. // Not to critic but if you guess it at the // first try ;). Keep it unverifiable please. if ( $key == 'userpassword' ) { $newpasswd = $this->prepare_userpassword($_POST[$key][$i]); $entry_new[$key] = $newpasswd; } } } } } } // Do action if pressent if ( isset( $entry_new ) ) { $message = $this->do_action( $entry_new, $action ); } else { $message = show_message(ucfirst(translate('nothing to do')), 'orange'); } } return $message; } //-----------/* Do actions (udpate|delete|add) /* $entry : is an array with the entry's key and value information. /* $action : is an string telling what to do with the $entry. /* Description : Actions are applied to just one entry at the same time. */ /* The returned value is a message telling what happend with the action requested.*/ function do_action( $entry, $action ) { // Define Entry's DN if ( isset( $entry['uid'] ) && $this->is_valid( 'uid', $entry['uid'] ) ) { $dn = 'uid=' . $entry['uid'] . ',' . LDAP_DN; } else { $message = show_message(ucfirst(translate('a valid uid is required')),'orange'); return $message; } // Define possible actions $possible_actions = '/^(add|update|delete)$/'; if ( ! preg_match( $possible_actions, $action ) ) { // There is nothing to do here so exit to finish action intention. $message = show_message(ucfirst(translate('invalid action')), 'red'); return $message; } // Define what to do in each action's case switch ( $action ) { case 'update': // If there are valid values then do the update action. if ( is_array( $entry ) ) { // Update sn attribute $entry['sn'] = preg_replace('/^([a-zA-Z0-9_]+ ?)/','', $entry['cn']); if ( $entry['sn'] == '' ) { $message = show_message(ucfirst(translate('invalid cn')), 'orange'); return $message; } if (ldap_modify($this->ldapconn, $dn, $entry)) { $message = show_message(ucfirst(translate('data was updated successfully')), 'green'); } else { $message = show_message(ucfirst(translate('data was not updated')), 'orange'); } } break; // Delete Entry case 'delete': // Delete Entry if ( is_array( $entry ) ) { if ( ldap_delete( $this->ldapconn, $dn ) ) { $message = show_message(ucfirst(translate('data was deleted successfully')), 'green'); } else { $message = show_message(ucfirst(translate('data was not deleted')), 'orange'); } } break; // Add Entry case 'add': // Verify uid presence if ( $this->is_uid_present( $entry['uid'] ) ) { // Abort this action commitment. $message = show_message(ucfirst(translate('user identifier already exists')), 'orange'); return $message; } // Define and validate required attributes $require_attrs = array('uid', 'userpassword', 'cn', 'displayname', 'preferredlanguage', 'employeetype'); foreach ( $require_attrs as $key ) { if ( !isset($entry[$key]) || ! $this->is_valid($key, $entry[$key])) { $message = show_message(ucfirst(translate('the field')) .' '. translate($key) .' ' . translate('requires a valid value') , 'orange'); return $message; } } // Prepare userPassword and other attributes. $entry['userpassword'] = $this->prepare_userpassword($entry['userpassword']); $entry['objectclass'] = 'inetOrgPerson'; $entry['sn'] = preg_replace('/^([a-zA-Z0-9_]+ ?)/','', $entry['cn']); if ( $entry['sn'] == '' ) { $message = show_message(ucfirst(translate('invalid cn')), 'orange'); return $message; } $entry['mail'] = $entry['uid']; // If there are valid values then do the add action. if ( ldap_add( $this->ldapconn, $dn, $entry ) ) { $message = show_message(ucfirst(translate('user added successfully')), 'green'); } else { $message = show_message(ucfirst(translate('user was not added')), 'orange'); } break; } return $message; } //-------------------/* Rename entry dn */ function rename_dn( $olddn, $newdn, $newparent, $deleteoldrdn ) { ldap_rename($this->ldapconn, $olddn, $newdn, $newparent, $deleteoldrdn ); return true; } //-----------/* Display useradmin information /* Description : Used in p_users.php /* $entries : is an array with the entries' keys and values. */ function show_useradmin_info( $entries ) { $html = ''; return $html; } //-------------------/* Close connection */ function __destruct() { if ( isset( $this->ldapconn ) ) { ldap_unbind( $this->ldapconn ); } } } $ldap = new LDAP; ?>