2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2 if the
4 * License as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * @brief LDAP module library functions.
21 * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22 * @copyright 2013 Network RADIUS SARL <info@networkradius.com>
23 * @copyright 2013 The FreeRADIUS Server Project.
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modules.h>
27 #include <freeradius-devel/rad_assert.h>
34 /** Converts "bad" strings into ones which are safe for LDAP
36 * This is a callback for xlat operations.
38 * Will escape any characters in input strings that would cause the string to be interpreted as part of a DN and or
39 * filter. Escape sequence is @verbatim \<hex><hex> @endverbatim
41 * @param request The current request.
42 * @param out Pointer to output buffer.
43 * @param outlen Size of the output buffer.
44 * @param in Raw unescaped string.
45 * @param arg Any additional arguments (unused).
47 size_t rlm_ldap_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
49 static char const encode[] = ",+\"\\<>;*=()";
50 static char const hextab[] = "0123456789abcdef";
53 if (*in && ((*in == ' ') || (*in == '#'))) {
59 * Encode unsafe characters.
61 if (memchr(encode, *in, sizeof(encode) - 1)) {
65 * Only 3 or less bytes available.
70 *out++ = hextab[(*in >> 4) & 0x0f];
71 *out++ = hextab[*in & 0x0f];
81 * Doesn't need encoding
92 /** Check whether a string looks like a DN
94 * @param[in] in Str to check.
95 * @param[in] inlen Length of string to check.
96 * @return true if string looks like a DN, else false.
98 bool rlm_ldap_is_dn(char const *in, size_t inlen)
103 bool too_soon = true;
106 for (p = in; inlen > 0; p++, inlen--) {
113 * Invalid escape sequence, not a DN
115 if (inlen < 2) return false;
118 * Double backslash, consume two chars
127 * Special, consume two chars
149 * Invalid escape sequence, not a DN
151 if (inlen < 3) return false;
154 * Hex encoding, consume three chars
156 if (fr_hex2bin((uint8_t *) &c, 1, p + 1, 2) == 1) {
163 * Invalid escape sequence, not a DN
170 if (too_soon || (*p != want)) return false; /* Too soon after last , or = */
176 if (too_soon || (*p != want)) return false; /* Too soon after last , or = */
189 * If the string ended with , or =, or the number
190 * of components was less than 2
192 * i.e. we don't have <attr>=<val>,<attr>=<val>
194 if (too_soon || (comp < 2)) return false;
199 /** Convert a berval to a talloced string
201 * The ldap_get_values function is deprecated, and ldap_get_values_len
202 * does not guarantee the berval buffers it returns are \0 terminated.
204 * For some cases this is fine, for others we require a \0 terminated
205 * buffer (feeding DNs back into libldap for example).
207 * @param ctx to allocate in.
208 * @param in Berval to copy.
209 * @return \0 terminated buffer containing in->bv_val.
211 char *rlm_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
215 out = talloc_array(ctx, char, in->bv_len + 1);
216 if (!out) return NULL;
218 memcpy(out, in->bv_val, in->bv_len);
219 out[in->bv_len] = '\0';
224 /** Normalise escape sequences in a DN
226 * Characters in a DN can either be escaped as
227 * @verbatim \<hex><hex> @endverbatim or @verbatim \<special> @endverbatim
229 * The LDAP directory chooses how characters are escaped, which can make
230 * local comparisons of DNs difficult.
232 * Here we search for hex sequences that match special chars, and convert
233 * them to the @verbatim \<special> @endverbatim form.
235 * @note the resulting output string will only ever be shorter than the
236 * input, so it's fine to use the same buffer for both out and in.
238 * @param out Where to write the normalised DN.
239 * @param in The input DN.
240 * @return The number of bytes written to out.
242 size_t rlm_ldap_normalise_dn(char *out, char const *in)
247 for (p = in; *p != '\0'; p++) {
252 * Double backslashes get processed specially
262 * Hex encodings that have an alternative
263 * special encoding, get rewritten to the
266 if (fr_hex2bin((uint8_t *) &c, 1, p + 1, 2) == 1) {
295 /** Find the place at which the two DN strings diverge
297 * Returns the length of the non matching string in full.
300 * @param part Partial DN as returned by ldap_parse_result.
301 * @return the length of the portion of full which wasn't matched or -1 on error.
303 static size_t rlm_ldap_common_dn(char const *full, char const *part)
305 size_t f_len, p_len, i;
311 f_len = strlen(full);
317 p_len = strlen(part);
322 if ((f_len < p_len) || !f_len) {
326 for (i = 0; i < p_len; i++) {
327 if (part[p_len - i] != full[f_len - i]) {
332 return f_len - p_len;
335 /** Combine and expand filters
337 * @param request Current request.
338 * @param out Where to write the expanded string.
339 * @param outlen Length of output buffer.
340 * @param sub Array of subfilters (may contain NULLs).
341 * @param sublen Number of potential subfilters in array.
342 * @return length of expanded data.
344 ssize_t rlm_ldap_xlat_filter(REQUEST *request, char const **sub, size_t sublen, char *out, size_t outlen)
346 char buffer[LDAP_MAX_FILTER_STR_LEN + 1];
347 char const *in = NULL;
356 * Figure out how many filter elements we need to integrate
358 for (i = 0; i < sublen; i++) {
359 if (sub[i] && *sub[i]) {
378 for (i = 0; i < sublen; i++) {
379 if (sub[i] && (*sub[i] != '\0')) {
380 len += strlcpy(p + len, sub[i], outlen - len);
382 if ((size_t) len >= outlen) {
384 REDEBUG("Out of buffer space creating filter");
391 if ((outlen - len) < 2) {
401 len = radius_xlat(out, outlen, request, in, rlm_ldap_escape_func, NULL);
403 REDEBUG("Failed creating filter");
411 /** Return the error string associated with a handle
413 * @param conn to retrieve error from.
414 * @return error string.
416 char const *rlm_ldap_error_str(ldap_handle_t const *conn)
419 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
420 if (lib_errno == LDAP_SUCCESS) {
424 return ldap_err2string(lib_errno);
427 /** Parse response from LDAP server dealing with any errors
429 * Should be called after an LDAP operation. Will check result of operation and if it was successful, then attempt
430 * to retrieve and parse the result.
432 * Will also produce extended error output including any messages the server sent, and information about partial
435 * @param[in] inst of LDAP module.
436 * @param[in] conn Current connection.
437 * @param[in] msgid returned from last operation.
438 * @param[in] dn Last search or bind DN.
439 * @param[out] result Where to write result, if NULL result will be freed.
440 * @param[out] error Where to write the error string, may be NULL, must not be freed.
441 * @param[out] extra Where to write additional error string to, may be NULL (faster) or must be freed
442 * (with talloc_free).
443 * @return One of the LDAP_PROC_* codes.
445 static ldap_rcode_t rlm_ldap_result(ldap_instance_t const *inst, ldap_handle_t const *conn, int msgid, char const *dn,
446 LDAPMessage **result, char const **error, char **extra)
448 ldap_rcode_t status = LDAP_PROC_SUCCESS;
450 int lib_errno = LDAP_SUCCESS; // errno returned by the library.
451 int srv_errno = LDAP_SUCCESS; // errno in the result message.
453 char *part_dn = NULL; // Partial DN match.
454 char *our_err = NULL; // Our extended error message.
455 char *srv_err = NULL; // Server's extended error message.
458 bool freeit = false; // Whether the message should be freed after being processed.
461 struct timeval tv; // Holds timeout values.
463 LDAPMessage *tmp_msg; // Temporary message pointer storage if we weren't provided with one.
465 char const *tmp_err; // Temporary error pointer storage if we weren't provided with one.
477 * We always need the result, but our caller may not
487 * Check if there was an error sending the request
489 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
490 if (lib_errno != LDAP_SUCCESS) goto process_error;
492 memset(&tv, 0, sizeof(tv));
493 tv.tv_sec = inst->res_timeout;
496 * Now retrieve the result and check for errors
497 * ldap_result returns -1 on error, and 0 on timeout
499 lib_errno = ldap_result(conn->handle, msgid, 1, &tv, result);
500 if (lib_errno == 0) {
501 lib_errno = LDAP_TIMEOUT;
506 if (lib_errno == -1) {
507 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
513 * Parse the result and check for errors sent by the server
515 lib_errno = ldap_parse_result(conn->handle, *result,
517 extra ? &part_dn : NULL,
518 extra ? &srv_err : NULL,
520 if (freeit) *result = NULL;
522 if (lib_errno != LDAP_SUCCESS) {
523 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
528 if ((lib_errno == LDAP_SUCCESS) && (srv_errno != LDAP_SUCCESS)) {
529 lib_errno = srv_errno;
530 } else if ((lib_errno != LDAP_SUCCESS) && (srv_errno == LDAP_SUCCESS)) {
531 srv_errno = lib_errno;
539 case LDAP_NO_SUCH_OBJECT:
540 *error = "The specified DN wasn't found, check base_dn and identity";
541 status = LDAP_PROC_BAD_DN;
546 * Build our own internal diagnostic string
548 len = rlm_ldap_common_dn(dn, part_dn);
551 our_err = talloc_typed_asprintf(conn, "Match stopped here: [%.*s]%s", len, dn, part_dn ? part_dn : "");
554 case LDAP_INSUFFICIENT_ACCESS:
555 *error = "Insufficient access. Check the identity and password configuration directives";
556 status = LDAP_PROC_NOT_PERMITTED;
559 case LDAP_UNWILLING_TO_PERFORM:
560 *error = "Server was unwilling to perform";
561 status = LDAP_PROC_NOT_PERMITTED;
564 case LDAP_FILTER_ERROR:
565 *error = "Bad search filter";
566 status = LDAP_PROC_ERROR;
570 *error = "Timed out while waiting for server to respond";
573 case LDAP_TIMELIMIT_EXCEEDED:
574 *error = "Time limit exceeded";
576 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", true);
580 case LDAP_UNAVAILABLE:
581 case LDAP_SERVER_DOWN:
582 status = LDAP_PROC_RETRY;
585 case LDAP_INVALID_CREDENTIALS:
586 case LDAP_CONSTRAINT_VIOLATION:
587 status = LDAP_PROC_REJECT;
590 case LDAP_OPERATIONS_ERROR:
591 *error = "Please set 'chase_referrals=yes' and 'rebind=yes'. See the ldap module configuration "
596 status = LDAP_PROC_ERROR;
599 if (!*error) *error = ldap_err2string(lib_errno);
601 if (!extra || ((lib_errno == srv_errno) && !our_err && !srv_err)) break;
604 * Output the error codes from the library and server
606 p = talloc_zero_array(conn, char, 1);
609 if (lib_errno != srv_errno) {
610 a = talloc_asprintf_append(p, "LDAP lib error: %s (%u), srv error: %s (%u). ",
611 ldap_err2string(lib_errno), lib_errno,
612 ldap_err2string(srv_errno), srv_errno);
622 a = talloc_asprintf_append_buffer(p, "%s. ", our_err);
632 a = talloc_asprintf_append_buffer(p, "Server said: %s. ", srv_err);
649 if (srv_err) ldap_memfree(srv_err);
650 if (part_dn) ldap_memfree(part_dn);
652 talloc_free(our_err);
654 if ((lib_errno || srv_errno) && *result) {
655 ldap_msgfree(*result);
662 /** Bind to the LDAP directory as a user
664 * Performs a simple bind to the LDAP directory, and handles any errors that occur.
666 * @param[in] inst rlm_ldap configuration.
667 * @param[in] request Current request, this may be NULL, in which case all debug logging is done with radlog.
668 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
669 * @param[in] dn of the user, may be NULL to bind anonymously.
670 * @param[in] password of the user, may be NULL if no password is specified.
671 * @param[in] retry if the server is down.
672 * @return one of the LDAP_PROC_* values.
674 ldap_rcode_t rlm_ldap_bind(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn, char const *dn,
675 char const *password, bool retry)
677 ldap_rcode_t status = LDAP_PROC_ERROR;
681 char const *error = NULL;
686 rad_assert(*pconn && (*pconn)->handle);
687 rad_assert(!retry || inst->pool);
690 * Bind as anonymous user
695 * For sanity, for when no connections are viable,
696 * and we can't make a new one.
698 num = retry ? fr_connection_get_num(inst->pool) : 0;
699 for (i = num; i >= 0; i--) {
700 msgid = ldap_bind((*pconn)->handle, dn, password, LDAP_AUTH_SIMPLE);
701 /* We got a valid message ID */
704 RDEBUG2("Waiting for bind result...");
706 DEBUG2("rlm_ldap (%s): Waiting for bind result...", inst->xlat_name);
710 status = rlm_ldap_result(inst, *pconn, msgid, dn, NULL, &error, &extra);
712 case LDAP_PROC_SUCCESS:
713 LDAP_DBG_REQ("Bind successful");
716 case LDAP_PROC_NOT_PERMITTED:
717 LDAP_ERR_REQ("Bind was not permitted: %s", error);
722 case LDAP_PROC_REJECT:
723 LDAP_ERR_REQ("Bind credentials incorrect: %s", error);
728 case LDAP_PROC_RETRY:
730 *pconn = fr_connection_reconnect(inst->pool, *pconn);
732 LDAP_DBGW_REQ("Bind with %s to %s failed: %s. Got new socket, retrying...",
733 *dn ? dn : "(anonymous)", inst->server, error);
735 talloc_free(extra); /* don't leak debug info */
740 status = LDAP_PROC_ERROR;
743 * Were not allowed to retry, or there are no more
744 * sockets, treat this as a hard failure.
748 LDAP_ERR_REQ("Bind with %s to %s failed: %s", *dn ? dn : "(anonymous)",
749 inst->server, error);
758 if (retry && (i < 0)) {
759 LDAP_ERR_REQ("Hit reconnection limit");
760 status = LDAP_PROC_ERROR;
765 return status; /* caller closes the connection */
768 /** Search for something in the LDAP directory
770 * Binds as the administrative user and performs a search, dealing with any errors.
772 * @param[in] inst rlm_ldap configuration.
773 * @param[in] request Current request.
774 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
775 * @param[in] dn to use as base for the search.
776 * @param[in] scope to use (LDAP_SCOPE_BASE, LDAP_SCOPE_ONE, LDAP_SCOPE_SUB).
777 * @param[in] filter to use, should be pre-escaped.
778 * @param[in] attrs to retrieve.
779 * @param[out] result Where to store the result. Must be freed with ldap_msgfree if LDAP_PROC_SUCCESS is returned.
780 * May be NULL in which case result will be automatically freed after use.
781 * @return One of the LDAP_PROC_* values.
783 ldap_rcode_t rlm_ldap_search(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
784 char const *dn, int scope, char const *filter, char const * const *attrs,
785 LDAPMessage **result)
788 LDAPMessage *our_result = NULL;
790 int msgid; // Message id returned by
793 int count = 0; // Number of results we got.
795 struct timeval tv; // Holds timeout values.
797 char const *error = NULL;
803 rad_assert(*pconn && (*pconn)->handle);
806 * OpenLDAP library doesn't declare attrs array as const, but
807 * it really should be *sigh*.
810 memcpy(&search_attrs, &attrs, sizeof(attrs));
813 * Do all searches as the admin user.
815 if ((*pconn)->rebound) {
816 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
817 if (status != LDAP_PROC_SUCCESS) {
818 return LDAP_PROC_ERROR;
823 (*pconn)->rebound = false;
827 LDAP_DBG_REQ("Performing search in '%s' with filter '%s', scope '%s'", dn, filter,
828 fr_int2str(ldap_scope, scope, "<INVALID>"));
830 LDAP_DBG_REQ("Performing unfiltered search in '%s', scope '%s'", dn,
831 fr_int2str(ldap_scope, scope, "<INVALID>"));
834 * If LDAP search produced an error it should also be logged
835 * to the ld. result should pick it up without us
836 * having to pass it explicitly.
838 memset(&tv, 0, sizeof(tv));
839 tv.tv_sec = inst->res_timeout;
842 * For sanity, for when no connections are viable,
843 * and we can't make a new one.
845 for (i = fr_connection_get_num(inst->pool); i >= 0; i--) {
846 (void) ldap_search_ext((*pconn)->handle, dn, scope, filter, search_attrs,
847 0, NULL, NULL, &tv, 0, &msgid);
849 LDAP_DBG_REQ("Waiting for search result...");
850 status = rlm_ldap_result(inst, *pconn, msgid, dn, &our_result, &error, &extra);
852 case LDAP_PROC_SUCCESS:
855 case LDAP_PROC_RETRY:
856 *pconn = fr_connection_reconnect(inst->pool, *pconn);
858 LDAP_DBGW_REQ("Search failed: %s. Got new socket, retrying...", error);
860 talloc_free(extra); /* don't leak debug info */
865 status = LDAP_PROC_ERROR;
869 LDAP_ERR_REQ("Failed performing search: %s", error);
870 if (extra) LDAP_ERR_REQ("%s", extra);
879 LDAP_ERR_REQ("Hit reconnection limit");
880 status = LDAP_PROC_ERROR;
885 count = ldap_count_entries((*pconn)->handle, our_result);
887 LDAP_ERR_REQ("Error counting results: %s", rlm_ldap_error_str(*pconn));
888 status = LDAP_PROC_ERROR;
890 ldap_msgfree(our_result);
892 } else if (count == 0) {
893 LDAP_DBG_REQ("Search returned no results");
894 status = LDAP_PROC_NO_RESULT;
896 ldap_msgfree(our_result);
904 * We always need to get the result to count entries, but the caller
905 * may not of requested one. If that's the case, free it, else write
906 * it to where our caller said.
910 ldap_msgfree(our_result);
913 *result = our_result;
919 /** Modify something in the LDAP directory
921 * Binds as the administrative user and attempts to modify an LDAP object.
923 * @param[in] inst rlm_ldap configuration.
924 * @param[in] request Current request.
925 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
926 * @param[in] dn of the object to modify.
927 * @param[in] mods to make, see 'man ldap_modify' for more information.
928 * @return One of the LDAP_PROC_* values.
930 ldap_rcode_t rlm_ldap_modify(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
931 char const *dn, LDAPMod *mods[])
935 int msgid; // Message id returned by ldap_search_ext.
937 char const *error = NULL;
942 rad_assert(*pconn && (*pconn)->handle);
945 * Perform all modifications as the admin user.
947 if ((*pconn)->rebound) {
948 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
949 if (status != LDAP_PROC_SUCCESS) {
950 return LDAP_PROC_ERROR;
955 (*pconn)->rebound = false;
959 * For sanity, for when no connections are viable,
960 * and we can't make a new one.
962 for (i = fr_connection_get_num(inst->pool); i >= 0; i--) {
963 RDEBUG2("Modifying object with DN \"%s\"", dn);
964 (void) ldap_modify_ext((*pconn)->handle, dn, mods, NULL, NULL, &msgid);
966 RDEBUG2("Waiting for modify result...");
967 status = rlm_ldap_result(inst, *pconn, msgid, dn, NULL, &error, &extra);
969 case LDAP_PROC_SUCCESS:
972 case LDAP_PROC_RETRY:
973 *pconn = fr_connection_reconnect(inst->pool, *pconn);
975 RWDEBUG("Modify failed: %s. Got new socket, retrying...", error);
977 talloc_free(extra); /* don't leak debug info */
982 status = LDAP_PROC_ERROR;
986 REDEBUG("Failed modifying object: %s", error);
987 REDEBUG("%s", extra);
996 LDAP_ERR_REQ("Hit reconnection limit");
997 status = LDAP_PROC_ERROR;
1006 /** Retrieve the DN of a user object
1008 * Retrieves the DN of a user and adds it to the control list as LDAP-UserDN. Will also retrieve any attributes
1009 * passed and return the result in *result.
1011 * This potentially allows for all authorization and authentication checks to be performed in one ldap search
1012 * operation, which is a big bonus given the number of crappy, slow *cough*AD*cough* LDAP directory servers out there.
1014 * @param[in] inst rlm_ldap configuration.
1015 * @param[in] request Current request.
1016 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
1017 * @param[in] attrs Additional attributes to retrieve, may be NULL.
1018 * @param[in] force Query even if the User-DN already exists.
1019 * @param[out] result Where to write the result, may be NULL in which case result is discarded.
1020 * @param[out] rcode The status of the operation, one of the RLM_MODULE_* codes.
1021 * @return The user's DN or NULL on error.
1023 char const *rlm_ldap_find_user(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
1024 char const *attrs[], bool force, LDAPMessage **result, rlm_rcode_t *rcode)
1026 static char const *tmp_attrs[] = { NULL };
1028 ldap_rcode_t status;
1029 VALUE_PAIR *vp = NULL;
1030 LDAPMessage *tmp_msg = NULL, *entry = NULL;
1033 char filter[LDAP_MAX_FILTER_STR_LEN];
1034 char *filter_p = NULL;
1035 char base_dn[LDAP_MAX_DN_STR_LEN];
1037 bool freeit = false; //!< Whether the message should
1038 //!< be freed after being processed.
1040 *rcode = RLM_MODULE_FAIL;
1049 memset(&attrs, 0, sizeof(tmp_attrs));
1053 * If the caller isn't looking for the result we can just return the current userdn value.
1056 vp = pairfind(request->config_items, PW_LDAP_USERDN, 0, TAG_ANY);
1058 RDEBUG("Using user DN from request \"%s\"", vp->vp_strvalue);
1059 *rcode = RLM_MODULE_OK;
1060 return vp->vp_strvalue;
1065 * Perform all searches as the admin user.
1067 if ((*pconn)->rebound) {
1068 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
1069 if (status != LDAP_PROC_SUCCESS) {
1070 *rcode = RLM_MODULE_FAIL;
1076 (*pconn)->rebound = false;
1079 if (inst->userobj_filter) {
1080 if (radius_xlat(filter, sizeof(filter), request, inst->userobj_filter,
1081 rlm_ldap_escape_func, NULL) < 0) {
1082 REDEBUG("Unable to create filter");
1083 *rcode = RLM_MODULE_INVALID;
1091 if (radius_xlat(base_dn, sizeof(base_dn), request, inst->userobj_base_dn, rlm_ldap_escape_func, NULL) < 0) {
1092 REDEBUG("Unable to create base_dn");
1093 *rcode = RLM_MODULE_INVALID;
1098 status = rlm_ldap_search(inst, request, pconn, base_dn, inst->userobj_scope, filter_p, attrs, result);
1100 case LDAP_PROC_SUCCESS:
1103 case LDAP_PROC_NO_RESULT:
1104 *rcode = RLM_MODULE_NOTFOUND;
1108 *rcode = RLM_MODULE_FAIL;
1114 entry = ldap_first_entry((*pconn)->handle, *result);
1116 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
1117 REDEBUG("Failed retrieving entry: %s",
1118 ldap_err2string(ldap_errno));
1123 dn = ldap_get_dn((*pconn)->handle, entry);
1125 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
1126 REDEBUG("Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
1130 rlm_ldap_normalise_dn(dn, dn);
1133 * We can't use pairmake here to copy the value into the
1134 * attribute, as the dn must be copied into the attribute
1135 * verbatim (without de-escaping).
1137 * Special chars are pre-escaped by libldap, and because
1138 * we pass the string back to libldap we must not alter it.
1140 RDEBUG("User object found at DN \"%s\"", dn);
1141 vp = pairmake(request, &request->config_items, "LDAP-UserDN", NULL, T_OP_EQ);
1144 *rcode = RLM_MODULE_OK;
1150 if ((freeit || (*rcode != RLM_MODULE_OK)) && *result) {
1151 ldap_msgfree(*result);
1155 return vp ? vp->vp_strvalue : NULL;
1158 /** Check for presence of access attribute in result
1160 * @param[in] inst rlm_ldap configuration.
1161 * @param[in] request Current request.
1162 * @param[in] conn used to retrieve access attributes.
1163 * @param[in] entry retrieved by rlm_ldap_find_user or rlm_ldap_search.
1164 * @return RLM_MODULE_USERLOCK if the user was denied access, else RLM_MODULE_OK.
1166 rlm_rcode_t rlm_ldap_check_access(ldap_instance_t const *inst, REQUEST *request,
1167 ldap_handle_t const *conn, LDAPMessage *entry)
1169 rlm_rcode_t rcode = RLM_MODULE_OK;
1170 struct berval **values = NULL;
1172 values = ldap_get_values_len(conn->handle, entry, inst->userobj_access_attr);
1174 if (inst->access_positive) {
1175 if ((values[0]->bv_len >= 5) && (strncasecmp(values[0]->bv_val, "false", 5) == 0)) {
1176 RDEBUG("\"%s\" attribute exists but is set to 'false' - user locked out",
1177 inst->userobj_access_attr);
1178 rcode = RLM_MODULE_USERLOCK;
1180 /* RLM_MODULE_OK set above... */
1181 } else if ((values[0]->bv_len < 5) || (strncasecmp(values[0]->bv_val, "false", 5) != 0)) {
1182 RDEBUG("\"%s\" attribute exists - user locked out", inst->userobj_access_attr);
1183 rcode = RLM_MODULE_USERLOCK;
1185 ldap_value_free_len(values);
1186 } else if (inst->access_positive) {
1187 RDEBUG("No \"%s\" attribute - user locked out", inst->userobj_access_attr);
1188 rcode = RLM_MODULE_USERLOCK;
1194 /** Verify we got a password from the search
1196 * Checks to see if after the LDAP to RADIUS mapping has been completed that a reference password.
1198 * @param inst rlm_ldap configuration.
1199 * @param request Current request.
1201 void rlm_ldap_check_reply(ldap_instance_t const *inst, REQUEST *request)
1204 * More warning messages for people who can't be bothered to read the documentation.
1206 * Expect_password is set when we process the mapping, and is only true if there was a mapping between
1207 * an LDAP attribute and a password reference attribute in the control list.
1209 if (inst->expect_password && (debug_flag > 1)) {
1210 if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY) &&
1211 !pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY) &&
1212 !pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
1213 !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
1214 !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
1215 RWDEBUG("No \"known good\" password added. Ensure the admin user has permission to "
1216 "read the password attribute");
1217 RWDEBUG("PAP authentication will *NOT* work with Active Directory (if that is what you "
1218 "were trying to configure)");
1223 #if LDAP_SET_REBIND_PROC_ARGS == 3
1224 /** Callback for OpenLDAP to rebind and chase referrals
1226 * Called by OpenLDAP when it receives a referral and has to rebind.
1228 * @param handle to rebind.
1229 * @param url to bind to.
1230 * @param request that triggered the rebind.
1231 * @param msgid that triggered the rebind.
1232 * @param ctx rlm_ldap configuration.
1234 static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
1237 ldap_rcode_t status;
1238 ldap_handle_t *conn = talloc_get_type_abort(ctx, ldap_handle_t);
1242 conn->referred = true;
1243 conn->rebound = true; /* not really, but oh well... */
1244 rad_assert(handle == conn->handle);
1246 DEBUG("rlm_ldap (%s): Rebinding to URL %s", conn->inst->xlat_name, url);
1248 status = rlm_ldap_bind(conn->inst, NULL, &conn, conn->inst->admin_dn, conn->inst->password, false);
1249 if (status != LDAP_PROC_SUCCESS) {
1250 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
1256 return LDAP_SUCCESS;
1260 /** Close and delete a connection
1262 * Unbinds the LDAP connection, informing the server and freeing any memory, then releases the memory used by the
1263 * connection handle.
1265 * @param conn to destroy.
1266 * @return always indicates success.
1268 static int _mod_conn_free(ldap_handle_t *conn)
1271 DEBUG3("rlm_ldap: Closing libldap handle %p", conn->handle);
1272 #ifdef HAVE_LDAP_UNBIND_EXT_S
1273 ldap_unbind_ext_s(conn->handle, NULL, NULL);
1275 ldap_unbind_s(conn->handle);
1282 /** Create and return a new connection
1284 * Create a new ldap connection and allocate memory for a new rlm_handle_t
1286 void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
1288 ldap_rcode_t status;
1290 int ldap_errno, ldap_version;
1293 ldap_instance_t *inst = instance;
1294 ldap_handle_t *conn;
1297 * Allocate memory for the handle.
1299 conn = talloc_zero(ctx, ldap_handle_t);
1300 if (!conn) return NULL;
1301 talloc_set_destructor(conn, _mod_conn_free);
1304 conn->rebound = false;
1305 conn->referred = false;
1307 DEBUG("rlm_ldap (%s): Connecting to %s", inst->xlat_name, inst->server);
1308 #ifdef HAVE_LDAP_INITIALIZE
1309 ldap_errno = ldap_initialize(&conn->handle, inst->server);
1310 if (ldap_errno != LDAP_SUCCESS) {
1311 LDAP_ERR("ldap_initialize failed: %s", ldap_err2string(ldap_errno));
1315 conn->handle = ldap_init(inst->server, inst->port);
1316 if (!conn->handle) {
1317 LDAP_ERR("ldap_init failed");
1321 DEBUG3("rlm_ldap (%s): New libldap handle %p", inst->xlat_name, conn->handle);
1324 * We now have a connection structure, but no actual TCP connection.
1326 * Set a bunch of LDAP options, using common code.
1328 #define do_ldap_option(_option, _name, _value) \
1329 if (ldap_set_option(conn->handle, _option, _value) != LDAP_OPT_SUCCESS) { \
1330 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
1331 LDAP_ERR("Could not set %s: %s", _name, ldap_err2string(ldap_errno)); \
1334 #define do_ldap_global_option(_option, _name, _value) \
1335 if (ldap_set_option(NULL, _option, _value) != LDAP_OPT_SUCCESS) { \
1336 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
1337 LDAP_ERR("Could not set %s: %s", _name, ldap_err2string(ldap_errno)); \
1341 if (inst->ldap_debug) {
1342 do_ldap_global_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug", &(inst->ldap_debug));
1346 * Leave "dereference" unset to use the OpenLDAP default.
1348 if (inst->dereference_str) {
1349 do_ldap_option(LDAP_OPT_DEREF, "dereference", &(inst->dereference));
1353 * Leave "chase_referrals" unset to use the OpenLDAP default.
1355 if (!inst->chase_referrals_unset) {
1356 if (inst->chase_referrals) {
1357 do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_ON);
1359 if (inst->rebind == true) {
1360 #if LDAP_SET_REBIND_PROC_ARGS == 3
1361 ldap_set_rebind_proc(conn->handle, rlm_ldap_rebind, conn);
1365 do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_OFF);
1369 #ifdef LDAP_OPT_NETWORK_TIMEOUT
1370 if (inst->net_timeout) {
1371 memset(&tv, 0, sizeof(tv));
1372 tv.tv_sec = inst->net_timeout;
1374 do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
1378 do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(inst->srv_timelimit));
1380 ldap_version = LDAP_VERSION3;
1381 do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version", &ldap_version);
1383 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
1384 do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive idle", &(inst->keepalive_idle));
1387 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
1388 do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive probes", &(inst->keepalive_probes));
1391 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
1392 do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive interval", &(inst->keepalive_interval));
1395 #ifdef HAVE_LDAP_START_TLS
1397 * Set all of the TLS options
1399 if (inst->tls_mode) {
1400 do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
1403 # define maybe_ldap_option(_option, _name, _value) \
1404 if (_value) do_ldap_option(_option, _name, _value)
1406 maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", inst->tls_ca_file);
1407 maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", inst->tls_ca_path);
1411 * Set certificate options
1413 maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", inst->tls_certificate_file);
1414 maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", inst->tls_private_key_file);
1415 maybe_ldap_option(LDAP_OPT_X_TLS_RANDOM_FILE, "random_file", inst->tls_random_file);
1417 # ifdef LDAP_OPT_X_TLS_NEVER
1418 if (inst->tls_require_cert_str) {
1419 do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &inst->tls_require_cert);
1424 * Counter intuitively the TLS context appears to need to be initialised
1425 * after all the TLS options are set on the handle.
1427 # ifdef LDAP_OPT_X_TLS_NEWCTX
1429 /* Always use the new TLS configuration context */
1431 do_ldap_option(LDAP_OPT_X_TLS_NEWCTX, "new TLS context", &is_server);
1437 * And finally start the TLS code.
1439 if (inst->start_tls) {
1440 if (inst->port == 636) {
1441 WARN("Told to Start TLS on LDAPS port this will probably fail, please correct the "
1445 if (ldap_start_tls_s(conn->handle, NULL, NULL) != LDAP_SUCCESS) {
1446 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
1448 LDAP_ERR("Could not start TLS: %s", ldap_err2string(ldap_errno));
1452 #endif /* HAVE_LDAP_START_TLS */
1454 status = rlm_ldap_bind(inst, NULL, &conn, inst->admin_dn, inst->password, false);
1455 if (status != LDAP_PROC_SUCCESS) {
1467 /** Gets an LDAP socket from the connection pool
1469 * Retrieve a socket from the connection pool, or NULL on error (of if no sockets are available).
1471 * @param inst rlm_ldap configuration.
1472 * @param request Current request (may be NULL).
1474 ldap_handle_t *mod_conn_get(ldap_instance_t const *inst, UNUSED REQUEST *request)
1476 return fr_connection_get(inst->pool);
1479 /** Frees an LDAP socket back to the connection pool
1481 * If the socket was rebound chasing a referral onto another server then we destroy it.
1482 * If the socket was rebound to another user on the same server, we let the next caller rebind it.
1484 * @param inst rlm_ldap configuration.
1485 * @param conn to release.
1487 void mod_conn_release(ldap_instance_t const *inst, ldap_handle_t *conn)
1490 * Could have already been free'd due to a previous error.
1495 * We chased a referral to another server.
1497 * This connection is no longer part of the pool which is connected to and bound to the configured server.
1500 * Note that we do NOT close it if it was bound to another user. Instead, we let the next caller do the
1503 if (conn->referred) {
1504 fr_connection_del(inst->pool, conn);
1508 fr_connection_release(inst->pool, conn);