27 RCSID(
"$Id: bbdd989b0f96f0da8f23e9179f16ebd92f85e796 $")
31 #include <freeradius-devel/util/debug.h>
33 #define LOG_PREFIX mctx->mi->name
79 if ((!user_ctx->
inst->
user.obj_sort_ctrl) && (cnt > 1)) {
80 REDEBUG(
"Ambiguous search result, returned %i unsorted entries (should return 1 or 0). "
81 "Enable sorting, or specify a more restrictive base_dn, filter or scope", cnt);
82 REDEBUG(
"The following entries were returned:");
97 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
98 REDEBUG(
"Failed retrieving entry: %s",
99 ldap_err2string(ldap_errno));
106 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
107 REDEBUG(
"Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
113 RDEBUG2(
"User object found at DN \"%s\"", dn);
118 if (user_ctx->
out) *user_ctx->
out = user_ctx->
query;
163 static char const *tmp_attrs[] = { NULL };
165 LDAPControl *serverctrls[] = {
inst->user.obj_sort_ctrl, NULL };
167 if (!attrs) memset(&attrs, 0,
sizeof(tmp_attrs));
173 .base_dn = base->vb_strvalue,
178 if (filter) user_ctx->
filter = filter->vb_strvalue;
187 user_ctx->
attrs, serverctrls, NULL);
202 struct berval **values = NULL;
206 size_t negate_value_len = talloc_array_length(
inst->user.access_value_negate) - 1;
207 if (
inst->user.access_positive) {
208 if ((values[0]->bv_len >= negate_value_len) &&
209 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_negate, negate_value_len) == 0)) {
210 REDEBUG(
"\"%s\" attribute exists but is set to '%s' - user locked out",
211 inst->user.obj_access_attr,
inst->user.access_value_negate);
216 }
else if ((values[0]->bv_len < negate_value_len) ||
217 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_negate, negate_value_len) != 0)) {
218 REDEBUG(
"\"%s\" attribute exists - user locked out",
inst->user.obj_access_attr);
223 size_t suspend_value_len = talloc_array_length(
inst->user.access_value_suspend) - 1;
224 if ((values[0]->bv_len == suspend_value_len) &&
225 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_suspend, suspend_value_len) == 0)) {
226 RIDEBUG(
"\"%s\" attribute exists and indicates suspension",
inst->user.obj_access_attr);
232 ldap_value_free_len(values);
233 }
else if (
inst->user.access_positive) {
234 REDEBUG(
"No \"%s\" attribute - user locked out",
inst->user.obj_access_attr);
261 if ((
inst->user.expect_password_is_set && !
inst->user.expect_password) || !expect_password || !
RDEBUG_ENABLED2)
return;
264 if (!
parent)
goto warnings;
274 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
275 RWDEBUG2(
"!!! %s does not allow passwords to be read via LDAP",
277 RWDEBUG2(
"!!! Remove the password map and either:");
278 RWDEBUG2(
"!!! - Configure authentication via ntlm_auth (mschapv2 only)");
279 RWDEBUG2(
"!!! - Configure authentication via wbclient (mschapv2 only)");
280 RWDEBUG2(
"!!! - Bind as the user by listing %s in an 'authenticate %s' section, and",
281 inst_name, inst_name);
282 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the 'recv Access-Request' section",
289 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
290 RWDEBUG2(
"!!! eDirectory does not allow passwords to be retrieved via LDAP search");
291 RWDEBUG2(
"!!! Remove the password map and either:");
292 RWDEBUG2(
"!!! - Set 'edir = yes' and enable the universal password feature on your");
293 RWDEBUG2(
"!!! eDir server (recommended)");
294 RWDEBUG2(
"!!! - Bind as the user by listing %s in an 'authenticate %s' section, and",
295 inst_name, inst_name);
296 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the 'recv Access-Request' section",
302 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
303 RWDEBUG2(
"!!! but no password attribute found in search result");
305 RWDEBUG2(
"!!! - Ensure the user object contains a password attribute, and that");
306 RWDEBUG2(
"!!! %c%s%c has permission to read that password attribute (recommended)",
310 RWDEBUG2(
"!!! - Bind as the user by listing %s in an 'authenticate %s' section, and",
311 inst_name, inst_name);
312 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the 'recv Access-Request' section",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
#define USES_APPLE_DEPRECATED_API
fr_dcursor_eval_t void const * uctx
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
@ FR_LDAP_DIRECTORY_EDIRECTORY
Directory server is eDir.
@ FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY
Directory server is Active Directory.
@ FR_LDAP_DIRECTORY_SAMBA
Directory server is Samba.
LDAP * handle
libldap handle.
char const * admin_identity
Identity we bind as when we need to query the LDAP directory.
fr_ldap_result_code_t ret
Result code.
trunk_request_t * treq
Trunk request this query is associated with.
fr_ldap_config_t config
Config used for this connection.
fr_ldap_connection_t * ldap_conn
LDAP connection this query is running on.
@ LDAP_RESULT_SUCCESS
Successfully got LDAP results.
@ LDAP_RESULT_NO_RESULT
No results returned.
@ LDAP_RESULT_BAD_DN
The requested DN does not exist.
LDAPMessage * result
Head of LDAP results list.
fr_ldap_directory_t * directory
The type of directory we're connected to.
fr_ldap_directory_type_t type
Canonical server implementation.
Thread LDAP trunk structure.
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
unlang_action_t fr_ldap_trunk_search(TALLOC_CTX *ctx, fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *base_dn, int scope, char const *filter, char const *const *attrs, LDAPControl **serverctrls, LDAPControl **clientctrls)
Run an async search LDAP query on a trunk connection.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RWDEBUG2(fmt,...)
#define RINDENT()
Indent R* messages by one level.
int strncasecmp(char *s1, char *s2, int n)
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
static fr_dict_attr_t const * attr_cleartext_password
#define RDEBUG_ENABLED2()
#define RETURN_MODULE_INVALID
rlm_rcode_t
Return codes indicating the result of the module call.
#define RETURN_MODULE_NOTFOUND
fr_dict_attr_t const * attr_nt_password
fr_dict_attr_t const * attr_ldap_userdn
fr_dict_attr_t const * attr_crypt_password
fr_dict_attr_t const * attr_password
fr_dict_attr_t const * attr_password_with_header
LDAP authorization and authentication module headers.
struct rlm_ldap_t::@160 user
ldap_access_state_t
User's access state.
@ LDAP_ACCESS_SUSPENDED
User account has been suspended.
@ LDAP_ACCESS_ALLOWED
User is allowed to login.
@ LDAP_ACCESS_DISALLOWED
User it not allow to login (disabled)
#define pair_update_control(_attr, _da)
Return or allocate a fr_pair_t in the control list.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
fr_ldap_thread_trunk_t * ttrunk
unlang_action_t rlm_ldap_find_user_async(TALLOC_CTX *ctx, rlm_ldap_t const *inst, request_t *request, fr_value_box_t *base, fr_value_box_t *filter, fr_ldap_thread_trunk_t *ttrunk, char const *attrs[], fr_ldap_query_t **query_out)
Initiate asynchronous retrieval of the DN of a user object.
static void ldap_find_user_async_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel a user search.
char const *const * attrs
void rlm_ldap_check_reply(request_t *request, rlm_ldap_t const *inst, char const *inst_name, bool expect_password, fr_ldap_thread_trunk_t const *ttrunk)
Verify we got a password from the search.
static unlang_action_t ldap_find_user_async_result(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Process the results of an async user lookup.
ldap_access_state_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request, LDAPMessage *entry)
Check for presence of access attribute in result.
Holds state of user searches in progress.