author | Dan Fuhry <dan@enanocms.org> |
Sat, 23 Feb 2013 14:26:38 -0500 | |
changeset 9 | f4bf6556fb9f |
parent 8 | f68fdcc18df9 |
permissions | -rw-r--r-- |
0 | 1 |
<?php |
2 |
||
3 |
// BEGIN CONSTANTS |
|
4 |
||
5 |
$ldap_readonly_attrs = array( |
|
6 |
'uid' |
|
7 |
, 'objectClass' |
|
8 |
, 'userPassword' |
|
9 |
, 'homeDirectory' |
|
10 |
, 'uidNumber' |
|
11 |
, 'gidNumber' |
|
12 |
); |
|
13 |
||
14 |
$ldap_field_names = array( |
|
15 |
'cn' => 'Common name' |
|
16 |
, 'uid' => 'Username' |
|
17 |
, 'givenName' => 'Given name' |
|
18 |
, 'sn' => 'Surname' |
|
19 |
, 'mail' => 'E-mail' |
|
20 |
, 'title' => 'Job title' |
|
21 |
, 'telephoneNumber' => 'Phone' |
|
22 |
); |
|
23 |
||
24 |
$ldap_add_single = array( |
|
25 |
'title' |
|
26 |
, 'mail' |
|
27 |
); |
|
28 |
||
29 |
$ldap_add_multiple = array( |
|
30 |
'telephoneNumber' |
|
31 |
, 'mobile' |
|
32 |
, 'mail' |
|
4
2212b2ded8bf
Added OpenSSH public key support in LDAP
Dan Fuhry <dan@fuhry.us>
parents:
3
diff
changeset
|
33 |
, 'sshPublicKey' |
0 | 34 |
); |
35 |
||
36 |
// END CONSTANTS |
|
37 |
||
38 |
global $_ldapconn; |
|
39 |
$_ldapconn = ldap_connect($ldap_server); |
|
40 |
if ( !$_ldapconn ) |
|
41 |
die("Failed to connect to the LDAP database"); |
|
42 |
||
43 |
if ( !ldap_set_option($_ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3) ) |
|
44 |
die("Failed to set LDAP version to 3"); |
|
45 |
||
46 |
if ( !ldap_bind($_ldapconn, $ldap_manager['dn'], $ldap_manager['password']) ) |
|
47 |
die("Failed to bind to LDAP as a manager"); |
|
48 |
||
49 |
register_shutdown_function(function() use ($_ldapconn) |
|
50 |
{ |
|
51 |
ldap_unbind($_ldapconn); |
|
52 |
}); |
|
53 |
||
54 |
||
55 |
function ldap_escape($str) |
|
56 |
{ |
|
57 |
// FIXME escape properly |
|
58 |
return $str; |
|
59 |
} |
|
60 |
||
61 |
function ldap_get_user($username) |
|
62 |
{ |
|
63 |
global $_ldapconn, $ldap_user_basedn; |
|
64 |
||
8 | 65 |
static $cache = array(); |
66 |
if ( isset($cache[$username]) ) |
|
67 |
return $cache[$username]; |
|
68 |
||
0 | 69 |
$search_filter = sprintf("(&(uid=%s)(objectClass=posixAccount))", ldap_escape($username)); |
70 |
||
71 |
$search_result = ldap_search($_ldapconn, $ldap_user_basedn, $search_filter); |
|
72 |
if ( ldap_count_entries($_ldapconn, $search_result) !== 1 ) |
|
73 |
return false; |
|
74 |
||
8 | 75 |
return $cache[$username] = ldap_array_cleanup(ldap_get_attributes($_ldapconn, ldap_first_entry($_ldapconn, $search_result))); |
0 | 76 |
} |
77 |
||
78 |
function ldap_get_group($group) |
|
79 |
{ |
|
80 |
global $_ldapconn, $ldap_group_basedn; |
|
81 |
||
82 |
$search_filter = sprintf("(&(cn=%s)(objectClass=posixGroup))", ldap_escape($group)); |
|
83 |
||
84 |
$search_result = ldap_search($_ldapconn, $ldap_group_basedn, $search_filter); |
|
85 |
if ( ldap_count_entries($_ldapconn, $search_result) !== 1 ) |
|
86 |
return false; |
|
87 |
||
88 |
$result = ldap_array_cleanup(ldap_get_attributes($_ldapconn, ldap_first_entry($_ldapconn, $search_result))); |
|
89 |
if ( !isset($result['memberUid']) ) |
|
90 |
$result['memberUid'] = array(); |
|
91 |
if ( !is_array($result['memberUid']) ) |
|
92 |
$result['memberUid'] = array($result['memberUid']); |
|
93 |
||
94 |
return $result; |
|
95 |
} |
|
96 |
||
97 |
function ldap_update_user($user, $entry) |
|
98 |
{ |
|
99 |
global $_ldapconn; |
|
100 |
||
101 |
return ldap_modify($_ldapconn, ldap_make_user_dn($user), $entry); |
|
102 |
} |
|
103 |
||
104 |
function ldap_list_users() |
|
105 |
{ |
|
106 |
global $_ldapconn, $ldap_user_basedn; |
|
107 |
||
108 |
$search_result = ldap_search($_ldapconn, $ldap_user_basedn, '(objectClass=organizationalPerson)'); |
|
109 |
||
110 |
$results = array(); |
|
111 |
for ( $entry = ldap_first_entry($_ldapconn, $search_result); |
|
112 |
$entry; |
|
113 |
$entry = ldap_next_entry($_ldapconn, $entry) ) |
|
114 |
{ |
|
115 |
$entry_arr = ldap_array_cleanup(ldap_get_attributes($_ldapconn, $entry)); |
|
116 |
$results[$entry_arr['uid']] = $entry_arr; |
|
117 |
} |
|
118 |
||
119 |
return $results; |
|
120 |
} |
|
121 |
||
122 |
function ldap_list_groups() |
|
123 |
{ |
|
124 |
global $_ldapconn, $ldap_group_basedn; |
|
125 |
||
126 |
$search_result = ldap_search($_ldapconn, $ldap_group_basedn, '(objectClass=posixGroup)'); |
|
127 |
||
128 |
$results = array(); |
|
129 |
for ( $entry = ldap_first_entry($_ldapconn, $search_result); |
|
130 |
$entry; |
|
131 |
$entry = ldap_next_entry($_ldapconn, $entry) ) |
|
132 |
{ |
|
133 |
$entry_arr = ldap_array_cleanup(ldap_get_attributes($_ldapconn, $entry)); |
|
134 |
$results[$entry_arr['cn']] = $entry_arr; |
|
135 |
} |
|
136 |
||
137 |
return $results; |
|
138 |
} |
|
139 |
||
140 |
function ldap_array_cleanup($arr) |
|
141 |
{ |
|
4
2212b2ded8bf
Added OpenSSH public key support in LDAP
Dan Fuhry <dan@fuhry.us>
parents:
3
diff
changeset
|
142 |
global $ldap_add_multiple; |
2212b2ded8bf
Added OpenSSH public key support in LDAP
Dan Fuhry <dan@fuhry.us>
parents:
3
diff
changeset
|
143 |
|
0 | 144 |
$result = array(); |
145 |
foreach ( $arr as $k => $v ) |
|
146 |
{ |
|
147 |
if ( is_int($k) || $k == 'count' ) |
|
148 |
continue; |
|
149 |
||
4
2212b2ded8bf
Added OpenSSH public key support in LDAP
Dan Fuhry <dan@fuhry.us>
parents:
3
diff
changeset
|
150 |
if ( $v['count'] === 1 && !in_array($k, $ldap_add_multiple) ) |
0 | 151 |
$v = $v[0]; |
152 |
else |
|
153 |
unset($v['count']); |
|
154 |
||
155 |
$result[$k] = $v; |
|
156 |
} |
|
157 |
||
158 |
return $result; |
|
159 |
} |
|
160 |
||
161 |
function ldap_make_user_dn($username) |
|
162 |
{ |
|
163 |
global $ldap_user_basedn; |
|
164 |
return sprintf('uid=%s,%s', ldap_escape($username), $ldap_user_basedn); |
|
165 |
} |
|
166 |
||
167 |
function ldap_make_group_dn($group) |
|
168 |
{ |
|
169 |
global $ldap_group_basedn; |
|
170 |
return sprintf('cn=%s,%s', ldap_escape($group), $ldap_group_basedn); |
|
171 |
} |
|
172 |
||
173 |
function ldap_replace_attr($dn, $attribute, $value) |
|
174 |
{ |
|
175 |
global $_ldapconn; |
|
176 |
||
177 |
$ldif = array( |
|
178 |
$attribute => array($value) |
|
179 |
); |
|
180 |
||
181 |
return ldap_mod_replace($_ldapconn, $dn, $ldif); |
|
182 |
} |
|
183 |
||
184 |
function ldap_delete_user($username) |
|
185 |
{ |
|
186 |
global $_ldapconn, $ldap_user_basedn, $ldap_group_basedn; |
|
187 |
||
188 |
// remove user from all LDAP groups |
|
189 |
$search_filter = sprintf("(&(memberUid=%s)(objectClass=posixGroup))", ldap_escape($username)); |
|
190 |
$search_result = ldap_search($_ldapconn, $ldap_group_basedn, $search_filter); |
|
191 |
for ( $entry = ldap_first_entry($_ldapconn, $search_result); |
|
192 |
$entry; |
|
193 |
$entry = ldap_next_entry($_ldapconn, $entry) ) |
|
194 |
{ |
|
195 |
$entry_arr = ldap_array_cleanup(ldap_get_attributes($_ldapconn, $entry)); |
|
196 |
$dn = ldap_get_dn($_ldapconn, $entry); |
|
197 |
ldap_mod_del($_ldapconn, $dn, array('memberUid' => array($username))); |
|
198 |
} |
|
199 |
||
200 |
// delete user DN |
|
201 |
return ldap_delete($_ldapconn, ldap_make_user_dn($username)); |
|
202 |
} |
|
203 |
||
204 |
function ldap_delete_group_member($gid, $uid) |
|
205 |
{ |
|
206 |
global $_ldapconn; |
|
207 |
||
208 |
return ldap_mod_del($_ldapconn, ldap_make_group_dn($gid), array('memberUid' => array($uid))); |
|
209 |
} |
|
210 |
||
211 |
function ldap_add_group_member($gid, $uid) |
|
212 |
{ |
|
213 |
global $_ldapconn; |
|
214 |
||
215 |
return ldap_mod_add($_ldapconn, ldap_make_group_dn($gid), array('memberUid' => array($uid))); |
|
216 |
} |
|
217 |
||
218 |
function get_next_available_uid() |
|
219 |
{ |
|
220 |
$users = ldap_list_users(); |
|
221 |
$uids = array(); |
|
222 |
foreach ( $users as $u ) |
|
223 |
$uids[] = intval($u['uidNumber']); |
|
224 |
||
225 |
asort($uids); |
|
226 |
$uid = UID_MIN; |
|
227 |
$last_uid = $uids[0]; |
|
228 |
foreach ( $uids as $u ) |
|
229 |
{ |
|
230 |
if ( $u > $last_uid + 1 && ($last_uid + 1) > UID_MIN ) |
|
231 |
{ |
|
232 |
return $last_uid + 1; |
|
233 |
} |
|
234 |
||
235 |
$last_uid = $u; |
|
236 |
} |
|
237 |
||
238 |
return max($uids) + 1; |
|
239 |
} |
|
240 |
||
241 |
function get_next_available_gid() |
|
242 |
{ |
|
243 |
$groups = ldap_list_groups(); |
|
244 |
$gids = array(); |
|
245 |
foreach ( $groups as $g ) |
|
246 |
$gids[] = intval($g['gidNumber']); |
|
247 |
||
248 |
asort($gids); |
|
249 |
$gid = GID_MIN; |
|
250 |
$last_gid = $gids[0]; |
|
251 |
foreach ( $gids as $g ) |
|
252 |
{ |
|
253 |
if ( $g > $last_gid + 1 && ($last_gid + 1) > GID_MIN ) |
|
254 |
{ |
|
255 |
return $last_gid + 1; |
|
256 |
} |
|
257 |
||
258 |
$last_gid = $g; |
|
259 |
} |
|
260 |
||
261 |
return max($gids) + 1; |
|
262 |
} |
|
263 |
||
264 |
function get_next_available_extension() |
|
265 |
{ |
|
266 |
$users = ldap_list_users(); |
|
267 |
$exts = array(); |
|
268 |
foreach ( $users as $u ) |
|
269 |
{ |
|
270 |
if ( !isset($u['telephoneNumber']) ) |
|
271 |
continue; |
|
272 |
||
273 |
if ( !is_array($u['telephoneNumber']) ) |
|
274 |
$u['telephoneNumber'] = array($u['telephoneNumber']); |
|
275 |
||
276 |
foreach ( $u['telephoneNumber'] as $n ) |
|
277 |
{ |
|
278 |
if ( preg_match('/^([0-9]+) \(extension\)$/', $n, $match) ) |
|
279 |
$exts[] = intval($n); |
|
280 |
} |
|
281 |
} |
|
282 |
||
283 |
asort($exts); |
|
284 |
$ext = PHONE_EXT_MIN; |
|
285 |
$last_ext = PHONE_EXT_MIN - 1; |
|
286 |
foreach ( $exts as $e ) |
|
287 |
{ |
|
288 |
if ( $e > $last_ext + 1 && ($last_ext + 1) > UID_MIN ) |
|
289 |
{ |
|
290 |
return $last_ext + 1; |
|
291 |
} |
|
292 |
||
293 |
$last_ext = $e; |
|
294 |
} |
|
295 |
||
296 |
return count($exts) ? max($exts) + 1 : PHONE_EXT_MIN; |
|
297 |
} |
|
298 |
||
299 |
function ldap_create_user($username, $gn, $sn, $cn, $title) |
|
300 |
{ |
|
301 |
global $_ldapconn; |
|
302 |
||
303 |
$krb_realm = get_default_kerberos_realm(); |
|
304 |
||
305 |
if ( !ldap_add($_ldapconn, ldap_make_user_dn($username), array( |
|
306 |
'cn' => array($cn) |
|
307 |
, 'uid' => array($username) |
|
308 |
, 'objectClass' => array( |
|
309 |
'top' |
|
310 |
, 'person' |
|
311 |
, 'inetOrgPerson' |
|
312 |
, 'organizationalPerson' |
|
313 |
, 'posixAccount' |
|
4
2212b2ded8bf
Added OpenSSH public key support in LDAP
Dan Fuhry <dan@fuhry.us>
parents:
3
diff
changeset
|
314 |
, 'ldapPublicKey' |
0 | 315 |
) |
316 |
, 'gn' => array($gn) |
|
317 |
, 'sn' => array($sn) |
|
318 |
, 'userPassword' => array("{SASL}$username@$krb_realm") |
|
319 |
, 'loginShell' => array('/bin/bash') |
|
320 |
, 'homeDirectory' => array("/home/users/$username") |
|
321 |
, 'uidNumber' => array(get_next_available_uid()) |
|
322 |
, 'gidNumber' => array(500) |
|
323 |
, 'title' => array($title) |
|
324 |
)) ) |
|
325 |
return false; |
|
326 |
||
327 |
if ( !ldap_mod_add($_ldapconn, ldap_make_group_dn('users'), array('memberUid' => array($username))) ) |
|
328 |
return false; |
|
329 |
||
330 |
return true; |
|
331 |
} |
|
332 |
||
333 |
function ldap_create_group($cn, $description) |
|
334 |
{ |
|
335 |
global $_ldapconn; |
|
336 |
||
337 |
if ( !ldap_add($_ldapconn, ldap_make_group_dn($cn), array( |
|
338 |
'cn' => array($cn) |
|
339 |
, 'description' => array($description) |
|
340 |
, 'gidNumber' => array(get_next_available_gid()) |
|
341 |
, 'objectClass' => array( |
|
342 |
'top' |
|
343 |
, 'posixGroup' |
|
344 |
) |
|
345 |
)) ) |
|
346 |
return false; |
|
347 |
} |
|
348 |
||
349 |
function ldap_delete_group($cn) |
|
350 |
{ |
|
351 |
global $_ldapconn; |
|
352 |
||
353 |
$group = ldap_get_group($cn); |
|
354 |
$users = ldap_list_users(); |
|
355 |
||
356 |
foreach ( $users as $u ) |
|
357 |
{ |
|
358 |
if ( $u['gidNumber'] === $group['gidNumber'] ) |
|
359 |
return false; |
|
360 |
} |
|
361 |
||
362 |
return ldap_delete($_ldapconn, ldap_make_group_dn($cn)); |
|
363 |
} |
|
3 | 364 |
|
365 |
/** |
|
366 |
* Is the given username in the specified LDAP group? |
|
367 |
* @param string username |
|
368 |
* @param string Group name |
|
369 |
* @return bool |
|
370 |
*/ |
|
371 |
||
372 |
function ldap_test_group_membership($username, $group) |
|
373 |
{ |
|
374 |
global $_ldapconn, $ldap_group_basedn; |
|
375 |
||
376 |
$filter = sprintf('(&(memberUid=%s)(cn=%s)(objectClass=posixGroup))', ldap_escape($username), ldap_escape($group)); |
|
377 |
||
378 |
$result = ldap_search($_ldapconn, $ldap_group_basedn, $filter); |
|
379 |
return ldap_count_entries($_ldapconn, $result) > 0; |
|
380 |
} |