Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2012 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "util/util.h"
24 : #include "providers/ldap/sdap_async.h"
25 : #include "providers/ldap/ldap_common.h"
26 :
27 : struct sdap_ad_match_rule_state {
28 : struct tevent_context *ev;
29 : struct sdap_handle *sh;
30 : const char **attrs;
31 :
32 : struct sdap_options *opts;
33 : const char *base_filter;
34 : char *filter;
35 : int timeout;
36 :
37 : size_t base_iter;
38 : struct sdap_search_base **search_bases;
39 :
40 : size_t count;
41 : struct sysdb_attrs **users;
42 : };
43 :
44 : static errno_t
45 : sdap_get_ad_match_rule_members_next_base(struct tevent_req *req);
46 : static void
47 : sdap_get_ad_match_rule_members_step(struct tevent_req *subreq);
48 :
49 : struct tevent_req *
50 0 : sdap_get_ad_match_rule_members_send(TALLOC_CTX *mem_ctx,
51 : struct tevent_context *ev,
52 : struct sdap_options *opts,
53 : struct sdap_handle *sh,
54 : struct sysdb_attrs *group,
55 : int timeout)
56 : {
57 : errno_t ret;
58 : struct tevent_req *req;
59 : struct sdap_ad_match_rule_state *state;
60 : const char *group_dn;
61 : char *sanitized_group_dn;
62 :
63 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_ad_match_rule_state);
64 0 : if (!req) return NULL;
65 :
66 0 : state->ev = ev;
67 0 : state->opts = opts;
68 0 : state->sh = sh;
69 0 : state->timeout = timeout;
70 0 : state->count = 0;
71 0 : state->base_iter = 0;
72 0 : state->search_bases = opts->sdom->user_search_bases;
73 :
74 : /* Request all of the user attributes that we know about. */
75 0 : ret = build_attrs_from_map(state, opts->user_map, opts->user_map_cnt,
76 0 : NULL, &state->attrs, NULL);
77 0 : if (ret != EOK) {
78 0 : DEBUG(SSSDBG_MINOR_FAILURE,
79 : "Could not build attribute map: [%s]\n",
80 : strerror(ret));
81 0 : goto immediate;
82 : }
83 :
84 : /* Get the DN of the group */
85 0 : ret = sysdb_attrs_get_string(group, SYSDB_ORIG_DN, &group_dn);
86 0 : if (ret != EOK) {
87 0 : DEBUG(SSSDBG_MINOR_FAILURE,
88 : "Could not retrieve originalDN for group: %s\n",
89 : strerror(ret));
90 0 : goto immediate;
91 : }
92 :
93 : /* Sanitize it in case we have special characters in DN */
94 0 : ret = sss_filter_sanitize(state, group_dn, &sanitized_group_dn);
95 0 : if (ret != EOK) {
96 0 : DEBUG(SSSDBG_MINOR_FAILURE,
97 : "Could not sanitize group DN: %s\n",
98 : strerror(ret));
99 0 : goto immediate;
100 : }
101 :
102 : /* Craft a special filter according to
103 : * http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx
104 : */
105 0 : state->base_filter =
106 0 : talloc_asprintf(state,
107 : "(&(%s:%s:=%s)(objectClass=%s))",
108 0 : state->opts->user_map[SDAP_AT_USER_MEMBEROF].name,
109 : SDAP_MATCHING_RULE_IN_CHAIN,
110 : sanitized_group_dn,
111 0 : state->opts->user_map[SDAP_OC_USER].name);
112 0 : talloc_zfree(sanitized_group_dn);
113 0 : if (!state->base_filter) {
114 0 : ret = ENOMEM;
115 0 : goto immediate;
116 : }
117 :
118 : /* Start the loop through the search bases to get all of the users */
119 0 : ret = sdap_get_ad_match_rule_members_next_base(req);
120 0 : if (ret != EOK) {
121 0 : DEBUG(SSSDBG_MINOR_FAILURE,
122 : "sdap_get_ad_match_rule_members_next_base failed: [%s]\n",
123 : strerror(ret));
124 0 : goto immediate;
125 : }
126 :
127 0 : return req;
128 :
129 : immediate:
130 0 : tevent_req_error(req, ret);
131 0 : tevent_req_post(req, ev);
132 0 : return req;
133 : }
134 :
135 : static errno_t
136 0 : sdap_get_ad_match_rule_members_next_base(struct tevent_req *req)
137 : {
138 : struct tevent_req *subreq;
139 : struct sdap_ad_match_rule_state *state;
140 :
141 0 : state = tevent_req_data(req, struct sdap_ad_match_rule_state);
142 :
143 0 : talloc_zfree(state->filter);
144 0 : state->filter = sdap_combine_filters(state, state->base_filter,
145 0 : state->search_bases[state->base_iter]->filter);
146 0 : if (!state->filter) {
147 0 : return ENOMEM;
148 : }
149 :
150 0 : DEBUG(SSSDBG_TRACE_FUNC,
151 : "Searching for users with base [%s]\n",
152 : state->search_bases[state->base_iter]->basedn);
153 :
154 0 : subreq = sdap_get_generic_send(
155 : state, state->ev, state->opts, state->sh,
156 0 : state->search_bases[state->base_iter]->basedn,
157 0 : state->search_bases[state->base_iter]->scope,
158 0 : state->filter, state->attrs,
159 0 : state->opts->user_map, state->opts->user_map_cnt,
160 : state->timeout, true);
161 0 : if (!subreq) {
162 0 : return ENOMEM;
163 : }
164 :
165 0 : tevent_req_set_callback(subreq, sdap_get_ad_match_rule_members_step, req);
166 :
167 0 : return EOK;
168 : }
169 :
170 : static void
171 0 : sdap_get_ad_match_rule_members_step(struct tevent_req *subreq)
172 : {
173 : errno_t ret;
174 0 : struct tevent_req *req =
175 0 : tevent_req_callback_data(subreq, struct tevent_req);
176 0 : struct sdap_ad_match_rule_state *state =
177 0 : tevent_req_data(req, struct sdap_ad_match_rule_state);
178 : size_t count, i;
179 : struct sysdb_attrs **users;
180 :
181 0 : ret = sdap_get_generic_recv(subreq, state, &count, &users);
182 0 : talloc_zfree(subreq);
183 0 : if (ret != EOK) {
184 0 : DEBUG(SSSDBG_MINOR_FAILURE,
185 : "LDAP search failed: [%s]\n", sss_strerror(ret));
186 0 : tevent_req_error(req, ret);
187 0 : return;
188 : }
189 :
190 0 : DEBUG(SSSDBG_TRACE_LIBS,
191 : "Search for users returned %zu results\n", count);
192 :
193 : /* Add this batch of users to the list */
194 0 : if (count > 0) {
195 0 : state->users = talloc_realloc(state, state->users,
196 : struct sysdb_attrs *,
197 : state->count + count + 1);
198 0 : if (!state->users) {
199 0 : tevent_req_error(req, ENOMEM);
200 0 : return;
201 : }
202 :
203 : /* Copy the new users into the list */
204 0 : for (i = 0; i < count; i++) {
205 0 : state->users[state->count + i] =
206 0 : talloc_steal(state->users, users[i]);
207 : }
208 :
209 0 : state->count += count;
210 0 : state->users[state->count] = NULL;
211 : }
212 :
213 : /* Continue checking other search bases */
214 0 : state->base_iter++;
215 0 : if (state->search_bases[state->base_iter]) {
216 : /* There are more search bases to try */
217 0 : ret = sdap_get_ad_match_rule_members_next_base(req);
218 0 : if (ret != EOK) {
219 0 : tevent_req_error(req, ret);
220 : }
221 0 : return;
222 : }
223 :
224 : /* No more search bases. We're done here. */
225 0 : if (state->count == 0) {
226 0 : DEBUG(SSSDBG_TRACE_LIBS,
227 : "No users matched in any search base\n");
228 0 : tevent_req_error(req, ENOENT);
229 0 : return;
230 : }
231 :
232 0 : tevent_req_done(req);
233 : }
234 :
235 : errno_t
236 0 : sdap_get_ad_match_rule_members_recv(struct tevent_req *req,
237 : TALLOC_CTX *mem_ctx,
238 : size_t *num_users,
239 : struct sysdb_attrs ***users)
240 : {
241 0 : struct sdap_ad_match_rule_state *state =
242 0 : tevent_req_data(req, struct sdap_ad_match_rule_state);
243 :
244 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
245 :
246 0 : *num_users = state->count;
247 0 : *users = talloc_steal(mem_ctx, state->users);
248 0 : return EOK;
249 : }
|