4 * @brief LDAP authorization and authentication module headers.
6 * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
7 * @copyright 2013 Network RADIUS SARL<info@networkradius.com>
8 * @copyright 2013 The FreeRADIUS Server Project.
13 #include <freeradius-devel/radiusd.h>
14 #include <freeradius-devel/modules.h>
17 #define LDAP_MAX_ATTRMAP 128 //!< Maximum number of mappings between LDAP and
18 //!< FreeRADIUS attributes.
19 #define LDAP_MAP_RESERVED 4 //!< Number of additional items to allocate in expanded
20 //!< attribute name arrays. Currently for enable attribute,
21 //!< group membership attribute, valuepair attribute,
22 //!< and profile attribute.
24 #define LDAP_MAX_CACHEABLE 64 //!< Maximum number of groups we retrieve from the server for
25 //!< a given user. If more than this number are retrieve the
26 //!< module returns invalid.
28 #define LDAP_MAX_GROUP_NAME_LEN 128 //!< Maximum name of a group name.
29 #define LDAP_MAX_ATTR_STR_LEN 256 //!< Maximum length of an xlat expanded LDAP attribute.
30 #define LDAP_MAX_FILTER_STR_LEN 1024 //!< Maximum length of an xlat expanded filter.
31 #define LDAP_MAX_DN_STR_LEN 2048 //!< Maximum length of an xlat expanded DN.
33 typedef struct ldap_acct_section {
34 CONF_SECTION *cs; //!< Section configuration.
36 char const *reference; //!< Configuration reference string.
37 } ldap_acct_section_t;
39 typedef struct ldap_instance {
40 CONF_SECTION *cs; //!< Main configuration section for this instance.
41 fr_connection_pool_t *pool; //!< Connection pool instance.
43 char const *server; //!< Initial server to bind to.
44 int is_url; //!< Whether ldap_is_ldap_url says 'server' is an
46 int port; //!< Port to use when binding to the server.
48 char const *admin_dn; //!< DN we bind as when we need to query the LDAP
50 char const *password; //!< Password used in administrative bind.
52 bool chase_referrals; //!< If the LDAP server returns a referral to another server
53 //!< or point in the tree, follow it, establishing new
54 //!< connections and binding where necessary.
55 bool chase_referrals_unset; //!< If true, use the OpenLDAP defaults for chase_referrals.
57 bool rebind; //!< Controls whether we set an ldad_rebind_proc function
58 //!< and so determines if we can bind to other servers whilst
59 //!< chasing referrals. If this is false, we will still chase
60 //!< referrals on the same server, but won't bind to other
63 int ldap_debug; //!< Debug flag for the SDK.
65 char const *xlat_name; //!< Instance name.
67 int expect_password; //!< True if the user_map included a mapping between an LDAP
68 //!< attribute and one of our password reference attributes.
71 * RADIUS attribute to LDAP attribute maps
73 value_pair_map_t *user_map; //!< Attribute map applied to users and profiles.
76 * User object attributes and filters
78 char const *userobj_filter; //!< Filter to retrieve only user objects.
79 char const *userobj_base_dn; //!< DN to search for users under.
80 char const *userobj_scope_str; //!< Scope (sub, one, base).
81 int userobj_scope; //!< Search scope.
83 char const *userobj_membership_attr; //!< Attribute that describes groups the user is a member of.
84 char *userobj_access_attr; //!< Attribute to check to see if the user should be locked out.
85 bool access_positive; //!< If true the presence of the attribute will allow access,
86 //!< else it will deny access.
88 char const *valuepair_attr; //!< Generic dynamic mapping attribute, contains a RADIUS
89 //!< attribute and value.
92 * Group object attributes and filters
95 char const *groupobj_filter; //!< Filter to retrieve only group objects.
96 char const *groupobj_base_dn; //!< DN to search for users under.
97 char const *groupobj_scope_str; //!< Scope (sub, one, base).
98 int groupobj_scope; //!< Search scope.
100 char const *groupobj_name_attr; //!< The name of the group.
101 char const *groupobj_membership_filter; //!< Filter to only retrieve groups which contain
102 //!< the user as a member.
104 bool cacheable_group_name; //!< If true the server will determine complete set of group
105 //!< memberships for the current user object, and perform any
106 //!< resolution necessary to determine the names of those
107 //!< groups, then right them to the control list (LDAP-Group).
109 bool cacheable_group_dn; //!< If true the server will determine complete set of group
110 //!< memberships for the current user object, and perform any
111 //!< resolution necessary to determine the DNs of those groups,
112 //!< then right them to the control list (LDAP-GroupDN).
114 DICT_ATTR const *group_da; //!< The DA associated with this specific version of the
115 //!< rlm_ldap module.
120 char const *clientobj_filter; //!< Filter to retrieve only client objects.
121 char const *clientobj_base_dn; //!< DN to search for clients under.
122 char const *clientobj_scope_str; //!< Scope (sub, one, base).
123 int clientobj_scope; //!< Search scope.
125 char const *clientobj_identifier; //!< IP/FQDN/IP Prefix for the NAS.
126 char const *clientobj_shortname; //!< Short/Friendly name to assign.
127 char const *clientobj_type; //!< Type of NAS (not usually used).
128 char const *clientobj_secret; //!< RADIUS secret.
129 char const *clientobj_server; //!< Virtual server to associate the client with.
130 char const *clientobj_require_ma; //!< Require message-authenticator.
132 bool do_clients; //!< If true, attempt to load clients on instantiation.
137 char const *default_profile; //!< If this is set, we will search for a profile object
138 //!< with this name, and map any attributes it contains.
139 //!< No value should be set if profiles are not being used
140 //!< as there is an associated performance penalty.
141 char const *profile_attr; //!< Attribute that identifies profiles to apply. May appear
142 //!< in userobj or groupobj.
143 char const *profile_filter; //!< Filter to retrieve only retrieve group objects.
148 ldap_acct_section_t *postauth; //!< Modify mappings for post-auth.
149 ldap_acct_section_t *accounting; //!< Modify mappings for accounting.
152 * TLS items. We should really normalize these with the
156 bool start_tls; //!< Send the Start TLS message to the LDAP directory
157 //!< to start encrypted communications using the standard
160 char const *tls_ca_file; //!< Sets the full path to a CA certificate (used to validate
161 //!< the certificate the server presents).
163 char const *tls_ca_path; //!< Sets the path to a directory containing CA certificates.
165 char const *tls_certificate_file; //!< Sets the path to the public certificate file we present
168 char const *tls_private_key_file; //!< Sets the path to the private key for our public
171 char const *tls_random_file; //!< Path to the random file if /dev/random and /dev/urandom
172 //!< are unavailable.
174 char const *tls_require_cert_str; //!< Sets requirements for validating the certificate the
175 //!< server presents.
177 int tls_require_cert; //!< OpenLDAP constant representing the require cert string.
183 int net_timeout; //!< How long we wait for new connections to the LDAP server
184 //!< to be established.
185 int res_timeout; //!< How long we wait for a result from the server.
186 int srv_timelimit; //!< How long the server should spent on a single request
187 //!< (also bounded by value on the server).
193 bool edir; //!< If true attempt to retrieve the user's Cleartext password
194 //!< using the Universal Password feature of Novell eDirectory.
195 bool edir_autz; //!< If true, and we have the Universal Password, bind with it
196 //!< to perform additional authorisation checks.
201 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
202 int keepalive_idle; //!< Number of seconds a connections needs to remain idle
203 //!< before TCP starts sending keepalive probes.
205 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
206 int keepalive_probes; //!< Number of missed timeouts before the connection is
209 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
210 int keepalive_interval; //!< Interval between keepalive probes.
215 typedef struct ldap_handle {
216 LDAP *handle; //!< LDAP LD handle.
217 int rebound; //!< Whether the connection has been rebound to something
218 //!< other than the admin user.
219 int referred; //!< Whether the connection is now established a server
220 //!< other than the configured one.
221 ldap_instance_t *inst; //!< rlm_ldap configuration.
224 typedef struct rlm_ldap_map_xlat {
225 value_pair_map_t const *maps;
226 char const *attrs[LDAP_MAX_ATTRMAP + LDAP_MAP_RESERVED + 1]; //!< Reserve some space for access attributes
227 //!< and NULL termination.
229 } rlm_ldap_map_xlat_t;
231 typedef struct rlm_ldap_result {
237 LDAP_PROC_SUCCESS = 0, //!< Operation was successfull.
239 LDAP_PROC_ERROR = -1, //!< Unrecoverable library/server error.
241 LDAP_PROC_RETRY = -2, //!< Transitory error, caller should retry the operation
242 //!< with a new connection.
244 LDAP_PROC_NOT_PERMITTED = -3, //!< Operation was not permitted, either current user was
245 //!< locked out in the case of binds, or has insufficient
248 LDAP_PROC_REJECT = -4, //!< Bind failed, user was rejected.
250 LDAP_PROC_BAD_DN = -5, //!< Specified an invalid object in a bind or search DN.
252 LDAP_PROC_NO_RESULT = -6 //!< Got no results.
256 * Some functions may be called with a NULL request structure, this
257 * simplifies switching certain messages from the request log to
260 #define LDAP_INFO(fmt, ...) INFO("rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
261 #define LDAP_WARN(fmt, ...) WARN("rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
263 #define LDAP_DBGW(fmt, ...) radlog(L_DBG_WARN, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
264 #define LDAP_DBGW_REQ(fmt, ...) do { if (request) {RWDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_DBGW(fmt, ##__VA_ARGS__);}} while (0)
266 #define LDAP_DBG(fmt, ...) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
267 #define LDAP_DBG_REQ(fmt, ...) do { if (request) {RDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
269 #define LDAP_DBG2(fmt, ...) if (debug_flag >= L_DBG_LVL_2) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
270 #define LDAP_DBG_REQ2(fmt, ...) do { if (request) {RDEBUG2(fmt, ##__VA_ARGS__);} else if (debug_flag >= L_DBG_LVL_2) {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
272 #define LDAP_DBG3(fmt, ...) if (debug_flag >= L_DBG_LVL_3) radlog(L_DBG, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
273 #define LDAP_DBG_REQ3(fmt, ...) do { if (request) {RDEBUG3(fmt, ##__VA_ARGS__);} else if (debug_flag >= L_DBG_LVL_3) {LDAP_DBG(fmt, ##__VA_ARGS__);}} while (0)
275 #define LDAP_ERR(fmt, ...) ERROR("rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
276 #define LDAP_ERR_REQ(fmt, ...) do { if (request) {REDEBUG(fmt, ##__VA_ARGS__);} else {LDAP_ERR(fmt, ##__VA_ARGS__);}} while (0)
278 #define LDAP_EXT() if (extra) LDAP_ERR(extra)
279 #define LDAP_EXT_REQ() do { if (extra) { if (request) REDEBUG("%s", extra); else LDAP_ERR("%s", extra); }} while (0)
281 extern FR_NAME_NUMBER const ldap_scope[];
282 extern FR_NAME_NUMBER const ldap_tls_require_cert[];
285 * ldap.c - Wrappers arounds OpenLDAP functions.
287 size_t rlm_ldap_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg);
289 int rlm_ldap_is_dn(char const *str);
291 ssize_t rlm_ldap_xlat_filter(REQUEST *request, char const **sub, size_t sublen, char *out, size_t outlen);
293 ldap_rcode_t rlm_ldap_bind(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn, char const *dn,
294 char const *password, int retry);
296 char const *rlm_ldap_error_str(ldap_handle_t const *conn);
298 ldap_rcode_t rlm_ldap_search(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
299 char const *dn, int scope, char const *filter, char const * const *attrs,
300 LDAPMessage **result);
302 ldap_rcode_t rlm_ldap_modify(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
303 char const *dn, LDAPMod *mods[]);
305 char const *rlm_ldap_find_user(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
306 char const *attrs[], int force, LDAPMessage **result, rlm_rcode_t *rcode);
308 rlm_rcode_t rlm_ldap_check_access(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t const *conn,
311 void rlm_ldap_check_reply(ldap_instance_t const *inst, REQUEST *request);
314 * ldap.c - Callbacks for the connection pool API.
316 void *mod_conn_create(void *ctx);
318 int mod_conn_delete(UNUSED void *instance, void *handle);
320 ldap_handle_t *rlm_ldap_get_socket(ldap_instance_t const *inst, REQUEST *request);
322 void rlm_ldap_release_socket(ldap_instance_t const *inst, ldap_handle_t *conn);
325 * groups.c - Group membership functions.
328 rlm_rcode_t rlm_ldap_cacheable_userobj(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
329 LDAPMessage *entry, char const *attr);
331 rlm_rcode_t rlm_ldap_cacheable_groupobj(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn);
333 rlm_rcode_t rlm_ldap_check_groupobj_dynamic(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
336 rlm_rcode_t rlm_ldap_check_userobj_dynamic(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
337 char const *dn, VALUE_PAIR *check);
339 rlm_rcode_t rlm_ldap_check_cached(ldap_instance_t const *inst, REQUEST *request, VALUE_PAIR *check);
342 * attrmap.c - Attribute mapping code.
344 int rlm_ldap_map_verify(ldap_instance_t *inst, value_pair_map_t **head);
346 void rlm_ldap_map_xlat_free(rlm_ldap_map_xlat_t const *expanded);
348 int rlm_ldap_map_xlat(REQUEST *request, value_pair_map_t const *maps, rlm_ldap_map_xlat_t *expanded);
350 void rlm_ldap_map_do(ldap_instance_t const *inst, REQUEST *request, LDAP *handle,
351 rlm_ldap_map_xlat_t const *expanded, LDAPMessage *entry);
353 rlm_rcode_t rlm_ldap_map_profile(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
354 char const *profile, rlm_ldap_map_xlat_t const *expanded);
357 * clients.c - Dynamic clients (bulk load).
359 int rlm_ldap_load_clients(ldap_instance_t const *inst);
362 * edir.c - Magic extensions for Novell
364 int nmasldap_get_password(LDAP *ld, char const *dn, char *password, size_t *len);
366 char const *edir_errstr(int code);