The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
profile.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: eaf3a74c5207144d24b4c6762ad0889d13626668 $
19  * @file rlm_ldap.c
20  * @brief LDAP authorization and authentication module.
21  *
22  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  * @author Alan DeKok (aland@freeradius.org)
24  *
25  * @copyright 2012,2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26  * @copyright 2013,2015 Network RADIUS SAS (legal@networkradius.com)
27  * @copyright 2012 Alan DeKok (aland@freeradius.org)
28  * @copyright 1999-2013 The FreeRADIUS Server Project.
29  */
30 RCSID("$Id: eaf3a74c5207144d24b4c6762ad0889d13626668 $")
31 
33 
34 #include "rlm_ldap.h"
35 #include <freeradius-devel/ldap/conf.h>
36 
37 #include <freeradius-devel/server/map_proc.h>
38 #include <freeradius-devel/server/module_rlm.h>
39 
40 /** Holds state of in progress async profile lookups
41  *
42  */
43 typedef struct {
44  fr_ldap_result_code_t *ret; //!< Result of the query and applying the map.
46  char const *dn;
47  rlm_ldap_t const *inst;
50 
51 /** Process the results of a profile lookup
52  *
53  */
54 static unlang_action_t ldap_map_profile_resume(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request,
55  void *uctx)
56 {
57  ldap_profile_ctx_t *profile_ctx = talloc_get_type_abort(uctx, ldap_profile_ctx_t);
58  fr_ldap_query_t *query = profile_ctx->query;
59  LDAP *handle;
60  LDAPMessage *entry = NULL;
61  int ldap_errno;
62  char *dn = NULL;
63 
64  /*
65  * Tell the caller what happened
66  */
67  if (profile_ctx->ret) *profile_ctx->ret = query->ret;
68 
69  switch (query->ret) {
71  break;
72 
74  case LDAP_RESULT_BAD_DN:
75  RDEBUG2("Profile object \"%s\" not found", profile_ctx->dn);
76  goto finish;
77 
78  default:
79  goto finish;
80  }
81 
82  fr_assert(query->result);
83  handle = query->ldap_conn->handle;
84 
85  entry = ldap_first_entry(handle, query->result);
86  if (!entry) {
87  ldap_get_option(handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
88  REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
89  if (profile_ctx->ret) *profile_ctx->ret = LDAP_RESULT_NO_RESULT;
90  goto finish;
91  }
92 
93  RDEBUG2("Processing profile attributes");
94  RINDENT();
95  while (entry) {
96  if (RDEBUG_ENABLED2) {
97  dn = ldap_get_dn(handle, entry);
98  RDEBUG2("Processing \"%s\"", dn);
99  ldap_memfree(dn);
100  }
101  RINDENT();
102  if (fr_ldap_map_do(request, profile_ctx->inst->valuepair_attr,
103  profile_ctx->expanded, entry) < 0) {
104  if (profile_ctx->ret) *profile_ctx->ret = LDAP_RESULT_ERROR;
105  }
106  entry = ldap_next_entry(handle, entry);
107  REXDENT();
108  }
109  REXDENT();
110 
111 finish:
112  talloc_free(profile_ctx);
114 }
115 
116 /** Cancel an in progress profile lookup
117  *
118  */
119 static void ldap_map_profile_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
120 {
121  ldap_profile_ctx_t *profile_ctx = talloc_get_type_abort(uctx, ldap_profile_ctx_t);
122 
123  if (!profile_ctx->query || !profile_ctx->query->treq) return;
124 
125  trunk_request_signal_cancel(profile_ctx->query->treq);
126 }
127 
128 /** Search for and apply an LDAP profile
129  *
130  * LDAP profiles are mapped using the same attribute map as user objects, they're used to add common
131  * sets of attributes to the request.
132  *
133  * @param[out] ret Where to write the result of the query.
134  * @param[in] inst LDAP module instance.
135  * @param[in] request Current request.
136  * @param[in] ttrunk Trunk connection on which to run LDAP queries.
137  * @param[in] dn of profile object to apply.
138  * @param[in] scope to apply when looking up profiles.
139  * @param[in] filter to apply when looking up profiles.
140  * @param[in] expanded Structure containing a list of xlat
141  * expanded attribute names and mapping information.
142  * @return One of the RLM_MODULE_* values.
143  */
145  rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk,
146  char const *dn, int scope, char const *filter, fr_ldap_map_exp_t const *expanded)
147 {
148  ldap_profile_ctx_t *profile_ctx;
149 
150  if (!dn || !*dn) return UNLANG_ACTION_CALCULATE_RESULT;
151 
152  MEM(profile_ctx = talloc(unlang_interpret_frame_talloc_ctx(request), ldap_profile_ctx_t));
153  *profile_ctx = (ldap_profile_ctx_t) {
154  .ret = ret,
155  .dn = dn,
156  .expanded = expanded,
157  .inst = inst
158  };
159  if (ret) *ret = LDAP_RESULT_ERROR;
160 
162  ~FR_SIGNAL_CANCEL, UNLANG_SUB_FRAME, profile_ctx) < 0) {
163  talloc_free(profile_ctx);
164  return UNLANG_ACTION_FAIL;
165  }
166 
167  return fr_ldap_trunk_search(profile_ctx, &profile_ctx->query, request, ttrunk, dn,
168  scope, filter,
169  expanded->attrs, NULL, NULL);
170 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
#define USES_APPLE_DEPRECATED_API
Definition: build.h:468
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition: function.h:111
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition: interpret.c:1403
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
LDAP * handle
libldap handle.
Definition: base.h:333
fr_ldap_result_code_t ret
Result code.
Definition: base.h:470
trunk_request_t * treq
Trunk request this query is associated with.
Definition: base.h:456
fr_ldap_connection_t * ldap_conn
LDAP connection this query is running on.
Definition: base.h:457
fr_ldap_result_code_t
LDAP query result codes.
Definition: base.h:188
@ LDAP_RESULT_ERROR
A general error occurred.
Definition: base.h:191
@ LDAP_RESULT_SUCCESS
Successfully got LDAP results.
Definition: base.h:190
@ LDAP_RESULT_NO_RESULT
No results returned.
Definition: base.h:194
@ LDAP_RESULT_BAD_DN
The requested DN does not exist.
Definition: base.h:193
LDAPMessage * result
Head of LDAP results list.
Definition: base.h:468
int fr_ldap_map_do(request_t *request, char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
Convert attribute map into valuepairs.
Definition: map.c:323
char const * attrs[LDAP_MAX_ATTRMAP+LDAP_MAP_RESERVED+1]
Reserve some space for access attributes.
Definition: base.h:372
Result of expanding the RHS of a set of maps.
Definition: base.h:370
LDAP query structure.
Definition: base.h:422
Thread LDAP trunk structure.
Definition: base.h:399
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.
Definition: base.c:708
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
talloc_free(reap)
static unlang_action_t ldap_map_profile_resume(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Process the results of a profile lookup.
Definition: profile.c:54
unlang_action_t rlm_ldap_map_profile(fr_ldap_result_code_t *ret, rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *dn, int scope, char const *filter, fr_ldap_map_exp_t const *expanded)
Search for and apply an LDAP profile.
Definition: profile.c:144
static void ldap_map_profile_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel an in progress profile lookup.
Definition: profile.c:119
fr_ldap_result_code_t * ret
Result of the query and applying the map.
Definition: profile.c:44
rlm_ldap_t const * inst
Definition: profile.c:47
char const * dn
Definition: profile.c:46
fr_ldap_map_exp_t const * expanded
Definition: profile.c:48
fr_ldap_query_t * query
Definition: profile.c:45
Holds state of in progress async profile lookups.
Definition: profile.c:43
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED2()
Definition: radclient.h:50
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
char const * valuepair_attr
Generic dynamic mapping attribute, contains a RADIUS attribute and value.
Definition: rlm_ldap.h:99
fr_signal_t
Definition: signal.h:48
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
Definition: trunk.c:2140