function save($curpass, $passwd) { $rcmail = rcmail::get_instance(); $this->debug = $rcmail->config->get('ldap_debug'); $ldap_host = $rcmail->config->get('password_ldap_host'); $ldap_port = $rcmail->config->get('password_ldap_port'); $this->_debug("C: Connect to {$ldap_host}:{$ldap_port}"); // Connect if (!($ds = ldap_connect($ldap_host, $ldap_port))) { $this->_debug("S: NOT OK"); rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not connect to LDAP server"), true); return PASSWORD_CONNECT_ERROR; } $this->_debug("S: OK"); // Set protocol version ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $rcmail->config->get('password_ldap_version')); // Start TLS if ($rcmail->config->get('password_ldap_starttls')) { if (!ldap_start_tls($ds)) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } } // include 'ldap' driver, we share some static methods with it require_once INSTALL_PATH . 'plugins/password/drivers/ldap.php'; // other plugins might want to modify user DN $plugin = $rcmail->plugins->exec_hook('password_ldap_bind', array('user_dn' => '', 'conn' => $ds)); // Build user DN if (!empty($plugin['user_dn'])) { $user_dn = $plugin['user_dn']; } else { if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) { $user_dn = rcube_ldap_password::substitute_vars($user_dn); } else { $user_dn = $this->search_userdn($rcmail, $ds); } } if (empty($user_dn)) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } // Connection method switch ($rcmail->config->get('password_ldap_method')) { case 'admin': $binddn = $rcmail->config->get('password_ldap_adminDN'); $bindpw = $rcmail->config->get('password_ldap_adminPW'); break; case 'user': default: $binddn = $user_dn; $bindpw = $curpass; break; } $lchattr = $rcmail->config->get('password_ldap_lchattr'); $pwattr = $rcmail->config->get('password_ldap_pwattr'); $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); $samba = $rcmail->config->get('password_ldap_samba'); $pass_mode = $rcmail->config->get('password_ldap_encodage'); $crypted_pass = password::hash_password($passwd, $pass_mode); // Support password_ldap_samba option for backward compat. if ($samba && !$smbpwattr) { $smbpwattr = 'sambaNTPassword'; $smblchattr = 'sambaPwdLastSet'; } // Crypt new password if (!$crypted_pass) { return PASSWORD_CRYPT_ERROR; } // Crypt new Samba password if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) { return PASSWORD_CRYPT_ERROR; } $this->_debug("C: Bind {$binddn}, pass: **** [" . strlen($bindpw) . "]"); // Bind if (!ldap_bind($ds, $binddn, $bindpw)) { $this->_debug("S: " . ldap_error($ds)); ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } $this->_debug("S: OK"); $entry[$pwattr] = $crypted_pass; // Update PasswordLastChange Attribute if desired if ($lchattr) { $entry[$lchattr] = (int) (time() / 86400); } // Update Samba password if ($smbpwattr) { $entry[$smbpwattr] = $samba_pass; } // Update Samba password last change if ($smblchattr) { $entry[$smblchattr] = time(); } $this->_debug("C: Modify {$user_dn}: " . print_r($entry, true)); if (!ldap_modify($ds, $user_dn, $entry)) { $this->_debug("S: " . ldap_error($ds)); ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } $this->_debug("S: OK"); // All done, no error ldap_unbind($ds); return PASSWORD_SUCCESS; }
public function save($curpass, $passwd) { $rcmail = rcmail::get_instance(); require_once 'Net/LDAP2.php'; // Building user DN if ($userDN = $rcmail->config->get('password_ldap_userDN_mask')) { $userDN = self::substitute_vars($userDN); } else { $userDN = $this->search_userdn($rcmail); } if (empty($userDN)) { return PASSWORD_CONNECT_ERROR; } // Connection Method switch ($rcmail->config->get('password_ldap_method')) { case 'admin': $binddn = $rcmail->config->get('password_ldap_adminDN'); $bindpw = $rcmail->config->get('password_ldap_adminPW'); break; case 'user': default: $binddn = $userDN; $bindpw = $curpass; break; } // Configuration array $ldapConfig = array('binddn' => $binddn, 'bindpw' => $bindpw, 'basedn' => $rcmail->config->get('password_ldap_basedn'), 'host' => $rcmail->config->get('password_ldap_host'), 'port' => $rcmail->config->get('password_ldap_port'), 'starttls' => $rcmail->config->get('password_ldap_starttls'), 'version' => $rcmail->config->get('password_ldap_version')); // Connecting using the configuration array $ldap = Net_LDAP2::connect($ldapConfig); // Checking for connection error if (is_a($ldap, 'PEAR_Error')) { return PASSWORD_CONNECT_ERROR; } $force = $rcmail->config->get('password_ldap_force_replace'); $pwattr = $rcmail->config->get('password_ldap_pwattr'); $lchattr = $rcmail->config->get('password_ldap_lchattr'); $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); $samba = $rcmail->config->get('password_ldap_samba'); $encodage = $rcmail->config->get('password_ldap_encodage'); // Support multiple userPassword values where desired. // multiple encodings can be specified separated by '+' (e.g. "cram-md5+ssha") $encodages = explode('+', $encodage); $crypted_pass = array(); foreach ($encodages as $enc) { if ($cpw = password::hash_password($passwd, $enc)) { $crypted_pass[] = $cpw; } } // Support password_ldap_samba option for backward compat. if ($samba && !$smbpwattr) { $smbpwattr = 'sambaNTPassword'; $smblchattr = 'sambaPwdLastSet'; } // Crypt new password if (empty($crypted_pass)) { return PASSWORD_CRYPT_ERROR; } // Crypt new samba password if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) { return PASSWORD_CRYPT_ERROR; } // Writing new crypted password to LDAP $userEntry = $ldap->getEntry($userDN); if (Net_LDAP2::isError($userEntry)) { return PASSWORD_CONNECT_ERROR; } if (!$userEntry->replace(array($pwattr => $crypted_pass), $force)) { return PASSWORD_CONNECT_ERROR; } // Updating PasswordLastChange Attribute if desired if ($lchattr) { $current_day = (int) (time() / 86400); if (!$userEntry->replace(array($lchattr => $current_day), $force)) { return PASSWORD_CONNECT_ERROR; } } // Update Samba password and last change fields if ($smbpwattr) { $userEntry->replace(array($smbpwattr => $samba_pass), $force); } // Update Samba password last change field if ($smblchattr) { $userEntry->replace(array($smblchattr => time()), $force); } if (Net_LDAP2::isError($userEntry->update())) { return PASSWORD_CONNECT_ERROR; } // All done, no error return PASSWORD_SUCCESS; }
function save($curpass, $passwd) { $rcmail = rcmail::get_instance(); if (!($sql = $rcmail->config->get('password_query'))) { $sql = 'SELECT update_passwd(%c, %u)'; } if ($dsn = $rcmail->config->get('password_db_dsn')) { $db = rcube_db::factory($dsn, '', false); $db->set_debug((bool) $rcmail->config->get('sql_debug')); } else { $db = $rcmail->get_dbh(); } if ($db->is_error()) { return PASSWORD_ERROR; } // new password - default hash method if (strpos($sql, '%P') !== false) { $password = password::hash_password($passwd); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%P', $db->quote($password), $sql); } // old password - default hash method if (strpos($sql, '%O') !== false) { $password = password::hash_password($curpass); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%O', $db->quote($password), $sql); } // crypted password (deprecated, use %P) if (strpos($sql, '%c') !== false) { $password = password::hash_password($passwd, 'crypt', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%c', $db->quote($password), $sql); } // dovecotpw (deprecated, use %P) if (strpos($sql, '%D') !== false) { $password = password::hash_password($passwd, 'dovecot', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%D', $db->quote($password), $sql); } // hashed passwords (deprecated, use %P) if (strpos($sql, '%n') !== false) { $password = password::hash_password($passwd, 'hash', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%n', $db->quote($password, 'text'), $sql); } // hashed passwords (deprecated, use %P) if (strpos($sql, '%q') !== false) { $password = password::hash_password($curpass, 'hash', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%q', $db->quote($password, 'text'), $sql); } // Handle clear text passwords securely (#1487034) $sql_vars = array(); if (preg_match_all('/%[p|o]/', $sql, $m)) { foreach ($m[0] as $var) { if ($var == '%p') { $sql = preg_replace('/%p/', '?', $sql, 1); $sql_vars[] = (string) $passwd; } else { // %o $sql = preg_replace('/%o/', '?', $sql, 1); $sql_vars[] = (string) $curpass; } } } $local_part = $rcmail->user->get_username('local'); $domain_part = $rcmail->user->get_username('domain'); $username = $_SESSION['username']; $host = $_SESSION['imap_host']; // convert domains to/from punnycode if ($rcmail->config->get('password_idn_ascii')) { $domain_part = rcube_utils::idn_to_ascii($domain_part); $username = rcube_utils::idn_to_ascii($username); $host = rcube_utils::idn_to_ascii($host); } else { $domain_part = rcube_utils::idn_to_utf8($domain_part); $username = rcube_utils::idn_to_utf8($username); $host = rcube_utils::idn_to_utf8($host); } // at least we should always have the local part $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql); $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql); $sql = str_replace('%u', $db->quote($username, 'text'), $sql); $sql = str_replace('%h', $db->quote($host, 'text'), $sql); $res = $db->query($sql, $sql_vars); if (!$db->is_error()) { if (strtolower(substr(trim($sql), 0, 6)) == 'select') { if ($db->fetch_array($res)) { return PASSWORD_SUCCESS; } } else { // This is the good case: 1 row updated if ($db->affected_rows($res) == 1) { return PASSWORD_SUCCESS; } // @TODO: Some queries don't affect any rows // Should we assume a success if there was no error? } } return PASSWORD_ERROR; }