1 | /* |
---|
2 | * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. |
---|
3 | * All rights reserved. |
---|
4 | * |
---|
5 | * By using this file, you agree to the terms and conditions set |
---|
6 | * forth in the LICENSE file which can be found at the top level of |
---|
7 | * the sendmail distribution. |
---|
8 | */ |
---|
9 | |
---|
10 | #include <sm/gen.h> |
---|
11 | SM_RCSID("@(#)$Id: ldap.c,v 1.1.1.1 2003-04-08 15:08:01 zacheiss Exp $") |
---|
12 | |
---|
13 | #if LDAPMAP |
---|
14 | # include <sys/types.h> |
---|
15 | # include <errno.h> |
---|
16 | # include <setjmp.h> |
---|
17 | # include <stdlib.h> |
---|
18 | # include <unistd.h> |
---|
19 | |
---|
20 | # include <sm/bitops.h> |
---|
21 | # include <sm/clock.h> |
---|
22 | # include <sm/conf.h> |
---|
23 | # include <sm/debug.h> |
---|
24 | # include <sm/errstring.h> |
---|
25 | # include <sm/ldap.h> |
---|
26 | # include <sm/string.h> |
---|
27 | # ifdef EX_OK |
---|
28 | # undef EX_OK /* for SVr4.2 SMP */ |
---|
29 | # endif /* EX_OK */ |
---|
30 | # include <sm/sysexits.h> |
---|
31 | |
---|
32 | SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", |
---|
33 | "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); |
---|
34 | |
---|
35 | static void ldaptimeout __P((int)); |
---|
36 | |
---|
37 | /* |
---|
38 | ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT |
---|
39 | ** |
---|
40 | ** Parameters: |
---|
41 | ** lmap -- pointer to SM_LDAP_STRUCT to clear |
---|
42 | ** |
---|
43 | ** Returns: |
---|
44 | ** None. |
---|
45 | ** |
---|
46 | */ |
---|
47 | |
---|
48 | void |
---|
49 | sm_ldap_clear(lmap) |
---|
50 | SM_LDAP_STRUCT *lmap; |
---|
51 | { |
---|
52 | if (lmap == NULL) |
---|
53 | return; |
---|
54 | |
---|
55 | lmap->ldap_target = NULL; |
---|
56 | lmap->ldap_port = LDAP_PORT; |
---|
57 | #if _FFR_LDAP_URI |
---|
58 | lmap->ldap_uri = false; |
---|
59 | #endif /* _FFR_LDAP_URI */ |
---|
60 | # if _FFR_LDAP_SETVERSION |
---|
61 | lmap->ldap_version = 0; |
---|
62 | # endif /* _FFR_LDAP_SETVERSION */ |
---|
63 | lmap->ldap_deref = LDAP_DEREF_NEVER; |
---|
64 | lmap->ldap_timelimit = LDAP_NO_LIMIT; |
---|
65 | lmap->ldap_sizelimit = LDAP_NO_LIMIT; |
---|
66 | # ifdef LDAP_REFERRALS |
---|
67 | lmap->ldap_options = LDAP_OPT_REFERRALS; |
---|
68 | # else /* LDAP_REFERRALS */ |
---|
69 | lmap->ldap_options = 0; |
---|
70 | # endif /* LDAP_REFERRALS */ |
---|
71 | lmap->ldap_attrsep = '\0'; |
---|
72 | lmap->ldap_binddn = NULL; |
---|
73 | lmap->ldap_secret = NULL; |
---|
74 | lmap->ldap_method = LDAP_AUTH_SIMPLE; |
---|
75 | lmap->ldap_base = NULL; |
---|
76 | lmap->ldap_scope = LDAP_SCOPE_SUBTREE; |
---|
77 | lmap->ldap_attrsonly = LDAPMAP_FALSE; |
---|
78 | lmap->ldap_timeout.tv_sec = 0; |
---|
79 | lmap->ldap_timeout.tv_usec = 0; |
---|
80 | lmap->ldap_ld = NULL; |
---|
81 | lmap->ldap_filter = NULL; |
---|
82 | lmap->ldap_attr[0] = NULL; |
---|
83 | #if _FFR_LDAP_RECURSION |
---|
84 | lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; |
---|
85 | lmap->ldap_attr_needobjclass[0] = NULL; |
---|
86 | #endif /* _FFR_LDAP_RECURSION */ |
---|
87 | lmap->ldap_res = NULL; |
---|
88 | lmap->ldap_next = NULL; |
---|
89 | lmap->ldap_pid = 0; |
---|
90 | } |
---|
91 | |
---|
92 | /* |
---|
93 | ** SM_LDAP_START -- actually connect to an LDAP server |
---|
94 | ** |
---|
95 | ** Parameters: |
---|
96 | ** name -- name of map for debug output. |
---|
97 | ** lmap -- the LDAP map being opened. |
---|
98 | ** |
---|
99 | ** Returns: |
---|
100 | ** true if connection is successful, false otherwise. |
---|
101 | ** |
---|
102 | ** Side Effects: |
---|
103 | ** Populates lmap->ldap_ld. |
---|
104 | */ |
---|
105 | |
---|
106 | static jmp_buf LDAPTimeout; |
---|
107 | |
---|
108 | #define SM_LDAP_SETTIMEOUT(to) \ |
---|
109 | do \ |
---|
110 | { \ |
---|
111 | if (to != 0) \ |
---|
112 | { \ |
---|
113 | if (setjmp(LDAPTimeout) != 0) \ |
---|
114 | { \ |
---|
115 | errno = ETIMEDOUT; \ |
---|
116 | return false; \ |
---|
117 | } \ |
---|
118 | ev = sm_setevent(to, ldaptimeout, 0); \ |
---|
119 | } \ |
---|
120 | } while (0) |
---|
121 | |
---|
122 | #define SM_LDAP_CLEARTIMEOUT() \ |
---|
123 | do \ |
---|
124 | { \ |
---|
125 | if (ev != NULL) \ |
---|
126 | sm_clrevent(ev); \ |
---|
127 | } while (0) |
---|
128 | |
---|
129 | bool |
---|
130 | sm_ldap_start(name, lmap) |
---|
131 | char *name; |
---|
132 | SM_LDAP_STRUCT *lmap; |
---|
133 | { |
---|
134 | int bind_result; |
---|
135 | int save_errno; |
---|
136 | SM_EVENT *ev = NULL; |
---|
137 | LDAP *ld; |
---|
138 | |
---|
139 | if (sm_debug_active(&SmLDAPTrace, 2)) |
---|
140 | sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); |
---|
141 | |
---|
142 | if (sm_debug_active(&SmLDAPTrace, 9)) |
---|
143 | sm_dprintf("ldapmap_start(%s, %d)\n", |
---|
144 | lmap->ldap_target == NULL ? "localhost" : lmap->ldap_target, |
---|
145 | lmap->ldap_port); |
---|
146 | |
---|
147 | # if USE_LDAP_INIT |
---|
148 | # if _FFR_LDAP_URI |
---|
149 | if (lmap->ldap_uri) |
---|
150 | errno = ldap_initialize(&ld, lmap->ldap_target); |
---|
151 | else |
---|
152 | # endif /* _FFR_LDAP_URI */ |
---|
153 | ld = ldap_init(lmap->ldap_target, lmap->ldap_port); |
---|
154 | save_errno = errno; |
---|
155 | # else /* USE_LDAP_INIT */ |
---|
156 | /* |
---|
157 | ** If using ldap_open(), the actual connection to the server |
---|
158 | ** happens now so we need the timeout here. For ldap_init(), |
---|
159 | ** the connection happens at bind time. |
---|
160 | */ |
---|
161 | |
---|
162 | SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); |
---|
163 | ld = ldap_open(lmap->ldap_target, lmap->ldap_port); |
---|
164 | save_errno = errno; |
---|
165 | |
---|
166 | /* clear the event if it has not sprung */ |
---|
167 | SM_LDAP_CLEARTIMEOUT(); |
---|
168 | # endif /* USE_LDAP_INIT */ |
---|
169 | |
---|
170 | errno = save_errno; |
---|
171 | if (ld == NULL) |
---|
172 | return false; |
---|
173 | |
---|
174 | sm_ldap_setopts(ld, lmap); |
---|
175 | |
---|
176 | # if USE_LDAP_INIT |
---|
177 | /* |
---|
178 | ** If using ldap_init(), the actual connection to the server |
---|
179 | ** happens at ldap_bind_s() so we need the timeout here. |
---|
180 | */ |
---|
181 | |
---|
182 | SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); |
---|
183 | # endif /* USE_LDAP_INIT */ |
---|
184 | |
---|
185 | # ifdef LDAP_AUTH_KRBV4 |
---|
186 | if (lmap->ldap_method == LDAP_AUTH_KRBV4 && |
---|
187 | lmap->ldap_secret != NULL) |
---|
188 | { |
---|
189 | /* |
---|
190 | ** Need to put ticket in environment here instead of |
---|
191 | ** during parseargs as there may be different tickets |
---|
192 | ** for different LDAP connections. |
---|
193 | */ |
---|
194 | |
---|
195 | (void) putenv(lmap->ldap_secret); |
---|
196 | } |
---|
197 | # endif /* LDAP_AUTH_KRBV4 */ |
---|
198 | |
---|
199 | bind_result = ldap_bind_s(ld, lmap->ldap_binddn, |
---|
200 | lmap->ldap_secret, lmap->ldap_method); |
---|
201 | |
---|
202 | # if USE_LDAP_INIT |
---|
203 | /* clear the event if it has not sprung */ |
---|
204 | SM_LDAP_CLEARTIMEOUT(); |
---|
205 | # endif /* USE_LDAP_INIT */ |
---|
206 | |
---|
207 | if (bind_result != LDAP_SUCCESS) |
---|
208 | { |
---|
209 | errno = bind_result + E_LDAPBASE; |
---|
210 | return false; |
---|
211 | } |
---|
212 | |
---|
213 | /* Save PID to make sure only this PID closes the LDAP connection */ |
---|
214 | lmap->ldap_pid = getpid(); |
---|
215 | lmap->ldap_ld = ld; |
---|
216 | return true; |
---|
217 | } |
---|
218 | |
---|
219 | /* ARGSUSED */ |
---|
220 | static void |
---|
221 | ldaptimeout(unused) |
---|
222 | int unused; |
---|
223 | { |
---|
224 | /* |
---|
225 | ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD |
---|
226 | ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE |
---|
227 | ** DOING. |
---|
228 | */ |
---|
229 | |
---|
230 | errno = ETIMEDOUT; |
---|
231 | longjmp(LDAPTimeout, 1); |
---|
232 | } |
---|
233 | |
---|
234 | /* |
---|
235 | ** SM_LDAP_SEARCH -- iniate LDAP search |
---|
236 | ** |
---|
237 | ** Initiate an LDAP search, return the msgid. |
---|
238 | ** The calling function must collect the results. |
---|
239 | ** |
---|
240 | ** Parameters: |
---|
241 | ** lmap -- LDAP map information |
---|
242 | ** key -- key to substitute in LDAP filter |
---|
243 | ** |
---|
244 | ** Returns: |
---|
245 | ** -1 on failure, msgid on success |
---|
246 | ** |
---|
247 | */ |
---|
248 | |
---|
249 | int |
---|
250 | sm_ldap_search(lmap, key) |
---|
251 | SM_LDAP_STRUCT *lmap; |
---|
252 | char *key; |
---|
253 | { |
---|
254 | int msgid; |
---|
255 | char *fp, *p, *q; |
---|
256 | char filter[LDAPMAP_MAX_FILTER + 1]; |
---|
257 | |
---|
258 | /* substitute key into filter, perhaps multiple times */ |
---|
259 | memset(filter, '\0', sizeof filter); |
---|
260 | fp = filter; |
---|
261 | p = lmap->ldap_filter; |
---|
262 | while ((q = strchr(p, '%')) != NULL) |
---|
263 | { |
---|
264 | if (q[1] == 's') |
---|
265 | { |
---|
266 | (void) sm_snprintf(fp, SPACELEFT(filter, fp), |
---|
267 | "%.*s%s", (int) (q - p), p, key); |
---|
268 | fp += strlen(fp); |
---|
269 | p = q + 2; |
---|
270 | } |
---|
271 | else if (q[1] == '0') |
---|
272 | { |
---|
273 | char *k = key; |
---|
274 | |
---|
275 | (void) sm_snprintf(fp, SPACELEFT(filter, fp), |
---|
276 | "%.*s", (int) (q - p), p); |
---|
277 | fp += strlen(fp); |
---|
278 | p = q + 2; |
---|
279 | |
---|
280 | /* Properly escape LDAP special characters */ |
---|
281 | while (SPACELEFT(filter, fp) > 0 && |
---|
282 | *k != '\0') |
---|
283 | { |
---|
284 | if (*k == '*' || *k == '(' || |
---|
285 | *k == ')' || *k == '\\') |
---|
286 | { |
---|
287 | (void) sm_strlcat(fp, |
---|
288 | (*k == '*' ? "\\2A" : |
---|
289 | (*k == '(' ? "\\28" : |
---|
290 | (*k == ')' ? "\\29" : |
---|
291 | (*k == '\\' ? "\\5C" : |
---|
292 | "\00")))), |
---|
293 | SPACELEFT(filter, fp)); |
---|
294 | fp += strlen(fp); |
---|
295 | k++; |
---|
296 | } |
---|
297 | else |
---|
298 | *fp++ = *k++; |
---|
299 | } |
---|
300 | } |
---|
301 | else |
---|
302 | { |
---|
303 | (void) sm_snprintf(fp, SPACELEFT(filter, fp), |
---|
304 | "%.*s", (int) (q - p + 1), p); |
---|
305 | p = q + (q[1] == '%' ? 2 : 1); |
---|
306 | fp += strlen(fp); |
---|
307 | } |
---|
308 | } |
---|
309 | (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); |
---|
310 | if (sm_debug_active(&SmLDAPTrace, 20)) |
---|
311 | sm_dprintf("ldap search filter=%s\n", filter); |
---|
312 | |
---|
313 | lmap->ldap_res = NULL; |
---|
314 | msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, |
---|
315 | lmap->ldap_scope, filter, |
---|
316 | (lmap->ldap_attr[0] == NULL ? NULL : |
---|
317 | lmap->ldap_attr), |
---|
318 | lmap->ldap_attrsonly); |
---|
319 | return msgid; |
---|
320 | } |
---|
321 | |
---|
322 | # if _FFR_LDAP_RECURSION |
---|
323 | /* |
---|
324 | ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a |
---|
325 | ** particular objectClass |
---|
326 | ** |
---|
327 | ** Parameters: |
---|
328 | ** lmap -- pointer to SM_LDAP_STRUCT in use |
---|
329 | ** entry -- current LDAP entry struct |
---|
330 | ** ocvalue -- particular objectclass in question. |
---|
331 | ** may be of form (fee|foo|fum) meaning |
---|
332 | ** any entry can be part of either fee, |
---|
333 | ** foo or fum objectclass |
---|
334 | ** |
---|
335 | ** Returns: |
---|
336 | ** true if item has that objectClass |
---|
337 | */ |
---|
338 | |
---|
339 | static bool |
---|
340 | sm_ldap_has_objectclass(lmap, entry, ocvalue) |
---|
341 | SM_LDAP_STRUCT *lmap; |
---|
342 | LDAPMessage *entry; |
---|
343 | char *ocvalue; |
---|
344 | { |
---|
345 | char **vals = NULL; |
---|
346 | int i; |
---|
347 | |
---|
348 | if (ocvalue == NULL) |
---|
349 | return false; |
---|
350 | |
---|
351 | vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); |
---|
352 | if (vals == NULL) |
---|
353 | return false; |
---|
354 | |
---|
355 | for (i = 0; vals[i] != NULL; i++) |
---|
356 | { |
---|
357 | char *p; |
---|
358 | char *q; |
---|
359 | |
---|
360 | p = q = ocvalue; |
---|
361 | while (*p != '\0') |
---|
362 | { |
---|
363 | while (*p != '\0' && *p != '|') |
---|
364 | p++; |
---|
365 | |
---|
366 | if ((p - q) == strlen(vals[i]) && |
---|
367 | sm_strncasecmp(vals[i], q, p - q) == 0) |
---|
368 | { |
---|
369 | ldap_value_free(vals); |
---|
370 | return true; |
---|
371 | } |
---|
372 | |
---|
373 | while (*p == '|') |
---|
374 | p++; |
---|
375 | q = p; |
---|
376 | } |
---|
377 | } |
---|
378 | |
---|
379 | ldap_value_free(vals); |
---|
380 | return false; |
---|
381 | } |
---|
382 | |
---|
383 | /* |
---|
384 | ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result |
---|
385 | ** |
---|
386 | ** Parameters: |
---|
387 | ** lmap -- pointer to SM_LDAP_STRUCT in use |
---|
388 | ** msgid -- msgid returned by sm_ldap_search() |
---|
389 | ** flags -- flags for the lookup |
---|
390 | ** delim -- delimiter for result concatenation |
---|
391 | ** rpool -- memory pool for storage |
---|
392 | ** result -- return string |
---|
393 | ** recurse -- recursion list |
---|
394 | ** |
---|
395 | ** Returns: |
---|
396 | ** status (sysexit) |
---|
397 | */ |
---|
398 | |
---|
399 | # define SM_LDAP_ERROR_CLEANUP() \ |
---|
400 | { \ |
---|
401 | if (lmap->ldap_res != NULL) \ |
---|
402 | { \ |
---|
403 | ldap_msgfree(lmap->ldap_res); \ |
---|
404 | lmap->ldap_res = NULL; \ |
---|
405 | } \ |
---|
406 | (void) ldap_abandon(lmap->ldap_ld, msgid); \ |
---|
407 | } |
---|
408 | |
---|
409 | static SM_LDAP_RECURSE_ENTRY * |
---|
410 | sm_ldap_add_recurse(top, item, type, rpool) |
---|
411 | SM_LDAP_RECURSE_LIST **top; |
---|
412 | char *item; |
---|
413 | int type; |
---|
414 | SM_RPOOL_T *rpool; |
---|
415 | { |
---|
416 | int n; |
---|
417 | int m; |
---|
418 | int p; |
---|
419 | int insertat; |
---|
420 | int moveb; |
---|
421 | int oldsizeb; |
---|
422 | int rc; |
---|
423 | SM_LDAP_RECURSE_ENTRY *newe; |
---|
424 | SM_LDAP_RECURSE_ENTRY **olddata; |
---|
425 | |
---|
426 | /* |
---|
427 | ** This code will maintain a list of |
---|
428 | ** SM_LDAP_RECURSE_ENTRY structures |
---|
429 | ** in ascending order. |
---|
430 | */ |
---|
431 | |
---|
432 | if (*top == NULL) |
---|
433 | { |
---|
434 | /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ |
---|
435 | *top = sm_rpool_malloc_x(rpool, sizeof **top); |
---|
436 | (*top)->lr_cnt = 0; |
---|
437 | (*top)->lr_size = 0; |
---|
438 | (*top)->lr_data = NULL; |
---|
439 | } |
---|
440 | |
---|
441 | if ((*top)->lr_cnt >= (*top)->lr_size) |
---|
442 | { |
---|
443 | /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ |
---|
444 | olddata = (*top)->lr_data; |
---|
445 | if ((*top)->lr_size == 0) |
---|
446 | { |
---|
447 | oldsizeb = 0; |
---|
448 | (*top)->lr_size = 256; |
---|
449 | } |
---|
450 | else |
---|
451 | { |
---|
452 | oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data); |
---|
453 | (*top)->lr_size *= 2; |
---|
454 | } |
---|
455 | (*top)->lr_data = sm_rpool_malloc_x(rpool, |
---|
456 | (*top)->lr_size * sizeof *((*top)->lr_data)); |
---|
457 | if (oldsizeb > 0) |
---|
458 | memcpy((*top)->lr_data, olddata, oldsizeb); |
---|
459 | } |
---|
460 | |
---|
461 | /* |
---|
462 | ** Binary search/insert item:type into list. |
---|
463 | ** Return current entry pointer if already exists. |
---|
464 | */ |
---|
465 | |
---|
466 | n = 0; |
---|
467 | m = (*top)->lr_cnt - 1; |
---|
468 | if (m < 0) |
---|
469 | insertat = 0; |
---|
470 | else |
---|
471 | insertat = -1; |
---|
472 | |
---|
473 | while (insertat == -1) |
---|
474 | { |
---|
475 | p = (m + n) / 2; |
---|
476 | |
---|
477 | rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search); |
---|
478 | if (rc == 0) |
---|
479 | rc = type - (*top)->lr_data[p]->lr_type; |
---|
480 | |
---|
481 | if (rc < 0) |
---|
482 | m = p - 1; |
---|
483 | else if (rc > 0) |
---|
484 | n = p + 1; |
---|
485 | else |
---|
486 | return (*top)->lr_data[p]; |
---|
487 | |
---|
488 | if (m == -1) |
---|
489 | insertat = 0; |
---|
490 | else if (n >= (*top)->lr_cnt) |
---|
491 | insertat = (*top)->lr_cnt; |
---|
492 | else if (m < n) |
---|
493 | insertat = m + 1; |
---|
494 | } |
---|
495 | |
---|
496 | /* |
---|
497 | ** Not found in list, make room |
---|
498 | ** at insert point and add it. |
---|
499 | */ |
---|
500 | |
---|
501 | newe = sm_rpool_malloc_x(rpool, sizeof *newe); |
---|
502 | if (newe != NULL) |
---|
503 | { |
---|
504 | moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data); |
---|
505 | if (moveb > 0) |
---|
506 | memmove(&((*top)->lr_data[insertat + 1]), |
---|
507 | &((*top)->lr_data[insertat]), |
---|
508 | moveb); |
---|
509 | |
---|
510 | newe->lr_search = sm_rpool_strdup_x(rpool, item); |
---|
511 | newe->lr_type = type; |
---|
512 | newe->lr_done = false; |
---|
513 | |
---|
514 | ((*top)->lr_data)[insertat] = newe; |
---|
515 | (*top)->lr_cnt++; |
---|
516 | } |
---|
517 | return newe; |
---|
518 | } |
---|
519 | |
---|
520 | int |
---|
521 | sm_ldap_results(lmap, msgid, flags, delim, rpool, result, |
---|
522 | resultln, resultsz, recurse) |
---|
523 | SM_LDAP_STRUCT *lmap; |
---|
524 | int msgid; |
---|
525 | int flags; |
---|
526 | int delim; |
---|
527 | SM_RPOOL_T *rpool; |
---|
528 | char **result; |
---|
529 | int *resultln; |
---|
530 | int *resultsz; |
---|
531 | SM_LDAP_RECURSE_LIST *recurse; |
---|
532 | { |
---|
533 | bool toplevel; |
---|
534 | int i; |
---|
535 | int statp; |
---|
536 | int vsize; |
---|
537 | int ret; |
---|
538 | int save_errno; |
---|
539 | char *p; |
---|
540 | SM_LDAP_RECURSE_ENTRY *rl; |
---|
541 | |
---|
542 | /* Are we the top top level of the search? */ |
---|
543 | toplevel = (recurse == NULL); |
---|
544 | |
---|
545 | /* Get results */ |
---|
546 | statp = EX_NOTFOUND; |
---|
547 | while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, |
---|
548 | (lmap->ldap_timeout.tv_sec == 0 ? NULL : |
---|
549 | &(lmap->ldap_timeout)), |
---|
550 | &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) |
---|
551 | { |
---|
552 | LDAPMessage *entry; |
---|
553 | |
---|
554 | /* If we don't want multiple values and we have one, break */ |
---|
555 | if ((char) delim == '\0' && *result != NULL) |
---|
556 | break; |
---|
557 | |
---|
558 | /* Cycle through all entries */ |
---|
559 | for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); |
---|
560 | entry != NULL; |
---|
561 | entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) |
---|
562 | { |
---|
563 | BerElement *ber; |
---|
564 | char *attr; |
---|
565 | char **vals = NULL; |
---|
566 | char *dn; |
---|
567 | |
---|
568 | /* |
---|
569 | ** If matching only and found an entry, |
---|
570 | ** no need to spin through attributes |
---|
571 | */ |
---|
572 | |
---|
573 | if (statp == EX_OK && |
---|
574 | bitset(SM_LDAP_MATCHONLY, flags)) |
---|
575 | continue; |
---|
576 | |
---|
577 | /* record completed DN's to prevent loops */ |
---|
578 | dn = ldap_get_dn(lmap->ldap_ld, entry); |
---|
579 | if (dn == NULL) |
---|
580 | { |
---|
581 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
582 | save_errno += E_LDAPBASE; |
---|
583 | SM_LDAP_ERROR_CLEANUP(); |
---|
584 | errno = save_errno; |
---|
585 | return EX_OSERR; |
---|
586 | } |
---|
587 | |
---|
588 | rl = sm_ldap_add_recurse(&recurse, dn, |
---|
589 | SM_LDAP_ATTR_DN, |
---|
590 | rpool); |
---|
591 | |
---|
592 | if (rl == NULL) |
---|
593 | { |
---|
594 | ldap_memfree(dn); |
---|
595 | SM_LDAP_ERROR_CLEANUP(); |
---|
596 | errno = ENOMEM; |
---|
597 | return EX_OSERR; |
---|
598 | } |
---|
599 | else if (rl->lr_done) |
---|
600 | { |
---|
601 | /* already on list, skip it */ |
---|
602 | ldap_memfree(dn); |
---|
603 | continue; |
---|
604 | } |
---|
605 | ldap_memfree(dn); |
---|
606 | |
---|
607 | # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) |
---|
608 | /* |
---|
609 | ** Reset value to prevent lingering |
---|
610 | ** LDAP_DECODING_ERROR due to |
---|
611 | ** OpenLDAP 1.X's hack (see below) |
---|
612 | */ |
---|
613 | |
---|
614 | lmap->ldap_ld->ld_errno = LDAP_SUCCESS; |
---|
615 | # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ |
---|
616 | |
---|
617 | for (attr = ldap_first_attribute(lmap->ldap_ld, entry, |
---|
618 | &ber); |
---|
619 | attr != NULL; |
---|
620 | attr = ldap_next_attribute(lmap->ldap_ld, entry, |
---|
621 | ber)) |
---|
622 | { |
---|
623 | char *tmp, *vp_tmp; |
---|
624 | int type; |
---|
625 | char *needobjclass = NULL; |
---|
626 | |
---|
627 | type = SM_LDAP_ATTR_NONE; |
---|
628 | for (i = 0; lmap->ldap_attr[i] != NULL; i++) |
---|
629 | { |
---|
630 | if (sm_strcasecmp(lmap->ldap_attr[i], |
---|
631 | attr) == 0) |
---|
632 | { |
---|
633 | type = lmap->ldap_attr_type[i]; |
---|
634 | needobjclass = lmap->ldap_attr_needobjclass[i]; |
---|
635 | break; |
---|
636 | } |
---|
637 | } |
---|
638 | |
---|
639 | if (bitset(SM_LDAP_USE_ALLATTR, flags) && |
---|
640 | type == SM_LDAP_ATTR_NONE) |
---|
641 | { |
---|
642 | /* URL lookups specify attrs to use */ |
---|
643 | type = SM_LDAP_ATTR_NORMAL; |
---|
644 | needobjclass = NULL; |
---|
645 | } |
---|
646 | |
---|
647 | if (type == SM_LDAP_ATTR_NONE) |
---|
648 | { |
---|
649 | /* attribute not requested */ |
---|
650 | ldap_memfree(attr); |
---|
651 | SM_LDAP_ERROR_CLEANUP(); |
---|
652 | errno = EFAULT; |
---|
653 | return EX_SOFTWARE; |
---|
654 | } |
---|
655 | |
---|
656 | /* |
---|
657 | ** For recursion on a particular attribute, |
---|
658 | ** we may need to see if this entry is |
---|
659 | ** part of a particular objectclass. |
---|
660 | ** Also, ignore objectClass attribute. |
---|
661 | ** Otherwise we just ignore this attribute. |
---|
662 | */ |
---|
663 | |
---|
664 | if (type == SM_LDAP_ATTR_OBJCLASS || |
---|
665 | (needobjclass != NULL && |
---|
666 | !sm_ldap_has_objectclass(lmap, entry, |
---|
667 | needobjclass))) |
---|
668 | { |
---|
669 | ldap_memfree(attr); |
---|
670 | continue; |
---|
671 | } |
---|
672 | |
---|
673 | if (lmap->ldap_attrsonly == LDAPMAP_FALSE) |
---|
674 | { |
---|
675 | vals = ldap_get_values(lmap->ldap_ld, |
---|
676 | entry, |
---|
677 | attr); |
---|
678 | if (vals == NULL) |
---|
679 | { |
---|
680 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
681 | if (save_errno == LDAP_SUCCESS) |
---|
682 | { |
---|
683 | ldap_memfree(attr); |
---|
684 | continue; |
---|
685 | } |
---|
686 | |
---|
687 | /* Must be an error */ |
---|
688 | save_errno += E_LDAPBASE; |
---|
689 | ldap_memfree(attr); |
---|
690 | SM_LDAP_ERROR_CLEANUP(); |
---|
691 | errno = save_errno; |
---|
692 | return EX_TEMPFAIL; |
---|
693 | } |
---|
694 | } |
---|
695 | |
---|
696 | statp = EX_OK; |
---|
697 | |
---|
698 | # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) |
---|
699 | /* |
---|
700 | ** Reset value to prevent lingering |
---|
701 | ** LDAP_DECODING_ERROR due to |
---|
702 | ** OpenLDAP 1.X's hack (see below) |
---|
703 | */ |
---|
704 | |
---|
705 | lmap->ldap_ld->ld_errno = LDAP_SUCCESS; |
---|
706 | # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ |
---|
707 | |
---|
708 | /* |
---|
709 | ** If matching only, |
---|
710 | ** no need to spin through entries |
---|
711 | */ |
---|
712 | |
---|
713 | if (bitset(SM_LDAP_MATCHONLY, flags)) |
---|
714 | { |
---|
715 | if (lmap->ldap_attrsonly == LDAPMAP_FALSE) |
---|
716 | ldap_value_free(vals); |
---|
717 | ldap_memfree(attr); |
---|
718 | continue; |
---|
719 | } |
---|
720 | |
---|
721 | /* |
---|
722 | ** If we don't want multiple values, |
---|
723 | ** return first found. |
---|
724 | */ |
---|
725 | |
---|
726 | if ((char) delim == '\0') |
---|
727 | { |
---|
728 | if (*result != NULL) |
---|
729 | { |
---|
730 | /* already have a value */ |
---|
731 | break; |
---|
732 | } |
---|
733 | |
---|
734 | if (bitset(SM_LDAP_SINGLEMATCH, |
---|
735 | flags) && |
---|
736 | *result != NULL) |
---|
737 | { |
---|
738 | /* only wanted one match */ |
---|
739 | SM_LDAP_ERROR_CLEANUP(); |
---|
740 | errno = ENOENT; |
---|
741 | return EX_NOTFOUND; |
---|
742 | } |
---|
743 | |
---|
744 | if (lmap->ldap_attrsonly == LDAPMAP_TRUE) |
---|
745 | { |
---|
746 | *result = sm_rpool_strdup_x(rpool, |
---|
747 | attr); |
---|
748 | ldap_memfree(attr); |
---|
749 | break; |
---|
750 | } |
---|
751 | |
---|
752 | if (vals[0] == NULL) |
---|
753 | { |
---|
754 | ldap_value_free(vals); |
---|
755 | ldap_memfree(attr); |
---|
756 | continue; |
---|
757 | } |
---|
758 | |
---|
759 | vsize = strlen(vals[0]) + 1; |
---|
760 | if (lmap->ldap_attrsep != '\0') |
---|
761 | vsize += strlen(attr) + 1; |
---|
762 | *result = sm_rpool_malloc_x(rpool, |
---|
763 | vsize); |
---|
764 | if (lmap->ldap_attrsep != '\0') |
---|
765 | sm_snprintf(*result, vsize, |
---|
766 | "%s%c%s", |
---|
767 | attr, |
---|
768 | lmap->ldap_attrsep, |
---|
769 | vals[0]); |
---|
770 | else |
---|
771 | sm_strlcpy(*result, vals[0], |
---|
772 | vsize); |
---|
773 | ldap_value_free(vals); |
---|
774 | ldap_memfree(attr); |
---|
775 | break; |
---|
776 | } |
---|
777 | |
---|
778 | /* attributes only */ |
---|
779 | if (lmap->ldap_attrsonly == LDAPMAP_TRUE) |
---|
780 | { |
---|
781 | if (*result == NULL) |
---|
782 | *result = sm_rpool_strdup_x(rpool, |
---|
783 | attr); |
---|
784 | else |
---|
785 | { |
---|
786 | if (bitset(SM_LDAP_SINGLEMATCH, |
---|
787 | flags) && |
---|
788 | *result != NULL) |
---|
789 | { |
---|
790 | /* only wanted one match */ |
---|
791 | SM_LDAP_ERROR_CLEANUP(); |
---|
792 | errno = ENOENT; |
---|
793 | return EX_NOTFOUND; |
---|
794 | } |
---|
795 | |
---|
796 | vsize = strlen(*result) + |
---|
797 | strlen(attr) + 2; |
---|
798 | tmp = sm_rpool_malloc_x(rpool, |
---|
799 | vsize); |
---|
800 | (void) sm_snprintf(tmp, |
---|
801 | vsize, "%s%c%s", |
---|
802 | *result, (char) delim, |
---|
803 | attr); |
---|
804 | *result = tmp; |
---|
805 | } |
---|
806 | ldap_memfree(attr); |
---|
807 | continue; |
---|
808 | } |
---|
809 | |
---|
810 | /* |
---|
811 | ** If there is more than one, munge then |
---|
812 | ** into a map_coldelim separated string. |
---|
813 | ** If we are recursing we may have an entry |
---|
814 | ** with no 'normal' values to put in the |
---|
815 | ** string. |
---|
816 | ** This is not an error. |
---|
817 | */ |
---|
818 | |
---|
819 | if (type == SM_LDAP_ATTR_NORMAL && |
---|
820 | bitset(SM_LDAP_SINGLEMATCH, flags) && |
---|
821 | *result != NULL) |
---|
822 | { |
---|
823 | /* only wanted one match */ |
---|
824 | SM_LDAP_ERROR_CLEANUP(); |
---|
825 | errno = ENOENT; |
---|
826 | return EX_NOTFOUND; |
---|
827 | } |
---|
828 | |
---|
829 | vsize = 0; |
---|
830 | for (i = 0; vals[i] != NULL; i++) |
---|
831 | { |
---|
832 | if (type == SM_LDAP_ATTR_DN || |
---|
833 | type == SM_LDAP_ATTR_FILTER || |
---|
834 | type == SM_LDAP_ATTR_URL) |
---|
835 | { |
---|
836 | /* add to recursion */ |
---|
837 | if (sm_ldap_add_recurse(&recurse, |
---|
838 | vals[i], |
---|
839 | type, |
---|
840 | rpool) == NULL) |
---|
841 | { |
---|
842 | SM_LDAP_ERROR_CLEANUP(); |
---|
843 | errno = ENOMEM; |
---|
844 | return EX_OSERR; |
---|
845 | } |
---|
846 | continue; |
---|
847 | } |
---|
848 | |
---|
849 | vsize += strlen(vals[i]) + 1; |
---|
850 | if (lmap->ldap_attrsep != '\0') |
---|
851 | vsize += strlen(attr) + 1; |
---|
852 | } |
---|
853 | |
---|
854 | /* |
---|
855 | ** Create/Append to string any normal |
---|
856 | ** attribute values. Otherwise, just free |
---|
857 | ** memory and move on to the next |
---|
858 | ** attribute in this entry. |
---|
859 | */ |
---|
860 | |
---|
861 | if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) |
---|
862 | { |
---|
863 | char *pe; |
---|
864 | |
---|
865 | /* Grow result string if needed */ |
---|
866 | if ((*resultln + vsize) >= *resultsz) |
---|
867 | { |
---|
868 | while ((*resultln + vsize) >= *resultsz) |
---|
869 | { |
---|
870 | if (*resultsz == 0) |
---|
871 | *resultsz = 1024; |
---|
872 | else |
---|
873 | *resultsz *= 2; |
---|
874 | } |
---|
875 | |
---|
876 | vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); |
---|
877 | *vp_tmp = '\0'; |
---|
878 | |
---|
879 | if (*result != NULL) |
---|
880 | sm_strlcpy(vp_tmp, |
---|
881 | *result, |
---|
882 | *resultsz); |
---|
883 | *result = vp_tmp; |
---|
884 | } |
---|
885 | |
---|
886 | p = *result + *resultln; |
---|
887 | pe = *result + *resultsz; |
---|
888 | |
---|
889 | for (i = 0; vals[i] != NULL; i++) |
---|
890 | { |
---|
891 | if (*resultln > 0 && |
---|
892 | p < pe) |
---|
893 | *p++ = (char) delim; |
---|
894 | |
---|
895 | if (lmap->ldap_attrsep != '\0') |
---|
896 | { |
---|
897 | p += sm_strlcpy(p, attr, |
---|
898 | pe - p); |
---|
899 | if (p < pe) |
---|
900 | *p++ = lmap->ldap_attrsep; |
---|
901 | } |
---|
902 | |
---|
903 | p += sm_strlcpy(p, vals[i], |
---|
904 | pe - p); |
---|
905 | *resultln = p - (*result); |
---|
906 | if (p >= pe) |
---|
907 | { |
---|
908 | /* Internal error: buffer too small for LDAP values */ |
---|
909 | SM_LDAP_ERROR_CLEANUP(); |
---|
910 | errno = ENOMEM; |
---|
911 | return EX_OSERR; |
---|
912 | } |
---|
913 | } |
---|
914 | } |
---|
915 | |
---|
916 | ldap_value_free(vals); |
---|
917 | ldap_memfree(attr); |
---|
918 | } |
---|
919 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
920 | |
---|
921 | /* |
---|
922 | ** We check save_errno != LDAP_DECODING_ERROR since |
---|
923 | ** OpenLDAP 1.X has a very ugly *undocumented* |
---|
924 | ** hack of returning this error code from |
---|
925 | ** ldap_next_attribute() if the library freed the |
---|
926 | ** ber attribute. See: |
---|
927 | ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html |
---|
928 | */ |
---|
929 | |
---|
930 | if (save_errno != LDAP_SUCCESS && |
---|
931 | save_errno != LDAP_DECODING_ERROR) |
---|
932 | { |
---|
933 | /* Must be an error */ |
---|
934 | save_errno += E_LDAPBASE; |
---|
935 | SM_LDAP_ERROR_CLEANUP(); |
---|
936 | errno = save_errno; |
---|
937 | return EX_TEMPFAIL; |
---|
938 | } |
---|
939 | |
---|
940 | /* mark this DN as done */ |
---|
941 | rl->lr_done = true; |
---|
942 | |
---|
943 | /* We don't want multiple values and we have one */ |
---|
944 | if ((char) delim == '\0' && *result != NULL) |
---|
945 | break; |
---|
946 | } |
---|
947 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
948 | if (save_errno != LDAP_SUCCESS && |
---|
949 | save_errno != LDAP_DECODING_ERROR) |
---|
950 | { |
---|
951 | /* Must be an error */ |
---|
952 | save_errno += E_LDAPBASE; |
---|
953 | SM_LDAP_ERROR_CLEANUP(); |
---|
954 | errno = save_errno; |
---|
955 | return EX_TEMPFAIL; |
---|
956 | } |
---|
957 | ldap_msgfree(lmap->ldap_res); |
---|
958 | lmap->ldap_res = NULL; |
---|
959 | } |
---|
960 | |
---|
961 | if (ret == 0) |
---|
962 | save_errno = ETIMEDOUT; |
---|
963 | else |
---|
964 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
965 | if (save_errno != LDAP_SUCCESS) |
---|
966 | { |
---|
967 | statp = EX_TEMPFAIL; |
---|
968 | if (ret != 0) |
---|
969 | { |
---|
970 | switch (save_errno) |
---|
971 | { |
---|
972 | #ifdef LDAP_SERVER_DOWN |
---|
973 | case LDAP_SERVER_DOWN: |
---|
974 | #endif /* LDAP_SERVER_DOWN */ |
---|
975 | case LDAP_TIMEOUT: |
---|
976 | case LDAP_UNAVAILABLE: |
---|
977 | |
---|
978 | /* |
---|
979 | ** server disappeared, |
---|
980 | ** try reopen on next search |
---|
981 | */ |
---|
982 | |
---|
983 | statp = EX_RESTART; |
---|
984 | break; |
---|
985 | } |
---|
986 | save_errno += E_LDAPBASE; |
---|
987 | } |
---|
988 | SM_LDAP_ERROR_CLEANUP(); |
---|
989 | errno = save_errno; |
---|
990 | return statp; |
---|
991 | } |
---|
992 | |
---|
993 | if (lmap->ldap_res != NULL) |
---|
994 | { |
---|
995 | ldap_msgfree(lmap->ldap_res); |
---|
996 | lmap->ldap_res = NULL; |
---|
997 | } |
---|
998 | |
---|
999 | if (toplevel) |
---|
1000 | { |
---|
1001 | int rlidx; |
---|
1002 | |
---|
1003 | /* |
---|
1004 | ** Spin through the built-up recurse list at the top |
---|
1005 | ** of the recursion. Since new items are added at the |
---|
1006 | ** end of the shared list, we actually only ever get |
---|
1007 | ** one level of recursion before things pop back to the |
---|
1008 | ** top. Any items added to the list during that recursion |
---|
1009 | ** will be expanded by the top level. |
---|
1010 | */ |
---|
1011 | |
---|
1012 | for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++) |
---|
1013 | { |
---|
1014 | int newflags; |
---|
1015 | int sid; |
---|
1016 | int status; |
---|
1017 | |
---|
1018 | rl = recurse->lr_data[rlidx]; |
---|
1019 | |
---|
1020 | newflags = flags; |
---|
1021 | if (rl->lr_done) |
---|
1022 | { |
---|
1023 | /* already expanded */ |
---|
1024 | continue; |
---|
1025 | } |
---|
1026 | |
---|
1027 | if (rl->lr_type == SM_LDAP_ATTR_DN) |
---|
1028 | { |
---|
1029 | /* do DN search */ |
---|
1030 | sid = ldap_search(lmap->ldap_ld, |
---|
1031 | rl->lr_search, |
---|
1032 | lmap->ldap_scope, |
---|
1033 | "(objectClass=*)", |
---|
1034 | (lmap->ldap_attr[0] == NULL ? |
---|
1035 | NULL : lmap->ldap_attr), |
---|
1036 | lmap->ldap_attrsonly); |
---|
1037 | } |
---|
1038 | else if (rl->lr_type == SM_LDAP_ATTR_FILTER) |
---|
1039 | { |
---|
1040 | /* do new search */ |
---|
1041 | sid = ldap_search(lmap->ldap_ld, |
---|
1042 | lmap->ldap_base, |
---|
1043 | lmap->ldap_scope, |
---|
1044 | rl->lr_search, |
---|
1045 | (lmap->ldap_attr[0] == NULL ? |
---|
1046 | NULL : lmap->ldap_attr), |
---|
1047 | lmap->ldap_attrsonly); |
---|
1048 | } |
---|
1049 | else if (rl->lr_type == SM_LDAP_ATTR_URL) |
---|
1050 | { |
---|
1051 | /* do new URL search */ |
---|
1052 | sid = ldap_url_search(lmap->ldap_ld, |
---|
1053 | rl->lr_search, |
---|
1054 | lmap->ldap_attrsonly); |
---|
1055 | newflags |= SM_LDAP_USE_ALLATTR; |
---|
1056 | } |
---|
1057 | else |
---|
1058 | { |
---|
1059 | /* unknown or illegal attribute type */ |
---|
1060 | errno = EFAULT; |
---|
1061 | return EX_SOFTWARE; |
---|
1062 | } |
---|
1063 | |
---|
1064 | /* Collect results */ |
---|
1065 | if (sid == -1) |
---|
1066 | { |
---|
1067 | save_errno = sm_ldap_geterrno(lmap->ldap_ld); |
---|
1068 | statp = EX_TEMPFAIL; |
---|
1069 | switch (save_errno) |
---|
1070 | { |
---|
1071 | #ifdef LDAP_SERVER_DOWN |
---|
1072 | case LDAP_SERVER_DOWN: |
---|
1073 | #endif /* LDAP_SERVER_DOWN */ |
---|
1074 | case LDAP_TIMEOUT: |
---|
1075 | case LDAP_UNAVAILABLE: |
---|
1076 | |
---|
1077 | /* |
---|
1078 | ** server disappeared, |
---|
1079 | ** try reopen on next search |
---|
1080 | */ |
---|
1081 | |
---|
1082 | statp = EX_RESTART; |
---|
1083 | break; |
---|
1084 | } |
---|
1085 | errno = save_errno + E_LDAPBASE; |
---|
1086 | return statp; |
---|
1087 | } |
---|
1088 | |
---|
1089 | status = sm_ldap_results(lmap, sid, newflags, delim, |
---|
1090 | rpool, result, resultln, |
---|
1091 | resultsz, recurse); |
---|
1092 | save_errno = errno; |
---|
1093 | if (status != EX_OK && status != EX_NOTFOUND) |
---|
1094 | { |
---|
1095 | errno = save_errno; |
---|
1096 | return status; |
---|
1097 | } |
---|
1098 | |
---|
1099 | /* Mark as done */ |
---|
1100 | rl->lr_done = true; |
---|
1101 | |
---|
1102 | /* Reset rlidx as new items may have been added */ |
---|
1103 | rlidx = -1; |
---|
1104 | } |
---|
1105 | } |
---|
1106 | return statp; |
---|
1107 | } |
---|
1108 | #endif /* _FFR_LDAP_RECURSION */ |
---|
1109 | |
---|
1110 | /* |
---|
1111 | ** SM_LDAP_CLOSE -- close LDAP connection |
---|
1112 | ** |
---|
1113 | ** Parameters: |
---|
1114 | ** lmap -- LDAP map information |
---|
1115 | ** |
---|
1116 | ** Returns: |
---|
1117 | ** None. |
---|
1118 | ** |
---|
1119 | */ |
---|
1120 | |
---|
1121 | void |
---|
1122 | sm_ldap_close(lmap) |
---|
1123 | SM_LDAP_STRUCT *lmap; |
---|
1124 | { |
---|
1125 | if (lmap->ldap_ld == NULL) |
---|
1126 | return; |
---|
1127 | |
---|
1128 | if (lmap->ldap_pid == getpid()) |
---|
1129 | ldap_unbind(lmap->ldap_ld); |
---|
1130 | lmap->ldap_ld = NULL; |
---|
1131 | lmap->ldap_pid = 0; |
---|
1132 | } |
---|
1133 | |
---|
1134 | /* |
---|
1135 | ** SM_LDAP_SETOPTS -- set LDAP options |
---|
1136 | ** |
---|
1137 | ** Parameters: |
---|
1138 | ** ld -- LDAP session handle |
---|
1139 | ** lmap -- LDAP map information |
---|
1140 | ** |
---|
1141 | ** Returns: |
---|
1142 | ** None. |
---|
1143 | ** |
---|
1144 | */ |
---|
1145 | |
---|
1146 | void |
---|
1147 | sm_ldap_setopts(ld, lmap) |
---|
1148 | LDAP *ld; |
---|
1149 | SM_LDAP_STRUCT *lmap; |
---|
1150 | { |
---|
1151 | # if USE_LDAP_SET_OPTION |
---|
1152 | # if _FFR_LDAP_SETVERSION |
---|
1153 | if (lmap->ldap_version != 0) |
---|
1154 | { |
---|
1155 | ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, |
---|
1156 | &lmap->ldap_version); |
---|
1157 | } |
---|
1158 | # endif /* _FFR_LDAP_SETVERSION */ |
---|
1159 | ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); |
---|
1160 | if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) |
---|
1161 | ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); |
---|
1162 | else |
---|
1163 | ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); |
---|
1164 | ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); |
---|
1165 | ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); |
---|
1166 | # ifdef LDAP_OPT_RESTART |
---|
1167 | ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); |
---|
1168 | # endif /* LDAP_OPT_RESTART */ |
---|
1169 | # else /* USE_LDAP_SET_OPTION */ |
---|
1170 | /* From here on in we can use ldap internal timelimits */ |
---|
1171 | ld->ld_deref = lmap->ldap_deref; |
---|
1172 | ld->ld_options = lmap->ldap_options; |
---|
1173 | ld->ld_sizelimit = lmap->ldap_sizelimit; |
---|
1174 | ld->ld_timelimit = lmap->ldap_timelimit; |
---|
1175 | # endif /* USE_LDAP_SET_OPTION */ |
---|
1176 | } |
---|
1177 | |
---|
1178 | /* |
---|
1179 | ** SM_LDAP_GETERRNO -- get ldap errno value |
---|
1180 | ** |
---|
1181 | ** Parameters: |
---|
1182 | ** ld -- LDAP session handle |
---|
1183 | ** |
---|
1184 | ** Returns: |
---|
1185 | ** LDAP errno. |
---|
1186 | ** |
---|
1187 | */ |
---|
1188 | |
---|
1189 | int |
---|
1190 | sm_ldap_geterrno(ld) |
---|
1191 | LDAP *ld; |
---|
1192 | { |
---|
1193 | int err = LDAP_SUCCESS; |
---|
1194 | |
---|
1195 | # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 |
---|
1196 | (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); |
---|
1197 | # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ |
---|
1198 | # ifdef LDAP_OPT_SIZELIMIT |
---|
1199 | err = ldap_get_lderrno(ld, NULL, NULL); |
---|
1200 | # else /* LDAP_OPT_SIZELIMIT */ |
---|
1201 | err = ld->ld_errno; |
---|
1202 | |
---|
1203 | /* |
---|
1204 | ** Reset value to prevent lingering LDAP_DECODING_ERROR due to |
---|
1205 | ** OpenLDAP 1.X's hack (see above) |
---|
1206 | */ |
---|
1207 | |
---|
1208 | ld->ld_errno = LDAP_SUCCESS; |
---|
1209 | # endif /* LDAP_OPT_SIZELIMIT */ |
---|
1210 | # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ |
---|
1211 | return err; |
---|
1212 | } |
---|
1213 | # endif /* LDAPMAP */ |
---|