Mercurial > hg > rc1
comparison plugins/password/drivers/ldap.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 * LDAP Password Driver | |
5 * | |
6 * Driver for passwords stored in LDAP | |
7 * This driver use the PEAR Net_LDAP2 class (http://pear.php.net/package/Net_LDAP2). | |
8 * | |
9 * @version 2.0 | |
10 * @author Edouard MOREAU <edouard.moreau@ensma.fr> | |
11 * | |
12 * method hashPassword based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/). | |
13 * method randomSalt based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/). | |
14 * | |
15 * Copyright (C) 2005-2014, The Roundcube Dev Team | |
16 * | |
17 * This program is free software: you can redistribute it and/or modify | |
18 * it under the terms of the GNU General Public License as published by | |
19 * the Free Software Foundation, either version 3 of the License, or | |
20 * (at your option) any later version. | |
21 * | |
22 * This program is distributed in the hope that it will be useful, | |
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 * GNU General Public License for more details. | |
26 * | |
27 * You should have received a copy of the GNU General Public License | |
28 * along with this program. If not, see http://www.gnu.org/licenses/. | |
29 */ | |
30 | |
31 class rcube_ldap_password | |
32 { | |
33 public function save($curpass, $passwd) | |
34 { | |
35 $rcmail = rcmail::get_instance(); | |
36 require_once 'Net/LDAP2.php'; | |
37 | |
38 // Building user DN | |
39 if ($userDN = $rcmail->config->get('password_ldap_userDN_mask')) { | |
40 $userDN = self::substitute_vars($userDN); | |
41 } | |
42 else { | |
43 $userDN = $this->search_userdn($rcmail); | |
44 } | |
45 | |
46 if (empty($userDN)) { | |
47 return PASSWORD_CONNECT_ERROR; | |
48 } | |
49 | |
50 // Connection Method | |
51 switch($rcmail->config->get('password_ldap_method')) { | |
52 case 'admin': | |
53 $binddn = $rcmail->config->get('password_ldap_adminDN'); | |
54 $bindpw = $rcmail->config->get('password_ldap_adminPW'); | |
55 break; | |
56 case 'user': | |
57 default: | |
58 $binddn = $userDN; | |
59 $bindpw = $curpass; | |
60 break; | |
61 } | |
62 | |
63 // Configuration array | |
64 $ldapConfig = array ( | |
65 'binddn' => $binddn, | |
66 'bindpw' => $bindpw, | |
67 'basedn' => $rcmail->config->get('password_ldap_basedn'), | |
68 'host' => $rcmail->config->get('password_ldap_host', 'localhost'), | |
69 'port' => $rcmail->config->get('password_ldap_port', '389'), | |
70 'starttls' => $rcmail->config->get('password_ldap_starttls'), | |
71 'version' => $rcmail->config->get('password_ldap_version', '3'), | |
72 ); | |
73 | |
74 // Connecting using the configuration array | |
75 $ldap = Net_LDAP2::connect($ldapConfig); | |
76 | |
77 // Checking for connection error | |
78 if (is_a($ldap, 'PEAR_Error')) { | |
79 return PASSWORD_CONNECT_ERROR; | |
80 } | |
81 | |
82 $force = $rcmail->config->get('password_ldap_force_replace', true); | |
83 $pwattr = $rcmail->config->get('password_ldap_pwattr', 'userPassword'); | |
84 $lchattr = $rcmail->config->get('password_ldap_lchattr'); | |
85 $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); | |
86 $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); | |
87 $samba = $rcmail->config->get('password_ldap_samba'); | |
88 $encodage = $rcmail->config->get('password_ldap_encodage', 'crypt'); | |
89 | |
90 // Support multiple userPassword values where desired. | |
91 // multiple encodings can be specified separated by '+' (e.g. "cram-md5+ssha") | |
92 $encodages = explode('+', $encodage); | |
93 $crypted_pass = array(); | |
94 | |
95 foreach ($encodages as $enc) { | |
96 if ($cpw = password::hash_password($passwd, $enc)) { | |
97 $crypted_pass[] = $cpw; | |
98 } | |
99 } | |
100 | |
101 // Support password_ldap_samba option for backward compat. | |
102 if ($samba && !$smbpwattr) { | |
103 $smbpwattr = 'sambaNTPassword'; | |
104 $smblchattr = 'sambaPwdLastSet'; | |
105 } | |
106 | |
107 // Crypt new password | |
108 if (empty($crypted_pass)) { | |
109 return PASSWORD_CRYPT_ERROR; | |
110 } | |
111 | |
112 // Crypt new samba password | |
113 if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) { | |
114 return PASSWORD_CRYPT_ERROR; | |
115 } | |
116 | |
117 // Writing new crypted password to LDAP | |
118 $userEntry = $ldap->getEntry($userDN); | |
119 if (Net_LDAP2::isError($userEntry)) { | |
120 return PASSWORD_CONNECT_ERROR; | |
121 } | |
122 | |
123 if (!$userEntry->replace(array($pwattr => $crypted_pass), $force)) { | |
124 return PASSWORD_CONNECT_ERROR; | |
125 } | |
126 | |
127 // Updating PasswordLastChange Attribute if desired | |
128 if ($lchattr) { | |
129 $current_day = (int)(time() / 86400); | |
130 if (!$userEntry->replace(array($lchattr => $current_day), $force)) { | |
131 return PASSWORD_CONNECT_ERROR; | |
132 } | |
133 } | |
134 | |
135 // Update Samba password and last change fields | |
136 if ($smbpwattr) { | |
137 $userEntry->replace(array($smbpwattr => $samba_pass), $force); | |
138 } | |
139 // Update Samba password last change field | |
140 if ($smblchattr) { | |
141 $userEntry->replace(array($smblchattr => time()), $force); | |
142 } | |
143 | |
144 if (Net_LDAP2::isError($userEntry->update())) { | |
145 return PASSWORD_CONNECT_ERROR; | |
146 } | |
147 | |
148 // All done, no error | |
149 return PASSWORD_SUCCESS; | |
150 } | |
151 | |
152 /** | |
153 * Bind with searchDN and searchPW and search for the user's DN. | |
154 * Use search_base and search_filter defined in config file. | |
155 * Return the found DN. | |
156 */ | |
157 function search_userdn($rcmail) | |
158 { | |
159 $binddn = $rcmail->config->get('password_ldap_searchDN'); | |
160 $bindpw = $rcmail->config->get('password_ldap_searchPW'); | |
161 | |
162 $ldapConfig = array ( | |
163 'basedn' => $rcmail->config->get('password_ldap_basedn'), | |
164 'host' => $rcmail->config->get('password_ldap_host', 'localhost'), | |
165 'port' => $rcmail->config->get('password_ldap_port', '389'), | |
166 'starttls' => $rcmail->config->get('password_ldap_starttls'), | |
167 'version' => $rcmail->config->get('password_ldap_version', '3'), | |
168 ); | |
169 | |
170 // allow anonymous searches | |
171 if (!empty($binddn)) { | |
172 $ldapConfig['binddn'] = $binddn; | |
173 $ldapConfig['bindpw'] = $bindpw; | |
174 } | |
175 | |
176 $ldap = Net_LDAP2::connect($ldapConfig); | |
177 | |
178 if (is_a($ldap, 'PEAR_Error')) { | |
179 return ''; | |
180 } | |
181 | |
182 $base = self::substitute_vars($rcmail->config->get('password_ldap_search_base')); | |
183 $filter = self::substitute_vars($rcmail->config->get('password_ldap_search_filter')); | |
184 $options = array ( | |
185 'scope' => 'sub', | |
186 'attributes' => array(), | |
187 ); | |
188 | |
189 $result = $ldap->search($base, $filter, $options); | |
190 if (is_a($result, 'PEAR_Error') || ($result->count() != 1)) { | |
191 $ldap->done(); | |
192 return ''; | |
193 } | |
194 $userDN = $result->current()->dn(); | |
195 $ldap->done(); | |
196 | |
197 return $userDN; | |
198 } | |
199 | |
200 /** | |
201 * Substitute %login, %name, %domain, %dc in $str | |
202 * See plugin config for details | |
203 */ | |
204 static function substitute_vars($str) | |
205 { | |
206 $str = str_replace('%login', $_SESSION['username'], $str); | |
207 $str = str_replace('%l', $_SESSION['username'], $str); | |
208 | |
209 $parts = explode('@', $_SESSION['username']); | |
210 | |
211 if (count($parts) == 2) { | |
212 $dc = 'dc='.strtr($parts[1], array('.' => ',dc=')); // hierarchal domain string | |
213 | |
214 $str = str_replace('%name', $parts[0], $str); | |
215 $str = str_replace('%n', $parts[0], $str); | |
216 $str = str_replace('%dc', $dc, $str); | |
217 $str = str_replace('%domain', $parts[1], $str); | |
218 $str = str_replace('%d', $parts[1], $str); | |
219 } | |
220 | |
221 return $str; | |
222 } | |
223 } |