4 * @brief LDAP authorization and authentication module headers.
6 * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
7 * @copyright 2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
8 * @copyright 2013 Network RADIUS SARL<info@networkradius.com>
9 * @copyright 2013-2015 The FreeRADIUS Server Project.
14 #include <freeradius-devel/radiusd.h>
15 #include <freeradius-devel/modules.h>
18 * We're mostly using the new API now, but ldap_bind
19 * is in the list of deprecated functions, at we may
20 * always need to support that.
22 #define LDAP_DEPRECATED 1
28 * Ensure the have the ldap_create_sort_keylist()
29 * function too, else we can't use ldap_create_sort_control()
31 #if !defined(LDAP_CREATE_SORT_KEYLIST) || !defined(LDAP_FREE_SORT_KEYLIST)
32 # undef HAVE_LDAP_CREATE_SORT_CONTROL
36 * Because the LTB people define LDAP_VENDOR_VERSION_PATCH
37 * as X, which precludes its use in printf statements *sigh*
39 * Identifiers that are not macros, all evaluate to 0,
40 * which is why this works.
42 #if !defined(LDAP_VENDOR_VERSION_PATCH) || LDAP_VENDOR_VERSION_PATCH == 0
43 # undef LDAP_VENDOR_VERSION_PATCH
44 # define LDAP_VENDOR_VERSION_PATCH 0
48 * For compatibility with other LDAP libraries
50 #if !defined(LDAP_SCOPE_BASE) && defined(LDAP_SCOPE_BASEOBJECT)
51 # define LDAP_SCOPE_BASE LDAP_SCOPE_BASEOBJECT
54 #if !defined(LDAP_SCOPE_ONE) && defined(LDAP_SCOPE_ONELEVEL)
55 # define LDAP_SCOPE_ONE LDAP_SCOPE_ONELEVEL
58 #if !defined(LDAP_SCOPE_SUB) && defined(LDAP_SCOPE_SUBTREE)
59 # define LDAP_SCOPE_SUB LDAP_SCOPE_SUBTREE
62 #if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER)
63 # define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER
70 #if defined(HAVE_LDAP_URL_PARSE) && defined(HAVE_LDAP_IS_LDAP_URL) && defined(HAVE_LDAP_URL_DESC2STR)
71 # define LDAP_CAN_PARSE_URLS
74 #define MOD_PREFIX "rlm_ldap" //!< The name of the module.
76 #define LDAP_MAX_ATTRMAP 128 //!< Maximum number of mappings between LDAP and
77 //!< FreeRADIUS attributes.
78 #define LDAP_MAP_RESERVED 4 //!< Number of additional items to allocate in expanded
79 //!< attribute name arrays. Currently for enable attribute,
80 //!< group membership attribute, valuepair attribute,
81 //!< and profile attribute.
83 #define LDAP_MAX_CACHEABLE 64 //!< Maximum number of groups we retrieve from the server for
84 //!< a given user. If more than this number are retrieve the
85 //!< module returns invalid.
87 #define LDAP_MAX_GROUP_NAME_LEN 128 //!< Maximum name of a group name.
88 #define LDAP_MAX_ATTR_STR_LEN 256 //!< Maximum length of an xlat expanded LDAP attribute.
89 #define LDAP_MAX_FILTER_STR_LEN 1024 //!< Maximum length of an xlat expanded filter.
90 #define LDAP_MAX_DN_STR_LEN 1024 //!< Maximum length of an xlat expanded DN.
92 #define LDAP_VIRTUAL_DN_ATTR "dn" //!< 'Virtual' attribute which maps to the DN of the object.
94 typedef struct ldap_acct_section {
95 CONF_SECTION *cs; //!< Section configuration.
97 char const *reference; //!< Configuration reference string.
98 } ldap_acct_section_t;
100 typedef struct ldap_sasl {
101 char const *mech; //!< SASL mech(s) to try.
102 char const *proxy; //!< Identity to proxy.
103 char const *realm; //!< Kerberos realm.
106 typedef struct ldap_sasl_dynamic {
107 vp_tmpl_t *mech; //!< SASL mech(s) to try.
108 vp_tmpl_t *proxy; //!< Identity to proxy.
109 vp_tmpl_t *realm; //!< Kerberos realm.
112 typedef struct ldap_instance {
113 CONF_SECTION *cs; //!< Main configuration section for this instance.
114 fr_connection_pool_t *pool; //!< Connection pool instance.
116 char const *config_server; //!< Server set in the config.
117 char *server; //!< Initial server to bind to.
118 uint16_t port; //!< Port to use when binding to the server.
120 char const *admin_identity; //!< Identity we bind as when we need to query the LDAP
122 char const *admin_password; //!< Password used in administrative bind.
124 ldap_sasl admin_sasl; //!< SASL parameters used when binding as the admin.
126 char const *dereference_str; //!< When to dereference (never, searching, finding, always)
127 int dereference; //!< libldap value specifying dereferencing behaviour.
129 bool chase_referrals; //!< If the LDAP server returns a referral to another server
130 //!< or point in the tree, follow it, establishing new
131 //!< connections and binding where necessary.
132 bool chase_referrals_unset; //!< If true, use the OpenLDAP defaults for chase_referrals.
134 bool rebind; //!< Controls whether we set an ldad_rebind_proc function
135 //!< and so determines if we can bind to other servers whilst
136 //!< chasing referrals. If this is false, we will still chase
137 //!< referrals on the same server, but won't bind to other
140 uint32_t ldap_debug; //!< Debug flag for the SDK.
142 char const *name; //!< Instance name.
144 bool expect_password; //!< True if the user_map included a mapping between an LDAP
145 //!< attribute and one of our password reference attributes.
148 * RADIUS attribute to LDAP attribute maps
150 vp_map_t *user_map; //!< Attribute map applied to users and profiles.
153 * User object attributes and filters
155 vp_tmpl_t *userobj_filter; //!< Filter to retrieve only user objects.
156 vp_tmpl_t *userobj_base_dn; //!< DN to search for users under.
157 char const *userobj_scope_str; //!< Scope (sub, one, base).
158 char const *userobj_sort_by; //!< List of attributes to sort by.
159 LDAPControl *userobj_sort_ctrl; //!< Server side sort control.
161 int userobj_scope; //!< Search scope.
163 char const *userobj_membership_attr; //!< Attribute that describes groups the user is a member of.
164 char const *userobj_access_attr; //!< Attribute to check to see if the user should be locked out.
165 bool access_positive; //!< If true the presence of the attribute will allow access,
166 //!< else it will deny access.
168 char const *valuepair_attr; //!< Generic dynamic mapping attribute, contains a RADIUS
169 //!< attribute and value.
171 ldap_sasl_dynamic user_sasl; //!< SASL parameters used when binding as the user.
174 * Group object attributes and filters
176 char const *groupobj_filter; //!< Filter to retrieve only group objects.
177 vp_tmpl_t *groupobj_base_dn; //!< DN to search for users under.
178 char const *groupobj_scope_str; //!< Scope (sub, one, base).
179 int groupobj_scope; //!< Search scope.
181 char const *groupobj_name_attr; //!< The name of the group.
182 char const *groupobj_membership_filter; //!< Filter to only retrieve groups which contain
183 //!< the user as a member.
185 bool cacheable_group_name; //!< If true the server will determine complete set of group
186 //!< memberships for the current user object, and perform any
187 //!< resolution necessary to determine the names of those
188 //!< groups, then right them to the control list (LDAP-Group).
190 bool cacheable_group_dn; //!< If true the server will determine complete set of group
191 //!< memberships for the current user object, and perform any
192 //!< resolution necessary to determine the DNs of those groups,
193 //!< then right them to the control list (LDAP-GroupDN).
195 char const *cache_attribute; //!< Sets the attribute we use when creating and retrieving
196 //!< cached group memberships.
198 DICT_ATTR const *cache_da; //!< The DA associated with this specific instance of the
199 //!< rlm_ldap module.
201 DICT_ATTR const *group_da; //!< The DA associated with this specific instance of the
202 //!< rlm_ldap module.
207 char const *clientobj_filter; //!< Filter to retrieve only client objects.
208 char const *clientobj_base_dn; //!< DN to search for clients under.
209 char const *clientobj_scope_str; //!< Scope (sub, one, base).
210 int clientobj_scope; //!< Search scope.
212 bool do_clients; //!< If true, attempt to load clients on instantiation.
217 vp_tmpl_t *default_profile; //!< If this is set, we will search for a profile object
218 //!< with this name, and map any attributes it contains.
219 //!< No value should be set if profiles are not being used
220 //!< as there is an associated performance penalty.
221 char const *profile_attr; //!< Attribute that identifies profiles to apply. May appear
222 //!< in userobj or groupobj.
223 vp_tmpl_t *profile_filter; //!< Filter to retrieve only retrieve group objects.
228 ldap_acct_section_t *postauth; //!< Modify mappings for post-auth.
229 ldap_acct_section_t *accounting; //!< Modify mappings for accounting.
232 * TLS items. We should really normalize these with the
236 bool start_tls; //!< Send the Start TLS message to the LDAP directory
237 //!< to start encrypted communications using the standard
240 char const *tls_ca_file; //!< Sets the full path to a CA certificate (used to validate
241 //!< the certificate the server presents).
243 char const *tls_ca_path; //!< Sets the path to a directory containing CA certificates.
245 char const *tls_certificate_file; //!< Sets the path to the public certificate file we present
248 char const *tls_private_key_file; //!< Sets the path to the private key for our public
251 char const *tls_random_file; //!< Path to the random file if /dev/random and /dev/urandom
252 //!< are unavailable.
254 char const *tls_require_cert_str; //!< Sets requirements for validating the certificate the
255 //!< server presents.
257 int tls_require_cert; //!< OpenLDAP constant representing the require cert string.
262 uint32_t net_timeout; //!< How long we wait for new connections to the LDAP server
263 //!< to be established.
264 uint32_t res_timeout; //!< How long we wait for a result from the server.
265 uint32_t srv_timelimit; //!< How long the server should spent on a single request
266 //!< (also bounded by value on the server).
272 bool edir; //!< If true attempt to retrieve the user's cleartext password
273 //!< using the Universal Password feature of Novell eDirectory.
274 bool edir_autz; //!< If true, and we have the Universal Password, bind with it
275 //!< to perform additional authorisation checks.
280 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
281 uint32_t keepalive_idle; //!< Number of seconds a connections needs to remain idle
282 //!< before TCP starts sending keepalive probes.
284 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
285 uint32_t keepalive_probes; //!< Number of missed timeouts before the connection is
288 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
289 uint32_t keepalive_interval; //!< Interval between keepalive probes.
292 LDAP *handle; //!< Hack for OpenLDAP libldap global initialisation.
295 /** Tracks the state of a libldap connection handle
298 typedef struct ldap_handle {
299 LDAP *handle; //!< libldap handle.
300 bool rebound; //!< Whether the connection has been rebound to something
301 //!< other than the admin user.
302 bool referred; //!< Whether the connection is now established a server
303 //!< other than the configured one.
304 rlm_ldap_t *inst; //!< rlm_ldap configuration.
307 /** Result of expanding the RHS of a set of maps
309 * Used to store the array of attributes we'll be querying for.
311 typedef struct rlm_ldap_map_exp {
312 vp_map_t const *maps; //!< Head of list of maps we expanded the RHS of.
313 char const *attrs[LDAP_MAX_ATTRMAP + LDAP_MAP_RESERVED + 1]; //!< Reserve some space for access attributes
314 //!< and NULL termination.
315 TALLOC_CTX *ctx; //!< Context to allocate new attributes in.
316 int count; //!< Index on next free element.
317 } rlm_ldap_map_exp_t;
319 /** Contains a collection of values
322 typedef struct rlm_ldap_result {
323 struct berval **values; //!< libldap struct containing bv_val (char *)
324 //!< and length bv_len.
325 int count; //!< Number of values.
328 /** Codes returned by rlm_ldap internal functions
332 LDAP_PROC_CONTINUE = 1, //!< Operation is in progress.
333 LDAP_PROC_SUCCESS = 0, //!< Operation was successfull.
335 LDAP_PROC_ERROR = -1, //!< Unrecoverable library/server error.
337 LDAP_PROC_RETRY = -2, //!< Transitory error, caller should retry the operation
338 //!< with a new connection.
340 LDAP_PROC_NOT_PERMITTED = -3, //!< Operation was not permitted, either current user was
341 //!< locked out in the case of binds, or has insufficient
344 LDAP_PROC_REJECT = -4, //!< Bind failed, user was rejected.
346 LDAP_PROC_BAD_DN = -5, //!< Specified an invalid object in a bind or search DN.
348 LDAP_PROC_NO_RESULT = -6 //!< Got no results.
352 * Some functions may be called with a NULL request structure, this
353 * simplifies switching certain messages from the request log to
356 #define LDAP_INFO(fmt, ...) INFO("rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
357 #define LDAP_WARN(fmt, ...) WARN("rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
359 #define LDAP_DBGW(fmt, ...) radlog(L_DBG_WARN, "rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
360 #define LDAP_DBGW_REQ(fmt, ...) do { if (request) {RWDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_DBGW(fmt, ##__VA_ARGS__);}} while (0)
362 #define LDAP_DBG(fmt, ...) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
363 #define LDAP_DBG_REQ(fmt, ...) do { if (request) {RDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
365 #define LDAP_DBG2(fmt, ...) if (rad_debug_lvl >= L_DBG_LVL_2) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
366 #define LDAP_DBG_REQ2(fmt, ...) do { if (request) {RDEBUG2(fmt, ##__VA_ARGS__);} else if (rad_debug_lvl >= L_DBG_LVL_2) {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
368 #define LDAP_DBG3(fmt, ...) if (rad_debug_lvl >= L_DBG_LVL_3) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
369 #define LDAP_DBG_REQ3(fmt, ...) do { if (request) {RDEBUG3(fmt, ##__VA_ARGS__);} else if (rad_debug_lvl >= L_DBG_LVL_3) {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
371 #define LDAP_ERR(fmt, ...) ERROR("rlm_ldap (%s): " fmt, inst->name, ##__VA_ARGS__)
372 #define LDAP_ERR_REQ(fmt, ...) do { if (request) {REDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_ERR(fmt, ##__VA_ARGS__);}} while (0)
374 #define LDAP_EXT() if (extra) LDAP_ERR(extra)
375 #define LDAP_EXT_REQ() do { if (extra) { if (request) REDEBUG("%s", extra); else LDAP_ERR("%s", extra); }} while (0)
377 extern FR_NAME_NUMBER const ldap_scope[];
378 extern FR_NAME_NUMBER const ldap_tls_require_cert[];
381 * ldap.c - Wrappers arounds OpenLDAP functions.
383 size_t rlm_ldap_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg);
385 bool rlm_ldap_is_dn(char const *in, size_t inlen);
387 size_t rlm_ldap_normalise_dn(char *out, char const *in);
389 ssize_t rlm_ldap_xlat_filter(REQUEST *request, char const **sub, size_t sublen, char *out, size_t outlen);
391 ldap_rcode_t rlm_ldap_bind(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn, char const *dn,
392 char const *password, ldap_sasl *sasl, bool retry);
394 char const *rlm_ldap_error_str(ldap_handle_t const *conn);
396 ldap_rcode_t rlm_ldap_search(LDAPMessage **result, rlm_ldap_t const *inst, REQUEST *request,
397 ldap_handle_t **pconn,
398 char const *dn, int scope, char const *filter, char const * const *attrs,
399 LDAPControl **serverctrls, LDAPControl **clientctrls);
401 ldap_rcode_t rlm_ldap_modify(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn,
402 char const *dn, LDAPMod *mods[]);
404 char const *rlm_ldap_find_user(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn,
405 char const *attrs[], bool force, LDAPMessage **result, rlm_rcode_t *rcode);
407 rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn,
410 void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request);
413 * ldap.c - Callbacks for the connection pool API.
415 ldap_rcode_t rlm_ldap_result(rlm_ldap_t const *inst, ldap_handle_t const *conn, int msgid, char const *dn,
416 LDAPMessage **result, char const **error, char **extra);
418 char *rlm_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in);
420 int rlm_ldap_global_init(rlm_ldap_t *inst) CC_HINT(nonnull);
422 void *mod_conn_create(TALLOC_CTX *ctx, void *instance);
424 ldap_handle_t *mod_conn_get(rlm_ldap_t const *inst, REQUEST *request);
426 void mod_conn_release(rlm_ldap_t const *inst, ldap_handle_t *conn);
429 * groups.c - Group membership functions.
431 rlm_rcode_t rlm_ldap_cacheable_userobj(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn,
432 LDAPMessage *entry, char const *attr);
434 rlm_rcode_t rlm_ldap_cacheable_groupobj(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn);
436 rlm_rcode_t rlm_ldap_check_groupobj_dynamic(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn,
439 rlm_rcode_t rlm_ldap_check_userobj_dynamic(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn,
440 char const *dn, VALUE_PAIR *check);
442 rlm_rcode_t rlm_ldap_check_cached(rlm_ldap_t const *inst, REQUEST *request, VALUE_PAIR *check);
445 * attrmap.c - Attribute mapping code.
447 int rlm_ldap_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx);
449 int rlm_ldap_map_verify(vp_map_t *map, void *instance);
451 int rlm_ldap_map_expand(rlm_ldap_map_exp_t *expanded, REQUEST *request, vp_map_t const *maps);
453 int rlm_ldap_map_do(rlm_ldap_t const *inst, REQUEST *request, LDAP *handle,
454 rlm_ldap_map_exp_t const *expanded, LDAPMessage *entry);
457 * clients.c - Dynamic clients (bulk load).
459 int rlm_ldap_client_load(rlm_ldap_t const *inst, CONF_SECTION *tmpl, CONF_SECTION *cs);
462 * edir.c - Magic extensions for Novell
464 int nmasldap_get_password(LDAP *ld, char const *dn, char *password, size_t *len);
466 char const *edir_errstr(int code);
469 * sasl.s - SASL bind functions
471 ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request,
472 ldap_handle_t *pconn, char const *dn,
473 char const *password, ldap_sasl *sasl,
474 char const **error, char **error_extra);