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 3 //!< Number of additional items to allocate in expanded
20 //!< attribute name arrays. Currently for enable attribute,
21 //!< group membership attribute, and profile attribute.
23 #define LDAP_MAX_CACHEABLE 64 //!< Maximum number of groups we retrieve from the server for
24 //!< a given user. If more than this number are retrieve the
25 //!< module returns invalid.
27 #define LDAP_MAX_GROUP_NAME_LEN 128 //!< Maximum name of a group name.
28 #define LDAP_MAX_ATTR_STR_LEN 256 //!< Maximum length of an xlat expanded LDAP attribute.
29 #define LDAP_MAX_FILTER_STR_LEN 1024 //!< Maximum length of an xlat expanded filter.
30 #define LDAP_MAX_DN_STR_LEN 2048 //!< Maximum length of an xlat expanded DN.
33 * The default setting for TLS Certificate Verification
35 #define TLS_DEFAULT_VERIFY "allow"
37 typedef struct ldap_acct_section {
38 CONF_SECTION *cs; //!< Section configuration.
40 const char *reference; //!< Configuration reference string.
41 } ldap_acct_section_t;
43 typedef struct ldap_instance {
44 CONF_SECTION *cs; //!< Main configuration section for this instance.
45 fr_connection_pool_t *pool; //!< Connection pool instance.
47 char *server; //!< Initial server to bind to.
48 int is_url; //!< Whether ldap_is_ldap_url says 'server' is an
50 int port; //!< Port to use when binding to the server.
52 char *admin_dn; //!< DN we bind as when we need to query the LDAP
54 char *password; //!< Password used in administrative bind.
56 char *base_dn; //!< The point in the LDAP directory that encompasses all the
57 //!< userobj and groupobj that we want to retrieve.
59 int chase_referrals; //!< If the LDAP server returns a referral to another server
60 //!< or point in the tree, follow it, establishing new
61 //!< connections and binding where necessary.
63 int rebind; //!< Controls whether we set an ldad_rebind_proc function
64 //!< and so determines if we can bind to other servers whilst
65 //!< chasing referrals. If this is false, we will still chase
66 //!< referrals on the same server, but won't bind to other
69 int ldap_debug; //!< Debug flag for the SDK.
71 const char *xlat_name; //!< Instance name.
73 int expect_password; //!< True if the user_map included a mapping between an LDAP
74 //!< attribute and one of our password reference attributes.
77 * RADIUS attribute to LDAP attribute maps
79 value_pair_map_t *user_map; //!< Attribute map applied to users and profiles.
82 * User object attributes and filters
84 const char *userobj_filter; //!< Filter to retrieve only user objects.
85 const char *userobj_membership_attr; //!< Attribute that describes groups the user is a member of.
86 char *userobj_access_attr; //!< Attribute to check to see if the user should be locked out.
87 int access_positive; //!< If true the presence of the attribute will allow access,
88 //!< else it will deny access.
90 int cacheable_group_name; //!< If true the server will determine complete set of group
91 //!< memberships for the current user object, and perform any
92 //!< resolution necessary to determine the names of those
93 //!< groups, then right them to the control list (LDAP-Group).
95 int cacheable_group_dn; //!< If true the server will determine complete set of group
96 //!< memberships for the current user object, and perform any
97 //!< resolution necessary to determine the DNs of those groups,
98 //!< then right them to the control list (LDAP-GroupDN).
100 * Group object attributes and filters
102 const char *groupobj_name_attr; //!< The name of the group.
103 const char *groupobj_membership_filter; //!< Filter to only retrieve groups which contain
104 //!< the user as a member.
109 const char *base_filter; //!< Base filter combined with all other filters.
110 const char *default_profile; //!< If this is set, we will search for a profile object
111 //!< with this name, and map any attributes it contains.
112 //!< No value should be set if profiles are not being used
113 //!< as there is an associated performance penalty.
114 const char *profile_attr; //!< Attribute that identifies profiles to apply. May appear
115 //!< in userobj or groupobj.
121 ldap_acct_section_t *postauth; //!< Modify mappings for post-auth.
122 ldap_acct_section_t *accounting; //!< Modify mappings for accounting.
125 * TLS items. We should really normalize these with the
129 int start_tls; //!< Send the Start TLS message to the LDAP directory
130 //!< to start encrypted communications using the standard
133 char *tls_cacertfile; //!< Sets the full path to a CA certificate (used to validate
134 //!< the certificate the server presents).
136 char *tls_cacertdir; //!< Sets the path to a directory containing CA certificates.
138 char *tls_certfile; //!< Sets the path to the public certificate file we present
141 char *tls_keyfile; //!< Sets the path to the private key for our public
144 char *tls_randfile; //!< Path to the random file if /dev/random and /dev/urandom
145 //!< are unavailable.
147 char *tls_require_cert; //!< Sets requirements for validating the certificate the
148 //!< server presents.
154 int net_timeout; //!< How long we wait for new connections to the LDAP server
155 //!< to be established.
156 int res_timeout; //!< How long we wait for a result from the server.
157 int srv_timelimit; //!< How long the server should spent on a single request
158 //!< (also bounded by value on the server).
164 int edir; //!< If true attempt to retrieve the user's Cleartext password
165 //!< using the Universal Password feature of Novell eDirectory.
166 int edir_autz; //!< If true, and we have the Universal Password, bind with it
167 //!< to perform additional authorisation checks.
172 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
173 int keepalive_idle; //!< Number of seconds a connections needs to remain idle
174 //!< before TCP starts sending keepalive probes.
176 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
177 int keepalive_probes; //!< Number of missed timeouts before the connection is
180 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
181 int keepalive_interval; //!< Interval between keepalive probes.
186 typedef struct ldap_handle {
187 LDAP *handle; //!< LDAP LD handle.
188 int rebound; //!< Whether the connection has been rebound to something
189 //!< other than the admin user.
190 int referred; //!< Whether the connection is now established a server
191 //!< other than the configured one.
192 ldap_instance_t *inst; //!< rlm_ldap configuration.
195 typedef struct rlm_ldap_map_xlat {
196 const value_pair_map_t *maps;
197 const char *attrs[LDAP_MAX_ATTRMAP + LDAP_MAP_RESERVED + 1]; //!< Reserve some space for access attributes
198 //!< and NULL termination.
200 } rlm_ldap_map_xlat_t;
202 typedef struct rlm_ldap_result {
208 LDAP_PROC_SUCCESS = 0, //!< Operation was successfull.
210 LDAP_PROC_ERROR = -1, //!< Unrecoverable library/server error.
212 LDAP_PROC_RETRY = -2, //!< Transitory error, caller should retry the operation
213 //!< with a new connection.
215 LDAP_PROC_NOT_PERMITTED = -3, //!< Operation was not permitted, either current user was
216 //!< locked out in the case of binds, or has insufficient
219 LDAP_PROC_REJECT = -4, //!< Bind failed, user was rejected.
221 LDAP_PROC_BAD_DN = -5, //!< Specified an invalid object in a bind or search DN.
223 LDAP_PROC_NO_RESULT = -6 //!< Got no results.
227 * Some functions may be called with a NULL request structure, this
228 * simplifies switching certain messages from the request log to
231 #define LDAP_INFO(fmt, ...) radlog(L_INFO, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
233 #define LDAP_DBGW(fmt, ...) radlog(L_DBG_WARN, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
234 #define LDAP_DBGW_REQ(fmt, ...) do { if (request) {RDEBUGW(fmt, ##__VA_ARGS__);} else {LDAP_DBGW(fmt, ##__VA_ARGS__);}} while (0)
236 #define LDAP_ERR(fmt, ...) radlog(L_ERR, "rlm_ldap (%s): " fmt, inst->xlat_name, ##__VA_ARGS__)
237 #define LDAP_ERR_REQ(fmt, ...) do { if (request) {RDEBUGE(fmt, ##__VA_ARGS__);} else {LDAP_ERR(fmt, ##__VA_ARGS__);}} while (0)
239 #define LDAP_EXT() if (extra) LDAP_ERR(extra)
240 #define LDAP_EXT_REQ() do { if (extra) { if (request) RDEBUGE("%s", extra); else LDAP_ERR("%s", extra); }} while (0)
243 * ldap.c - Wrappers arounds OpenLDAP functions.
245 size_t rlm_ldap_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, const char *in, UNUSED void *arg);
247 int rlm_ldap_is_dn(const char *str);
249 ldap_rcode_t rlm_ldap_bind(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn, const char *dn,
250 const char *password, int retry);
252 ldap_rcode_t rlm_ldap_search(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
253 const char *dn, int scope, const char *filter, const char * const *attrs,
254 LDAPMessage **result);
256 ldap_rcode_t rlm_ldap_modify(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
257 const char *dn, LDAPMod *mods[]);
259 const char *rlm_ldap_find_user(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
260 const char *attrs[], int force, LDAPMessage **result, rlm_rcode_t *rcode);
262 rlm_rcode_t rlm_ldap_group_name2dn(const ldap_instance_t *inst, REQUEST *request,
263 ldap_handle_t **pconn, char **names, char **out,
266 rlm_rcode_t rlm_ldap_group_dn2name(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
267 const char *dn, char **out);
269 rlm_rcode_t rlm_ldap_cacheable_membership(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
272 rlm_rcode_t rlm_ldap_check_access(const ldap_instance_t *inst, REQUEST *request, const ldap_handle_t *conn,
275 void rlm_ldap_check_reply(const ldap_instance_t *inst, REQUEST *request);
278 * ldap.c - Callbacks for the connection pool API.
280 void *rlm_ldap_conn_create(void *ctx);
282 int rlm_ldap_conn_delete(UNUSED void *ctx, void *connection);
284 ldap_handle_t *rlm_ldap_get_socket(const ldap_instance_t *inst, REQUEST *request);
286 void rlm_ldap_release_socket(const ldap_instance_t *inst, ldap_handle_t *conn);
289 * attrmap.c - Attribute mapping code.
291 int rlm_ldap_map_verify(ldap_instance_t *inst, value_pair_map_t **head);
293 void rlm_ldap_map_xlat_free(const rlm_ldap_map_xlat_t *expanded);
295 int rlm_ldap_map_xlat(REQUEST *request, const value_pair_map_t *maps, rlm_ldap_map_xlat_t *expanded);
297 void rlm_ldap_map_do(const ldap_instance_t *inst, REQUEST *request, LDAP *handle,
298 const rlm_ldap_map_xlat_t *expanded, LDAPMessage *entry);
300 rlm_rcode_t rlm_ldap_map_profile(const ldap_instance_t *inst, REQUEST *request, ldap_handle_t **pconn,
301 const char *profile, const rlm_ldap_map_xlat_t *expanded);
304 * edir.c - Magic extensions for Novell
307 int nmasldap_get_password(LDAP *ld, const char *dn, char *password, size_t *len);