Blame Scripts/CentOS-Web/admin/includes/classes/ldap.php

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