Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <dbus/dbus.h>
22 : #include <ldb.h>
23 : #include <talloc.h>
24 : #include <tevent.h>
25 :
26 : #include "util/util.h"
27 : #include "db/sysdb.h"
28 : #include "responder/common/responder_cache_req.h"
29 : #include "providers/data_provider.h"
30 :
31 : #define CACHE_REQ_DEBUG(level, cr, fmt, ...) \
32 : DEBUG(level, "Cache Request [%s #%u]: " fmt, \
33 : (cr)->reqname, (cr)->reqid, ##__VA_ARGS__)
34 :
35 10 : static errno_t updated_users_by_filter(TALLOC_CTX *mem_ctx,
36 : struct sss_domain_info *domain,
37 : const char *name_filter,
38 : time_t since,
39 : struct ldb_result **_res)
40 : {
41 : int ret;
42 : char *recent_filter;
43 :
44 10 : recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
45 : SYSDB_LAST_UPDATE, since);
46 10 : if (recent_filter == NULL) {
47 0 : return ENOMEM;
48 : }
49 :
50 10 : ret = sysdb_enumpwent_filter_with_views(mem_ctx, domain,
51 : name_filter, recent_filter,
52 : _res);
53 10 : talloc_free(recent_filter);
54 10 : return ret;
55 : }
56 :
57 8 : static errno_t updated_groups_by_filter(TALLOC_CTX *mem_ctx,
58 : struct sss_domain_info *domain,
59 : const char *name_filter,
60 : time_t since,
61 : struct ldb_result **_res)
62 : {
63 : int ret;
64 : char *recent_filter;
65 :
66 8 : recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
67 : SYSDB_LAST_UPDATE, since);
68 8 : if (recent_filter == NULL) {
69 0 : return ENOMEM;
70 : }
71 :
72 8 : ret = sysdb_enumgrent_filter_with_views(mem_ctx, domain,
73 : name_filter, recent_filter,
74 : _res);
75 8 : talloc_free(recent_filter);
76 8 : return ret;
77 : }
78 :
79 : struct cache_req_data {
80 : enum cache_req_type type;
81 : struct {
82 : const char *input; /* Original input. */
83 : const char *name; /* Parsed name or UPN. */
84 : const char *lookup; /* Converted per domain rules. */
85 : } name;
86 : uint32_t id;
87 : const char *cert;
88 : const char *sid;
89 : const char **attrs;
90 : };
91 :
92 : static struct cache_req_data *
93 77 : cache_req_data_create(TALLOC_CTX *mem_ctx,
94 : enum cache_req_type type,
95 : struct cache_req_data *input)
96 : {
97 : struct cache_req_data *data;
98 : errno_t ret;
99 :
100 77 : data = talloc_zero(mem_ctx, struct cache_req_data);
101 77 : if (data == NULL) {
102 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n");
103 0 : return NULL;
104 : }
105 :
106 77 : data->type = type;
107 :
108 77 : switch (type) {
109 : case CACHE_REQ_USER_BY_NAME:
110 : case CACHE_REQ_USER_BY_UPN:
111 : case CACHE_REQ_GROUP_BY_NAME:
112 : case CACHE_REQ_USER_BY_FILTER:
113 : case CACHE_REQ_GROUP_BY_FILTER:
114 : case CACHE_REQ_INITGROUPS:
115 : case CACHE_REQ_INITGROUPS_BY_UPN:
116 35 : if (input->name.input == NULL) {
117 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL!\n");
118 0 : ret = ERR_INTERNAL;
119 0 : goto done;
120 : }
121 :
122 35 : data->name.input = talloc_strdup(data, input->name.input);
123 35 : if (data->name.input == NULL) {
124 0 : ret = ENOMEM;
125 0 : goto done;
126 : }
127 35 : break;
128 : case CACHE_REQ_USER_BY_CERT:
129 10 : if (input->cert == NULL) {
130 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: certificate cannot be NULL!\n");
131 0 : ret = ERR_INTERNAL;
132 0 : goto done;
133 : }
134 :
135 10 : data->cert = talloc_strdup(data, input->cert);
136 10 : if (data->cert == NULL) {
137 0 : ret = ENOMEM;
138 0 : goto done;
139 : }
140 10 : break;
141 : case CACHE_REQ_USER_BY_ID:
142 : case CACHE_REQ_GROUP_BY_ID:
143 16 : if (input->id == 0) {
144 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0!\n");
145 0 : ret = ERR_INTERNAL;
146 0 : goto done;
147 : }
148 :
149 16 : data->id = input->id;
150 16 : break;
151 : case CACHE_REQ_OBJECT_BY_SID:
152 16 : if (input->sid == NULL) {
153 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: SID cannot be NULL!\n");
154 0 : ret = ERR_INTERNAL;
155 0 : goto done;
156 : }
157 :
158 16 : data->sid = talloc_strdup(data, input->sid);
159 16 : if (data->sid == NULL) {
160 0 : ret = ENOMEM;
161 0 : goto done;
162 : }
163 16 : break;
164 : }
165 :
166 77 : if (input->attrs != NULL) {
167 16 : data->attrs = dup_string_list(data, input->attrs);
168 16 : if (data->attrs == NULL) {
169 0 : ret = ENOMEM;
170 0 : goto done;
171 : }
172 : }
173 :
174 77 : ret = EOK;
175 :
176 : done:
177 77 : if (ret != EOK) {
178 0 : talloc_zfree(data);
179 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create cache_req data "
180 : "[%d]: %s\n", ret, sss_strerror(ret));
181 0 : return NULL;
182 : }
183 :
184 77 : return data;
185 : }
186 :
187 : struct cache_req_data *
188 35 : cache_req_data_name(TALLOC_CTX *mem_ctx,
189 : enum cache_req_type type,
190 : const char *name)
191 : {
192 35 : struct cache_req_data input = {0};
193 :
194 35 : input.name.input = name;
195 :
196 35 : return cache_req_data_create(mem_ctx, type, &input);
197 : }
198 :
199 : struct cache_req_data *
200 16 : cache_req_data_id(TALLOC_CTX *mem_ctx,
201 : enum cache_req_type type,
202 : uint32_t id)
203 : {
204 16 : struct cache_req_data input = {0};
205 :
206 16 : input.id = id;
207 :
208 16 : return cache_req_data_create(mem_ctx, type, &input);
209 : }
210 :
211 : struct cache_req_data *
212 10 : cache_req_data_cert(TALLOC_CTX *mem_ctx,
213 : enum cache_req_type type,
214 : const char *cert)
215 : {
216 10 : struct cache_req_data input = {0};
217 :
218 10 : input.cert = cert;
219 :
220 10 : return cache_req_data_create(mem_ctx, type, &input);
221 : }
222 :
223 : struct cache_req_data *
224 16 : cache_req_data_sid(TALLOC_CTX *mem_ctx,
225 : enum cache_req_type type,
226 : const char *sid,
227 : const char **attrs)
228 : {
229 16 : struct cache_req_data input = {0};
230 :
231 16 : input.sid = sid;
232 16 : input.attrs = attrs;
233 :
234 16 : return cache_req_data_create(mem_ctx, type, &input);
235 : }
236 :
237 : struct cache_req {
238 : /* Provided input. */
239 : struct cache_req_data *data;
240 :
241 : /* Data Provider request type resolved from @type.
242 : * FIXME: This is currently needed for data provider calls. We should
243 : * refactor responder_dp.c to get rid of this member. */
244 : enum sss_dp_acct_type dp_type;
245 :
246 : /* Domain related informations. */
247 : struct sss_domain_info *domain;
248 :
249 : /* Debug information */
250 : uint32_t reqid;
251 : const char *reqname;
252 : const char *debugobj;
253 :
254 : /* Time when the request started. Useful for by-filter lookups */
255 : time_t req_start;
256 : };
257 :
258 : static void
259 77 : cache_req_set_dp(struct cache_req *cr, enum cache_req_type type)
260 : {
261 77 : switch (type) {
262 : case CACHE_REQ_USER_BY_NAME:
263 : case CACHE_REQ_USER_BY_UPN:
264 : case CACHE_REQ_USER_BY_ID:
265 25 : cr->dp_type = SSS_DP_USER;
266 25 : break;
267 :
268 : case CACHE_REQ_GROUP_BY_NAME:
269 : case CACHE_REQ_GROUP_BY_ID:
270 17 : cr->dp_type = SSS_DP_GROUP;
271 17 : break;
272 :
273 : case CACHE_REQ_INITGROUPS:
274 : case CACHE_REQ_INITGROUPS_BY_UPN:
275 0 : cr->dp_type = SSS_DP_INITGROUPS;
276 0 : break;
277 :
278 : case CACHE_REQ_USER_BY_CERT:
279 10 : cr->dp_type = SSS_DP_CERT;
280 10 : break;
281 :
282 : case CACHE_REQ_USER_BY_FILTER:
283 5 : cr->dp_type = SSS_DP_WILDCARD_USER;
284 5 : break;
285 :
286 : case CACHE_REQ_GROUP_BY_FILTER:
287 4 : cr->dp_type = SSS_DP_WILDCARD_GROUP;
288 4 : break;
289 :
290 : case CACHE_REQ_OBJECT_BY_SID:
291 16 : cr->dp_type = SSS_DP_SECID;
292 16 : break;
293 : }
294 :
295 77 : return;
296 : }
297 :
298 : static void
299 77 : cache_req_set_reqname(struct cache_req *cr, enum cache_req_type type)
300 : {
301 77 : switch (type) {
302 : case CACHE_REQ_USER_BY_NAME:
303 17 : cr->reqname = "User by name";
304 17 : break;
305 : case CACHE_REQ_USER_BY_UPN:
306 0 : cr->reqname = "User by UPN";
307 0 : break;
308 : case CACHE_REQ_USER_BY_ID:
309 8 : cr->reqname = "User by ID";
310 8 : break;
311 : case CACHE_REQ_GROUP_BY_NAME:
312 9 : cr->reqname = "Group by name";
313 9 : break;
314 : case CACHE_REQ_GROUP_BY_ID:
315 8 : cr->reqname = "Group by ID";
316 8 : break;
317 : case CACHE_REQ_INITGROUPS:
318 0 : cr->reqname = "Initgroups by name";
319 0 : break;
320 : case CACHE_REQ_INITGROUPS_BY_UPN:
321 0 : cr->reqname = "Initgroups by UPN";
322 0 : break;
323 : case CACHE_REQ_USER_BY_CERT:
324 10 : cr->reqname = "User by certificate";
325 10 : break;
326 : case CACHE_REQ_USER_BY_FILTER:
327 5 : cr->reqname = "User by filter";
328 5 : break;
329 : case CACHE_REQ_GROUP_BY_FILTER:
330 4 : cr->reqname = "Group by filter";
331 4 : break;
332 : case CACHE_REQ_OBJECT_BY_SID:
333 16 : cr->reqname = "Object by SID";
334 16 : break;
335 : }
336 :
337 77 : return;
338 : }
339 :
340 : static struct cache_req *
341 77 : cache_req_create(TALLOC_CTX *mem_ctx,
342 : struct resp_ctx *rctx,
343 : struct cache_req_data *data)
344 : {
345 : struct cache_req *cr;
346 :
347 77 : cr = talloc_zero(mem_ctx, struct cache_req);
348 77 : if (cr == NULL) {
349 0 : return NULL;
350 : }
351 :
352 77 : cr->data = data;
353 77 : cr->req_start = time(NULL);
354 :
355 : /* It is perfectly fine to just overflow here. */
356 77 : cr->reqid = rctx->cache_req_num++;
357 :
358 77 : cache_req_set_reqname(cr, data->type);
359 77 : cache_req_set_dp(cr, data->type);
360 :
361 77 : return cr;
362 : }
363 :
364 : static errno_t
365 35 : cache_req_set_name(struct cache_req *cr, const char *name)
366 : {
367 : const char *dup_name;
368 :
369 35 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Setting name [%s]\n", name);
370 :
371 35 : dup_name = talloc_strdup(cr->data, name);
372 35 : if (dup_name == NULL) {
373 0 : return ENOMEM;
374 : }
375 :
376 35 : talloc_zfree(cr->data->name.name);
377 35 : cr->data->name.name = dup_name;
378 :
379 35 : return EOK;
380 : }
381 :
382 : static errno_t
383 119 : cache_req_set_domain(struct cache_req *cr,
384 : struct sss_domain_info *domain,
385 : struct resp_ctx *rctx)
386 : {
387 119 : TALLOC_CTX *tmp_ctx = NULL;
388 119 : const char *name = NULL;
389 119 : const char *debugobj = NULL;
390 : errno_t ret;
391 :
392 119 : tmp_ctx = talloc_new(NULL);
393 119 : if (tmp_ctx == NULL) {
394 0 : return ENOMEM;
395 : }
396 :
397 119 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Using domain [%s]\n", domain->name);
398 :
399 119 : talloc_zfree(cr->data->name.lookup);
400 119 : talloc_zfree(cr->debugobj);
401 :
402 119 : switch (cr->data->type) {
403 : case CACHE_REQ_USER_BY_NAME:
404 : case CACHE_REQ_USER_BY_UPN:
405 : case CACHE_REQ_GROUP_BY_NAME:
406 : case CACHE_REQ_USER_BY_FILTER:
407 : case CACHE_REQ_GROUP_BY_FILTER:
408 : case CACHE_REQ_INITGROUPS:
409 : case CACHE_REQ_INITGROUPS_BY_UPN:
410 53 : if (cr->data->name.name == NULL) {
411 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n");
412 0 : ret = ERR_INTERNAL;
413 0 : goto done;
414 : }
415 :
416 53 : name = sss_get_cased_name(tmp_ctx, cr->data->name.name,
417 53 : domain->case_sensitive);
418 53 : if (name == NULL) {
419 0 : ret = ENOMEM;
420 0 : goto done;
421 : }
422 :
423 53 : name = sss_reverse_replace_space(tmp_ctx, name, rctx->override_space);
424 53 : if (name == NULL) {
425 0 : ret = ENOMEM;
426 0 : goto done;
427 : }
428 :
429 53 : debugobj = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name);
430 53 : if (debugobj == NULL) {
431 0 : ret = ENOMEM;
432 0 : goto done;
433 : }
434 :
435 53 : break;
436 :
437 : case CACHE_REQ_USER_BY_ID:
438 28 : debugobj = talloc_asprintf(tmp_ctx, "UID:%d@%s",
439 14 : cr->data->id, domain->name);
440 14 : if (debugobj == NULL) {
441 0 : ret = ENOMEM;
442 0 : goto done;
443 : }
444 14 : break;
445 :
446 : case CACHE_REQ_GROUP_BY_ID:
447 28 : debugobj = talloc_asprintf(tmp_ctx, "GID:%d@%s",
448 14 : cr->data->id, domain->name);
449 14 : if (debugobj == NULL) {
450 0 : ret = ENOMEM;
451 0 : goto done;
452 : }
453 14 : break;
454 : case CACHE_REQ_USER_BY_CERT:
455 : /* certificates might be quite long, only use the last 10 charcters
456 : * for logging */
457 20 : debugobj = talloc_asprintf(tmp_ctx, "CERT:%s@%s",
458 10 : get_last_x_chars(cr->data->cert, 10),
459 : domain->name);
460 10 : if (debugobj == NULL) {
461 0 : ret = ENOMEM;
462 0 : goto done;
463 : }
464 10 : break;
465 : case CACHE_REQ_OBJECT_BY_SID:
466 56 : debugobj = talloc_asprintf(tmp_ctx, "SID:%s@%s",
467 28 : cr->data->sid, domain->name);
468 28 : if (debugobj == NULL) {
469 0 : ret = ENOMEM;
470 0 : goto done;
471 : }
472 28 : break;
473 : }
474 :
475 119 : cr->domain = domain;
476 119 : cr->data->name.lookup = talloc_steal(cr->data, name);
477 119 : cr->debugobj = talloc_steal(cr, debugobj);
478 :
479 119 : ret = EOK;
480 :
481 : done:
482 119 : talloc_free(tmp_ctx);
483 119 : return ret;
484 : }
485 :
486 : static bool
487 183 : cache_req_is_upn(struct cache_req *cr)
488 : {
489 183 : switch (cr->data->type) {
490 : case CACHE_REQ_USER_BY_UPN:
491 : case CACHE_REQ_INITGROUPS_BY_UPN:
492 27 : return true;
493 : default:
494 156 : return false;
495 : }
496 : }
497 :
498 : static bool
499 24 : cache_req_assume_upn(struct cache_req *cr)
500 : {
501 : errno_t ret;
502 : bool bret;
503 :
504 24 : if (cr->data->name.input == NULL
505 16 : || strchr(cr->data->name.input, '@') == NULL) {
506 16 : return false;
507 : }
508 :
509 8 : switch (cr->data->type) {
510 : case CACHE_REQ_USER_BY_NAME:
511 8 : cr->data->type = CACHE_REQ_USER_BY_UPN;
512 8 : bret = true;
513 8 : break;
514 : case CACHE_REQ_INITGROUPS:
515 0 : cr->data->type = CACHE_REQ_INITGROUPS_BY_UPN;
516 0 : bret = true;
517 0 : break;
518 : default:
519 0 : bret = false;
520 0 : break;
521 : }
522 :
523 8 : if (bret == true) {
524 8 : ret = cache_req_set_name(cr, cr->data->name.input);
525 8 : if (ret != EOK) {
526 0 : DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_set_name() failed\n");
527 0 : return false;
528 : }
529 :
530 8 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Assuming UPN [%s]\n",
531 : cr->data->name.input);
532 : }
533 :
534 8 : return bret;
535 : }
536 :
537 119 : static errno_t cache_req_check_ncache(struct cache_req *cr,
538 : struct sss_nc_ctx *ncache)
539 : {
540 119 : errno_t ret = ERR_INTERNAL;
541 :
542 119 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Checking negative cache "
543 : "for [%s]\n", cr->debugobj);
544 :
545 119 : switch (cr->data->type) {
546 : case CACHE_REQ_USER_BY_NAME:
547 : case CACHE_REQ_USER_BY_UPN:
548 : case CACHE_REQ_INITGROUPS:
549 : case CACHE_REQ_INITGROUPS_BY_UPN:
550 29 : ret = sss_ncache_check_user(ncache, cr->domain, cr->data->name.lookup);
551 29 : break;
552 : case CACHE_REQ_GROUP_BY_NAME:
553 15 : ret = sss_ncache_check_group(ncache, cr->domain, cr->data->name.lookup);
554 15 : break;
555 : case CACHE_REQ_USER_BY_ID:
556 14 : ret = sss_ncache_check_uid(ncache, NULL, cr->data->id);
557 14 : break;
558 : case CACHE_REQ_GROUP_BY_ID:
559 14 : ret = sss_ncache_check_gid(ncache, NULL, cr->data->id);
560 14 : break;
561 : case CACHE_REQ_USER_BY_CERT:
562 10 : ret = sss_ncache_check_cert(ncache, cr->data->cert);
563 10 : break;
564 : case CACHE_REQ_USER_BY_FILTER:
565 : case CACHE_REQ_GROUP_BY_FILTER:
566 9 : ret = EOK;
567 9 : break;
568 : case CACHE_REQ_OBJECT_BY_SID:
569 28 : ret = sss_ncache_check_sid(ncache, cr->data->sid);
570 28 : break;
571 : }
572 :
573 119 : if (ret == EEXIST) {
574 8 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "[%s] does not exist "
575 : "(negative cache)\n", cr->debugobj);
576 : }
577 :
578 119 : return ret;
579 : }
580 :
581 63 : static void cache_req_add_to_ncache(struct cache_req *cr,
582 : struct sss_nc_ctx *ncache)
583 : {
584 63 : errno_t ret = ERR_INTERNAL;
585 :
586 63 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Adding [%s] to negative cache\n",
587 : cr->debugobj);
588 :
589 63 : switch (cr->data->type) {
590 : case CACHE_REQ_USER_BY_NAME:
591 : case CACHE_REQ_USER_BY_UPN:
592 : case CACHE_REQ_INITGROUPS:
593 : case CACHE_REQ_INITGROUPS_BY_UPN:
594 16 : ret = sss_ncache_set_user(ncache, false, cr->domain,
595 16 : cr->data->name.lookup);
596 16 : break;
597 : case CACHE_REQ_GROUP_BY_NAME:
598 8 : ret = sss_ncache_set_group(ncache, false, cr->domain,
599 8 : cr->data->name.lookup);
600 8 : break;
601 : case CACHE_REQ_USER_BY_FILTER:
602 : case CACHE_REQ_GROUP_BY_FILTER:
603 : /* Nothing to do, adding a wildcard request to ncache doesn't
604 : * make sense */
605 : case CACHE_REQ_USER_BY_ID:
606 : case CACHE_REQ_GROUP_BY_ID:
607 : case CACHE_REQ_USER_BY_CERT:
608 : case CACHE_REQ_OBJECT_BY_SID:
609 : /* Nothing to do. Those types must be unique among all domains so
610 : * the don't contain domain part. Therefore they must be set only
611 : * if all domains are search and the entry is not found. */
612 39 : ret = EOK;
613 39 : break;
614 : }
615 :
616 63 : if (ret != EOK) {
617 0 : CACHE_REQ_DEBUG(SSSDBG_MINOR_FAILURE, cr,
618 : "Cannot set negative cache for [%s] [%d]: %s\n",
619 : cr->debugobj, ret, sss_strerror(ret));
620 :
621 : /* not fatal */
622 : }
623 :
624 63 : return;
625 : }
626 :
627 13 : static void cache_req_add_to_ncache_global(struct cache_req *cr,
628 : struct sss_nc_ctx *ncache)
629 : {
630 13 : errno_t ret = ERR_INTERNAL;
631 :
632 13 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Adding [%s] to global "
633 : "negative cache\n", cr->debugobj);
634 :
635 13 : switch (cr->data->type) {
636 : case CACHE_REQ_USER_BY_FILTER:
637 : case CACHE_REQ_GROUP_BY_FILTER:
638 : /* Nothing to do, adding a wildcard request to ncache doesn't
639 : * make sense */
640 : case CACHE_REQ_USER_BY_NAME:
641 : case CACHE_REQ_USER_BY_UPN:
642 : case CACHE_REQ_GROUP_BY_NAME:
643 : case CACHE_REQ_INITGROUPS:
644 : case CACHE_REQ_INITGROUPS_BY_UPN:
645 : /* Nothing to do. Those types are already in ncache for selected
646 : * domains. */
647 5 : ret = EOK;
648 5 : break;
649 : case CACHE_REQ_USER_BY_ID:
650 1 : ret = sss_ncache_set_uid(ncache, false, NULL, cr->data->id);
651 1 : break;
652 : case CACHE_REQ_GROUP_BY_ID:
653 1 : ret = sss_ncache_set_gid(ncache, false, NULL, cr->data->id);
654 1 : break;
655 : case CACHE_REQ_USER_BY_CERT:
656 4 : ret = sss_ncache_set_cert(ncache, false, cr->data->cert);
657 4 : break;
658 : case CACHE_REQ_OBJECT_BY_SID:
659 2 : ret = sss_ncache_set_sid(ncache, false, cr->data->sid);
660 2 : break;
661 : }
662 :
663 13 : if (ret != EOK) {
664 0 : CACHE_REQ_DEBUG(SSSDBG_MINOR_FAILURE, cr, "Cannot set negcache for "
665 : "[%s] [%d]: %s\n", cr->debugobj,
666 : ret, sss_strerror(ret));
667 :
668 : /* not fatal */
669 : }
670 :
671 13 : return;
672 : }
673 :
674 198 : static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx,
675 : struct cache_req *cr,
676 : struct ldb_result **_result)
677 : {
678 198 : struct ldb_result *result = NULL;
679 198 : bool one_item_only = false;
680 198 : errno_t ret = ERR_INTERNAL;
681 :
682 198 : CACHE_REQ_DEBUG(SSSDBG_FUNC_DATA, cr, "Requesting info for [%s]\n",
683 : cr->debugobj);
684 :
685 198 : switch (cr->data->type) {
686 : case CACHE_REQ_USER_BY_NAME:
687 24 : one_item_only = true;
688 24 : ret = sysdb_getpwnam_with_views(mem_ctx, cr->domain,
689 24 : cr->data->name.lookup, &result);
690 24 : break;
691 : case CACHE_REQ_USER_BY_UPN:
692 23 : one_item_only = true;
693 23 : ret = sysdb_getpwupn(mem_ctx, cr->domain,
694 23 : cr->data->name.lookup, &result);
695 23 : break;
696 : case CACHE_REQ_USER_BY_ID:
697 23 : one_item_only = true;
698 23 : ret = sysdb_getpwuid_with_views(mem_ctx, cr->domain,
699 23 : cr->data->id, &result);
700 23 : break;
701 : case CACHE_REQ_GROUP_BY_NAME:
702 24 : one_item_only = true;
703 24 : ret = sysdb_getgrnam_with_views(mem_ctx, cr->domain,
704 24 : cr->data->name.lookup, &result);
705 24 : break;
706 : case CACHE_REQ_GROUP_BY_ID:
707 23 : one_item_only = true;
708 23 : ret = sysdb_getgrgid_with_views(mem_ctx, cr->domain,
709 23 : cr->data->id, &result);
710 23 : break;
711 : case CACHE_REQ_INITGROUPS:
712 0 : one_item_only = false;
713 0 : ret = sysdb_initgroups_with_views(mem_ctx, cr->domain,
714 0 : cr->data->name.lookup, &result);
715 0 : break;
716 : case CACHE_REQ_INITGROUPS_BY_UPN:
717 0 : one_item_only = false;
718 0 : ret = sysdb_initgroups_by_upn(mem_ctx, cr->domain,
719 0 : cr->data->name.lookup, &result);
720 0 : break;
721 : case CACHE_REQ_USER_BY_CERT:
722 17 : one_item_only = true;
723 17 : ret = sysdb_search_user_by_cert_with_views(mem_ctx, cr->domain,
724 17 : cr->data->cert, &result);
725 17 : break;
726 : case CACHE_REQ_USER_BY_FILTER:
727 10 : one_item_only = false;
728 20 : ret = updated_users_by_filter(mem_ctx, cr->domain,
729 10 : cr->data->name.lookup, cr->req_start,
730 : &result);
731 10 : break;
732 : case CACHE_REQ_GROUP_BY_FILTER:
733 8 : one_item_only = false;
734 16 : ret = updated_groups_by_filter(mem_ctx, cr->domain,
735 8 : cr->data->name.lookup, cr->req_start,
736 : &result);
737 8 : break;
738 : case CACHE_REQ_OBJECT_BY_SID:
739 46 : one_item_only = true;
740 92 : ret = sysdb_search_object_by_sid(mem_ctx, cr->domain,
741 92 : cr->data->sid, cr->data->attrs,
742 : &result);
743 46 : break;
744 : }
745 :
746 198 : if (ret != EOK) {
747 62 : goto done;
748 136 : } else if (result->count == 0) {
749 81 : ret = ENOENT;
750 81 : goto done;
751 55 : } else if (one_item_only && result->count > 1) {
752 0 : ret = ERR_INTERNAL;
753 0 : CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr,
754 : "Multiple objects were found when "
755 : "sysdb search expected only one!\n");
756 0 : goto done;
757 : }
758 :
759 55 : *_result = result;
760 :
761 : done:
762 198 : return ret;
763 : }
764 :
765 : /* Return true if the request bypasses cache or false if the cache_req
766 : * code can leverage sysdb for this request.
767 : */
768 31 : static bool cache_req_bypass_cache(struct cache_req *cr)
769 : {
770 62 : if (cr->data->type == CACHE_REQ_USER_BY_FILTER ||
771 31 : cr->data->type == CACHE_REQ_GROUP_BY_FILTER) {
772 0 : return true;
773 : }
774 :
775 31 : return false;
776 : }
777 :
778 111 : static errno_t cache_req_expiration_status(struct cache_req *cr,
779 : struct ldb_result *result,
780 : time_t cache_refresh_percent)
781 : {
782 : time_t expire;
783 :
784 111 : if (result == NULL || result->count == 0 || cache_req_bypass_cache(cr)) {
785 80 : return ENOENT;
786 : }
787 :
788 31 : if (cr->data->type == CACHE_REQ_INITGROUPS) {
789 0 : expire = ldb_msg_find_attr_as_uint64(result->msgs[0],
790 : SYSDB_INITGR_EXPIRE, 0);
791 : } else {
792 31 : expire = ldb_msg_find_attr_as_uint64(result->msgs[0],
793 : SYSDB_CACHE_EXPIRE, 0);
794 : }
795 :
796 31 : return sss_cmd_check_cache(result->msgs[0], cache_refresh_percent, expire);
797 : }
798 :
799 111 : static void cache_req_dpreq_params(TALLOC_CTX *mem_ctx,
800 : struct cache_req *cr,
801 : struct ldb_result *result,
802 : const char **_string,
803 : uint32_t *_id,
804 : const char **_flag)
805 : {
806 111 : struct ldb_result *user = NULL;
807 111 : const char *name = NULL;
808 111 : uint32_t id = 0;
809 : errno_t ret;
810 :
811 111 : *_id = cr->data->id;
812 111 : *_string = cr->data->name.lookup;
813 111 : *_flag = NULL;
814 :
815 111 : if (cache_req_is_upn(cr)) {
816 13 : *_flag = EXTRA_NAME_IS_UPN;
817 124 : return;
818 : }
819 :
820 98 : if (cr->data->type == CACHE_REQ_USER_BY_CERT) {
821 9 : *_string = cr->data->cert;
822 9 : return;
823 89 : } else if (cr->data->type == CACHE_REQ_OBJECT_BY_SID) {
824 26 : *_string = cr->data->sid;
825 26 : return;
826 : }
827 :
828 63 : if (!DOM_HAS_VIEWS(cr->domain)) {
829 63 : return;
830 : }
831 :
832 : /* We must search with views. */
833 0 : if (result == NULL || result->count == 0) {
834 0 : *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
835 0 : return;
836 : }
837 :
838 : /* If domain has views we will try to user original values instead of the
839 : * overridden ones. This is a must for the LOCAL view since we can't look
840 : * it up otherwise. But it is also a shortcut for non-local views where
841 : * we will not fail over to the overridden value. */
842 :
843 0 : switch (cr->data->type) {
844 : case CACHE_REQ_USER_BY_NAME:
845 : case CACHE_REQ_GROUP_BY_NAME:
846 0 : name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL);
847 0 : if (name == NULL) {
848 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n");
849 : }
850 0 : break;
851 : case CACHE_REQ_USER_BY_ID:
852 0 : id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_UIDNUM, 0);
853 0 : if (id == 0) {
854 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n");
855 : }
856 0 : break;
857 : case CACHE_REQ_GROUP_BY_ID:
858 0 : id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_GIDNUM, 0);
859 0 : if (id == 0) {
860 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n");
861 : }
862 0 : break;
863 : case CACHE_REQ_INITGROUPS:
864 0 : ret = sysdb_getpwnam_with_views(NULL, cr->domain,
865 0 : cr->data->name.lookup, &user);
866 0 : if (ret != EOK || user == NULL || user->count != 1) {
867 : /* Case where the user is not found has been already handled. If
868 : * this is not OK, it is an error. */
869 0 : CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr,
870 : "Unable to match initgroups user [%d]: %s\n",
871 : ret, sss_strerror(ret));
872 0 : break;
873 : }
874 :
875 0 : name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME,
876 : NULL);
877 0 : if (name == NULL) {
878 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n");
879 0 : break;
880 : }
881 :
882 0 : talloc_steal(mem_ctx, name);
883 0 : talloc_free(user);
884 0 : break;
885 : default:
886 0 : return;
887 : }
888 :
889 : /* Now we have the original name and id. We don't have to search with
890 : * views unless some error occurred. */
891 0 : if (name == NULL && id == 0) {
892 0 : *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
893 0 : return;
894 : }
895 :
896 0 : *_string = talloc_steal(mem_ctx, name);
897 0 : *_id = id;
898 : }
899 :
900 : struct cache_req_cache_state {
901 : /* input data */
902 : struct tevent_context *ev;
903 : struct resp_ctx *rctx;
904 : struct sss_nc_ctx *ncache;
905 : int cache_refresh_percent;
906 : struct cache_req *cr;
907 :
908 : /* output data */
909 : struct ldb_result *result;
910 : };
911 :
912 : static errno_t cache_req_cache_search(struct tevent_req *req);
913 : static errno_t cache_req_cache_check(struct tevent_req *req);
914 : static void cache_req_cache_done(struct tevent_req *subreq);
915 :
916 119 : static struct tevent_req *cache_req_cache_send(TALLOC_CTX *mem_ctx,
917 : struct tevent_context *ev,
918 : struct resp_ctx *rctx,
919 : struct sss_nc_ctx *ncache,
920 : int cache_refresh_percent,
921 : struct cache_req *cr)
922 : {
923 119 : struct cache_req_cache_state *state = NULL;
924 119 : struct tevent_req *req = NULL;
925 : errno_t ret;
926 :
927 119 : req = tevent_req_create(mem_ctx, &state, struct cache_req_cache_state);
928 119 : if (req == NULL) {
929 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
930 0 : return NULL;
931 : }
932 :
933 119 : state->ev = ev;
934 119 : state->rctx = rctx;
935 119 : state->ncache = ncache;
936 119 : state->cache_refresh_percent = cache_refresh_percent;
937 119 : state->cr = cr;
938 :
939 : /* Check negative cache first. */
940 119 : ret = cache_req_check_ncache(state->cr, state->ncache);
941 119 : if (ret == EEXIST) {
942 8 : ret = ENOENT;
943 8 : goto immediately;
944 : }
945 :
946 : /* We will first search the cache. If we get cache miss or the entry
947 : * is expired we will contact data provider and then search again. */
948 111 : ret = cache_req_cache_search(req);
949 111 : if (ret != EAGAIN) {
950 24 : goto immediately;
951 : }
952 :
953 87 : return req;
954 :
955 : immediately:
956 32 : if (ret == EOK) {
957 24 : tevent_req_done(req);
958 : } else {
959 8 : tevent_req_error(req, ret);
960 : }
961 32 : tevent_req_post(req, ev);
962 :
963 32 : return req;
964 : }
965 :
966 111 : static errno_t cache_req_cache_search(struct tevent_req *req)
967 : {
968 111 : struct cache_req_cache_state *state = NULL;
969 : errno_t ret;
970 :
971 111 : state = tevent_req_data(req, struct cache_req_cache_state);
972 :
973 111 : ret = cache_req_get_object(state, state->cr, &state->result);
974 111 : if (ret != EOK && ret != ENOENT) {
975 0 : CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, state->cr, "Failed to make "
976 : "request to our cache [%d]: %s\n",
977 : ret, sss_strerror(ret));
978 0 : return ret;
979 : }
980 :
981 : /* Verify that the cache is up to date. */
982 111 : ret = cache_req_cache_check(req);
983 111 : if (ret != EOK) {
984 87 : CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, state->cr,
985 : "Cannot find info for [%s]\n", state->cr->debugobj);
986 87 : return ret;
987 : }
988 :
989 : /* One result found */
990 24 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
991 : "Returning info for [%s]\n", state->cr->debugobj);
992 24 : return EOK;
993 : }
994 :
995 111 : static errno_t cache_req_cache_check(struct tevent_req *req)
996 : {
997 111 : struct cache_req_cache_state *state = NULL;
998 111 : struct tevent_req *subreq = NULL;
999 111 : const char *extra_flag = NULL;
1000 : const char *search_str;
1001 : uint32_t search_id;
1002 : errno_t ret;
1003 :
1004 111 : state = tevent_req_data(req, struct cache_req_cache_state);
1005 :
1006 111 : cache_req_dpreq_params(state, state->cr, state->result,
1007 : &search_str, &search_id, &extra_flag);
1008 :
1009 111 : ret = cache_req_expiration_status(state->cr, state->result,
1010 111 : state->cache_refresh_percent);
1011 :
1012 111 : switch (ret) {
1013 : case EOK:
1014 17 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1015 : "[%s] entry is valid\n", state->cr->debugobj);
1016 17 : return EOK;
1017 : case EAGAIN:
1018 : /* Out of band update. The calling function will return the cached
1019 : * entry immediately. No callback is required. */
1020 :
1021 7 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1022 : "Performing midpoint cache update of [%s]\n",
1023 : state->cr->debugobj);
1024 :
1025 21 : subreq = sss_dp_get_account_send(state, state->rctx,
1026 7 : state->cr->domain, true,
1027 7 : state->cr->dp_type,
1028 : search_str, search_id, extra_flag);
1029 7 : if (subreq == NULL) {
1030 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band "
1031 : "data provider request\n");
1032 : /* This is non-fatal, so we'll continue here */
1033 : }
1034 :
1035 7 : return EOK;
1036 : case ENOENT:
1037 : /* Cache miss or the cache is expired. We need to get the updated
1038 : * information before returning it. */
1039 :
1040 87 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1041 : "Looking up [%s] in data provider\n",
1042 : state->cr->debugobj);
1043 :
1044 261 : subreq = sss_dp_get_account_send(state, state->rctx,
1045 87 : state->cr->domain, true,
1046 87 : state->cr->dp_type,
1047 : search_str, search_id, extra_flag);
1048 87 : if (subreq == NULL) {
1049 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1050 : "Out of memory sending data provider request\n");
1051 0 : return ENOMEM;
1052 : }
1053 :
1054 87 : tevent_req_set_callback(subreq, cache_req_cache_done, req);
1055 87 : return EAGAIN;
1056 : default:
1057 : /* error */
1058 0 : CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, state->cr, "Error checking "
1059 : "cache [%d]: %s\n", ret, sss_strerror(ret));
1060 0 : return ret;
1061 : }
1062 : }
1063 :
1064 87 : static void cache_req_cache_done(struct tevent_req *subreq)
1065 : {
1066 87 : struct cache_req_cache_state *state = NULL;
1067 87 : struct tevent_req *req = NULL;
1068 87 : char *err_msg = NULL;
1069 : dbus_uint16_t err_maj;
1070 : dbus_uint32_t err_min;
1071 : errno_t ret;
1072 :
1073 87 : req = tevent_req_callback_data(subreq, struct tevent_req);
1074 87 : state = tevent_req_data(req, struct cache_req_cache_state);
1075 :
1076 87 : ret = sss_dp_get_account_recv(state, subreq, &err_maj, &err_min, &err_msg);
1077 87 : talloc_zfree(subreq);
1078 87 : if (ret != EOK) {
1079 0 : CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, state->cr,
1080 : "Could not get account info [%d]: %s\n",
1081 : ret, sss_strerror(ret));
1082 : }
1083 :
1084 87 : if (err_maj) {
1085 0 : CACHE_REQ_DEBUG(SSSDBG_MINOR_FAILURE, state->cr,
1086 : "Data Provider Error: %u, %u, %s (will return cached data)\n",
1087 : (unsigned int)err_maj, (unsigned int)err_min, err_msg);
1088 : }
1089 :
1090 : /* Get result from cache again. */
1091 87 : ret = cache_req_get_object(state, state->cr, &state->result);
1092 87 : if (ret == ENOENT) {
1093 63 : cache_req_add_to_ncache(state->cr, state->ncache);
1094 63 : ret = ENOENT;
1095 24 : } else if (ret != EOK) {
1096 0 : CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, state->cr,
1097 : "Failed to make request to our cache [%d]: %s\n",
1098 : ret, sss_strerror(ret));
1099 : }
1100 :
1101 87 : if (ret != EOK) {
1102 63 : tevent_req_error(req, ret);
1103 150 : return;
1104 : }
1105 :
1106 : /* One result found */
1107 24 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1108 : "Returning %u results for [%s]\n", state->result->count,
1109 : state->cr->debugobj);
1110 :
1111 24 : tevent_req_done(req);
1112 : }
1113 :
1114 119 : static errno_t cache_req_cache_recv(TALLOC_CTX *mem_ctx,
1115 : struct tevent_req *req,
1116 : struct ldb_result **_result)
1117 : {
1118 119 : struct cache_req_cache_state *state = NULL;
1119 119 : state = tevent_req_data(req, struct cache_req_cache_state);
1120 :
1121 190 : TEVENT_REQ_RETURN_ON_ERROR(req);
1122 :
1123 48 : *_result = talloc_steal(mem_ctx, state->result);
1124 :
1125 48 : return EOK;
1126 : }
1127 :
1128 :
1129 : struct cache_req_state {
1130 : /* input data */
1131 : struct tevent_context *ev;
1132 : struct resp_ctx *rctx;
1133 : struct sss_nc_ctx *ncache;
1134 : int cache_refresh_percent;
1135 : struct cache_req *cr;
1136 :
1137 : /* work data */
1138 : struct ldb_result *result;
1139 : struct sss_domain_info *domain;
1140 : struct sss_domain_info *selected_domain;
1141 : bool check_next;
1142 : };
1143 :
1144 : static void cache_req_input_parsed(struct tevent_req *subreq);
1145 :
1146 : static errno_t cache_req_select_domains(struct tevent_req *req,
1147 : const char *domain);
1148 :
1149 : static errno_t cache_req_next_domain(struct tevent_req *req);
1150 :
1151 : static void cache_req_done(struct tevent_req *subreq);
1152 :
1153 77 : struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx,
1154 : struct tevent_context *ev,
1155 : struct resp_ctx *rctx,
1156 : struct sss_nc_ctx *ncache,
1157 : int cache_refresh_percent,
1158 : const char *domain,
1159 : struct cache_req_data *data)
1160 : {
1161 77 : struct cache_req_state *state = NULL;
1162 77 : struct cache_req *cr = NULL;
1163 77 : struct tevent_req *req = NULL;
1164 77 : struct tevent_req *subreq = NULL;
1165 : errno_t ret;
1166 :
1167 77 : req = tevent_req_create(mem_ctx, &state, struct cache_req_state);
1168 77 : if (req == NULL) {
1169 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1170 0 : return NULL;
1171 : }
1172 :
1173 77 : state->ev = ev;
1174 77 : state->rctx = rctx;
1175 77 : state->ncache = ncache;
1176 77 : state->cache_refresh_percent = cache_refresh_percent;
1177 77 : state->cr = cr = cache_req_create(state, rctx, data);
1178 77 : if (state->cr == NULL) {
1179 0 : ret = ENOMEM;
1180 0 : goto immediately;
1181 : }
1182 :
1183 77 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "New request\n");
1184 :
1185 77 : if (cr->data->name.input != NULL && domain == NULL) {
1186 : /* Parse input name first, since it may contain domain name. */
1187 14 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Parsing input name [%s]\n",
1188 : cr->data->name.input);
1189 :
1190 14 : subreq = sss_parse_inp_send(state, rctx, cr->data->name.input);
1191 14 : if (subreq == NULL) {
1192 0 : ret = ENOMEM;
1193 0 : goto immediately;
1194 : }
1195 :
1196 14 : tevent_req_set_callback(subreq, cache_req_input_parsed, req);
1197 : } else {
1198 63 : if (state->cr->data->name.input != NULL) {
1199 21 : ret = cache_req_set_name(cr, cr->data->name.input);
1200 21 : if (ret != EOK) {
1201 0 : goto immediately;
1202 : }
1203 : }
1204 :
1205 63 : ret = cache_req_select_domains(req, domain);
1206 63 : if (ret != EAGAIN) {
1207 0 : goto immediately;
1208 : }
1209 : }
1210 :
1211 77 : return req;
1212 :
1213 : immediately:
1214 0 : if (ret == EOK) {
1215 0 : tevent_req_done(req);
1216 : } else {
1217 0 : tevent_req_error(req, ret);
1218 : }
1219 0 : tevent_req_post(req, ev);
1220 :
1221 0 : return req;
1222 : }
1223 :
1224 14 : static void cache_req_input_parsed(struct tevent_req *subreq)
1225 : {
1226 : struct tevent_req *req;
1227 : struct cache_req_state *state;
1228 : char *name;
1229 : char *domain;
1230 : errno_t ret;
1231 : bool maybe_upn;
1232 :
1233 14 : req = tevent_req_callback_data(subreq, struct tevent_req);
1234 14 : state = tevent_req_data(req, struct cache_req_state);
1235 :
1236 14 : ret = sss_parse_inp_recv(subreq, state, &name, &domain);
1237 14 : switch (ret) {
1238 : case EOK:
1239 6 : ret = cache_req_set_name(state->cr, name);
1240 6 : if (ret != EOK) {
1241 0 : tevent_req_error(req, ret);
1242 0 : return;
1243 : }
1244 6 : break;
1245 : case ERR_DOMAIN_NOT_FOUND:
1246 8 : maybe_upn = cache_req_assume_upn(state->cr);
1247 8 : if (!maybe_upn) {
1248 0 : tevent_req_error(req, ret);
1249 0 : return;
1250 : }
1251 :
1252 8 : domain = NULL;
1253 8 : break;
1254 : default:
1255 0 : tevent_req_error(req, ret);
1256 0 : return;
1257 : }
1258 :
1259 14 : ret = cache_req_select_domains(req, domain);
1260 14 : if (ret != EAGAIN) {
1261 0 : tevent_req_error(req, ret);
1262 0 : return;
1263 : }
1264 : }
1265 :
1266 77 : static errno_t cache_req_select_domains(struct tevent_req *req,
1267 : const char *domain)
1268 : {
1269 77 : struct cache_req_state *state = NULL;
1270 :
1271 77 : state = tevent_req_data(req, struct cache_req_state);
1272 :
1273 77 : if (domain != NULL) {
1274 47 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1275 : "Performing a single domain search\n");
1276 :
1277 47 : state->domain = responder_get_domain(state->rctx, domain);
1278 47 : if (state->domain == NULL) {
1279 0 : return ERR_DOMAIN_NOT_FOUND;
1280 : }
1281 :
1282 47 : state->check_next = false;
1283 : } else {
1284 30 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1285 : "Performing a multi-domain search\n");
1286 :
1287 30 : state->domain = state->rctx->domains;
1288 30 : state->check_next = true;
1289 : }
1290 :
1291 77 : return cache_req_next_domain(req);
1292 : }
1293 :
1294 132 : static errno_t cache_req_next_domain(struct tevent_req *req)
1295 : {
1296 132 : struct cache_req_state *state = NULL;
1297 132 : struct tevent_req *subreq = NULL;
1298 : errno_t ret;
1299 :
1300 132 : state = tevent_req_data(req, struct cache_req_state);
1301 :
1302 132 : while (state->domain != NULL) {
1303 : /* If it is a domainless search, skip domains that require fully
1304 : * qualified names instead. */
1305 238 : while (state->domain != NULL && state->check_next
1306 72 : && state->domain->fqnames
1307 0 : && state->cr->data->type != CACHE_REQ_USER_BY_CERT
1308 0 : && !cache_req_is_upn(state->cr)) {
1309 0 : state->domain = get_next_domain(state->domain, 0);
1310 : }
1311 :
1312 119 : state->selected_domain = state->domain;
1313 :
1314 119 : if (state->domain == NULL) {
1315 0 : break;
1316 : }
1317 :
1318 119 : ret = cache_req_set_domain(state->cr, state->domain,
1319 : state->rctx);
1320 119 : if (ret != EOK) {
1321 0 : return ret;
1322 : }
1323 :
1324 119 : subreq = cache_req_cache_send(state, state->ev, state->rctx,
1325 : state->ncache,
1326 : state->cache_refresh_percent,
1327 : state->cr);
1328 119 : if (subreq == NULL) {
1329 0 : return ENOMEM;
1330 : }
1331 :
1332 119 : tevent_req_set_callback(subreq, cache_req_done, req);
1333 :
1334 : /* we will continue with the following domain the next time */
1335 119 : if (state->check_next) {
1336 72 : if (cache_req_is_upn(state->cr)
1337 58 : || state->cr->data->type == CACHE_REQ_USER_BY_CERT ) {
1338 24 : state->domain = get_next_domain(state->domain, SSS_GND_DESCEND);
1339 : } else {
1340 48 : state->domain = get_next_domain(state->domain, 0);
1341 : }
1342 : }
1343 :
1344 119 : return EAGAIN;
1345 : }
1346 :
1347 : /* If the object searched has to be unique among all maintained domains,
1348 : * we have to add it into negative cache here when all domains have
1349 : * been searched. */
1350 :
1351 13 : cache_req_add_to_ncache_global(state->cr, state->ncache);
1352 :
1353 13 : return ENOENT;
1354 : }
1355 :
1356 119 : static void cache_req_done(struct tevent_req *subreq)
1357 : {
1358 119 : struct cache_req_state *state = NULL;
1359 119 : struct tevent_req *req = NULL;
1360 : errno_t ret;
1361 :
1362 119 : req = tevent_req_callback_data(subreq, struct tevent_req);
1363 119 : state = tevent_req_data(req, struct cache_req_state);
1364 :
1365 119 : ret = cache_req_cache_recv(state, subreq, &state->result);
1366 119 : talloc_zfree(subreq);
1367 119 : if (ret == EOK) {
1368 48 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Finished: Success\n");
1369 48 : tevent_req_done(req);
1370 48 : return;
1371 : }
1372 :
1373 71 : if (state->check_next == false) {
1374 16 : if (ret == ENOENT && cache_req_assume_upn(state->cr)) {
1375 : /* search by upn now */
1376 0 : cache_req_select_domains(req, NULL);
1377 0 : return;
1378 : }
1379 :
1380 16 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Finished: Not found\n");
1381 16 : tevent_req_error(req, ret);
1382 16 : return;
1383 : }
1384 :
1385 55 : ret = cache_req_next_domain(req);
1386 55 : if (ret != EAGAIN) {
1387 13 : CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
1388 : "Finished: Error %d: %s\n", ret, sss_strerror(ret));
1389 13 : tevent_req_error(req, ret);
1390 : }
1391 :
1392 55 : return;
1393 : }
1394 :
1395 77 : errno_t cache_req_recv(TALLOC_CTX *mem_ctx,
1396 : struct tevent_req *req,
1397 : struct ldb_result **_result,
1398 : struct sss_domain_info **_domain,
1399 : char **_name)
1400 : {
1401 77 : struct cache_req_state *state = NULL;
1402 : char *name;
1403 :
1404 77 : state = tevent_req_data(req, struct cache_req_state);
1405 :
1406 106 : TEVENT_REQ_RETURN_ON_ERROR(req);
1407 :
1408 48 : if (_name != NULL) {
1409 17 : if (state->cr->data->name.lookup == NULL) {
1410 0 : *_name = NULL;
1411 : } else {
1412 17 : name = talloc_strdup(mem_ctx, state->cr->data->name.name);
1413 17 : if (name == NULL) {
1414 0 : return ENOMEM;
1415 : }
1416 :
1417 17 : *_name = name;
1418 : }
1419 : }
1420 :
1421 48 : if (_result != NULL) {
1422 48 : *_result = talloc_steal(mem_ctx, state->result);
1423 : }
1424 :
1425 48 : if (_domain != NULL) {
1426 48 : *_domain = state->selected_domain;
1427 : }
1428 :
1429 48 : return EOK;
1430 : }
1431 :
1432 : static struct tevent_req *
1433 77 : cache_req_steal_data_and_send(TALLOC_CTX *mem_ctx,
1434 : struct tevent_context *ev,
1435 : struct resp_ctx *rctx,
1436 : struct sss_nc_ctx *ncache,
1437 : int cache_refresh_percent,
1438 : const char *domain,
1439 : struct cache_req_data *data)
1440 : {
1441 : struct tevent_req *req;
1442 :
1443 77 : req = cache_req_send(mem_ctx, ev, rctx, ncache,
1444 : cache_refresh_percent, domain, data);
1445 77 : if (req == NULL) {
1446 0 : talloc_zfree(data);
1447 0 : return NULL;
1448 : }
1449 :
1450 77 : talloc_steal(req, data);
1451 :
1452 77 : return req;
1453 : }
1454 :
1455 : struct tevent_req *
1456 17 : cache_req_user_by_name_send(TALLOC_CTX *mem_ctx,
1457 : struct tevent_context *ev,
1458 : struct resp_ctx *rctx,
1459 : struct sss_nc_ctx *ncache,
1460 : int cache_refresh_percent,
1461 : const char *domain,
1462 : const char *name)
1463 : {
1464 : struct cache_req_data *data;
1465 :
1466 17 : data = cache_req_data_name(mem_ctx, CACHE_REQ_USER_BY_NAME, name);
1467 17 : if (data == NULL) {
1468 0 : return NULL;
1469 : }
1470 :
1471 17 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1472 : cache_refresh_percent, domain, data);
1473 : }
1474 :
1475 : struct tevent_req *
1476 8 : cache_req_user_by_id_send(TALLOC_CTX *mem_ctx,
1477 : struct tevent_context *ev,
1478 : struct resp_ctx *rctx,
1479 : struct sss_nc_ctx *ncache,
1480 : int cache_refresh_percent,
1481 : const char *domain,
1482 : uid_t uid)
1483 : {
1484 : struct cache_req_data *data;
1485 :
1486 8 : data = cache_req_data_id(mem_ctx, CACHE_REQ_USER_BY_ID, uid);
1487 8 : if (data == NULL) {
1488 0 : return NULL;
1489 : }
1490 :
1491 8 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1492 : cache_refresh_percent, domain, data);
1493 : }
1494 :
1495 : struct tevent_req *
1496 10 : cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx,
1497 : struct tevent_context *ev,
1498 : struct resp_ctx *rctx,
1499 : struct sss_nc_ctx *ncache,
1500 : int cache_refresh_percent,
1501 : const char *domain,
1502 : const char *pem_cert)
1503 : {
1504 : struct cache_req_data *data;
1505 :
1506 10 : data = cache_req_data_cert(mem_ctx, CACHE_REQ_USER_BY_CERT, pem_cert);
1507 10 : if (data == NULL) {
1508 0 : return NULL;
1509 : }
1510 :
1511 10 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1512 : cache_refresh_percent,
1513 : domain, data);
1514 : }
1515 :
1516 : struct tevent_req *
1517 9 : cache_req_group_by_name_send(TALLOC_CTX *mem_ctx,
1518 : struct tevent_context *ev,
1519 : struct resp_ctx *rctx,
1520 : struct sss_nc_ctx *ncache,
1521 : int cache_refresh_percent,
1522 : const char *domain,
1523 : const char *name)
1524 : {
1525 : struct cache_req_data *data;
1526 :
1527 9 : data = cache_req_data_name(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name);
1528 9 : if (data == NULL) {
1529 0 : return NULL;
1530 : }
1531 :
1532 9 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1533 : cache_refresh_percent, domain, data);
1534 : }
1535 :
1536 : struct tevent_req *
1537 8 : cache_req_group_by_id_send(TALLOC_CTX *mem_ctx,
1538 : struct tevent_context *ev,
1539 : struct resp_ctx *rctx,
1540 : struct sss_nc_ctx *ncache,
1541 : int cache_refresh_percent,
1542 : const char *domain,
1543 : gid_t gid)
1544 : {
1545 : struct cache_req_data *data;
1546 :
1547 8 : data = cache_req_data_id(mem_ctx, CACHE_REQ_GROUP_BY_ID, gid);
1548 8 : if (data == NULL) {
1549 0 : return NULL;
1550 : }
1551 :
1552 8 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1553 : cache_refresh_percent, domain, data);
1554 : }
1555 :
1556 : struct tevent_req *
1557 0 : cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
1558 : struct tevent_context *ev,
1559 : struct resp_ctx *rctx,
1560 : struct sss_nc_ctx *ncache,
1561 : int cache_refresh_percent,
1562 : const char *domain,
1563 : const char *name)
1564 : {
1565 : struct cache_req_data *data;
1566 :
1567 0 : data = cache_req_data_name(mem_ctx, CACHE_REQ_INITGROUPS, name);
1568 0 : if (data == NULL) {
1569 0 : return NULL;
1570 : }
1571 :
1572 0 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1573 : cache_refresh_percent, domain, data);
1574 : }
1575 :
1576 : struct tevent_req *
1577 5 : cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx,
1578 : struct tevent_context *ev,
1579 : struct resp_ctx *rctx,
1580 : const char *domain,
1581 : const char *filter)
1582 : {
1583 : struct cache_req_data *data;
1584 :
1585 5 : data = cache_req_data_name(mem_ctx, CACHE_REQ_USER_BY_FILTER, filter);
1586 5 : if (data == NULL) {
1587 0 : return NULL;
1588 : }
1589 :
1590 5 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL,
1591 : 0, domain, data);
1592 : }
1593 :
1594 : struct tevent_req *
1595 4 : cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx,
1596 : struct tevent_context *ev,
1597 : struct resp_ctx *rctx,
1598 : const char *domain,
1599 : const char *filter)
1600 : {
1601 : struct cache_req_data *data;
1602 :
1603 4 : data = cache_req_data_name(mem_ctx, CACHE_REQ_GROUP_BY_FILTER, filter);
1604 4 : if (data == NULL) {
1605 0 : return NULL;
1606 : }
1607 :
1608 4 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL,
1609 : 0, domain, data);
1610 : }
1611 :
1612 : struct tevent_req *
1613 16 : cache_req_object_by_sid_send(TALLOC_CTX *mem_ctx,
1614 : struct tevent_context *ev,
1615 : struct resp_ctx *rctx,
1616 : struct sss_nc_ctx *ncache,
1617 : int cache_refresh_percent,
1618 : const char *domain,
1619 : const char *sid,
1620 : const char **attrs)
1621 : {
1622 : struct cache_req_data *data;
1623 :
1624 16 : data = cache_req_data_sid(mem_ctx, CACHE_REQ_OBJECT_BY_SID, sid, attrs);
1625 16 : if (data == NULL) {
1626 0 : return NULL;
1627 : }
1628 :
1629 16 : return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache,
1630 : cache_refresh_percent, domain, data);
1631 : }
|