Line data Source code
1 : /*
2 : SSSD
3 :
4 : IPA Identity Backend Module for views and overrides
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2014 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "util/util.h"
26 : #include "util/strtonum.h"
27 : #include "providers/ldap/sdap_async.h"
28 : #include "providers/ipa/ipa_id.h"
29 :
30 0 : static errno_t be_acct_req_to_override_filter(TALLOC_CTX *mem_ctx,
31 : struct ipa_options *ipa_opts,
32 : struct be_acct_req *ar,
33 : char **override_filter)
34 : {
35 : char *filter;
36 : uint32_t id;
37 : char *endptr;
38 :
39 0 : switch (ar->filter_type) {
40 : case BE_FILTER_NAME:
41 0 : switch ((ar->entry_type & BE_REQ_TYPE_MASK)) {
42 : case BE_REQ_USER:
43 : case BE_REQ_INITGROUPS:
44 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
45 0 : ipa_opts->override_map[IPA_OC_OVERRIDE_USER].name,
46 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_USER_NAME].name,
47 : ar->filter_value);
48 0 : break;
49 :
50 : case BE_REQ_GROUP:
51 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
52 0 : ipa_opts->override_map[IPA_OC_OVERRIDE_GROUP].name,
53 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_NAME].name,
54 : ar->filter_value);
55 0 : break;
56 :
57 : case BE_REQ_USER_AND_GROUP:
58 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
59 0 : ipa_opts->override_map[IPA_OC_OVERRIDE].name,
60 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_USER_NAME].name,
61 : ar->filter_value,
62 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_NAME].name,
63 : ar->filter_value);
64 0 : break;
65 : default:
66 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d] for name filter.\n",
67 : ar->entry_type);
68 0 : return EINVAL;
69 : }
70 0 : break;
71 :
72 : case BE_FILTER_IDNUM:
73 0 : errno = 0;
74 0 : id = strtouint32(ar->filter_value, &endptr, 10);
75 0 : if (errno != 0|| *endptr != '\0' || (ar->filter_value == endptr)) {
76 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid id value [%s].\n",
77 : ar->filter_value);
78 0 : return EINVAL;
79 : }
80 0 : switch ((ar->entry_type & BE_REQ_TYPE_MASK)) {
81 : case BE_REQ_USER:
82 : case BE_REQ_INITGROUPS:
83 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%"PRIu32"))",
84 0 : ipa_opts->override_map[IPA_OC_OVERRIDE_USER].name,
85 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_UID_NUMBER].name,
86 : id);
87 0 : break;
88 :
89 : case BE_REQ_GROUP:
90 0 : filter = talloc_asprintf(mem_ctx,
91 : "(&(objectClass=%s)(%s=%"PRIu32"))",
92 0 : ipa_opts->override_map[IPA_OC_OVERRIDE_GROUP].name,
93 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_GID_NUMBER].name,
94 : id);
95 0 : break;
96 :
97 : case BE_REQ_USER_AND_GROUP:
98 0 : filter = talloc_asprintf(mem_ctx,
99 : "(&(objectClass=%s)(|(%s=%"PRIu32")(%s=%"PRIu32")))",
100 0 : ipa_opts->override_map[IPA_OC_OVERRIDE].name,
101 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_UID_NUMBER].name,
102 : id,
103 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_GID_NUMBER].name,
104 : id);
105 0 : break;
106 : default:
107 0 : DEBUG(SSSDBG_CRIT_FAILURE,
108 : "Unexpected entry type [%d] for id filter.\n",
109 : ar->entry_type);
110 0 : return EINVAL;
111 : }
112 0 : break;
113 :
114 : case BE_FILTER_SECID:
115 0 : if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_SECID) {
116 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=:SID:%s))",
117 0 : ipa_opts->override_map[IPA_OC_OVERRIDE].name,
118 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name,
119 : ar->filter_value);
120 : } else {
121 0 : DEBUG(SSSDBG_CRIT_FAILURE,
122 : "Unexpected entry type [%d] for SID filter.\n",
123 : ar->entry_type);
124 0 : return EINVAL;
125 : }
126 0 : break;
127 :
128 : case BE_FILTER_UUID:
129 0 : if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_UUID) {
130 0 : filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=:IPA:%s:%s))",
131 0 : ipa_opts->override_map[IPA_OC_OVERRIDE].name,
132 0 : ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name,
133 : dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN),
134 : ar->filter_value);
135 : } else {
136 0 : DEBUG(SSSDBG_CRIT_FAILURE,
137 : "Unexpected entry type [%d] for UUID filter.\n",
138 : ar->entry_type);
139 0 : return EINVAL;
140 : }
141 0 : break;
142 :
143 : default:
144 0 : DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n");
145 0 : return EINVAL;
146 : }
147 :
148 0 : if (filter == NULL) {
149 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
150 0 : return ENOMEM;
151 : }
152 :
153 0 : *override_filter = filter;
154 :
155 0 : return EOK;
156 : }
157 :
158 0 : static errno_t get_be_acct_req_for_xyz(TALLOC_CTX *mem_ctx, const char *val,
159 : const char *domain_name,
160 : int type,
161 : struct be_acct_req **_ar)
162 : {
163 : struct be_acct_req *ar;
164 :
165 0 : ar = talloc_zero(mem_ctx, struct be_acct_req);
166 0 : if (ar == NULL) {
167 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
168 0 : return ENOMEM;
169 : }
170 :
171 0 : switch (type) {
172 : case BE_REQ_BY_SECID:
173 0 : ar->entry_type = BE_REQ_BY_SECID;
174 0 : ar->filter_type = BE_FILTER_SECID;
175 0 : break;
176 : case BE_REQ_BY_UUID:
177 0 : ar->entry_type = BE_REQ_BY_UUID;
178 0 : ar->filter_type = BE_FILTER_UUID;
179 0 : break;
180 : case BE_REQ_USER:
181 0 : ar->entry_type = BE_REQ_USER;
182 0 : ar->filter_type = BE_FILTER_NAME;
183 0 : break;
184 : default:
185 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type [%d].\n", type);
186 0 : talloc_free(ar);
187 0 : return EINVAL;
188 : }
189 :
190 0 : ar->filter_value = talloc_strdup(ar, val);
191 0 : ar->domain = talloc_strdup(ar, domain_name);
192 0 : if (ar->filter_value == NULL || ar->domain == NULL) {
193 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
194 0 : talloc_free(ar);
195 0 : return ENOMEM;
196 : }
197 :
198 :
199 0 : *_ar = ar;
200 :
201 0 : return EOK;
202 : }
203 :
204 0 : errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
205 : const char *domain_name,
206 : struct be_acct_req **_ar)
207 : {
208 0 : return get_be_acct_req_for_xyz(mem_ctx, sid, domain_name, BE_REQ_BY_SECID,
209 : _ar);
210 : }
211 :
212 0 : errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
213 : const char *domain_name,
214 : struct be_acct_req **_ar)
215 : {
216 0 : return get_be_acct_req_for_xyz(mem_ctx, uuid, domain_name, BE_REQ_BY_UUID,
217 : _ar);
218 : }
219 :
220 0 : errno_t get_be_acct_req_for_user_name(TALLOC_CTX *mem_ctx,
221 : const char *user_name,
222 : const char *domain_name,
223 : struct be_acct_req **_ar)
224 : {
225 0 : return get_be_acct_req_for_xyz(mem_ctx, user_name, domain_name, BE_REQ_USER,
226 : _ar);
227 : }
228 :
229 : struct ipa_get_ad_override_state {
230 : struct tevent_context *ev;
231 : struct sdap_id_ctx *sdap_id_ctx;
232 : struct ipa_options *ipa_options;
233 : const char *ipa_realm;
234 : const char *ipa_view_name;
235 : struct be_acct_req *ar;
236 :
237 : struct sdap_id_op *sdap_op;
238 : int dp_error;
239 : struct sysdb_attrs *override_attrs;
240 : char *filter;
241 : };
242 :
243 : static void ipa_get_ad_override_connect_done(struct tevent_req *subreq);
244 : static void ipa_get_ad_override_done(struct tevent_req *subreq);
245 :
246 0 : struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx,
247 : struct tevent_context *ev,
248 : struct sdap_id_ctx *sdap_id_ctx,
249 : struct ipa_options *ipa_options,
250 : const char *ipa_realm,
251 : const char *view_name,
252 : struct be_acct_req *ar)
253 : {
254 : int ret;
255 : struct tevent_req *req;
256 : struct tevent_req *subreq;
257 : struct ipa_get_ad_override_state *state;
258 :
259 0 : req = tevent_req_create(mem_ctx, &state, struct ipa_get_ad_override_state);
260 0 : if (req == NULL) {
261 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
262 0 : return NULL;
263 : }
264 :
265 0 : state->ev = ev;
266 0 : state->sdap_id_ctx = sdap_id_ctx;
267 0 : state->ipa_options = ipa_options;
268 0 : state->ipa_realm = ipa_realm;
269 0 : state->ar = ar;
270 0 : state->dp_error = -1;
271 0 : state->override_attrs = NULL;
272 0 : state->filter = NULL;
273 :
274 0 : if (view_name == NULL) {
275 0 : DEBUG(SSSDBG_TRACE_ALL, "View not defined, nothing to do.\n");
276 0 : ret = EOK;
277 0 : goto done;
278 : }
279 :
280 0 : if (is_default_view(view_name)) {
281 0 : state->ipa_view_name = IPA_DEFAULT_VIEW_NAME;
282 : } else {
283 0 : state->ipa_view_name = view_name;
284 : }
285 :
286 0 : state->sdap_op = sdap_id_op_create(state,
287 0 : state->sdap_id_ctx->conn->conn_cache);
288 0 : if (state->sdap_op == NULL) {
289 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
290 0 : ret = ENOMEM;
291 0 : goto done;
292 : }
293 :
294 0 : subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
295 0 : if (subreq == NULL) {
296 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
297 : ret, strerror(ret));
298 0 : goto done;
299 : }
300 :
301 0 : tevent_req_set_callback(subreq, ipa_get_ad_override_connect_done, req);
302 :
303 0 : return req;
304 :
305 : done:
306 0 : if (ret != EOK) {
307 0 : state->dp_error = DP_ERR_FATAL;
308 0 : tevent_req_error(req, ret);
309 : } else {
310 0 : state->dp_error = DP_ERR_OK;
311 0 : tevent_req_done(req);
312 : }
313 0 : tevent_req_post(req, state->ev);
314 :
315 0 : return req;
316 : }
317 :
318 0 : static void ipa_get_ad_override_connect_done(struct tevent_req *subreq)
319 : {
320 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
321 : struct tevent_req);
322 0 : struct ipa_get_ad_override_state *state = tevent_req_data(req,
323 : struct ipa_get_ad_override_state);
324 : int ret;
325 : char *basedn;
326 : char *search_base;
327 0 : struct ipa_options *ipa_opts = state->ipa_options;
328 :
329 0 : ret = sdap_id_op_connect_recv(subreq, &state->dp_error);
330 0 : talloc_zfree(subreq);
331 0 : if (ret != EOK) {
332 0 : if (state->dp_error == DP_ERR_OFFLINE) {
333 0 : DEBUG(SSSDBG_MINOR_FAILURE,
334 : "No IPA server is available, going offline\n");
335 : } else {
336 0 : DEBUG(SSSDBG_OP_FAILURE,
337 : "Failed to connect to IPA server: [%d](%s)\n",
338 : ret, strerror(ret));
339 : }
340 :
341 0 : goto fail;
342 : }
343 :
344 0 : ret = domain_to_basedn(state, state->ipa_realm, &basedn);
345 0 : if (ret != EOK) {
346 0 : DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n");
347 0 : goto fail;
348 : }
349 :
350 0 : search_base = talloc_asprintf(state, "cn=%s,%s", state->ipa_view_name,
351 0 : ipa_opts->views_search_bases[0]->basedn);
352 0 : if (search_base == NULL) {
353 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
354 0 : ret = ENOMEM;
355 0 : goto fail;
356 : }
357 :
358 0 : ret = be_acct_req_to_override_filter(state, state->ipa_options, state->ar,
359 : &state->filter);
360 0 : if (ret != EOK) {
361 0 : DEBUG(SSSDBG_OP_FAILURE, "be_acct_req_to_override_filter failed.\n");
362 0 : goto fail;
363 : }
364 :
365 0 : DEBUG(SSSDBG_TRACE_ALL,
366 : "Searching for overrides in view [%s] with filter [%s].\n",
367 : state->ipa_view_name, state->filter);
368 :
369 0 : subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts,
370 : sdap_id_op_handle(state->sdap_op), search_base,
371 : LDAP_SCOPE_SUBTREE,
372 0 : state->filter, NULL,
373 0 : state->ipa_options->override_map,
374 : IPA_OPTS_OVERRIDE,
375 0 : dp_opt_get_int(state->sdap_id_ctx->opts->basic,
376 : SDAP_ENUM_SEARCH_TIMEOUT),
377 : false);
378 0 : if (subreq == NULL) {
379 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
380 0 : ret = ENOMEM;
381 0 : goto fail;
382 : }
383 :
384 0 : tevent_req_set_callback(subreq, ipa_get_ad_override_done, req);
385 0 : return;
386 :
387 : fail:
388 0 : state->dp_error = DP_ERR_FATAL;
389 0 : tevent_req_error(req, ret);
390 0 : return;
391 : }
392 :
393 0 : static void ipa_get_ad_override_done(struct tevent_req *subreq)
394 : {
395 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
396 : struct tevent_req);
397 0 : struct ipa_get_ad_override_state *state = tevent_req_data(req,
398 : struct ipa_get_ad_override_state);
399 : int ret;
400 0 : size_t reply_count = 0;
401 0 : struct sysdb_attrs **reply = NULL;
402 :
403 0 : ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
404 0 : talloc_zfree(subreq);
405 0 : if (ret != EOK) {
406 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override request failed.\n");
407 0 : goto fail;
408 : }
409 :
410 0 : if (reply_count == 0) {
411 0 : DEBUG(SSSDBG_TRACE_ALL, "No override found with filter [%s].\n",
412 : state->filter);
413 0 : state->dp_error = DP_ERR_OK;
414 0 : tevent_req_done(req);
415 0 : return;
416 0 : } else if (reply_count > 1) {
417 0 : DEBUG(SSSDBG_CRIT_FAILURE,
418 : "Found [%zu] overrides with filter [%s], expected only 1.\n",
419 : reply_count, state->filter);
420 0 : ret = EINVAL;
421 0 : goto fail;
422 : }
423 :
424 0 : DEBUG(SSSDBG_TRACE_ALL, "Found override for object with filter [%s].\n",
425 : state->filter);
426 :
427 0 : state->override_attrs = reply[0];
428 0 : state->dp_error = DP_ERR_OK;
429 0 : tevent_req_done(req);
430 0 : return;
431 :
432 : fail:
433 0 : state->dp_error = DP_ERR_FATAL;
434 0 : tevent_req_error(req, ret);
435 0 : return;
436 : }
437 :
438 0 : errno_t ipa_get_ad_override_recv(struct tevent_req *req, int *dp_error_out,
439 : TALLOC_CTX *mem_ctx,
440 : struct sysdb_attrs **override_attrs)
441 : {
442 0 : struct ipa_get_ad_override_state *state = tevent_req_data(req,
443 : struct ipa_get_ad_override_state);
444 :
445 0 : if (dp_error_out != NULL) {
446 0 : *dp_error_out = state->dp_error;
447 : }
448 :
449 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
450 :
451 0 : if (override_attrs != NULL) {
452 0 : *override_attrs = talloc_steal(mem_ctx, state->override_attrs);
453 : }
454 :
455 0 : return EOK;
456 : }
|