27 RCSID(
"$Id: 2be5316bd858286318a4e4266dd6e7c3be9de668 $")
31 #include <freeradius-devel/util/debug.h>
33 #define LOG_PREFIX mctx->inst->name
75 if ((!user_ctx->
inst->
user.obj_sort_ctrl) && (cnt > 1)) {
76 REDEBUG(
"Ambiguous search result, returned %i unsorted entries (should return 1 or 0). "
77 "Enable sorting, or specify a more restrictive base_dn, filter or scope", cnt);
78 REDEBUG(
"The following entries were returned:");
93 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
94 REDEBUG(
"Failed retrieving entry: %s",
95 ldap_err2string(ldap_errno));
102 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
103 REDEBUG(
"Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
109 RDEBUG2(
"User object found at DN \"%s\"", dn);
114 if (user_ctx->
out) *user_ctx->
out = user_ctx->
query;
159 static char const *tmp_attrs[] = { NULL };
161 LDAPControl *serverctrls[] = {
inst->user.obj_sort_ctrl, NULL };
163 if (!attrs) memset(&attrs, 0,
sizeof(tmp_attrs));
169 .base_dn = base->vb_strvalue,
174 if (filter) user_ctx->
filter = filter->vb_strvalue;
183 user_ctx->
attrs, serverctrls, NULL);
198 struct berval **values = NULL;
202 size_t negate_value_len = talloc_array_length(
inst->user.access_value_negate) - 1;
203 if (
inst->user.access_positive) {
204 if ((values[0]->bv_len >= negate_value_len) &&
205 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_negate, negate_value_len) == 0)) {
206 REDEBUG(
"\"%s\" attribute exists but is set to '%s' - user locked out",
207 inst->user.obj_access_attr,
inst->user.access_value_negate);
212 }
else if ((values[0]->bv_len < negate_value_len) ||
213 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_negate, negate_value_len) != 0)) {
214 REDEBUG(
"\"%s\" attribute exists - user locked out",
inst->user.obj_access_attr);
219 size_t suspend_value_len = talloc_array_length(
inst->user.access_value_suspend) - 1;
220 if ((values[0]->bv_len == suspend_value_len) &&
221 (
strncasecmp(values[0]->bv_val,
inst->user.access_value_suspend, suspend_value_len) == 0)) {
222 RIDEBUG(
"\"%s\" attribute exists and indicates suspension",
inst->user.obj_access_attr);
228 ldap_value_free_len(values);
229 }
else if (
inst->user.access_positive) {
230 REDEBUG(
"No \"%s\" attribute - user locked out",
inst->user.obj_access_attr);
257 if ((
inst->user.expect_password_is_set && !
inst->user.expect_password) || !expect_password || !
RDEBUG_ENABLED2)
return;
268 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
269 RWDEBUG2(
"!!! Active Directory does not allow passwords to be read via LDAP");
270 RWDEBUG2(
"!!! Remove the password map and either:");
271 RWDEBUG2(
"!!! - Configure authentication via ntlm_auth (mschapv2 only)");
272 RWDEBUG2(
"!!! - Configure authentication via wbclient (mschapv2 only)");
273 RWDEBUG2(
"!!! - Bind as the user by listing %s in the authenticate section, and",
275 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the authorize section",
282 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
283 RWDEBUG2(
"!!! eDirectory does not allow passwords to be retrieved via LDAP search");
284 RWDEBUG2(
"!!! Remove the password map and either:");
285 RWDEBUG2(
"!!! - Set 'edir = yes' and enable the universal password feature on your");
286 RWDEBUG2(
"!!! eDir server (recommended)");
287 RWDEBUG2(
"!!! - Bind as the user by listing %s in the authenticate section, and",
289 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the authorize section",
295 RWDEBUG2(
"!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
296 RWDEBUG2(
"!!! but no password attribute found in search result");
298 RWDEBUG2(
"!!! - Ensure the user object contains a password attribute, and that");
299 RWDEBUG2(
"!!! %c%s%c has permission to read that password attribute (recommended)",
303 RWDEBUG2(
"!!! - Bind as the user by listing %s in the authenticate section, and",
305 RWDEBUG2(
"!!! setting attribute &control.Auth-Type := '%s' in the authorize 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
#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_trunk_request_t * treq
Trunk request this query is associated with.
@ FR_LDAP_DIRECTORY_EDIRECTORY
Directory server is eDir.
@ FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY
Directory server is Active Directory.
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.
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.
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)
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
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.
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)
struct rlm_ldap_t::@151 user
#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 fr_trunk_request_signal_cancel(fr_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.