Esempio n. 1
0
 /**
  * Get password expiration time for a given user from Active Directory
  *
  * @param string $pwdlastset The time last time we changed the password.
  * @param resource $lcapconn The open LDAP connection.
  * @param string $user_dn The distinguished name of the user we are checking.
  *
  * @return string $unixtime
  */
 function ldap_get_ad_pwdexpire($pwdlastset, $ldapconn, $user_dn)
 {
     global $CFG;
     if (!function_exists('bcsub')) {
         error_log($this->errorlogtag . get_string('needbcmath', 'auth_ldap'));
         return 0;
     }
     // If UF_DONT_EXPIRE_PASSWD flag is set in user's
     // userAccountControl attribute, the password doesn't expire.
     $sr = ldap_read($ldapconn, $user_dn, '(objectClass=*)', array('userAccountControl'));
     if (!$sr) {
         error_log($this->errorlogtag . get_string('useracctctrlerror', 'auth_ldap', $user_dn));
         // Don't expire password, as we are not sure if it has to be
         // expired or not.
         return 0;
     }
     $entry = ldap_get_entries_moodle($ldapconn, $sr);
     $info = array_change_key_case($entry[0], CASE_LOWER);
     $useraccountcontrol = $info['useraccountcontrol'][0];
     if ($useraccountcontrol & UF_DONT_EXPIRE_PASSWD) {
         // Password doesn't expire.
         return 0;
     }
     // If pwdLastSet is zero, the user must change his/her password now
     // (unless UF_DONT_EXPIRE_PASSWD flag is set, but we already
     // tested this above)
     if ($pwdlastset === '0') {
         // Password has expired
         return -1;
     }
     // ----------------------------------------------------------------
     // Password expiration time in Active Directory is the composition of
     // two values:
     //
     //   - User's pwdLastSet attribute, that stores the last time
     //     the password was changed.
     //
     //   - Domain's maxPwdAge attribute, that sets how long
     //     passwords last in this domain.
     //
     // We already have the first value (passed in as a parameter). We
     // need to get the second one. As we don't know the domain DN, we
     // have to query rootDSE's defaultNamingContext attribute to get
     // it. Then we have to query that DN's maxPwdAge attribute to get
     // the real value.
     //
     // Once we have both values, we just need to combine them. But MS
     // chose to use a different base and unit for time measurements.
     // So we need to convert the values to Unix timestamps (see
     // details below).
     // ----------------------------------------------------------------
     $sr = ldap_read($ldapconn, ROOTDSE, '(objectClass=*)', array('defaultNamingContext'));
     if (!$sr) {
         error_log($this->errorlogtag . get_string('rootdseerror', 'auth_ldap'));
         return 0;
     }
     $entry = ldap_get_entries_moodle($ldapconn, $sr);
     $info = array_change_key_case($entry[0], CASE_LOWER);
     $domaindn = $info['defaultnamingcontext'][0];
     $sr = ldap_read($ldapconn, $domaindn, '(objectClass=*)', array('maxPwdAge'));
     $entry = ldap_get_entries_moodle($ldapconn, $sr);
     $info = array_change_key_case($entry[0], CASE_LOWER);
     $maxpwdage = $info['maxpwdage'][0];
     // ----------------------------------------------------------------
     // MSDN says that "pwdLastSet contains the number of 100 nanosecond
     // intervals since January 1, 1601 (UTC), stored in a 64 bit integer".
     //
     // According to Perl's Date::Manip, the number of seconds between
     // this date and Unix epoch is 11644473600. So we have to
     // substract this value to calculate a Unix time, once we have
     // scaled pwdLastSet to seconds. This is the script used to
     // calculate the value shown above:
     //
     //    #!/usr/bin/perl -w
     //
     //    use Date::Manip;
     //
     //    $date1 = ParseDate ("160101010000 UTC");
     //    $date2 = ParseDate ("197001010000 UTC");
     //    $delta = DateCalc($date1, $date2, \$err);
     //    $secs = Delta_Format($delta, 0, "%st");
     //    print "$secs \n";
     //
     // MSDN also says that "maxPwdAge is stored as a large integer that
     // represents the number of 100 nanosecond intervals from the time
     // the password was set before the password expires." We also need
     // to scale this to seconds. Bear in mind that this value is stored
     // as a _negative_ quantity (at least in my AD domain).
     //
     // As a last remark, if the low 32 bits of maxPwdAge are equal to 0,
     // the maximum password age in the domain is set to 0, which means
     // passwords do not expire (see
     // http://msdn2.microsoft.com/en-us/library/ms974598.aspx)
     //
     // As the quantities involved are too big for PHP integers, we
     // need to use BCMath functions to work with arbitrary precision
     // numbers.
     // ----------------------------------------------------------------
     // If the low order 32 bits are 0, then passwords do not expire in
     // the domain. Just do '$maxpwdage mod 2^32' and check the result
     // (2^32 = 4294967296)
     if (bcmod($maxpwdage, 4294967296) === '0') {
         return 0;
     }
     // Add up pwdLastSet and maxPwdAge to get password expiration
     // time, in MS time units. Remember maxPwdAge is stored as a
     // _negative_ quantity, so we need to substract it in fact.
     $pwdexpire = bcsub($pwdlastset, $maxpwdage);
     // Scale the result to convert it to Unix time units and return
     // that value.
     return bcsub(bcdiv($pwdexpire, '10000000'), '11644473600');
 }
