<?php
/**
* LDAP Access
*
* @category Logic
* @package CentOS-News
* @author Alain Reguera Delgado <alain.reguera@gmail.com>
* @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 = '<div class="filter">';
$html .= '<form name="filter" method="post" action="">';
// 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 .= '<select name="type">';
foreach ($this->filter_type as $key => $value)
{
if ($clean['type'] == $key )
{
$html .= '<option selected value="'.$key.'">' . $value . '</option>';
}
else
{
$html .= '<option value="'.$key.'">' . $value . '</option>';
}
}
$html .= '</select>';
// Build value's text form field
$html .= '<input type="text" name="value" value="'.$clean['value'].'">';
// Build submit form button
$html .= '<input type="submit" name="submit_filter" value="'.ucfirst(translate('filter')).'">';
// End html form
$html .= '</form>';
$html .= '</div>';
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 = '<ul>';
$html .= '<li>LDAP Host: ' . LDAP_HOST . '</li>';
$html .= '<li>Domain Component (dc): ' . LDAP_DN . '</li>';
$html .= '<li>' . $this->show_filter() .'</li>';
$html .= '<li>' . ucfirst(translate('results')) . ': '. $entries['count']; '</li>';
$html .= '</ul>';
return $html;
}
//-------------------/* Close connection */
function __destruct()
{
if ( isset( $this->ldapconn ) )
{
ldap_unbind( $this->ldapconn );
}
}
}
$ldap = new LDAP;
?>