Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Identity Backend Module
5 :
6 : Authors:
7 : Simo Sorce <ssorce@redhat.com>
8 :
9 : Copyright (C) 2008 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 <errno.h>
26 : #include <time.h>
27 : #include <sys/time.h>
28 :
29 : #include "util/util.h"
30 : #include "util/probes.h"
31 : #include "util/strtonum.h"
32 : #include "util/cert.h"
33 : #include "db/sysdb.h"
34 : #include "providers/ldap/ldap_common.h"
35 : #include "providers/ldap/sdap_async.h"
36 : #include "providers/ldap/sdap_idmap.h"
37 : #include "providers/ldap/sdap_users.h"
38 : #include "providers/ad/ad_common.h"
39 :
40 : /* =Users-Related-Functions-(by-name,by-uid)============================== */
41 :
42 : struct users_get_state {
43 : struct tevent_context *ev;
44 : struct sdap_id_ctx *ctx;
45 : struct sdap_domain *sdom;
46 : struct sdap_id_conn_ctx *conn;
47 : struct sdap_id_op *op;
48 : struct sysdb_ctx *sysdb;
49 : struct sss_domain_info *domain;
50 :
51 : const char *name;
52 : int filter_type;
53 :
54 : char *filter;
55 : const char **attrs;
56 : bool use_id_mapping;
57 :
58 : int dp_error;
59 : int sdap_ret;
60 : bool noexist_delete;
61 : };
62 :
63 : static int users_get_retry(struct tevent_req *req);
64 : static void users_get_connect_done(struct tevent_req *subreq);
65 : static void users_get_posix_check_done(struct tevent_req *subreq);
66 : static void users_get_search(struct tevent_req *req);
67 : static void users_get_done(struct tevent_req *subreq);
68 :
69 0 : struct tevent_req *users_get_send(TALLOC_CTX *memctx,
70 : struct tevent_context *ev,
71 : struct sdap_id_ctx *ctx,
72 : struct sdap_domain *sdom,
73 : struct sdap_id_conn_ctx *conn,
74 : const char *name,
75 : int filter_type,
76 : const char *extra_value,
77 : int attrs_type,
78 : bool noexist_delete)
79 : {
80 : struct tevent_req *req;
81 : struct users_get_state *state;
82 0 : const char *attr_name = NULL;
83 0 : char *clean_name = NULL;
84 : char *endptr;
85 : int ret;
86 : uid_t uid;
87 : enum idmap_error_code err;
88 : char *sid;
89 0 : char *user_filter = NULL;
90 :
91 0 : req = tevent_req_create(memctx, &state, struct users_get_state);
92 0 : if (!req) return NULL;
93 :
94 0 : state->ev = ev;
95 0 : state->ctx = ctx;
96 0 : state->sdom = sdom;
97 0 : state->conn = conn;
98 0 : state->dp_error = DP_ERR_FATAL;
99 0 : state->noexist_delete = noexist_delete;
100 :
101 0 : state->op = sdap_id_op_create(state, state->conn->conn_cache);
102 0 : if (!state->op) {
103 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
104 0 : ret = ENOMEM;
105 0 : goto done;
106 : }
107 :
108 0 : state->domain = sdom->dom;
109 0 : state->sysdb = sdom->dom->sysdb;
110 0 : state->name = name;
111 0 : state->filter_type = filter_type;
112 :
113 0 : state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
114 0 : ctx->opts->idmap_ctx,
115 0 : sdom->dom->name,
116 0 : sdom->dom->domain_id);
117 0 : switch (filter_type) {
118 : case BE_FILTER_WILDCARD:
119 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
120 0 : ret = sss_filter_sanitize_ex(state, name, &clean_name,
121 : LDAP_ALLOWED_WILDCARDS);
122 0 : if (ret != EOK) {
123 0 : goto done;
124 : }
125 0 : break;
126 : case BE_FILTER_NAME:
127 0 : if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) {
128 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name;
129 : } else {
130 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
131 : }
132 0 : ret = sss_filter_sanitize(state, name, &clean_name);
133 0 : if (ret != EOK) {
134 0 : goto done;
135 : }
136 0 : break;
137 : case BE_FILTER_IDNUM:
138 0 : if (state->use_id_mapping) {
139 : /* If we're ID-mapping, we need to use the objectSID
140 : * in the search filter.
141 : */
142 0 : uid = strtouint32(name, &endptr, 10);
143 0 : if (errno != EOK) {
144 0 : ret = EINVAL;
145 0 : goto done;
146 : }
147 :
148 : /* Convert the UID to its objectSID */
149 0 : err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map,
150 : uid, &sid);
151 0 : if (err == IDMAP_NO_DOMAIN) {
152 0 : DEBUG(SSSDBG_MINOR_FAILURE,
153 : "[%s] did not match any configured ID mapping domain\n",
154 : name);
155 :
156 0 : ret = sysdb_delete_user(state->domain, NULL, uid);
157 0 : if (ret == ENOENT) {
158 : /* Ignore errors to remove users that were not cached previously */
159 0 : ret = EOK;
160 : }
161 :
162 0 : goto done;
163 0 : } else if (err != IDMAP_SUCCESS) {
164 0 : DEBUG(SSSDBG_MINOR_FAILURE,
165 : "Mapping ID [%s] to SID failed: [%s]\n",
166 : name, idmap_error_string(err));
167 0 : ret = EIO;
168 0 : goto done;
169 : }
170 :
171 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name;
172 0 : ret = sss_filter_sanitize(state, sid, &clean_name);
173 0 : sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid);
174 0 : if (ret != EOK) {
175 0 : goto done;
176 : }
177 :
178 : } else {
179 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_UID].name;
180 0 : ret = sss_filter_sanitize(state, name, &clean_name);
181 0 : if (ret != EOK) {
182 0 : goto done;
183 : }
184 : }
185 0 : break;
186 : case BE_FILTER_SECID:
187 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name;
188 :
189 0 : ret = sss_filter_sanitize(state, name, &clean_name);
190 0 : if (ret != EOK) {
191 0 : goto done;
192 : }
193 0 : break;
194 : case BE_FILTER_UUID:
195 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_UUID].name;
196 0 : if (attr_name == NULL) {
197 0 : DEBUG(SSSDBG_CRIT_FAILURE,
198 : "UUID search not configured for this backend.\n");
199 0 : ret = EINVAL;
200 0 : goto done;
201 : }
202 :
203 0 : ret = sss_filter_sanitize(state, name, &clean_name);
204 0 : if (ret != EOK) {
205 0 : goto done;
206 : }
207 0 : break;
208 : case BE_FILTER_CERT:
209 0 : attr_name = ctx->opts->user_map[SDAP_AT_USER_CERT].name;
210 0 : if (attr_name == NULL) {
211 0 : DEBUG(SSSDBG_CRIT_FAILURE,
212 : "Certificate search not configured for this backend.\n");
213 0 : ret = EINVAL;
214 0 : goto done;
215 : }
216 :
217 0 : ret = sss_cert_derb64_to_ldap_filter(state, name, attr_name,
218 : &user_filter);
219 0 : if (ret != EOK) {
220 0 : DEBUG(SSSDBG_OP_FAILURE,
221 : "sss_cert_derb64_to_ldap_filter failed.\n");
222 0 : goto done;
223 : }
224 0 : break;
225 : default:
226 0 : ret = EINVAL;
227 0 : goto done;
228 : }
229 :
230 0 : if (attr_name == NULL) {
231 0 : DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n");
232 0 : ret = EINVAL;
233 0 : goto done;
234 : }
235 :
236 0 : if (user_filter == NULL) {
237 0 : user_filter = talloc_asprintf(state, "(%s=%s)", attr_name, clean_name);
238 0 : talloc_free(clean_name);
239 0 : if (user_filter == NULL) {
240 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
241 0 : ret = ENOMEM;
242 0 : goto done;
243 : }
244 : }
245 :
246 0 : if (state->use_id_mapping || filter_type == BE_FILTER_SECID) {
247 : /* When mapping IDs or looking for SIDs, we don't want to limit
248 : * ourselves to users with a UID value. But there must be a SID to map
249 : * from.
250 : */
251 0 : state->filter = talloc_asprintf(state,
252 : "(&%s(objectclass=%s)(%s=*)(%s=*))",
253 : user_filter,
254 0 : ctx->opts->user_map[SDAP_OC_USER].name,
255 0 : ctx->opts->user_map[SDAP_AT_USER_NAME].name,
256 0 : ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name);
257 : } else {
258 : /* When not ID-mapping, make sure there is a non-NULL UID */
259 0 : state->filter = talloc_asprintf(state,
260 : "(&%s(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))",
261 : user_filter,
262 0 : ctx->opts->user_map[SDAP_OC_USER].name,
263 0 : ctx->opts->user_map[SDAP_AT_USER_NAME].name,
264 0 : ctx->opts->user_map[SDAP_AT_USER_UID].name,
265 0 : ctx->opts->user_map[SDAP_AT_USER_UID].name);
266 : }
267 :
268 0 : talloc_zfree(user_filter);
269 0 : if (!state->filter) {
270 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n");
271 0 : ret = ENOMEM;
272 0 : goto done;
273 : }
274 :
275 : /* TODO: handle attrs_type */
276 0 : ret = build_attrs_from_map(state, ctx->opts->user_map,
277 0 : ctx->opts->user_map_cnt,
278 0 : NULL, &state->attrs, NULL);
279 0 : if (ret != EOK) goto done;
280 :
281 0 : ret = users_get_retry(req);
282 0 : if (ret != EOK) {
283 0 : goto done;
284 : }
285 :
286 0 : return req;
287 :
288 : done:
289 0 : if (ret != EOK) {
290 0 : tevent_req_error(req, ret);
291 : } else {
292 0 : tevent_req_done(req);
293 : }
294 0 : return tevent_req_post(req, ev);
295 : }
296 :
297 0 : static int users_get_retry(struct tevent_req *req)
298 : {
299 0 : struct users_get_state *state = tevent_req_data(req,
300 : struct users_get_state);
301 : struct tevent_req *subreq;
302 0 : int ret = EOK;
303 :
304 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
305 0 : if (!subreq) {
306 0 : return ret;
307 : }
308 :
309 0 : tevent_req_set_callback(subreq, users_get_connect_done, req);
310 0 : return EOK;
311 : }
312 :
313 0 : static void users_get_connect_done(struct tevent_req *subreq)
314 : {
315 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
316 : struct tevent_req);
317 0 : struct users_get_state *state = tevent_req_data(req,
318 : struct users_get_state);
319 0 : int dp_error = DP_ERR_FATAL;
320 : int ret;
321 :
322 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
323 0 : talloc_zfree(subreq);
324 :
325 0 : if (ret != EOK) {
326 0 : state->dp_error = dp_error;
327 0 : tevent_req_error(req, ret);
328 0 : return;
329 : }
330 :
331 : /* If POSIX attributes have been requested with an AD server and we
332 : * have no idea about POSIX attributes support, run a one-time check
333 : */
334 0 : if (state->use_id_mapping == false &&
335 0 : state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
336 0 : state->ctx->srv_opts &&
337 0 : state->ctx->srv_opts->posix_checked == false) {
338 0 : subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
339 : sdap_id_op_handle(state->op),
340 0 : state->sdom->user_search_bases,
341 0 : dp_opt_get_int(state->ctx->opts->basic,
342 : SDAP_SEARCH_TIMEOUT));
343 0 : if (subreq == NULL) {
344 0 : tevent_req_error(req, ENOMEM);
345 0 : return;
346 : }
347 0 : tevent_req_set_callback(subreq, users_get_posix_check_done, req);
348 0 : return;
349 : }
350 :
351 0 : users_get_search(req);
352 : }
353 :
354 0 : static void users_get_posix_check_done(struct tevent_req *subreq)
355 : {
356 : errno_t ret;
357 : errno_t ret2;
358 : bool has_posix;
359 : int dp_error;
360 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
361 : struct tevent_req);
362 0 : struct users_get_state *state = tevent_req_data(req,
363 : struct users_get_state);
364 :
365 0 : ret = sdap_posix_check_recv(subreq, &has_posix);
366 0 : talloc_zfree(subreq);
367 0 : if (ret != EOK) {
368 : /* We can only finish the id_op on error as the connection
369 : * is re-used by the user search
370 : */
371 0 : ret2 = sdap_id_op_done(state->op, ret, &dp_error);
372 0 : if (dp_error == DP_ERR_OK && ret2 != EOK) {
373 : /* retry */
374 0 : ret = users_get_retry(req);
375 0 : if (ret != EOK) {
376 0 : tevent_req_error(req, ret);
377 : }
378 0 : return;
379 : }
380 : }
381 :
382 0 : state->ctx->srv_opts->posix_checked = true;
383 :
384 : /* If the check ran to completion, we know for certain about the attributes
385 : */
386 0 : if (ret == EOK && has_posix == false) {
387 0 : state->sdap_ret = ERR_NO_POSIX;
388 0 : tevent_req_done(req);
389 0 : return;
390 : }
391 :
392 0 : users_get_search(req);
393 : }
394 :
395 0 : static void users_get_search(struct tevent_req *req)
396 : {
397 0 : struct users_get_state *state = tevent_req_data(req,
398 : struct users_get_state);
399 : struct tevent_req *subreq;
400 : enum sdap_entry_lookup_type lookup_type;
401 :
402 0 : if (state->filter_type == BE_FILTER_WILDCARD) {
403 0 : lookup_type = SDAP_LOOKUP_WILDCARD;
404 : } else {
405 0 : lookup_type = SDAP_LOOKUP_SINGLE;
406 : }
407 :
408 0 : subreq = sdap_get_users_send(state, state->ev,
409 : state->domain, state->sysdb,
410 0 : state->ctx->opts,
411 0 : state->sdom->user_search_bases,
412 : sdap_id_op_handle(state->op),
413 0 : state->attrs, state->filter,
414 0 : dp_opt_get_int(state->ctx->opts->basic,
415 : SDAP_SEARCH_TIMEOUT),
416 : lookup_type);
417 0 : if (!subreq) {
418 0 : tevent_req_error(req, ENOMEM);
419 0 : return;
420 : }
421 0 : tevent_req_set_callback(subreq, users_get_done, req);
422 : }
423 :
424 0 : static void users_get_done(struct tevent_req *subreq)
425 : {
426 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
427 : struct tevent_req);
428 0 : struct users_get_state *state = tevent_req_data(req,
429 : struct users_get_state);
430 : char *endptr;
431 : uid_t uid;
432 0 : int dp_error = DP_ERR_FATAL;
433 : int ret;
434 :
435 0 : ret = sdap_get_users_recv(subreq, NULL, NULL);
436 0 : talloc_zfree(subreq);
437 :
438 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
439 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
440 : /* retry */
441 0 : ret = users_get_retry(req);
442 0 : if (ret != EOK) {
443 0 : tevent_req_error(req, ret);
444 0 : return;
445 : }
446 :
447 0 : return;
448 : }
449 :
450 0 : if ((ret == ENOENT) &&
451 0 : (state->ctx->opts->schema_type == SDAP_SCHEMA_RFC2307) &&
452 0 : (dp_opt_get_bool(state->ctx->opts->basic,
453 : SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS) == true)) {
454 : struct sysdb_attrs **usr_attrs;
455 0 : const char *name = NULL;
456 : bool fallback;
457 :
458 0 : switch (state->filter_type) {
459 : case BE_FILTER_NAME:
460 0 : name = state->name;
461 0 : uid = -1;
462 0 : fallback = true;
463 0 : break;
464 : case BE_FILTER_IDNUM:
465 0 : uid = (uid_t) strtouint32(state->name, &endptr, 10);
466 0 : if (errno || *endptr || (state->name == endptr)) {
467 0 : tevent_req_error(req, errno ? errno : EINVAL);
468 0 : return;
469 : }
470 0 : fallback = true;
471 0 : break;
472 : default:
473 0 : fallback = false;
474 0 : break;
475 : }
476 :
477 0 : if (fallback) {
478 0 : ret = sdap_fallback_local_user(state, name, uid, &usr_attrs);
479 0 : if (ret == EOK) {
480 0 : ret = sdap_save_user(state, state->ctx->opts, state->domain,
481 : usr_attrs[0], NULL, 0);
482 : }
483 : }
484 : }
485 0 : state->sdap_ret = ret;
486 :
487 0 : if (ret && ret != ENOENT) {
488 0 : state->dp_error = dp_error;
489 0 : tevent_req_error(req, ret);
490 0 : return;
491 : }
492 :
493 0 : if (ret == ENOENT && state->noexist_delete == true) {
494 0 : switch (state->filter_type) {
495 : case BE_FILTER_ENUM:
496 0 : tevent_req_error(req, ret);
497 0 : return;
498 : case BE_FILTER_NAME:
499 0 : ret = sysdb_delete_user(state->domain, state->name, 0);
500 0 : if (ret != EOK && ret != ENOENT) {
501 0 : tevent_req_error(req, ret);
502 0 : return;
503 : }
504 0 : break;
505 :
506 : case BE_FILTER_IDNUM:
507 0 : uid = (uid_t) strtouint32(state->name, &endptr, 10);
508 0 : if (errno || *endptr || (state->name == endptr)) {
509 0 : tevent_req_error(req, errno ? errno : EINVAL);
510 0 : return;
511 : }
512 :
513 0 : ret = sysdb_delete_user(state->domain, NULL, uid);
514 0 : if (ret != EOK && ret != ENOENT) {
515 0 : tevent_req_error(req, ret);
516 0 : return;
517 : }
518 0 : break;
519 :
520 : case BE_FILTER_SECID:
521 : case BE_FILTER_UUID:
522 : /* Since it is not clear if the SID/UUID belongs to a user or a
523 : * group we have nothing to do here. */
524 0 : break;
525 :
526 : case BE_FILTER_WILDCARD:
527 : /* We can't know if all users are up-to-date, especially in a large
528 : * environment. Do not delete any records, let the responder fetch
529 : * the entries they are requested in
530 : */
531 0 : break;
532 :
533 : case BE_FILTER_CERT:
534 0 : ret = sysdb_remove_cert(state->domain, state->name);
535 0 : if (ret != EOK) {
536 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to remove user certificate"
537 : "[%d]: %s\n", ret, sss_strerror(ret));
538 0 : tevent_req_error(req, ret);
539 0 : return;
540 : }
541 0 : break;
542 :
543 : default:
544 0 : tevent_req_error(req, EINVAL);
545 0 : return;
546 : }
547 : }
548 :
549 0 : state->dp_error = DP_ERR_OK;
550 : /* FIXME - return sdap error so that we know the user was not found */
551 0 : tevent_req_done(req);
552 : }
553 :
554 0 : int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
555 : {
556 0 : struct users_get_state *state = tevent_req_data(req,
557 : struct users_get_state);
558 :
559 0 : if (dp_error_out) {
560 0 : *dp_error_out = state->dp_error;
561 : }
562 :
563 0 : if (sdap_ret) {
564 0 : *sdap_ret = state->sdap_ret;
565 : }
566 :
567 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
568 :
569 0 : return EOK;
570 : }
571 :
572 : /* =Groups-Related-Functions-(by-name,by-uid)============================= */
573 :
574 : struct groups_get_state {
575 : struct tevent_context *ev;
576 : struct sdap_id_ctx *ctx;
577 : struct sdap_domain *sdom;
578 : struct sdap_id_conn_ctx *conn;
579 : struct sdap_id_op *op;
580 : struct sysdb_ctx *sysdb;
581 : struct sss_domain_info *domain;
582 :
583 : const char *name;
584 : int filter_type;
585 :
586 : char *filter;
587 : const char **attrs;
588 : bool use_id_mapping;
589 :
590 : int dp_error;
591 : int sdap_ret;
592 : bool noexist_delete;
593 : bool no_members;
594 : };
595 :
596 : static int groups_get_retry(struct tevent_req *req);
597 : static void groups_get_connect_done(struct tevent_req *subreq);
598 : static void groups_get_posix_check_done(struct tevent_req *subreq);
599 : static void groups_get_search(struct tevent_req *req);
600 : static void groups_get_done(struct tevent_req *subreq);
601 :
602 0 : struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
603 : struct tevent_context *ev,
604 : struct sdap_id_ctx *ctx,
605 : struct sdap_domain *sdom,
606 : struct sdap_id_conn_ctx *conn,
607 : const char *name,
608 : int filter_type,
609 : int attrs_type,
610 : bool noexist_delete,
611 : bool no_members)
612 : {
613 : struct tevent_req *req;
614 : struct groups_get_state *state;
615 0 : const char *attr_name = NULL;
616 : char *clean_name;
617 : char *endptr;
618 : int ret;
619 : gid_t gid;
620 : enum idmap_error_code err;
621 : char *sid;
622 : const char *member_filter[2];
623 : char *oc_list;
624 :
625 0 : req = tevent_req_create(memctx, &state, struct groups_get_state);
626 0 : if (!req) return NULL;
627 :
628 0 : state->ev = ev;
629 0 : state->ctx = ctx;
630 0 : state->sdom = sdom;
631 0 : state->conn = conn;
632 0 : state->dp_error = DP_ERR_FATAL;
633 0 : state->noexist_delete = noexist_delete;
634 0 : state->no_members = no_members;
635 :
636 0 : state->op = sdap_id_op_create(state, state->conn->conn_cache);
637 0 : if (!state->op) {
638 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
639 0 : ret = ENOMEM;
640 0 : goto done;
641 : }
642 :
643 0 : state->domain = sdom->dom;
644 0 : state->sysdb = sdom->dom->sysdb;
645 0 : state->name = name;
646 0 : state->filter_type = filter_type;
647 :
648 0 : state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
649 0 : ctx->opts->idmap_ctx,
650 0 : sdom->dom->name,
651 0 : sdom->dom->domain_id);
652 :
653 0 : switch(filter_type) {
654 : case BE_FILTER_WILDCARD:
655 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
656 0 : ret = sss_filter_sanitize_ex(state, name, &clean_name,
657 : LDAP_ALLOWED_WILDCARDS);
658 0 : if (ret != EOK) {
659 0 : goto done;
660 : }
661 0 : break;
662 : case BE_FILTER_NAME:
663 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
664 :
665 0 : ret = sss_filter_sanitize(state, name, &clean_name);
666 0 : if (ret != EOK) {
667 0 : goto done;
668 : }
669 0 : break;
670 : case BE_FILTER_IDNUM:
671 0 : if (state->use_id_mapping) {
672 : /* If we're ID-mapping, we need to use the objectSID
673 : * in the search filter.
674 : */
675 0 : gid = strtouint32(name, &endptr, 10);
676 0 : if (errno != EOK) {
677 0 : ret = EINVAL;
678 0 : goto done;
679 : }
680 :
681 : /* Convert the GID to its objectSID */
682 0 : err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map,
683 : gid, &sid);
684 0 : if (err == IDMAP_NO_DOMAIN) {
685 0 : DEBUG(SSSDBG_MINOR_FAILURE,
686 : "[%s] did not match any configured ID mapping domain\n",
687 : name);
688 :
689 0 : ret = sysdb_delete_group(state->domain, NULL, gid);
690 0 : if (ret == ENOENT) {
691 : /* Ignore errors to remove users that were not cached previously */
692 0 : ret = EOK;
693 : }
694 :
695 0 : goto done;
696 0 : } else if (err != IDMAP_SUCCESS) {
697 0 : DEBUG(SSSDBG_MINOR_FAILURE,
698 : "Mapping ID [%s] to SID failed: [%s]\n",
699 : name, idmap_error_string(err));
700 0 : ret = EIO;
701 0 : goto done;
702 : }
703 :
704 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name;
705 0 : ret = sss_filter_sanitize(state, sid, &clean_name);
706 0 : sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid);
707 0 : if (ret != EOK) {
708 0 : goto done;
709 : }
710 :
711 : } else {
712 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_GID].name;
713 0 : ret = sss_filter_sanitize(state, name, &clean_name);
714 0 : if (ret != EOK) {
715 0 : goto done;
716 : }
717 : }
718 0 : break;
719 : case BE_FILTER_SECID:
720 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name;
721 :
722 0 : ret = sss_filter_sanitize(state, name, &clean_name);
723 0 : if (ret != EOK) {
724 0 : goto done;
725 : }
726 0 : break;
727 : case BE_FILTER_UUID:
728 0 : attr_name = ctx->opts->group_map[SDAP_AT_GROUP_UUID].name;
729 0 : if (attr_name == NULL) {
730 0 : DEBUG(SSSDBG_CRIT_FAILURE,
731 : "UUID search not configured for this backend.\n");
732 0 : ret = EINVAL;
733 0 : goto done;
734 : }
735 :
736 0 : ret = sss_filter_sanitize(state, name, &clean_name);
737 0 : if (ret != EOK) {
738 0 : goto done;
739 : }
740 0 : break;
741 : default:
742 0 : ret = EINVAL;
743 0 : goto done;
744 : }
745 :
746 0 : if (attr_name == NULL) {
747 0 : DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n");
748 0 : ret = EINVAL;
749 0 : goto done;
750 : }
751 :
752 0 : oc_list = sdap_make_oc_list(state, ctx->opts->group_map);
753 0 : if (oc_list == NULL) {
754 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
755 0 : ret = ENOMEM;
756 0 : goto done;
757 : }
758 :
759 0 : if (state->use_id_mapping || filter_type == BE_FILTER_SECID) {
760 : /* When mapping IDs or looking for SIDs, we don't want to limit
761 : * ourselves to groups with a GID value
762 : */
763 :
764 0 : state->filter = talloc_asprintf(state,
765 : "(&(%s=%s)(%s)(%s=*))",
766 : attr_name, clean_name, oc_list,
767 0 : ctx->opts->group_map[SDAP_AT_GROUP_NAME].name);
768 : } else {
769 0 : state->filter = talloc_asprintf(state,
770 : "(&(%s=%s)(%s)(%s=*)(&(%s=*)(!(%s=0))))",
771 : attr_name, clean_name, oc_list,
772 0 : ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
773 0 : ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
774 0 : ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
775 : }
776 :
777 0 : talloc_zfree(clean_name);
778 0 : if (!state->filter) {
779 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n");
780 0 : ret = ENOMEM;
781 0 : goto done;
782 : }
783 :
784 0 : member_filter[0] = (const char *)ctx->opts->group_map[SDAP_AT_GROUP_MEMBER].name;
785 0 : member_filter[1] = NULL;
786 :
787 : /* TODO: handle attrs_type */
788 0 : ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
789 0 : (state->domain->ignore_group_members
790 0 : || state->no_members) ?
791 : (const char **)member_filter : NULL,
792 0 : &state->attrs, NULL);
793 :
794 0 : if (ret != EOK) goto done;
795 :
796 0 : ret = groups_get_retry(req);
797 0 : if (ret != EOK) {
798 0 : goto done;
799 : }
800 :
801 0 : return req;
802 :
803 : done:
804 0 : if (ret != EOK) {
805 0 : tevent_req_error(req, ret);
806 : } else {
807 0 : tevent_req_done(req);
808 : }
809 0 : return tevent_req_post(req, ev);
810 : }
811 :
812 0 : static int groups_get_retry(struct tevent_req *req)
813 : {
814 0 : struct groups_get_state *state = tevent_req_data(req,
815 : struct groups_get_state);
816 : struct tevent_req *subreq;
817 0 : int ret = EOK;
818 :
819 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
820 0 : if (!subreq) {
821 0 : return ret;
822 : }
823 :
824 0 : tevent_req_set_callback(subreq, groups_get_connect_done, req);
825 0 : return EOK;
826 : }
827 :
828 0 : static void groups_get_connect_done(struct tevent_req *subreq)
829 : {
830 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
831 : struct tevent_req);
832 0 : struct groups_get_state *state = tevent_req_data(req,
833 : struct groups_get_state);
834 0 : int dp_error = DP_ERR_FATAL;
835 : int ret;
836 :
837 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
838 0 : talloc_zfree(subreq);
839 :
840 0 : if (ret != EOK) {
841 0 : state->dp_error = dp_error;
842 0 : tevent_req_error(req, ret);
843 0 : return;
844 : }
845 :
846 : /* If POSIX attributes have been requested with an AD server and we
847 : * have no idea about POSIX attributes support, run a one-time check
848 : */
849 0 : if (state->use_id_mapping == false &&
850 0 : state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
851 0 : state->ctx->srv_opts &&
852 0 : state->ctx->srv_opts->posix_checked == false) {
853 0 : subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
854 : sdap_id_op_handle(state->op),
855 0 : state->sdom->user_search_bases,
856 0 : dp_opt_get_int(state->ctx->opts->basic,
857 : SDAP_SEARCH_TIMEOUT));
858 0 : if (subreq == NULL) {
859 0 : tevent_req_error(req, ENOMEM);
860 0 : return;
861 : }
862 0 : tevent_req_set_callback(subreq, groups_get_posix_check_done, req);
863 0 : return;
864 : }
865 :
866 0 : groups_get_search(req);
867 : }
868 :
869 0 : static void groups_get_posix_check_done(struct tevent_req *subreq)
870 : {
871 : errno_t ret;
872 : bool has_posix;
873 : int dp_error;
874 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
875 : struct tevent_req);
876 0 : struct groups_get_state *state = tevent_req_data(req,
877 : struct groups_get_state);
878 :
879 0 : ret = sdap_posix_check_recv(subreq, &has_posix);
880 0 : talloc_zfree(subreq);
881 0 : if (ret != EOK) {
882 : /* We can only finish the id_op on error as the connection
883 : * is re-used by the group search
884 : */
885 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
886 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
887 : /* retry */
888 0 : ret = groups_get_retry(req);
889 0 : if (ret != EOK) {
890 0 : tevent_req_error(req, ret);
891 : }
892 0 : return;
893 : }
894 : }
895 :
896 0 : state->ctx->srv_opts->posix_checked = true;
897 :
898 : /* If the check ran to completion, we know for certain about the attributes
899 : */
900 0 : if (has_posix == false) {
901 0 : state->sdap_ret = ERR_NO_POSIX;
902 0 : tevent_req_done(req);
903 0 : return;
904 : }
905 :
906 0 : groups_get_search(req);
907 : }
908 :
909 0 : static void groups_get_search(struct tevent_req *req)
910 : {
911 0 : struct groups_get_state *state = tevent_req_data(req,
912 : struct groups_get_state);
913 : struct tevent_req *subreq;
914 : enum sdap_entry_lookup_type lookup_type;
915 :
916 0 : if (state->filter_type == BE_FILTER_WILDCARD) {
917 0 : lookup_type = SDAP_LOOKUP_WILDCARD;
918 : } else {
919 0 : lookup_type = SDAP_LOOKUP_SINGLE;
920 : }
921 :
922 0 : subreq = sdap_get_groups_send(state, state->ev,
923 : state->sdom,
924 0 : state->ctx->opts,
925 : sdap_id_op_handle(state->op),
926 0 : state->attrs, state->filter,
927 0 : dp_opt_get_int(state->ctx->opts->basic,
928 : SDAP_SEARCH_TIMEOUT),
929 : lookup_type,
930 0 : state->no_members);
931 0 : if (!subreq) {
932 0 : tevent_req_error(req, ENOMEM);
933 0 : return;
934 : }
935 0 : tevent_req_set_callback(subreq, groups_get_done, req);
936 : }
937 :
938 0 : static void groups_get_done(struct tevent_req *subreq)
939 : {
940 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
941 : struct tevent_req);
942 0 : struct groups_get_state *state = tevent_req_data(req,
943 : struct groups_get_state);
944 : char *endptr;
945 : gid_t gid;
946 0 : int dp_error = DP_ERR_FATAL;
947 : int ret;
948 :
949 0 : ret = sdap_get_groups_recv(subreq, NULL, NULL);
950 0 : talloc_zfree(subreq);
951 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
952 :
953 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
954 : /* retry */
955 0 : ret = groups_get_retry(req);
956 0 : if (ret != EOK) {
957 0 : tevent_req_error(req, ret);
958 0 : return;
959 : }
960 :
961 0 : return;
962 : }
963 0 : state->sdap_ret = ret;
964 :
965 0 : if (ret && ret != ENOENT) {
966 0 : state->dp_error = dp_error;
967 0 : tevent_req_error(req, ret);
968 0 : return;
969 : }
970 :
971 0 : if (ret == ENOENT && state->noexist_delete == true) {
972 0 : switch (state->filter_type) {
973 : case BE_FILTER_ENUM:
974 0 : tevent_req_error(req, ret);
975 0 : return;
976 : case BE_FILTER_NAME:
977 0 : ret = sysdb_delete_group(state->domain, state->name, 0);
978 0 : if (ret != EOK && ret != ENOENT) {
979 0 : tevent_req_error(req, ret);
980 0 : return;
981 : }
982 0 : break;
983 :
984 : case BE_FILTER_IDNUM:
985 0 : gid = (gid_t) strtouint32(state->name, &endptr, 10);
986 0 : if (errno || *endptr || (state->name == endptr)) {
987 0 : tevent_req_error(req, errno ? errno : EINVAL);
988 0 : return;
989 : }
990 :
991 0 : ret = sysdb_delete_group(state->domain, NULL, gid);
992 0 : if (ret != EOK && ret != ENOENT) {
993 0 : tevent_req_error(req, ret);
994 0 : return;
995 : }
996 0 : break;
997 :
998 : case BE_FILTER_SECID:
999 : case BE_FILTER_UUID:
1000 : /* Since it is not clear if the SID/UUID belongs to a user or a
1001 : * group we have nothing to do here. */
1002 0 : break;
1003 :
1004 : case BE_FILTER_WILDCARD:
1005 : /* We can't know if all groups are up-to-date, especially in
1006 : * a large environment. Do not delete any records, let the
1007 : * responder fetch the entries they are requested in.
1008 : */
1009 0 : break;
1010 :
1011 :
1012 : default:
1013 0 : tevent_req_error(req, EINVAL);
1014 0 : return;
1015 : }
1016 : }
1017 :
1018 0 : state->dp_error = DP_ERR_OK;
1019 0 : tevent_req_done(req);
1020 : }
1021 :
1022 0 : int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
1023 : {
1024 0 : struct groups_get_state *state = tevent_req_data(req,
1025 : struct groups_get_state);
1026 :
1027 0 : if (dp_error_out) {
1028 0 : *dp_error_out = state->dp_error;
1029 : }
1030 :
1031 0 : if (sdap_ret) {
1032 0 : *sdap_ret = state->sdap_ret;
1033 : }
1034 :
1035 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1036 :
1037 0 : return EOK;
1038 : }
1039 :
1040 :
1041 : /* =Get-Groups-for-User================================================== */
1042 :
1043 : struct groups_by_user_state {
1044 : struct tevent_context *ev;
1045 : struct sdap_id_ctx *ctx;
1046 : struct sdap_domain *sdom;
1047 : struct sdap_id_conn_ctx *conn;
1048 : struct sdap_id_op *op;
1049 : struct sysdb_ctx *sysdb;
1050 : struct sss_domain_info *domain;
1051 :
1052 : const char *name;
1053 : int name_type;
1054 : const char *extra_value;
1055 : const char **attrs;
1056 :
1057 : int dp_error;
1058 : int sdap_ret;
1059 : bool noexist_delete;
1060 : };
1061 :
1062 : static int groups_by_user_retry(struct tevent_req *req);
1063 : static void groups_by_user_connect_done(struct tevent_req *subreq);
1064 : static void groups_by_user_done(struct tevent_req *subreq);
1065 :
1066 0 : static errno_t set_initgroups_expire_attribute(struct sss_domain_info *domain,
1067 : const char *name)
1068 : {
1069 : errno_t ret;
1070 : time_t cache_timeout;
1071 : struct sysdb_attrs *attrs;
1072 :
1073 0 : attrs = sysdb_new_attrs(NULL);
1074 0 : if (attrs == NULL) {
1075 0 : return ENOMEM;
1076 : }
1077 :
1078 0 : cache_timeout = domain->user_timeout
1079 0 : ? time(NULL) + domain->user_timeout
1080 0 : : 0;
1081 :
1082 0 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_INITGR_EXPIRE, cache_timeout);
1083 0 : if (ret != EOK) {
1084 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up attrs\n");
1085 0 : goto done;
1086 : }
1087 :
1088 0 : ret = sysdb_set_user_attr(domain, name, attrs, SYSDB_MOD_REP);
1089 0 : if (ret != EOK) {
1090 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1091 : "Failed to set initgroups expire attribute\n");
1092 0 : goto done;
1093 : }
1094 :
1095 : done:
1096 0 : talloc_zfree(attrs);
1097 0 : return ret;
1098 : }
1099 :
1100 0 : static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
1101 : struct tevent_context *ev,
1102 : struct sdap_id_ctx *ctx,
1103 : struct sdap_domain *sdom,
1104 : struct sdap_id_conn_ctx *conn,
1105 : const char *name,
1106 : int name_type,
1107 : const char *extra_value,
1108 : bool noexist_delete)
1109 : {
1110 : struct tevent_req *req;
1111 : struct groups_by_user_state *state;
1112 : int ret;
1113 :
1114 0 : req = tevent_req_create(memctx, &state, struct groups_by_user_state);
1115 0 : if (!req) return NULL;
1116 :
1117 0 : state->ev = ev;
1118 0 : state->ctx = ctx;
1119 0 : state->dp_error = DP_ERR_FATAL;
1120 0 : state->conn = conn;
1121 0 : state->sdom = sdom;
1122 0 : state->noexist_delete = noexist_delete;
1123 :
1124 0 : state->op = sdap_id_op_create(state, state->conn->conn_cache);
1125 0 : if (!state->op) {
1126 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
1127 0 : ret = ENOMEM;
1128 0 : goto fail;
1129 : }
1130 :
1131 0 : state->name = name;
1132 0 : state->name_type = name_type;
1133 0 : state->extra_value = extra_value;
1134 0 : state->domain = sdom->dom;
1135 0 : state->sysdb = sdom->dom->sysdb;
1136 :
1137 0 : ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
1138 0 : NULL, &state->attrs, NULL);
1139 0 : if (ret != EOK) goto fail;
1140 :
1141 0 : ret = groups_by_user_retry(req);
1142 0 : if (ret != EOK) {
1143 0 : goto fail;
1144 : }
1145 :
1146 0 : return req;
1147 :
1148 : fail:
1149 0 : tevent_req_error(req, ret);
1150 0 : tevent_req_post(req, ev);
1151 0 : return req;
1152 : }
1153 :
1154 0 : static int groups_by_user_retry(struct tevent_req *req)
1155 : {
1156 0 : struct groups_by_user_state *state = tevent_req_data(req,
1157 : struct groups_by_user_state);
1158 : struct tevent_req *subreq;
1159 0 : int ret = EOK;
1160 :
1161 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
1162 0 : if (!subreq) {
1163 0 : return ret;
1164 : }
1165 :
1166 0 : tevent_req_set_callback(subreq, groups_by_user_connect_done, req);
1167 0 : return EOK;
1168 : }
1169 :
1170 0 : static void groups_by_user_connect_done(struct tevent_req *subreq)
1171 : {
1172 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1173 : struct tevent_req);
1174 0 : struct groups_by_user_state *state = tevent_req_data(req,
1175 : struct groups_by_user_state);
1176 0 : int dp_error = DP_ERR_FATAL;
1177 : int ret;
1178 :
1179 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
1180 0 : talloc_zfree(subreq);
1181 :
1182 0 : if (ret != EOK) {
1183 0 : state->dp_error = dp_error;
1184 0 : tevent_req_error(req, ret);
1185 0 : return;
1186 : }
1187 :
1188 0 : subreq = sdap_get_initgr_send(state,
1189 : state->ev,
1190 : state->sdom,
1191 : sdap_id_op_handle(state->op),
1192 : state->ctx,
1193 : state->conn,
1194 : state->name,
1195 : state->name_type,
1196 : state->extra_value,
1197 : state->attrs);
1198 0 : if (!subreq) {
1199 0 : tevent_req_error(req, ENOMEM);
1200 0 : return;
1201 : }
1202 0 : tevent_req_set_callback(subreq, groups_by_user_done, req);
1203 : }
1204 :
1205 0 : static void groups_by_user_done(struct tevent_req *subreq)
1206 : {
1207 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1208 : struct tevent_req);
1209 0 : struct groups_by_user_state *state = tevent_req_data(req,
1210 : struct groups_by_user_state);
1211 0 : int dp_error = DP_ERR_FATAL;
1212 : int ret;
1213 : const char *cname;
1214 :
1215 0 : ret = sdap_get_initgr_recv(subreq);
1216 0 : talloc_zfree(subreq);
1217 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
1218 :
1219 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
1220 : /* retry */
1221 0 : ret = groups_by_user_retry(req);
1222 0 : if (ret != EOK) {
1223 0 : tevent_req_error(req, ret);
1224 0 : return;
1225 : }
1226 :
1227 0 : return;
1228 : }
1229 0 : state->sdap_ret = ret;
1230 :
1231 0 : if (ret == EOK || ret == ENOENT) {
1232 : /* state->name is still the name used for the original req. The cached
1233 : * object might have a different name, e.g. a fully-qualified name. */
1234 0 : ret = sysdb_get_real_name(state, state->domain, state->name, &cname);
1235 0 : if (ret != EOK) {
1236 0 : cname = state->name;
1237 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1238 : "Failed to canonicalize name, using [%s] [%d]: %s.\n",
1239 : cname, ret, sss_strerror(ret));
1240 : }
1241 : }
1242 :
1243 0 : switch (state->sdap_ret) {
1244 : case ENOENT:
1245 0 : if (state->noexist_delete == true) {
1246 0 : ret = sysdb_delete_user(state->domain, cname, 0);
1247 0 : if (ret != EOK && ret != ENOENT) {
1248 0 : tevent_req_error(req, ret);
1249 0 : return;
1250 : }
1251 : }
1252 0 : break;
1253 : case EOK:
1254 0 : ret = set_initgroups_expire_attribute(state->domain, cname);
1255 0 : if (ret != EOK) {
1256 0 : state->dp_error = DP_ERR_FATAL;
1257 0 : tevent_req_error(req, ret);
1258 0 : return;
1259 : }
1260 0 : break;
1261 : default:
1262 0 : state->dp_error = dp_error;
1263 0 : tevent_req_error(req, ret);
1264 0 : return;
1265 : }
1266 :
1267 0 : state->dp_error = DP_ERR_OK;
1268 0 : tevent_req_done(req);
1269 : }
1270 :
1271 0 : int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
1272 : {
1273 0 : struct groups_by_user_state *state = tevent_req_data(req,
1274 : struct groups_by_user_state);
1275 :
1276 0 : if (dp_error_out) {
1277 0 : *dp_error_out = state->dp_error;
1278 : }
1279 :
1280 0 : if (sdap_ret) {
1281 0 : *sdap_ret = state->sdap_ret;
1282 : }
1283 :
1284 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1285 :
1286 0 : return EOK;
1287 : }
1288 :
1289 : /* =Get-Account-Info-Call================================================= */
1290 :
1291 : /* FIXME: embed this function in sssd_be and only call out
1292 : * specific functions from modules ? */
1293 :
1294 : static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
1295 : struct tevent_context *ev,
1296 : struct sdap_id_ctx *ctx,
1297 : struct sdap_domain *sdom,
1298 : struct sdap_id_conn_ctx *conn,
1299 : const char *name,
1300 : int filter_type,
1301 : int attrs_type,
1302 : bool noexist_delete);
1303 :
1304 : errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
1305 : int *dp_error_out, int *sdap_ret);
1306 :
1307 0 : bool sdap_is_enum_request(struct be_acct_req *ar)
1308 : {
1309 0 : switch (ar->entry_type & BE_REQ_TYPE_MASK) {
1310 : case BE_REQ_USER:
1311 : case BE_REQ_GROUP:
1312 : case BE_REQ_SERVICES:
1313 0 : if (ar->filter_type == BE_FILTER_ENUM) {
1314 0 : return true;
1315 : }
1316 : }
1317 :
1318 0 : return false;
1319 : }
1320 :
1321 : /* A generic LDAP account info handler */
1322 : struct sdap_handle_acct_req_state {
1323 : struct be_acct_req *ar;
1324 : const char *err;
1325 : int dp_error;
1326 : int sdap_ret;
1327 : };
1328 :
1329 : static void sdap_handle_acct_req_done(struct tevent_req *subreq);
1330 :
1331 : struct tevent_req *
1332 0 : sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
1333 : struct be_ctx *be_ctx,
1334 : struct be_acct_req *ar,
1335 : struct sdap_id_ctx *id_ctx,
1336 : struct sdap_domain *sdom,
1337 : struct sdap_id_conn_ctx *conn,
1338 : bool noexist_delete)
1339 : {
1340 : struct tevent_req *req;
1341 : struct tevent_req *subreq;
1342 : struct sdap_handle_acct_req_state *state;
1343 : errno_t ret;
1344 :
1345 :
1346 0 : req = tevent_req_create(mem_ctx, &state,
1347 : struct sdap_handle_acct_req_state);
1348 0 : if (!req) {
1349 0 : return NULL;
1350 : }
1351 0 : state->ar = ar;
1352 :
1353 0 : if (ar == NULL) {
1354 0 : ret = EINVAL;
1355 0 : goto done;
1356 : }
1357 :
1358 : PROBE(SDAP_ACCT_REQ_SEND,
1359 : state->ar->entry_type & BE_REQ_TYPE_MASK,
1360 : state->ar->filter_type, state->ar->filter_value,
1361 : PROBE_SAFE_STR(state->ar->extra_value));
1362 :
1363 0 : switch (ar->entry_type & BE_REQ_TYPE_MASK) {
1364 : case BE_REQ_USER: /* user */
1365 0 : subreq = users_get_send(state, be_ctx->ev, id_ctx,
1366 : sdom, conn,
1367 : ar->filter_value,
1368 0 : ar->filter_type,
1369 : ar->extra_value,
1370 0 : ar->attr_type,
1371 : noexist_delete);
1372 0 : break;
1373 :
1374 : case BE_REQ_GROUP: /* group */
1375 0 : subreq = groups_get_send(state, be_ctx->ev, id_ctx,
1376 : sdom, conn,
1377 : ar->filter_value,
1378 0 : ar->filter_type,
1379 0 : ar->attr_type,
1380 : noexist_delete, false);
1381 0 : break;
1382 :
1383 : case BE_REQ_INITGROUPS: /* init groups for user */
1384 0 : if (ar->filter_type != BE_FILTER_NAME
1385 0 : && ar->filter_type != BE_FILTER_SECID
1386 0 : && ar->filter_type != BE_FILTER_UUID) {
1387 0 : ret = EINVAL;
1388 0 : state->err = "Invalid filter type";
1389 0 : goto done;
1390 : }
1391 0 : if (ar->attr_type != BE_ATTR_CORE) {
1392 0 : ret = EINVAL;
1393 0 : state->err = "Invalid attr type";
1394 0 : goto done;
1395 : }
1396 :
1397 0 : subreq = groups_by_user_send(state, be_ctx->ev, id_ctx,
1398 : sdom, conn,
1399 : ar->filter_value,
1400 0 : ar->filter_type,
1401 : ar->extra_value,
1402 : noexist_delete);
1403 0 : break;
1404 :
1405 : case BE_REQ_NETGROUP:
1406 0 : if (ar->filter_type != BE_FILTER_NAME) {
1407 0 : ret = EINVAL;
1408 0 : state->err = "Invalid filter type";
1409 0 : goto done;
1410 : }
1411 :
1412 0 : subreq = ldap_netgroup_get_send(state, be_ctx->ev, id_ctx,
1413 : sdom, conn,
1414 : ar->filter_value,
1415 : noexist_delete);
1416 0 : break;
1417 :
1418 : case BE_REQ_SERVICES:
1419 0 : if (ar->filter_type == BE_FILTER_SECID
1420 0 : || ar->filter_type == BE_FILTER_UUID) {
1421 0 : ret = EINVAL;
1422 0 : state->err = "Invalid filter type";
1423 0 : goto done;
1424 : }
1425 :
1426 0 : subreq = services_get_send(state, be_ctx->ev, id_ctx,
1427 : sdom, conn,
1428 : ar->filter_value,
1429 : ar->extra_value,
1430 0 : ar->filter_type,
1431 : noexist_delete);
1432 0 : break;
1433 :
1434 : case BE_REQ_BY_SECID:
1435 0 : if (ar->filter_type != BE_FILTER_SECID) {
1436 0 : ret = EINVAL;
1437 0 : state->err = "Invalid filter type";
1438 0 : goto done;
1439 : }
1440 :
1441 0 : subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
1442 : sdom, conn,
1443 : ar->filter_value,
1444 0 : ar->filter_type,
1445 0 : ar->attr_type,
1446 : noexist_delete);
1447 0 : break;
1448 :
1449 : case BE_REQ_BY_UUID:
1450 0 : if (ar->filter_type != BE_FILTER_UUID) {
1451 0 : ret = EINVAL;
1452 0 : state->err = "Invalid filter type";
1453 0 : goto done;
1454 : }
1455 :
1456 0 : subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
1457 : sdom, conn,
1458 : ar->filter_value,
1459 0 : ar->filter_type,
1460 0 : ar->attr_type,
1461 : noexist_delete);
1462 0 : break;
1463 :
1464 : case BE_REQ_USER_AND_GROUP:
1465 0 : if (!(ar->filter_type == BE_FILTER_NAME ||
1466 0 : ar->filter_type == BE_FILTER_IDNUM)) {
1467 0 : ret = EINVAL;
1468 0 : state->err = "Invalid filter type";
1469 0 : goto done;
1470 : }
1471 :
1472 0 : subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
1473 : sdom, conn,
1474 : ar->filter_value,
1475 0 : ar->filter_type,
1476 0 : ar->attr_type,
1477 : noexist_delete);
1478 0 : break;
1479 :
1480 : case BE_REQ_BY_CERT:
1481 0 : subreq = users_get_send(state, be_ctx->ev, id_ctx,
1482 : sdom, conn,
1483 : ar->filter_value,
1484 0 : ar->filter_type,
1485 : ar->extra_value,
1486 0 : ar->attr_type,
1487 : noexist_delete);
1488 0 : break;
1489 :
1490 : default: /*fail*/
1491 0 : ret = EINVAL;
1492 0 : state->err = "Invalid request type";
1493 0 : goto done;
1494 : }
1495 :
1496 0 : if (!subreq) {
1497 0 : ret = ENOMEM;
1498 0 : goto done;
1499 : }
1500 :
1501 0 : tevent_req_set_callback(subreq, sdap_handle_acct_req_done, req);
1502 0 : return req;
1503 :
1504 : done:
1505 0 : if (ret == EOK) {
1506 0 : tevent_req_done(req);
1507 : } else {
1508 0 : tevent_req_error(req, ret);
1509 : }
1510 :
1511 0 : tevent_req_post(req, be_ctx->ev);
1512 0 : return req;
1513 : }
1514 :
1515 : static void
1516 0 : sdap_handle_acct_req_done(struct tevent_req *subreq)
1517 : {
1518 0 : struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
1519 : struct sdap_handle_acct_req_state *state;
1520 : errno_t ret;
1521 0 : const char *err = "Invalid request type";
1522 :
1523 0 : state = tevent_req_data(req, struct sdap_handle_acct_req_state);
1524 :
1525 0 : switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
1526 : case BE_REQ_USER: /* user */
1527 0 : err = "User lookup failed";
1528 0 : ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1529 0 : break;
1530 : case BE_REQ_GROUP: /* group */
1531 0 : err = "Group lookup failed";
1532 0 : ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1533 0 : break;
1534 : case BE_REQ_INITGROUPS: /* init groups for user */
1535 0 : err = "Init group lookup failed";
1536 0 : ret = groups_by_user_recv(subreq, &state->dp_error, &state->sdap_ret);
1537 0 : break;
1538 : case BE_REQ_NETGROUP:
1539 0 : err = "Netgroup lookup failed";
1540 0 : ret = ldap_netgroup_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1541 0 : break;
1542 : case BE_REQ_SERVICES:
1543 0 : err = "Service lookup failed";
1544 0 : ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1545 0 : break;
1546 : case BE_REQ_BY_SECID:
1547 : /* Fallthrough */
1548 : case BE_REQ_BY_UUID:
1549 : /* Fallthrough */
1550 : case BE_REQ_USER_AND_GROUP:
1551 0 : err = "Lookup by SID failed";
1552 0 : ret = sdap_get_user_and_group_recv(subreq, &state->dp_error,
1553 : &state->sdap_ret);
1554 0 : break;
1555 : case BE_REQ_BY_CERT:
1556 0 : err = "User lookup by certificate failed";
1557 0 : ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1558 0 : break;
1559 : default: /*fail*/
1560 0 : ret = EINVAL;
1561 0 : break;
1562 : }
1563 0 : talloc_zfree(subreq);
1564 :
1565 0 : if (ret != EOK) {
1566 0 : state->err = err;
1567 0 : tevent_req_error(req, ret);
1568 0 : return;
1569 : }
1570 :
1571 0 : state->err = "Success";
1572 0 : tevent_req_done(req);
1573 : }
1574 :
1575 : errno_t
1576 0 : sdap_handle_acct_req_recv(struct tevent_req *req,
1577 : int *_dp_error, const char **_err,
1578 : int *sdap_ret)
1579 : {
1580 : struct sdap_handle_acct_req_state *state;
1581 :
1582 0 : state = tevent_req_data(req, struct sdap_handle_acct_req_state);
1583 :
1584 : PROBE(SDAP_ACCT_REQ_RECV,
1585 : state->ar->entry_type & BE_REQ_TYPE_MASK,
1586 : state->ar->filter_type, state->ar->filter_value,
1587 : PROBE_SAFE_STR(state->ar->extra_value));
1588 :
1589 0 : if (_dp_error) {
1590 0 : *_dp_error = state->dp_error;
1591 : }
1592 :
1593 0 : if (_err) {
1594 0 : *_err = state->err;
1595 : }
1596 :
1597 0 : if (sdap_ret) {
1598 0 : *sdap_ret = state->sdap_ret;
1599 : }
1600 :
1601 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1602 0 : return EOK;
1603 : }
1604 :
1605 : struct get_user_and_group_state {
1606 : struct tevent_context *ev;
1607 : struct sdap_id_ctx *id_ctx;
1608 : struct sdap_domain *sdom;
1609 : struct sdap_id_conn_ctx *conn;
1610 : struct sdap_id_op *op;
1611 : struct sysdb_ctx *sysdb;
1612 : struct sss_domain_info *domain;
1613 :
1614 : const char *filter_val;
1615 : int filter_type;
1616 : int attrs_type;
1617 :
1618 : char *filter;
1619 : const char **attrs;
1620 :
1621 : int dp_error;
1622 : int sdap_ret;
1623 : bool noexist_delete;
1624 : };
1625 :
1626 : static void get_user_and_group_users_done(struct tevent_req *subreq);
1627 : static void get_user_and_group_groups_done(struct tevent_req *subreq);
1628 :
1629 0 : static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
1630 : struct tevent_context *ev,
1631 : struct sdap_id_ctx *id_ctx,
1632 : struct sdap_domain *sdom,
1633 : struct sdap_id_conn_ctx *conn,
1634 : const char *filter_val,
1635 : int filter_type,
1636 : int attrs_type,
1637 : bool noexist_delete)
1638 : {
1639 : struct tevent_req *req;
1640 : struct tevent_req *subreq;
1641 : struct get_user_and_group_state *state;
1642 : int ret;
1643 :
1644 0 : req = tevent_req_create(memctx, &state, struct get_user_and_group_state);
1645 0 : if (req == NULL) {
1646 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
1647 0 : return NULL;
1648 : }
1649 :
1650 0 : state->ev = ev;
1651 0 : state->id_ctx = id_ctx;
1652 0 : state->sdom = sdom;
1653 0 : state->conn = conn;
1654 0 : state->dp_error = DP_ERR_FATAL;
1655 0 : state->noexist_delete = noexist_delete;
1656 :
1657 0 : state->op = sdap_id_op_create(state, state->conn->conn_cache);
1658 0 : if (!state->op) {
1659 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
1660 0 : ret = ENOMEM;
1661 0 : goto fail;
1662 : }
1663 :
1664 0 : state->domain = sdom->dom;
1665 0 : state->sysdb = sdom->dom->sysdb;
1666 0 : state->filter_val = filter_val;
1667 0 : state->filter_type = filter_type;
1668 0 : state->attrs_type = attrs_type;
1669 :
1670 0 : subreq = groups_get_send(req, state->ev, state->id_ctx,
1671 0 : state->sdom, state->conn,
1672 0 : state->filter_val, state->filter_type,
1673 0 : state->attrs_type, state->noexist_delete, false);
1674 0 : if (subreq == NULL) {
1675 0 : DEBUG(SSSDBG_OP_FAILURE, "users_get_send failed.\n");
1676 0 : ret = ENOMEM;
1677 0 : goto fail;
1678 : }
1679 :
1680 0 : tevent_req_set_callback(subreq, get_user_and_group_groups_done, req);
1681 :
1682 0 : return req;
1683 :
1684 : fail:
1685 0 : tevent_req_error(req, ret);
1686 0 : tevent_req_post(req, ev);
1687 0 : return req;
1688 : }
1689 :
1690 0 : static void get_user_and_group_groups_done(struct tevent_req *subreq)
1691 : {
1692 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1693 : struct tevent_req);
1694 0 : struct get_user_and_group_state *state = tevent_req_data(req,
1695 : struct get_user_and_group_state);
1696 : int ret;
1697 : struct ad_id_ctx *ad_id_ctx;
1698 : struct sdap_id_conn_ctx *user_conn;
1699 :
1700 0 : ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1701 0 : talloc_zfree(subreq);
1702 :
1703 0 : if (ret != EOK) { /* Fatal error while looking up group */
1704 0 : tevent_req_error(req, ret);
1705 0 : return;
1706 : }
1707 :
1708 0 : if (state->sdap_ret == EOK) { /* Matching group found */
1709 0 : tevent_req_done(req);
1710 0 : return;
1711 0 : } else if (state->sdap_ret != ENOENT) {
1712 0 : tevent_req_error(req, EIO);
1713 0 : return;
1714 : }
1715 :
1716 : /* Now the search finished fine but did not find an entry.
1717 : * Retry with users. */
1718 :
1719 0 : user_conn = state->conn;
1720 : /* Prefer LDAP over GC for users */
1721 0 : if (state->id_ctx->opts->schema_type == SDAP_SCHEMA_AD
1722 0 : && state->sdom->pvt != NULL) {
1723 0 : ad_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx);
1724 0 : if (ad_id_ctx != NULL && ad_id_ctx->ldap_ctx != NULL
1725 0 : && state->conn == ad_id_ctx->gc_ctx) {
1726 0 : DEBUG(SSSDBG_TRACE_ALL,
1727 : "Switching to LDAP connection for user lookup.\n");
1728 0 : user_conn = ad_id_ctx->ldap_ctx;
1729 : }
1730 : }
1731 :
1732 0 : subreq = users_get_send(req, state->ev, state->id_ctx,
1733 : state->sdom, user_conn,
1734 : state->filter_val, state->filter_type, NULL,
1735 0 : state->attrs_type, state->noexist_delete);
1736 0 : if (subreq == NULL) {
1737 0 : DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n");
1738 0 : tevent_req_error(req, ENOMEM);
1739 0 : return;
1740 : }
1741 :
1742 0 : tevent_req_set_callback(subreq, get_user_and_group_users_done, req);
1743 : }
1744 :
1745 0 : static void get_user_and_group_users_done(struct tevent_req *subreq)
1746 : {
1747 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1748 : struct tevent_req);
1749 0 : struct get_user_and_group_state *state = tevent_req_data(req,
1750 : struct get_user_and_group_state);
1751 : int ret;
1752 :
1753 0 : ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
1754 0 : talloc_zfree(subreq);
1755 :
1756 0 : if (ret != EOK) {
1757 0 : tevent_req_error(req, ret);
1758 0 : return;
1759 : }
1760 0 : if (state->sdap_ret == ENOENT) {
1761 0 : if (state->noexist_delete == true) {
1762 : /* The search ran to completion, but nothing was found.
1763 : * Delete the existing entry, if any. */
1764 0 : ret = sysdb_delete_by_sid(state->sysdb, state->domain,
1765 : state->filter_val);
1766 0 : if (ret != EOK) {
1767 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not delete entry by SID!\n");
1768 0 : tevent_req_error(req, ret);
1769 0 : return;
1770 : }
1771 : }
1772 0 : } else if (state->sdap_ret != EOK) {
1773 0 : tevent_req_error(req, EIO);
1774 0 : return;
1775 : }
1776 :
1777 : /* Both ret and sdap->ret are EOK. Matching user found */
1778 0 : tevent_req_done(req);
1779 0 : return;
1780 : }
1781 :
1782 0 : errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
1783 : int *dp_error_out, int *sdap_ret)
1784 : {
1785 0 : struct get_user_and_group_state *state = tevent_req_data(req,
1786 : struct get_user_and_group_state);
1787 :
1788 0 : if (dp_error_out) {
1789 0 : *dp_error_out = state->dp_error;
1790 : }
1791 :
1792 0 : if (sdap_ret) {
1793 0 : *sdap_ret = state->sdap_ret;
1794 : }
1795 :
1796 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1797 :
1798 0 : return EOK;
1799 : }
1800 :
1801 : struct sdap_account_info_handler_state {
1802 : struct dp_reply_std reply;
1803 : };
1804 :
1805 : static void sdap_account_info_handler_done(struct tevent_req *subreq);
1806 :
1807 : struct tevent_req *
1808 0 : sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
1809 : struct sdap_id_ctx *id_ctx,
1810 : struct be_acct_req *data,
1811 : struct dp_req_params *params)
1812 : {
1813 : struct sdap_account_info_handler_state *state;
1814 : struct tevent_req *subreq;
1815 : struct tevent_req *req;
1816 : errno_t ret;
1817 :
1818 0 : req = tevent_req_create(mem_ctx, &state,
1819 : struct sdap_account_info_handler_state);
1820 0 : if (req == NULL) {
1821 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1822 0 : return NULL;
1823 : }
1824 :
1825 0 : if (sdap_is_enum_request(data)) {
1826 0 : DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
1827 0 : ret = EOK;
1828 0 : goto immediately;
1829 : }
1830 :
1831 0 : subreq = sdap_handle_acct_req_send(state, params->be_ctx, data, id_ctx,
1832 0 : id_ctx->opts->sdom, id_ctx->conn, true);
1833 0 : if (subreq == NULL) {
1834 0 : ret = ENOMEM;
1835 0 : goto immediately;
1836 : }
1837 :
1838 0 : tevent_req_set_callback(subreq, sdap_account_info_handler_done, req);
1839 :
1840 0 : return req;
1841 :
1842 : immediately:
1843 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
1844 :
1845 : /* TODO For backward compatibility we always return EOK to DP now. */
1846 0 : tevent_req_done(req);
1847 0 : tevent_req_post(req, params->ev);
1848 :
1849 0 : return req;
1850 : }
1851 :
1852 0 : static void sdap_account_info_handler_done(struct tevent_req *subreq)
1853 : {
1854 : struct sdap_account_info_handler_state *state;
1855 : struct tevent_req *req;
1856 : const char *error_msg;
1857 : int dp_error;
1858 : errno_t ret;
1859 :
1860 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1861 0 : state = tevent_req_data(req, struct sdap_account_info_handler_state);
1862 :
1863 0 : ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL);
1864 0 : talloc_zfree(subreq);
1865 :
1866 : /* TODO For backward compatibility we always return EOK to DP now. */
1867 0 : dp_reply_std_set(&state->reply, dp_error, ret, error_msg);
1868 0 : tevent_req_done(req);
1869 0 : }
1870 :
1871 0 : errno_t sdap_account_info_handler_recv(TALLOC_CTX *mem_ctx,
1872 : struct tevent_req *req,
1873 : struct dp_reply_std *data)
1874 : {
1875 0 : struct sdap_account_info_handler_state *state = NULL;
1876 :
1877 0 : state = tevent_req_data(req, struct sdap_account_info_handler_state);
1878 :
1879 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1880 :
1881 0 : *data = state->reply;
1882 :
1883 0 : return EOK;
1884 : }
|