2 * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
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.
11 SM_RCSID("@(#)$Id: ldap.c,v 1.44.2.3 2003/07/07 20:16:16 gshapiro Exp $")
14 # include <sys/types.h>
20 # include <sm/bitops.h>
21 # include <sm/clock.h>
23 # include <sm/debug.h>
24 # include <sm/errstring.h>
26 # include <sm/string.h>
28 # undef EX_OK /* for SVr4.2 SMP */
30 # include <sm/sysexits.h>
32 SM_DEBUG_T SmLDAPTrace
= SM_DEBUG_INITIALIZER("sm_trace_ldap",
33 "@(#)$Debug: sm_trace_ldap - trace LDAP operations $");
35 static void ldaptimeout
__P((int));
38 ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT
41 ** lmap -- pointer to SM_LDAP_STRUCT to clear
55 lmap
->ldap_target
= NULL
;
56 lmap
->ldap_port
= LDAP_PORT
;
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;
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
;
93 ** SM_LDAP_START -- actually connect to an LDAP server
96 ** name -- name of map for debug output.
97 ** lmap -- the LDAP map being opened.
100 ** true if connection is successful, false otherwise.
103 ** Populates lmap->ldap_ld.
106 static jmp_buf LDAPTimeout
;
108 #define SM_LDAP_SETTIMEOUT(to) \
113 if (setjmp(LDAPTimeout) != 0) \
118 ev = sm_setevent(to, ldaptimeout, 0); \
122 #define SM_LDAP_CLEARTIMEOUT() \
130 sm_ldap_start(name
, lmap
)
132 SM_LDAP_STRUCT
*lmap
;
139 if (sm_debug_active(&SmLDAPTrace
, 2))
140 sm_dprintf("ldapmap_start(%s)\n", name
== NULL
? "" : name
);
142 if (sm_debug_active(&SmLDAPTrace
, 9))
143 sm_dprintf("ldapmap_start(%s, %d)\n",
144 lmap
->ldap_target
== NULL
? "localhost" : lmap
->ldap_target
,
150 errno
= ldap_initialize(&ld
, lmap
->ldap_target
);
152 # endif /* _FFR_LDAP_URI */
153 ld
= ldap_init(lmap
->ldap_target
, lmap
->ldap_port
);
155 # else /* USE_LDAP_INIT */
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.
162 SM_LDAP_SETTIMEOUT(lmap
->ldap_timeout
.tv_sec
);
163 ld
= ldap_open(lmap
->ldap_target
, lmap
->ldap_port
);
166 /* clear the event if it has not sprung */
167 SM_LDAP_CLEARTIMEOUT();
168 # endif /* USE_LDAP_INIT */
174 sm_ldap_setopts(ld
, lmap
);
178 ** If using ldap_init(), the actual connection to the server
179 ** happens at ldap_bind_s() so we need the timeout here.
182 SM_LDAP_SETTIMEOUT(lmap
->ldap_timeout
.tv_sec
);
183 # endif /* USE_LDAP_INIT */
185 # ifdef LDAP_AUTH_KRBV4
186 if (lmap
->ldap_method
== LDAP_AUTH_KRBV4
&&
187 lmap
->ldap_secret
!= NULL
)
190 ** Need to put ticket in environment here instead of
191 ** during parseargs as there may be different tickets
192 ** for different LDAP connections.
195 (void) putenv(lmap
->ldap_secret
);
197 # endif /* LDAP_AUTH_KRBV4 */
199 bind_result
= ldap_bind_s(ld
, lmap
->ldap_binddn
,
200 lmap
->ldap_secret
, lmap
->ldap_method
);
203 /* clear the event if it has not sprung */
204 SM_LDAP_CLEARTIMEOUT();
205 # endif /* USE_LDAP_INIT */
207 if (bind_result
!= LDAP_SUCCESS
)
209 errno
= bind_result
+ E_LDAPBASE
;
213 /* Save PID to make sure only this PID closes the LDAP connection */
214 lmap
->ldap_pid
= getpid();
225 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
226 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
231 longjmp(LDAPTimeout
, 1);
235 ** SM_LDAP_SEARCH -- iniate LDAP search
237 ** Initiate an LDAP search, return the msgid.
238 ** The calling function must collect the results.
241 ** lmap -- LDAP map information
242 ** key -- key to substitute in LDAP filter
245 ** -1 on failure, msgid on success
250 sm_ldap_search(lmap
, key
)
251 SM_LDAP_STRUCT
*lmap
;
256 char filter
[LDAPMAP_MAX_FILTER
+ 1];
258 /* substitute key into filter, perhaps multiple times */
259 memset(filter
, '\0', sizeof filter
);
261 p
= lmap
->ldap_filter
;
262 while ((q
= strchr(p
, '%')) != NULL
)
266 (void) sm_snprintf(fp
, SPACELEFT(filter
, fp
),
267 "%.*s%s", (int) (q
- p
), p
, key
);
271 else if (q
[1] == '0')
275 (void) sm_snprintf(fp
, SPACELEFT(filter
, fp
),
276 "%.*s", (int) (q
- p
), p
);
280 /* Properly escape LDAP special characters */
281 while (SPACELEFT(filter
, fp
) > 0 &&
284 if (*k
== '*' || *k
== '(' ||
285 *k
== ')' || *k
== '\\')
287 (void) sm_strlcat(fp
,
288 (*k
== '*' ? "\\2A" :
289 (*k
== '(' ? "\\28" :
290 (*k
== ')' ? "\\29" :
291 (*k
== '\\' ? "\\5C" :
293 SPACELEFT(filter
, fp
));
303 (void) sm_snprintf(fp
, SPACELEFT(filter
, fp
),
304 "%.*s", (int) (q
- p
+ 1), p
);
305 p
= q
+ (q
[1] == '%' ? 2 : 1);
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
);
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
:
318 lmap
->ldap_attrsonly
);
322 # if _FFR_LDAP_RECURSION
324 ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a
325 ** particular objectClass
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
336 ** true if item has that objectClass
340 sm_ldap_has_objectclass(lmap
, entry
, ocvalue
)
341 SM_LDAP_STRUCT
*lmap
;
351 vals
= ldap_get_values(lmap
->ldap_ld
, entry
, "objectClass");
355 for (i
= 0; vals
[i
] != NULL
; i
++)
363 while (*p
!= '\0' && *p
!= '|')
366 if ((p
- q
) == strlen(vals
[i
]) &&
367 sm_strncasecmp(vals
[i
], q
, p
- q
) == 0)
369 ldap_value_free(vals
);
379 ldap_value_free(vals
);
384 ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result
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
399 # define SM_LDAP_ERROR_CLEANUP() \
401 if (lmap->ldap_res != NULL) \
403 ldap_msgfree(lmap->ldap_res); \
404 lmap->ldap_res = NULL; \
406 (void) ldap_abandon(lmap->ldap_ld, msgid); \
409 static SM_LDAP_RECURSE_ENTRY
*
410 sm_ldap_add_recurse(top
, item
, type
, rpool
)
411 SM_LDAP_RECURSE_LIST
**top
;
423 SM_LDAP_RECURSE_ENTRY
*newe
;
424 SM_LDAP_RECURSE_ENTRY
**olddata
;
427 ** This code will maintain a list of
428 ** SM_LDAP_RECURSE_ENTRY structures
429 ** in ascending order.
434 /* Allocate an initial SM_LDAP_RECURSE_LIST struct */
435 *top
= sm_rpool_malloc_x(rpool
, sizeof **top
);
438 (*top
)->lr_data
= NULL
;
441 if ((*top
)->lr_cnt
>= (*top
)->lr_size
)
443 /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */
444 olddata
= (*top
)->lr_data
;
445 if ((*top
)->lr_size
== 0)
448 (*top
)->lr_size
= 256;
452 oldsizeb
= (*top
)->lr_size
* sizeof *((*top
)->lr_data
);
453 (*top
)->lr_size
*= 2;
455 (*top
)->lr_data
= sm_rpool_malloc_x(rpool
,
456 (*top
)->lr_size
* sizeof *((*top
)->lr_data
));
458 memcpy((*top
)->lr_data
, olddata
, oldsizeb
);
462 ** Binary search/insert item:type into list.
463 ** Return current entry pointer if already exists.
467 m
= (*top
)->lr_cnt
- 1;
473 while (insertat
== -1)
477 rc
= sm_strcasecmp(item
, (*top
)->lr_data
[p
]->lr_search
);
479 rc
= type
- (*top
)->lr_data
[p
]->lr_type
;
486 return (*top
)->lr_data
[p
];
490 else if (n
>= (*top
)->lr_cnt
)
491 insertat
= (*top
)->lr_cnt
;
497 ** Not found in list, make room
498 ** at insert point and add it.
501 newe
= sm_rpool_malloc_x(rpool
, sizeof *newe
);
504 moveb
= ((*top
)->lr_cnt
- insertat
) * sizeof *((*top
)->lr_data
);
506 memmove(&((*top
)->lr_data
[insertat
+ 1]),
507 &((*top
)->lr_data
[insertat
]),
510 newe
->lr_search
= sm_rpool_strdup_x(rpool
, item
);
511 newe
->lr_type
= type
;
512 newe
->lr_done
= false;
514 ((*top
)->lr_data
)[insertat
] = newe
;
521 sm_ldap_results(lmap
, msgid
, flags
, delim
, rpool
, result
,
522 resultln
, resultsz
, recurse
)
523 SM_LDAP_STRUCT
*lmap
;
531 SM_LDAP_RECURSE_LIST
*recurse
;
540 SM_LDAP_RECURSE_ENTRY
*rl
;
542 /* Are we the top top level of the search? */
543 toplevel
= (recurse
== NULL
);
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
)
554 /* If we don't want multiple values and we have one, break */
555 if ((char) delim
== '\0' && *result
!= NULL
)
558 /* Cycle through all entries */
559 for (entry
= ldap_first_entry(lmap
->ldap_ld
, lmap
->ldap_res
);
561 entry
= ldap_next_entry(lmap
->ldap_ld
, lmap
->ldap_res
))
569 ** If matching only and found an entry,
570 ** no need to spin through attributes
573 if (statp
== EX_OK
&&
574 bitset(SM_LDAP_MATCHONLY
, flags
))
577 /* record completed DN's to prevent loops */
578 dn
= ldap_get_dn(lmap
->ldap_ld
, entry
);
581 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
582 save_errno
+= E_LDAPBASE
;
583 SM_LDAP_ERROR_CLEANUP();
588 rl
= sm_ldap_add_recurse(&recurse
, dn
,
595 SM_LDAP_ERROR_CLEANUP();
599 else if (rl
->lr_done
)
601 /* already on list, skip it */
607 # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
609 ** Reset value to prevent lingering
610 ** LDAP_DECODING_ERROR due to
611 ** OpenLDAP 1.X's hack (see below)
614 lmap
->ldap_ld
->ld_errno
= LDAP_SUCCESS
;
615 # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
617 for (attr
= ldap_first_attribute(lmap
->ldap_ld
, entry
,
620 attr
= ldap_next_attribute(lmap
->ldap_ld
, entry
,
625 char *needobjclass
= NULL
;
627 type
= SM_LDAP_ATTR_NONE
;
628 for (i
= 0; lmap
->ldap_attr
[i
] != NULL
; i
++)
630 if (sm_strcasecmp(lmap
->ldap_attr
[i
],
633 type
= lmap
->ldap_attr_type
[i
];
634 needobjclass
= lmap
->ldap_attr_needobjclass
[i
];
639 if (bitset(SM_LDAP_USE_ALLATTR
, flags
) &&
640 type
== SM_LDAP_ATTR_NONE
)
642 /* URL lookups specify attrs to use */
643 type
= SM_LDAP_ATTR_NORMAL
;
647 if (type
== SM_LDAP_ATTR_NONE
)
649 /* attribute not requested */
651 SM_LDAP_ERROR_CLEANUP();
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.
664 if (type
== SM_LDAP_ATTR_OBJCLASS
||
665 (needobjclass
!= NULL
&&
666 !sm_ldap_has_objectclass(lmap
, entry
,
673 if (lmap
->ldap_attrsonly
== LDAPMAP_FALSE
)
675 vals
= ldap_get_values(lmap
->ldap_ld
,
680 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
681 if (save_errno
== LDAP_SUCCESS
)
687 /* Must be an error */
688 save_errno
+= E_LDAPBASE
;
690 SM_LDAP_ERROR_CLEANUP();
698 # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
700 ** Reset value to prevent lingering
701 ** LDAP_DECODING_ERROR due to
702 ** OpenLDAP 1.X's hack (see below)
705 lmap
->ldap_ld
->ld_errno
= LDAP_SUCCESS
;
706 # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
710 ** no need to spin through entries
713 if (bitset(SM_LDAP_MATCHONLY
, flags
))
715 if (lmap
->ldap_attrsonly
== LDAPMAP_FALSE
)
716 ldap_value_free(vals
);
722 ** If we don't want multiple values,
723 ** return first found.
726 if ((char) delim
== '\0')
730 /* already have a value */
734 if (bitset(SM_LDAP_SINGLEMATCH
,
738 /* only wanted one match */
739 SM_LDAP_ERROR_CLEANUP();
744 if (lmap
->ldap_attrsonly
== LDAPMAP_TRUE
)
746 *result
= sm_rpool_strdup_x(rpool
,
754 ldap_value_free(vals
);
759 vsize
= strlen(vals
[0]) + 1;
760 if (lmap
->ldap_attrsep
!= '\0')
761 vsize
+= strlen(attr
) + 1;
762 *result
= sm_rpool_malloc_x(rpool
,
764 if (lmap
->ldap_attrsep
!= '\0')
765 sm_snprintf(*result
, vsize
,
771 sm_strlcpy(*result
, vals
[0],
773 ldap_value_free(vals
);
778 /* attributes only */
779 if (lmap
->ldap_attrsonly
== LDAPMAP_TRUE
)
782 *result
= sm_rpool_strdup_x(rpool
,
786 if (bitset(SM_LDAP_SINGLEMATCH
,
790 /* only wanted one match */
791 SM_LDAP_ERROR_CLEANUP();
796 vsize
= strlen(*result
) +
798 tmp
= sm_rpool_malloc_x(rpool
,
800 (void) sm_snprintf(tmp
,
802 *result
, (char) delim
,
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
816 ** This is not an error.
819 if (type
== SM_LDAP_ATTR_NORMAL
&&
820 bitset(SM_LDAP_SINGLEMATCH
, flags
) &&
823 /* only wanted one match */
824 SM_LDAP_ERROR_CLEANUP();
830 for (i
= 0; vals
[i
] != NULL
; i
++)
832 if (type
== SM_LDAP_ATTR_DN
||
833 type
== SM_LDAP_ATTR_FILTER
||
834 type
== SM_LDAP_ATTR_URL
)
836 /* add to recursion */
837 if (sm_ldap_add_recurse(&recurse
,
842 SM_LDAP_ERROR_CLEANUP();
849 vsize
+= strlen(vals
[i
]) + 1;
850 if (lmap
->ldap_attrsep
!= '\0')
851 vsize
+= strlen(attr
) + 1;
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.
861 if (type
== SM_LDAP_ATTR_NORMAL
&& vsize
> 0)
865 /* Grow result string if needed */
866 if ((*resultln
+ vsize
) >= *resultsz
)
868 while ((*resultln
+ vsize
) >= *resultsz
)
876 vp_tmp
= sm_rpool_malloc_x(rpool
, *resultsz
);
886 p
= *result
+ *resultln
;
887 pe
= *result
+ *resultsz
;
889 for (i
= 0; vals
[i
] != NULL
; i
++)
895 if (lmap
->ldap_attrsep
!= '\0')
897 p
+= sm_strlcpy(p
, attr
,
900 *p
++ = lmap
->ldap_attrsep
;
903 p
+= sm_strlcpy(p
, vals
[i
],
905 *resultln
= p
- (*result
);
908 /* Internal error: buffer too small for LDAP values */
909 SM_LDAP_ERROR_CLEANUP();
916 ldap_value_free(vals
);
919 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
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
930 if (save_errno
!= LDAP_SUCCESS
&&
931 save_errno
!= LDAP_DECODING_ERROR
)
933 /* Must be an error */
934 save_errno
+= E_LDAPBASE
;
935 SM_LDAP_ERROR_CLEANUP();
940 /* mark this DN as done */
943 /* We don't want multiple values and we have one */
944 if ((char) delim
== '\0' && *result
!= NULL
)
947 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
948 if (save_errno
!= LDAP_SUCCESS
&&
949 save_errno
!= LDAP_DECODING_ERROR
)
951 /* Must be an error */
952 save_errno
+= E_LDAPBASE
;
953 SM_LDAP_ERROR_CLEANUP();
957 ldap_msgfree(lmap
->ldap_res
);
958 lmap
->ldap_res
= NULL
;
962 save_errno
= ETIMEDOUT
;
964 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
965 if (save_errno
!= LDAP_SUCCESS
)
972 #ifdef LDAP_SERVER_DOWN
973 case LDAP_SERVER_DOWN
:
974 #endif /* LDAP_SERVER_DOWN */
976 case LDAP_UNAVAILABLE
:
979 ** server disappeared,
980 ** try reopen on next search
986 save_errno
+= E_LDAPBASE
;
988 SM_LDAP_ERROR_CLEANUP();
993 if (lmap
->ldap_res
!= NULL
)
995 ldap_msgfree(lmap
->ldap_res
);
996 lmap
->ldap_res
= NULL
;
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.
1012 for (rlidx
= 0; recurse
!= NULL
&& rlidx
< recurse
->lr_cnt
; rlidx
++)
1018 rl
= recurse
->lr_data
[rlidx
];
1023 /* already expanded */
1027 if (rl
->lr_type
== SM_LDAP_ATTR_DN
)
1030 sid
= ldap_search(lmap
->ldap_ld
,
1034 (lmap
->ldap_attr
[0] == NULL
?
1035 NULL
: lmap
->ldap_attr
),
1036 lmap
->ldap_attrsonly
);
1038 else if (rl
->lr_type
== SM_LDAP_ATTR_FILTER
)
1041 sid
= ldap_search(lmap
->ldap_ld
,
1045 (lmap
->ldap_attr
[0] == NULL
?
1046 NULL
: lmap
->ldap_attr
),
1047 lmap
->ldap_attrsonly
);
1049 else if (rl
->lr_type
== SM_LDAP_ATTR_URL
)
1051 /* do new URL search */
1052 sid
= ldap_url_search(lmap
->ldap_ld
,
1054 lmap
->ldap_attrsonly
);
1055 newflags
|= SM_LDAP_USE_ALLATTR
;
1059 /* unknown or illegal attribute type */
1064 /* Collect results */
1067 save_errno
= sm_ldap_geterrno(lmap
->ldap_ld
);
1068 statp
= EX_TEMPFAIL
;
1071 #ifdef LDAP_SERVER_DOWN
1072 case LDAP_SERVER_DOWN
:
1073 #endif /* LDAP_SERVER_DOWN */
1075 case LDAP_UNAVAILABLE
:
1078 ** server disappeared,
1079 ** try reopen on next search
1085 errno
= save_errno
+ E_LDAPBASE
;
1089 status
= sm_ldap_results(lmap
, sid
, newflags
, delim
,
1090 rpool
, result
, resultln
,
1093 if (status
!= EX_OK
&& status
!= EX_NOTFOUND
)
1102 /* Reset rlidx as new items may have been added */
1108 #endif /* _FFR_LDAP_RECURSION */
1111 ** SM_LDAP_CLOSE -- close LDAP connection
1114 ** lmap -- LDAP map information
1123 SM_LDAP_STRUCT
*lmap
;
1125 if (lmap
->ldap_ld
== NULL
)
1128 if (lmap
->ldap_pid
== getpid())
1129 ldap_unbind(lmap
->ldap_ld
);
1130 lmap
->ldap_ld
= NULL
;
1135 ** SM_LDAP_SETOPTS -- set LDAP options
1138 ** ld -- LDAP session handle
1139 ** lmap -- LDAP map information
1147 sm_ldap_setopts(ld
, lmap
)
1149 SM_LDAP_STRUCT
*lmap
;
1151 # if USE_LDAP_SET_OPTION
1152 # if _FFR_LDAP_SETVERSION
1153 if (lmap
->ldap_version
!= 0)
1155 ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
,
1156 &lmap
->ldap_version
);
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
);
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 */
1179 ** SM_LDAP_GETERRNO -- get ldap errno value
1182 ** ld -- LDAP session handle
1190 sm_ldap_geterrno(ld
)
1193 int err
= LDAP_SUCCESS
;
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 */
1204 ** Reset value to prevent lingering LDAP_DECODING_ERROR due to
1205 ** OpenLDAP 1.X's hack (see above)
1208 ld
->ld_errno
= LDAP_SUCCESS
;
1209 # endif /* LDAP_OPT_SIZELIMIT */
1210 # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
1213 # endif /* LDAPMAP */