Esempio n. 2
0
/**
 * Checks if user belongs to specific group(s) or is in a subtree.
 *
 * Returns true if user belongs to a group in grupdns string OR if the
 * DN of the user is in a subtree of the DN provided as "group"
 *
 * @param mixed $ldapconnection A valid LDAP connection.
 * @param string $userid LDAP user id (dn/cn/uid/...) to test membership for.
 * @param array $group_dns arrary of group dn
 * @param string $member_attrib the name of the membership attribute.
 * @return boolean
 *
 */
function ldap_isgroupmember($ldapconnection, $userid, $group_dns, $member_attrib)
{
    if (empty($ldapconnection) || empty($userid) || empty($group_dns) || empty($member_attrib)) {
        return false;
    }
    $result = false;
    foreach ($group_dns as $group) {
        $group = trim($group);
        if (empty($group)) {
            continue;
        }
        // Check cheaply if the user's DN sits in a subtree of the
        // "group" DN provided. Granted, this isn't a proper LDAP
        // group, but it's a popular usage.
        if (stripos(strrev(strtolower($userid)), strrev(strtolower($group))) === 0) {
            $result = true;
            break;
        }
        $search = ldap_read($ldapconnection, $group, '(' . $member_attrib . '=' . ldap_filter_addslashes($userid) . ')', array($member_attrib));
        if (!empty($search) && ldap_count_entries($ldapconnection, $search)) {
            $info = ldap_get_entries_moodle($ldapconnection, $search);
            if (count($info) > 0) {
                // User is member of group
                $result = true;
                break;
            }
        }
    }
    return $result;
}
Esempio n. 3
0
/**
 * Reads user information from ldap and returns it in array()
 *
 * Function should return all information available. If you are saving
 * this information to moodle user-table you should honor syncronization flags
 *
 * @param object $ldapauth the ldap authentication instance
 * @param string $username username
 * @param array $options an array with CLI input options
 *
 * @return mixed array with no magic quotes or false on error
 */
