/
ldap_api.php
358 lines (301 loc) · 10.8 KB
/
ldap_api.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
<?php
# MantisBT - a php based bugtracking system
# MantisBT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MantisBT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
/**
* LDAP API
* @package CoreAPI
* @subpackage LDAPAPI
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2009 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
*/
/**
* Connect and bind to the LDAP directory
* @param string $p_binddn
* @param string $p_password
* @return resource
*/
function ldap_connect_bind( $p_binddn = '', $p_password = '' ) {
if( !extension_loaded( 'ldap' ) ) {
log_event( LOG_LDAP, "Error: LDAP extension missing in php" );
trigger_error( ERROR_LDAP_EXTENSION_NOT_LOADED, ERROR );
}
$t_ldap_server = config_get( 'ldap_server' );
$t_ldap_port = config_get( 'ldap_port' );
log_event( LOG_LDAP, "Attempting connection to LDAP server '{$t_ldap_server}' port '{$t_ldap_port}'." );
$t_ds = @ldap_connect( $t_ldap_server, $t_ldap_port );
if( $t_ds > 0 ) {
log_event( LOG_LDAP, "Connection accepted to LDAP server" );
$t_protocol_version = config_get( 'ldap_protocol_version' );
if( $t_protocol_version > 0 ) {
log_event( LOG_LDAP, "Setting LDAP protocol to to ldap server to " . $t_protocol_version );
ldap_set_option( $t_ds, LDAP_OPT_PROTOCOL_VERSION, $t_protocol_version );
}
# Set referrals flag.
$t_follow_referrals = ON == config_get( 'ldap_follow_referrals' );
ldap_set_option( $t_ds, LDAP_OPT_REFERRALS, $t_follow_referrals );
# If no Bind DN and Password is set, attempt to login as the configured
# Bind DN.
if( is_blank( $p_binddn ) && is_blank( $p_password ) ) {
$p_binddn = config_get( 'ldap_bind_dn', '' );
$p_password = config_get( 'ldap_bind_passwd', '' );
}
if( !is_blank( $p_binddn ) && !is_blank( $p_password ) ) {
log_event( LOG_LDAP, "Attempting bind to ldap server with username and password" );
$t_br = @ldap_bind( $t_ds, $p_binddn, $p_password );
} else {
# Either the Bind DN or the Password are empty, so attempt an anonymous bind.
log_event( LOG_LDAP, "Attempting anonymous bind to ldap server" );
$t_br = @ldap_bind( $t_ds );
}
if( !$t_br ) {
log_event( LOG_LDAP, "bind to ldap server failed - authentication error?" );
trigger_error( ERROR_LDAP_AUTH_FAILED, ERROR );
}
log_event( LOG_LDAP, "bind to ldap server successful" );
} else {
log_event( LOG_LDAP, "Connection to ldap server failed" );
trigger_error( ERROR_LDAP_SERVER_CONNECT_FAILED, ERROR );
}
return $t_ds;
}
$g_cache_ldap_email = array();
/**
* returns an email address from LDAP, given a userid
* @param int $p_user_id
* @return string
*/
function ldap_email( $p_user_id ) {
global $g_cache_ldap_email;
if( isset( $g_cache_ldap_email[ (int)$p_user_id ] ) ) {
return $g_cache_ldap_email[ (int)$p_user_id ];
}
$t_username = user_get_field( $p_user_id, 'username' );
$t_email = ldap_email_from_username( $t_username );
$g_cache_ldap_email[ (int)$p_user_id ] = $t_email;
return $t_email;
}
/**
* Return an email address from LDAP, given a username
* @param string $p_username
* @return string
*/
function ldap_email_from_username( $p_username ) {
if ( ldap_simulation_is_enabled() ) {
return ldap_simulation_email_from_username( $p_username );
}
$t_email = ldap_get_field_from_username( $p_username, 'mail' );
if ( $t_email === null ) {
return '';
}
return $t_email;
}
/**
* Gets a user's real name (common name) given the id.
*
* @param int $p_user_id The user id.
* @return string real name.
*/
function ldap_realname( $p_user_id ) {
$t_username = user_get_field( $p_user_id, 'username' );
return ldap_realname_from_username( $t_username );
}
/**
* Gets a user real name given their user name.
*
* @param string $p_username The user's name.
* @return string The user's real name.
*/
function ldap_realname_from_username( $p_username ) {
if ( ldap_simulation_is_enabled() ) {
return ldap_simulatiom_realname_from_username( $p_username );
}
$t_ldap_realname_field = config_get( 'ldap_realname_field' );
$t_realname = ldap_get_field_from_username( $p_username, $t_ldap_realname_field );
if ( $t_realname === null ) {
return '';
}
return $t_realname;
}
/**
* Gets the value of a specific field from LDAP given the user name
* and LDAP field name.
*
* @todo Implement caching by retrieving all needed information in one query.
* @todo Implement logging to LDAP queries same way like DB queries.
*
* @param string $p_username The user name.
* @param string $p_field The LDAP field name.
* @return string The field value or null if not found.
*/
function ldap_get_field_from_username( $p_username, $p_field ) {
$t_ldap_organization = config_get( 'ldap_organization' );
$t_ldap_root_dn = config_get( 'ldap_root_dn' );
$t_ldap_uid_field = config_get( 'ldap_uid_field' );
# Bind
log_event( LOG_LDAP, "Binding to LDAP server" );
$t_ds = ldap_connect_bind();
# Search
$t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$p_username))";
$t_search_attrs = array( $t_ldap_uid_field, $p_field, 'dn' );
log_event( LOG_LDAP, "Searching for $t_search_filter" );
$t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs );
# Get results
$t_info = ldap_get_entries( $t_ds, $t_sr );
# Free results / unbind
log_event( LOG_LDAP, "Unbinding from LDAP server" );
ldap_free_result( $t_sr );
ldap_unbind( $t_ds );
# If no matches, return null.
if ( count( $t_info ) == 0 ) {
log_event( LOG_LDAP, "No matches found." );
return null;
}
$t_value = $t_info[0][$p_field][0];
log_event( LOG_LDAP, "Found value '{$t_value}' for field '{$p_field}'." );
return $t_value;
}
/**
* Attempt to authenticate the user against the LDAP directory
* return true on successful authentication, false otherwise
* @param int $p_user_id
* @param string $p_password
* @return bool
*/
function ldap_authenticate( $p_user_id, $p_password ) {
# if password is empty and ldap allows anonymous login, then
# the user will be able to login, hence, we need to check
# for this special case.
if( is_blank( $p_password ) ) {
return false;
}
if ( ldap_simulation_is_enabled() ) {
return ldap_simulation_authenticate( $p_user_id, $p_password );
}
$t_ldap_organization = config_get( 'ldap_organization' );
$t_ldap_root_dn = config_get( 'ldap_root_dn' );
$t_username = user_get_field( $p_user_id, 'username' );
$t_ldap_uid_field = config_get( 'ldap_uid_field', 'uid' );
$t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$t_username))";
$t_search_attrs = array(
$t_ldap_uid_field,
'dn',
);
$t_ds = ldap_connect_bind();
# Search for the user id
log_event( LOG_LDAP, "Searching for $t_search_filter" );
$t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs );
$t_info = ldap_get_entries( $t_ds, $t_sr );
$t_authenticated = false;
if( $t_info ) {
# Try to authenticate to each until we get a match
for( $i = 0;$i < $t_info['count'];$i++ ) {
$t_dn = $t_info[$i]['dn'];
# Attempt to bind with the DN and password
if( @ldap_bind( $t_ds, $t_dn, $p_password ) ) {
$t_authenticated = true;
break;
# Don't need to go any further
}
}
}
ldap_free_result( $t_sr );
ldap_unbind( $t_ds );
return $t_authenticated;
}
/**
* Checks if the LDAP simulation mode is enabled.
*
* @return bool true if enabled, false otherwise.
*/
function ldap_simulation_is_enabled() {
$t_filename = config_get( 'ldap_simulation_file_path' );
return !is_blank( $t_filename );
}
/**
* Gets a user from LDAP simulation mode given the username.
*
* @param string $p_username The user name.
* @return mixed an associate array with user information or null if not found.
*/
function ldap_simulation_get_user( $p_username ) {
$t_filename = config_get( 'ldap_simulation_file_path' );
$t_lines = file( $t_filename );
foreach ( $t_lines as $t_line ) {
$t_line = trim( $t_line, " \t\r\n" );
$t_row = explode( ',', $t_line );
if ( $t_row[0] != $p_username ) {
continue;
}
$t_user = array();
$t_user['username'] = $t_row[0];
$t_user['realname'] = $t_row[1];
$t_user['email'] = $t_row[2];
$t_user['password'] = $t_row[3];
return $t_user;
}
log_event( LOG_LDAP, "ldap_simulation_get_user: user '$p_username' not found." );
return null;
}
/**
* Given a username, gets the email address or empty address if user is not found.
*
* @param string $p_username The user name.
* @return The email address or blank if user is not found.
*/
function ldap_simulation_email_from_username( $p_username ) {
$t_user = ldap_simulation_get_user( $p_username );
if ( $t_user === null ) {
log_event( LOG_LDAP, "ldap_simulation_email_from_username: user '$p_username' not found." );
return '';
}
log_event( LOG_LDAP, "ldap_simulation_email_from_username: user '$p_username' has email '{$t_user['email']}'." );
return $t_user['email'];
}
/**
* Given a username, this methods gets the realname or empty string if not found.
*
* @param string $p_username The username.
* @return string The real name or an empty string if not found.
*/
function ldap_simulatiom_realname_from_username( $p_username ) {
$t_user = ldap_simulation_get_user( $p_username );
if ( $t_user === null ) {
log_event( LOG_LDAP, "ldap_simulatiom_realname_from_username: user '$p_username' not found." );
return '';
}
log_event( LOG_LDAP, "ldap_simulatiom_realname_from_username: user '$p_username' has email '{$t_user['realname']}'." );
return $t_user['realname'];
}
/**
* Authenticates the specified user id / password based on the simulation data.
*
* @param string $p_user_id The user id.
* @param string $p_password The password.
* @return bool true for authenticated, false otherwise.
*/
function ldap_simulation_authenticate( $p_user_id, $p_password ) {
$t_username = user_get_field( $p_user_id, 'username' );
$t_user = ldap_simulation_get_user( $t_username );
if ( $t_user === null ) {
log_event( LOG_LDAP, "ldap_simulation_authenticate: user '$t_username' not found." );
return false;
}
if ( $t_user['password'] != $p_password ) {
log_event( LOG_LDAP, "ldap_simulation_authenticate: expected password '{$t_user['password']}' and got '$p_password'." );
return false;
}
log_event( LOG_LDAP, "ldap_simulation_authenticate: authentication successful for user '$t_username'." );
return true;
}