Mercurial > hg > rc1
comparison plugins/password/drivers/sql.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
| author | Charlie Root |
|---|---|
| date | Thu, 04 Jan 2018 15:50:29 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:1e000243b222 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 /** | |
| 4 * SQL Password Driver | |
| 5 * | |
| 6 * Driver for passwords stored in SQL database | |
| 7 * | |
| 8 * @version 2.0 | |
| 9 * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl> | |
| 10 * | |
| 11 * Copyright (C) 2005-2013, The Roundcube Dev Team | |
| 12 * | |
| 13 * This program is free software: you can redistribute it and/or modify | |
| 14 * it under the terms of the GNU General Public License as published by | |
| 15 * the Free Software Foundation, either version 3 of the License, or | |
| 16 * (at your option) any later version. | |
| 17 * | |
| 18 * This program is distributed in the hope that it will be useful, | |
| 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 21 * GNU General Public License for more details. | |
| 22 * | |
| 23 * You should have received a copy of the GNU General Public License | |
| 24 * along with this program. If not, see http://www.gnu.org/licenses/. | |
| 25 */ | |
| 26 | |
| 27 class rcube_sql_password | |
| 28 { | |
| 29 function save($curpass, $passwd) | |
| 30 { | |
| 31 $rcmail = rcmail::get_instance(); | |
| 32 | |
| 33 if (!($sql = $rcmail->config->get('password_query'))) { | |
| 34 $sql = 'SELECT update_passwd(%c, %u)'; | |
| 35 } | |
| 36 | |
| 37 if ($dsn = $rcmail->config->get('password_db_dsn')) { | |
| 38 $db = rcube_db::factory($dsn, '', false); | |
| 39 $db->set_debug((bool)$rcmail->config->get('sql_debug')); | |
| 40 } | |
| 41 else { | |
| 42 $db = $rcmail->get_dbh(); | |
| 43 } | |
| 44 | |
| 45 if ($db->is_error()) { | |
| 46 return PASSWORD_ERROR; | |
| 47 } | |
| 48 | |
| 49 // new password - default hash method | |
| 50 if (strpos($sql, '%P') !== false) { | |
| 51 $password = password::hash_password($passwd); | |
| 52 | |
| 53 if ($password === false) { | |
| 54 return PASSWORD_CRYPT_ERROR; | |
| 55 } | |
| 56 | |
| 57 $sql = str_replace('%P', $db->quote($password), $sql); | |
| 58 } | |
| 59 | |
| 60 // old password - default hash method | |
| 61 if (strpos($sql, '%O') !== false) { | |
| 62 $password = password::hash_password($curpass); | |
| 63 | |
| 64 if ($password === false) { | |
| 65 return PASSWORD_CRYPT_ERROR; | |
| 66 } | |
| 67 | |
| 68 $sql = str_replace('%O', $db->quote($password), $sql); | |
| 69 } | |
| 70 | |
| 71 // crypted password (deprecated, use %P) | |
| 72 if (strpos($sql, '%c') !== false) { | |
| 73 $password = password::hash_password($passwd, 'crypt', false); | |
| 74 | |
| 75 if ($password === false) { | |
| 76 return PASSWORD_CRYPT_ERROR; | |
| 77 } | |
| 78 | |
| 79 $sql = str_replace('%c', $db->quote($password), $sql); | |
| 80 } | |
| 81 | |
| 82 // dovecotpw (deprecated, use %P) | |
| 83 if (strpos($sql, '%D') !== false) { | |
| 84 $password = password::hash_password($passwd, 'dovecot', false); | |
| 85 | |
| 86 if ($password === false) { | |
| 87 return PASSWORD_CRYPT_ERROR; | |
| 88 } | |
| 89 | |
| 90 $sql = str_replace('%D', $db->quote($password), $sql); | |
| 91 } | |
| 92 | |
| 93 // hashed passwords (deprecated, use %P) | |
| 94 if (strpos($sql, '%n') !== false) { | |
| 95 $password = password::hash_password($passwd, 'hash', false); | |
| 96 | |
| 97 if ($password === false) { | |
| 98 return PASSWORD_CRYPT_ERROR; | |
| 99 } | |
| 100 | |
| 101 $sql = str_replace('%n', $db->quote($password, 'text'), $sql); | |
| 102 } | |
| 103 | |
| 104 // hashed passwords (deprecated, use %P) | |
| 105 if (strpos($sql, '%q') !== false) { | |
| 106 $password = password::hash_password($curpass, 'hash', false); | |
| 107 | |
| 108 if ($password === false) { | |
| 109 return PASSWORD_CRYPT_ERROR; | |
| 110 } | |
| 111 | |
| 112 $sql = str_replace('%q', $db->quote($password, 'text'), $sql); | |
| 113 } | |
| 114 | |
| 115 // Handle clear text passwords securely (#1487034) | |
| 116 $sql_vars = array(); | |
| 117 if (preg_match_all('/%[p|o]/', $sql, $m)) { | |
| 118 foreach ($m[0] as $var) { | |
| 119 if ($var == '%p') { | |
| 120 $sql = preg_replace('/%p/', '?', $sql, 1); | |
| 121 $sql_vars[] = (string) $passwd; | |
| 122 } | |
| 123 else { // %o | |
| 124 $sql = preg_replace('/%o/', '?', $sql, 1); | |
| 125 $sql_vars[] = (string) $curpass; | |
| 126 } | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 $local_part = $rcmail->user->get_username('local'); | |
| 131 $domain_part = $rcmail->user->get_username('domain'); | |
| 132 $username = $_SESSION['username']; | |
| 133 $host = $_SESSION['imap_host']; | |
| 134 | |
| 135 // convert domains to/from punnycode | |
| 136 if ($rcmail->config->get('password_idn_ascii')) { | |
| 137 $domain_part = rcube_utils::idn_to_ascii($domain_part); | |
| 138 $username = rcube_utils::idn_to_ascii($username); | |
| 139 $host = rcube_utils::idn_to_ascii($host); | |
| 140 } | |
| 141 else { | |
| 142 $domain_part = rcube_utils::idn_to_utf8($domain_part); | |
| 143 $username = rcube_utils::idn_to_utf8($username); | |
| 144 $host = rcube_utils::idn_to_utf8($host); | |
| 145 } | |
| 146 | |
| 147 // at least we should always have the local part | |
| 148 $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql); | |
| 149 $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql); | |
| 150 $sql = str_replace('%u', $db->quote($username, 'text'), $sql); | |
| 151 $sql = str_replace('%h', $db->quote($host, 'text'), $sql); | |
| 152 | |
| 153 $res = $db->query($sql, $sql_vars); | |
| 154 | |
| 155 if (!$db->is_error()) { | |
| 156 if (strtolower(substr(trim($sql),0,6)) == 'select') { | |
| 157 if ($db->fetch_array($res)) { | |
| 158 return PASSWORD_SUCCESS; | |
| 159 } | |
| 160 } | |
| 161 else { | |
| 162 // This is the good case: 1 row updated | |
| 163 if ($db->affected_rows($res) == 1) | |
| 164 return PASSWORD_SUCCESS; | |
| 165 // @TODO: Some queries don't affect any rows | |
| 166 // Should we assume a success if there was no error? | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 return PASSWORD_ERROR; | |
| 171 } | |
| 172 } |
