typedef struct {
fr_dict_attr_t const *group_da;
fr_dict_attr_t const *cache_da;
+ fr_dict_attr_t const *user_da;
} rlm_ldap_boot_t;
typedef struct {
{ FR_CONF_OFFSET("access_positive", rlm_ldap_t, user.access_positive), .dflt = "yes" },
{ FR_CONF_OFFSET("access_value_negate", rlm_ldap_t, user.access_value_negate), .dflt = "false" },
{ FR_CONF_OFFSET("access_value_suspend", rlm_ldap_t, user.access_value_suspend), .dflt = "suspended" },
+ { FR_CONF_OFFSET("dn_attribute", rlm_ldap_t, user.dn_attr_str), .dflt = "LDAP-UserDN" },
{ FR_CONF_OFFSET_IS_SET("expect_password", FR_TYPE_BOOL, 0, rlm_ldap_t, user.expect_password) },
CONF_PARSER_TERMINATOR
};
{ FR_CONF_OFFSET_FLAGS("membership_filter", CONF_FLAG_XLAT, rlm_ldap_t, group.obj_membership_filter) },
{ FR_CONF_OFFSET("cacheable_name", rlm_ldap_t, group.cacheable_name), .dflt = "no" },
{ FR_CONF_OFFSET("cacheable_dn", rlm_ldap_t, group.cacheable_dn), .dflt = "no" },
- { FR_CONF_OFFSET("cache_attribute", rlm_ldap_t, group.cache_attribute) },
+ { FR_CONF_OFFSET("cache_attribute", rlm_ldap_t, group.cache_attr_str) },
{ FR_CONF_OFFSET("group_attribute", rlm_ldap_t, group.attribute) },
{ FR_CONF_OFFSET("allow_dangling_group_ref", rlm_ldap_t, group.allow_dangling_refs), .dflt = "no" },
{ FR_CONF_OFFSET("skip_on_suspend", rlm_ldap_t, group.skip_on_suspend), .dflt = "yes"},
fr_dict_attr_t const *attr_password;
fr_dict_attr_t const *attr_cleartext_password;
fr_dict_attr_t const *attr_crypt_password;
-fr_dict_attr_t const *attr_ldap_userdn;
fr_dict_attr_t const *attr_nt_password;
fr_dict_attr_t const *attr_password_with_header;
static fr_dict_attr_t const *attr_expr_bool_enum;
{ .out = &attr_password, .name = "Password", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
{ .out = &attr_cleartext_password, .name = "Password.Cleartext", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
{ .out = &attr_crypt_password, .name = "Password.Crypt", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
- { .out = &attr_ldap_userdn, .name = "LDAP-UserDN", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
{ .out = &attr_nt_password, .name = "Password.NT", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
{ .out = &attr_password_with_header, .name = "Password.With-Header", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
{ .out = &attr_expr_bool_enum, .name = "Expr-Bool-Enum", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
switch (xlat_ctx->status) {
case GROUP_XLAT_FIND_USER:
- if (!xlat_ctx->dn) xlat_ctx->dn = rlm_find_user_dn_cached(request);
+ if (!xlat_ctx->dn) xlat_ctx->dn = rlm_find_user_dn_cached(inst, request);
if (!xlat_ctx->dn) RETURN_UNLANG_FAIL;
RDEBUG3("Entered GROUP_XLAT_FIND_USER with user DN \"%s\"", xlat_ctx->dn);
*xlat_ctx = (ldap_group_xlat_ctx_t){
.inst = inst,
.group = group_vb,
- .dn = rlm_find_user_dn_cached(request),
+ .dn = rlm_find_user_dn_cached(inst, request),
.attrs = { inst->group.userobj_membership_attr, NULL },
.group_is_dn = group_is_dn,
.env_data = env_data
/*
* Find the user's DN
*/
- auth_ctx->dn = rlm_find_user_dn_cached(request);
+ auth_ctx->dn = rlm_find_user_dn_cached(inst, request);
/*
* The DN is required for non-SASL auth
*/
if (!auth_ctx->dn && (call_env->user_sasl_mech.type != FR_TYPE_STRING)) {
REDEBUG("No DN found for authentication. Populate control.%s with the DN to use in authentication.",
- attr_ldap_userdn->name);
+ inst->user.da->name);
REDEBUG("You should call %s in the recv section and check its return.", inst->mi->name);
talloc_free(auth_ctx);
RETURN_UNLANG_FAIL;
* Retrieve Universal Password if we use eDirectory
*/
if (inst->edir) {
- autz_ctx->dn = rlm_find_user_dn_cached(request);
+ autz_ctx->dn = rlm_find_user_dn_cached(inst, request);
/*
* Retrieve universal password
* If an LDAP search was used to find the user DN
* usermod_ctx->dn will be NULL.
*/
- if (!usermod_ctx->dn) usermod_ctx->dn = rlm_find_user_dn_cached(request);
+ if (!usermod_ctx->dn) usermod_ctx->dn = rlm_find_user_dn_cached(mctx->mi->data, request);
if (!usermod_ctx->dn) {
fail:
RETURN_UNLANG_FAIL;
}
- usermod_ctx->dn = rlm_find_user_dn_cached(request);
+ usermod_ctx->dn = rlm_find_user_dn_cached(inst, request);
/*
* Find the user first
*/
inst->mi = mctx->mi; /* Cached for IO callbacks */
inst->group.da = boot->group_da;
inst->group.cache_da = boot->cache_da;
+ inst->user.da = boot->user_da;
inst->handle_config.name = talloc_typed_asprintf(inst, "rlm_ldap (%s)", mctx->mi->name);
/*
* Setup the cache attribute
*/
-
- if (inst->group.cache_attribute) {
- boot->cache_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->group.cache_attribute);
+ if (inst->group.cache_attr_str) {
+ boot->cache_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->group.cache_attr_str);
if (!boot->cache_da) {
if (fr_dict_attr_add_name_only(fr_dict_unconst(dict_freeradius), fr_dict_root(dict_freeradius),
- inst->group.cache_attribute, FR_TYPE_STRING, NULL) < 0) {
+ inst->group.cache_attr_str, FR_TYPE_STRING, NULL) < 0) {
PERROR("Error creating cache attribute");
return -1;
}
- boot->cache_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->group.cache_attribute);
+ boot->cache_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->group.cache_attr_str);
}
} else {
boot->cache_da = boot->group_da; /* Default to the group_da */
}
+
+ if (inst->user.dn_attr_str) {
+ boot->user_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->user.dn_attr_str);
+ if (!boot->user_da) {
+ if (fr_dict_attr_add_name_only(fr_dict_unconst(dict_freeradius), fr_dict_root(dict_freeradius),
+ inst->user.dn_attr_str, FR_TYPE_STRING, NULL) < 0) {
+ PERROR("Error creating user DN cache attribute");
+ return -1;
+ }
+ boot->user_da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_freeradius), inst->user.dn_attr_str);
+ }
+ }
+
xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, NULL, ldap_xlat, FR_TYPE_STRING);
xlat_func_args_set(xlat, ldap_xlat_arg);
bool expect_password; //!< Allow the user to forcefully decide if a password should be
///< expected. Controls whether warnings are issued.
bool expect_password_is_set; //!< Whether an expect password value was provided.
+
+ char const *dn_attr_str; //!< Sets the attribute we use when creating and retrieving
+ //!< cached group memberships.
+
+ fr_dict_attr_t const *da; //!< The DA associated with this specific instance of the
+ //!< rlm_ldap module for caching user DNs between autz and
+ ///< auth phases.
} user;
/*
//!< resolution necessary to determine the DNs of those groups,
//!< then right them to the control list (LDAP-GroupDN).
- char const *cache_attribute; //!< Sets the attribute we use when creating and retrieving
+ char const *cache_attr_str; //!< Sets the attribute we use when creating and retrieving
//!< cached group memberships.
fr_dict_attr_t const *cache_da; //!< The DA associated with this specific instance of the
extern HIDDEN fr_dict_attr_t const *attr_password;
extern HIDDEN fr_dict_attr_t const *attr_cleartext_password;
extern HIDDEN fr_dict_attr_t const *attr_crypt_password;
-extern HIDDEN fr_dict_attr_t const *attr_ldap_userdn;
extern HIDDEN fr_dict_attr_t const *attr_nt_password;
extern HIDDEN fr_dict_attr_t const *attr_password_with_header;
/*
* user.c - User lookup functions
*/
-static inline char const *rlm_find_user_dn_cached(request_t *request)
+static inline char const *rlm_find_user_dn_cached(rlm_ldap_t const *inst, request_t *request)
{
fr_pair_t *vp;
- vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_ldap_userdn);
+ vp = fr_pair_find_by_da(&request->control_pairs, NULL, inst->user.da);
if (!vp) return NULL;
RDEBUG2("Using user DN from request \"%pV\"", &vp->data);