function local_ent_installer_get_userinfo($ldapauth, $username, $options = array())
{
    static $entattributes;
    // Load some cached static data.
    if (!isset($entattributes)) {
        // aggregate additional ent specific attributes that hold interesting information
        $configattribs = get_config('local_ent_installer', 'ent_userinfo_attributes');
        if (empty($configattribs)) {
            $entattributes = array('ENTPersonFonctions', 'ENTPersonJointure', 'ENTEleveClasses', 'ENTEleveGroupes', 'ENTEleveTransport', 'ENTEleveRegime', 'ENTPersonProfils', 'objectGUID');
        } else {
            $entattributes = explode(',', $configattribs);
        }
    }
    $extusername = core_text::convert($username, 'utf-8', $ldapauth->config->ldapencoding);
    $ldapconnection = $ldapauth->ldap_connect();
    if (!($user_dn = $ldapauth->ldap_find_userdn($ldapconnection, $extusername))) {
        $ldapauth->ldap_close();
        return false;
    }
    $search_attribs = array();
    $attrmap = $ldapauth->ldap_attributes();
    foreach ($attrmap as $key => $values) {
        if (!is_array($values)) {
            $values = array($values);
        }
        foreach ($values as $value) {
            if (!in_array($value, $search_attribs)) {
                array_push($search_attribs, $value);
            }
        }
    }
    foreach ($entattributes as $value) {
        if (!in_array($value, $search_attribs)) {
            array_push($search_attribs, $value);
            // Add attributes to $attrmap so they are pulled down into final user object.
            $attrmap[$value] = strtolower($value);
        }
    }
    if ($options['verbose']) {
        mtrace("Getting {$user_dn} for " . implode(',', $search_attribs));
    }
    if (!($user_info_result = ldap_read($ldapconnection, $user_dn, '(objectClass=*)', $search_attribs))) {
        $ldapauth->ldap_close();
        return false;
    }
    $user_entry = ldap_get_entries_moodle($ldapconnection, $user_info_result);
    if (empty($user_entry)) {
        $ldapauth->ldap_close();
        return false;
        // Entry not found.
    }
    $result = array();
    foreach ($attrmap as $key => $values) {
        if (!is_array($values)) {
            $values = array($values);
        }
        $ldapval = NULL;
        foreach ($values as $value) {
            $entry = array_change_key_case($user_entry[0], CASE_LOWER);
            if ($value == 'dn' || $value == 'distinguishedname') {
                $result[$key] = $user_dn;
                continue;
            }
            if (!array_key_exists($value, $entry)) {
                if ($options['verbose']) {
                    mtrace("Requested value {$value} but missing in record");
                }
                continue;
                // wrong data mapping!
            }
            if ($value == 'objectguid') {
                if (strlen($entry[$value][0]) == 16) {
                    $tmp = bin2hex($entry[$value][0]);
                    $t = $tmp[6] . $tmp[7] . $tmp[4] . $tmp[5] . $tmp[2] . $tmp[3] . $tmp[0] . $tmp[1] . '-';
                    $t .= $tmp[10] . $tmp[11] . $tmp[8] . $tmp[9] . '-';
                    $t .= $tmp[14] . $tmp[15] . $tmp[12] . $tmp[13] . '-';
                    $t .= substr($tmp, 16, 4) . '-';
                    $t .= substr($tmp, 20);
                    $objectguid = $t;
                }
                $newval = $objectguid;
            } else {
                if ($value == 'entelevegroupes' && is_array($entry[$value])) {
                    $newval = array();
                    foreach ($entry[$value] as $subkey => $subvalue) {
                        if ($subkey !== 'count') {
                            $newval[] = core_text::convert($subvalue, $ldapauth->config->ldapencoding, 'utf-8');
                        }
                    }
                } else {
                    if (is_array($entry[$value])) {
                        $newval = core_text::convert($entry[$value][0], $ldapauth->config->ldapencoding, 'utf-8');
                    } else {
                        $newval = core_text::convert($entry[$value], $ldapauth->config->ldapencoding, 'utf-8');
                    }
                }
            }
            if (!empty($newval)) {
                // Favour ldap entries that are set.
                $ldapval = $newval;
            }
        }
        if (!is_null($ldapval)) {
            $result[$key] = $ldapval;
        }
    }
    $ldapauth->ldap_close();
    return $result;
}
 /**
  * 
  * returns the distinct values of the target LDAP attribute
  * these will be the idnumbers of the synched Moodle cohorts
  * @returns array of string 
  */
 function get_attribute_distinct_values()
 {
     //return array ('affiliate','retired','student','faculty','staff','employee','affiliate','member','alum','emeritus','researcher');
     global $CFG, $DB;
     // only these cohorts will be synched
     if (!empty($this->config->cohort_synching_ldap_attribute_idnumbers)) {
         return explode(',', $this->config->cohort_synching_ldap_attribute_idnumbers);
     }
     //build a filter to fetch all users having something in the target LDAP attribute
     $filter = '(&(' . $this->config->user_attribute . '=*)' . $this->config->objectclass . ')';
     $filter = '(&' . $filter . '(' . $this->config->cohort_synching_ldap_attribute_attribute . '=*))';
     if ($CFG->debug_ldap_groupes) {
         pp_print_object('looking for ', $filter);
     }
     $ldapconnection = $this->ldap_connect();
     $contexts = explode(';', $this->config->contexts);
     if (!empty($this->config->create_context)) {
         array_push($contexts, $this->config->create_context);
     }
     $matchings = array();
     foreach ($contexts as $context) {
         $context = trim($context);
         if (empty($context)) {
             continue;
         }
         if ($this->config->search_sub) {
             // Use ldap_search to find first user from subtree
             $ldap_result = ldap_search($ldapconnection, $context, $filter, array($this->config->cohort_synching_ldap_attribute_attribute));
         } else {
             // Search only in this context
             $ldap_result = ldap_list($ldapconnection, $context, $filter, array($this->config->cohort_synching_ldap_attribute_attribute));
         }
         if (!$ldap_result) {
             continue;
         }
         // this API function returns all attributes as an array
         // wether they are single or multiple
         $users = ldap_get_entries_moodle($ldapconnection, $ldap_result);
         // Add found DISTINCT values to list
         for ($i = 0; $i < count($users); $i++) {
             $count = $users[$i][$this->config->cohort_synching_ldap_attribute_attribute]['count'];
             for ($j = 0; $j < $count; $j++) {
                 $value = textlib::convert($users[$i][$this->config->cohort_synching_ldap_attribute_attribute][$j], $this->config->ldapencoding, 'utf-8');
                 if (!in_array($value, $matchings)) {
                     array_push($matchings, $value);
                 }
             }
         }
     }
     $this->ldap_close();
     return $matchings;
 }
 /**
  * Get ldap entry by user name
  * @param required $username
  */
 private function _getldap_entry($username)
 {
     $ap_ldap = new auth_plugin_ldap();
     $ldapconnection = $ap_ldap->ldap_connect();
     $user_dn = $ap_ldap->ldap_find_userdn($ldapconnection, $username);
     $sr = ldap_read($ldapconnection, $user_dn, 'objectclass=*', array());
     if ($sr) {
         $info = ldap_get_entries_moodle($ldapconnection, $sr);
     } else {
         return false;
     }
     return $info;
 }