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