Mercurial > hg > rc1
comparison plugins/password/drivers/ldap_simple.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 * Simple LDAP Password Driver | |
5 * | |
6 * Driver for passwords stored in LDAP | |
7 * This driver is based on Edouard's LDAP Password Driver, but does not | |
8 * require PEAR's Net_LDAP2 to be installed | |
9 * | |
10 * @version 2.0 | |
11 * @author Wout Decre <wout@canodus.be> | |
12 * @author Aleksander Machniak <machniak@kolabsys.com> | |
13 * | |
14 * Copyright (C) 2005-2014, The Roundcube Dev Team | |
15 * | |
16 * This program is free software: you can redistribute it and/or modify | |
17 * it under the terms of the GNU General Public License as published by | |
18 * the Free Software Foundation, either version 3 of the License, or | |
19 * (at your option) any later version. | |
20 * | |
21 * This program is distributed in the hope that it will be useful, | |
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 * GNU General Public License for more details. | |
25 * | |
26 * You should have received a copy of the GNU General Public License | |
27 * along with this program. If not, see http://www.gnu.org/licenses/. | |
28 */ | |
29 | |
30 class rcube_ldap_simple_password | |
31 { | |
32 private $debug = false; | |
33 | |
34 function save($curpass, $passwd) | |
35 { | |
36 $rcmail = rcmail::get_instance(); | |
37 | |
38 $this->debug = $rcmail->config->get('ldap_debug'); | |
39 | |
40 $ldap_host = $rcmail->config->get('password_ldap_host', 'localhost'); | |
41 $ldap_port = $rcmail->config->get('password_ldap_port', '389'); | |
42 | |
43 $this->_debug("C: Connect to $ldap_host:$ldap_port"); | |
44 | |
45 // Connect | |
46 if (!$ds = ldap_connect($ldap_host, $ldap_port)) { | |
47 $this->_debug("S: NOT OK"); | |
48 | |
49 rcube::raise_error(array( | |
50 'code' => 100, 'type' => 'ldap', | |
51 'file' => __FILE__, 'line' => __LINE__, | |
52 'message' => "Could not connect to LDAP server" | |
53 ), | |
54 true); | |
55 | |
56 return PASSWORD_CONNECT_ERROR; | |
57 } | |
58 | |
59 $this->_debug("S: OK"); | |
60 | |
61 // Set protocol version | |
62 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, | |
63 $rcmail->config->get('password_ldap_version', '3')); | |
64 | |
65 // Start TLS | |
66 if ($rcmail->config->get('password_ldap_starttls')) { | |
67 if (!ldap_start_tls($ds)) { | |
68 ldap_unbind($ds); | |
69 return PASSWORD_CONNECT_ERROR; | |
70 } | |
71 } | |
72 | |
73 // include 'ldap' driver, we share some static methods with it | |
74 require_once INSTALL_PATH . 'plugins/password/drivers/ldap.php'; | |
75 | |
76 // other plugins might want to modify user DN | |
77 $plugin = $rcmail->plugins->exec_hook('password_ldap_bind', array( | |
78 'user_dn' => '', 'conn' => $ds)); | |
79 | |
80 // Build user DN | |
81 if (!empty($plugin['user_dn'])) { | |
82 $user_dn = $plugin['user_dn']; | |
83 } | |
84 else if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) { | |
85 $user_dn = rcube_ldap_password::substitute_vars($user_dn); | |
86 } | |
87 else { | |
88 $user_dn = $this->search_userdn($rcmail, $ds); | |
89 } | |
90 | |
91 if (empty($user_dn)) { | |
92 ldap_unbind($ds); | |
93 return PASSWORD_CONNECT_ERROR; | |
94 } | |
95 | |
96 // Connection method | |
97 switch ($rcmail->config->get('password_ldap_method')) { | |
98 case 'admin': | |
99 $binddn = $rcmail->config->get('password_ldap_adminDN'); | |
100 $bindpw = $rcmail->config->get('password_ldap_adminPW'); | |
101 break; | |
102 case 'user': | |
103 default: | |
104 $binddn = $user_dn; | |
105 $bindpw = $curpass; | |
106 break; | |
107 } | |
108 | |
109 $lchattr = $rcmail->config->get('password_ldap_lchattr'); | |
110 $pwattr = $rcmail->config->get('password_ldap_pwattr', 'userPassword'); | |
111 $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); | |
112 $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); | |
113 $samba = $rcmail->config->get('password_ldap_samba'); | |
114 $pass_mode = $rcmail->config->get('password_ldap_encodage', 'crypt'); | |
115 $crypted_pass = password::hash_password($passwd, $pass_mode); | |
116 | |
117 // Support password_ldap_samba option for backward compat. | |
118 if ($samba && !$smbpwattr) { | |
119 $smbpwattr = 'sambaNTPassword'; | |
120 $smblchattr = 'sambaPwdLastSet'; | |
121 } | |
122 | |
123 // Crypt new password | |
124 if (!$crypted_pass) { | |
125 return PASSWORD_CRYPT_ERROR; | |
126 } | |
127 | |
128 // Crypt new Samba password | |
129 if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) { | |
130 return PASSWORD_CRYPT_ERROR; | |
131 } | |
132 | |
133 $this->_debug("C: Bind $binddn, pass: **** [" . strlen($bindpw) . "]"); | |
134 | |
135 // Bind | |
136 if (!ldap_bind($ds, $binddn, $bindpw)) { | |
137 $this->_debug("S: ".ldap_error($ds)); | |
138 | |
139 ldap_unbind($ds); | |
140 | |
141 return PASSWORD_CONNECT_ERROR; | |
142 } | |
143 | |
144 $this->_debug("S: OK"); | |
145 | |
146 $entry[$pwattr] = $crypted_pass; | |
147 | |
148 // Update PasswordLastChange Attribute if desired | |
149 if ($lchattr) { | |
150 $entry[$lchattr] = (int)(time() / 86400); | |
151 } | |
152 | |
153 // Update Samba password | |
154 if ($smbpwattr) { | |
155 $entry[$smbpwattr] = $samba_pass; | |
156 } | |
157 | |
158 // Update Samba password last change | |
159 if ($smblchattr) { | |
160 $entry[$smblchattr] = time(); | |
161 } | |
162 | |
163 $this->_debug("C: Modify $user_dn: " . print_r($entry, true)); | |
164 | |
165 if (!ldap_modify($ds, $user_dn, $entry)) { | |
166 $this->_debug("S: ".ldap_error($ds)); | |
167 | |
168 $errno = ldap_errno($ds); | |
169 | |
170 ldap_unbind($ds); | |
171 | |
172 if ($errno == 0x13) { // LDAP_CONSTRAINT_VIOLATION | |
173 return PASSWORD_CONSTRAINT_VIOLATION; | |
174 } | |
175 | |
176 return PASSWORD_CONNECT_ERROR; | |
177 } | |
178 | |
179 $this->_debug("S: OK"); | |
180 | |
181 // All done, no error | |
182 ldap_unbind($ds); | |
183 | |
184 return PASSWORD_SUCCESS; | |
185 } | |
186 | |
187 /** | |
188 * Bind with searchDN and searchPW and search for the user's DN | |
189 * Use search_base and search_filter defined in config file | |
190 * Return the found DN | |
191 */ | |
192 function search_userdn($rcmail, $ds) | |
193 { | |
194 $search_user = $rcmail->config->get('password_ldap_searchDN'); | |
195 $search_pass = $rcmail->config->get('password_ldap_searchPW'); | |
196 $search_base = $rcmail->config->get('password_ldap_search_base'); | |
197 $search_filter = $rcmail->config->get('password_ldap_search_filter'); | |
198 | |
199 if (empty($search_filter)) { | |
200 return false; | |
201 } | |
202 | |
203 $this->_debug("C: Bind " . ($search_user ? $search_user : '[anonymous]')); | |
204 | |
205 // Bind | |
206 if (!ldap_bind($ds, $search_user, $search_pass)) { | |
207 $this->_debug("S: ".ldap_error($ds)); | |
208 return false; | |
209 } | |
210 | |
211 $this->_debug("S: OK"); | |
212 | |
213 $search_base = rcube_ldap_password::substitute_vars($search_base); | |
214 $search_filter = rcube_ldap_password::substitute_vars($search_filter); | |
215 | |
216 $this->_debug("C: Search $search_base for $search_filter"); | |
217 | |
218 // Search for the DN | |
219 if (!$sr = ldap_search($ds, $search_base, $search_filter)) { | |
220 $this->_debug("S: ".ldap_error($ds)); | |
221 return false; | |
222 } | |
223 | |
224 $found = ldap_count_entries($ds, $sr); | |
225 | |
226 $this->_debug("S: OK [found $found records]"); | |
227 | |
228 // If no or more entries were found, return false | |
229 if ($found != 1) { | |
230 return false; | |
231 } | |
232 | |
233 return ldap_get_dn($ds, ldap_first_entry($ds, $sr)); | |
234 } | |
235 | |
236 /** | |
237 * Prints debug info to the log | |
238 */ | |
239 private function _debug($str) | |
240 { | |
241 if ($this->debug) { | |
242 rcube::write_log('ldap', $str); | |
243 } | |
244 } | |
245 } |