Line data Source code
1 : /*
2 : SSSD
3 :
4 : NSS Responder
5 :
6 : Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "util/util.h"
23 : #include "confdb/confdb.h"
24 : #include "responder/common/responder.h"
25 : #include "responder/common/negcache.h"
26 : #include <fcntl.h>
27 : #include <time.h>
28 : #include "tdb.h"
29 :
30 : #define NC_ENTRY_PREFIX "NCE/"
31 : #define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
32 : #define NC_GROUP_PREFIX NC_ENTRY_PREFIX"GROUP"
33 : #define NC_NETGROUP_PREFIX NC_ENTRY_PREFIX"NETGR"
34 : #define NC_SERVICE_PREFIX NC_ENTRY_PREFIX"SERVICE"
35 : #define NC_UID_PREFIX NC_ENTRY_PREFIX"UID"
36 : #define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
37 : #define NC_SID_PREFIX NC_ENTRY_PREFIX"SID"
38 : #define NC_CERT_PREFIX NC_ENTRY_PREFIX"CERT"
39 :
40 : struct sss_nc_ctx {
41 : struct tdb_context *tdb;
42 : };
43 :
44 : typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
45 : const char *, const char *);
46 :
47 : static int sss_ncache_set_ent(struct sss_nc_ctx *ctx, bool permanent,
48 : struct sss_domain_info *dom, const char *name,
49 : ncache_set_byname_fn_t setter);
50 :
51 532 : static int string_to_tdb_data(char *str, TDB_DATA *ret)
52 : {
53 532 : if (!str || !ret) return EINVAL;
54 :
55 532 : ret->dptr = (uint8_t *)str;
56 532 : ret->dsize = strlen(str)+1;
57 :
58 532 : return EOK;
59 : }
60 :
61 139 : int sss_ncache_init(TALLOC_CTX *memctx, struct sss_nc_ctx **_ctx)
62 : {
63 : struct sss_nc_ctx *ctx;
64 :
65 139 : ctx = talloc_zero(memctx, struct sss_nc_ctx);
66 139 : if (!ctx) return ENOMEM;
67 :
68 139 : errno = 0;
69 : /* open a memory only tdb with default hash size */
70 139 : ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
71 139 : if (!ctx->tdb) return errno;
72 :
73 139 : *_ctx = ctx;
74 139 : return EOK;
75 : };
76 :
77 232 : static int sss_ncache_check_str(struct sss_nc_ctx *ctx, char *str, int ttl)
78 : {
79 : TDB_DATA key;
80 : TDB_DATA data;
81 : unsigned long long int timestamp;
82 232 : bool expired = false;
83 : char *ep;
84 : int ret;
85 :
86 232 : DEBUG(SSSDBG_TRACE_INTERNAL, "Checking negative cache for [%s]\n", str);
87 :
88 232 : data.dptr = NULL;
89 :
90 232 : ret = string_to_tdb_data(str, &key);
91 232 : if (ret != EOK) goto done;
92 :
93 232 : data = tdb_fetch(ctx->tdb, key);
94 :
95 232 : if (!data.dptr) {
96 174 : ret = ENOENT;
97 174 : goto done;
98 : }
99 :
100 58 : if (ttl == -1) {
101 : /* a negative ttl means: never expires */
102 9 : ret = EEXIST;
103 9 : goto done;
104 : }
105 :
106 49 : errno = 0;
107 49 : timestamp = strtoull((const char *)data.dptr, &ep, 10);
108 49 : if (errno != 0 || *ep != '\0') {
109 : /* Malformed entry, remove it and return no entry */
110 0 : expired = true;
111 0 : goto done;
112 : }
113 :
114 49 : if (timestamp == 0) {
115 : /* a 0 timestamp means this is a permanent entry */
116 26 : ret = EEXIST;
117 26 : goto done;
118 : }
119 :
120 23 : if (timestamp + ttl >= time(NULL)) {
121 : /* still valid */
122 22 : ret = EEXIST;
123 22 : goto done;
124 : }
125 :
126 1 : expired = true;
127 :
128 : done:
129 232 : if (expired) {
130 : /* expired, remove and return no entry */
131 1 : tdb_delete(ctx->tdb, key);
132 1 : ret = ENOENT;
133 : }
134 :
135 232 : free(data.dptr);
136 232 : return ret;
137 : }
138 :
139 150 : static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
140 : char *str, bool permanent)
141 : {
142 : TDB_DATA key;
143 : TDB_DATA data;
144 : char *timest;
145 : int ret;
146 :
147 150 : ret = string_to_tdb_data(str, &key);
148 150 : if (ret != EOK) return ret;
149 :
150 150 : if (permanent) {
151 101 : timest = talloc_strdup(ctx, "0");
152 : } else {
153 49 : timest = talloc_asprintf(ctx, "%llu",
154 49 : (unsigned long long int)time(NULL));
155 : }
156 150 : if (!timest) return ENOMEM;
157 :
158 150 : ret = string_to_tdb_data(timest, &data);
159 150 : if (ret != EOK) goto done;
160 :
161 150 : DEBUG(SSSDBG_TRACE_FUNC, "Adding [%s] to negative cache%s\n",
162 : str, permanent?" permanently":"");
163 :
164 150 : ret = tdb_store(ctx->tdb, key, data, TDB_REPLACE);
165 150 : if (ret != 0) {
166 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Negative cache failed to set entry: [%s]\n",
167 : tdb_errorstr(ctx->tdb));
168 0 : ret = EFAULT;
169 : }
170 :
171 : done:
172 150 : talloc_free(timest);
173 150 : return ret;
174 : }
175 :
176 111 : static int sss_ncache_check_user_int(struct sss_nc_ctx *ctx, int ttl,
177 : const char *domain, const char *name)
178 : {
179 : char *str;
180 : int ret;
181 :
182 111 : if (!name || !*name) return EINVAL;
183 :
184 111 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
185 111 : if (!str) return ENOMEM;
186 :
187 111 : ret = sss_ncache_check_str(ctx, str, ttl);
188 :
189 111 : talloc_free(str);
190 111 : return ret;
191 : }
192 :
193 40 : static int sss_ncache_check_group_int(struct sss_nc_ctx *ctx, int ttl,
194 : const char *domain, const char *name)
195 : {
196 : char *str;
197 : int ret;
198 :
199 40 : if (!name || !*name) return EINVAL;
200 :
201 40 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
202 40 : if (!str) return ENOMEM;
203 :
204 40 : ret = sss_ncache_check_str(ctx, str, ttl);
205 :
206 40 : talloc_free(str);
207 40 : return ret;
208 : }
209 :
210 5 : static int sss_ncache_check_netgr_int(struct sss_nc_ctx *ctx, int ttl,
211 : const char *domain, const char *name)
212 : {
213 : char *str;
214 : int ret;
215 :
216 5 : if (!name || !*name) return EINVAL;
217 :
218 5 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
219 5 : if (!str) return ENOMEM;
220 :
221 5 : ret = sss_ncache_check_str(ctx, str, ttl);
222 :
223 5 : talloc_free(str);
224 5 : return ret;
225 : }
226 :
227 10 : static int sss_ncache_check_service_int(struct sss_nc_ctx *ctx,
228 : int ttl,
229 : const char *domain,
230 : const char *name)
231 : {
232 : char *str;
233 : int ret;
234 :
235 10 : if (!name || !*name) return EINVAL;
236 :
237 10 : str = talloc_asprintf(ctx, "%s/%s/%s",
238 : NC_SERVICE_PREFIX,
239 : domain,
240 : name);
241 10 : if (!str) return ENOMEM;
242 :
243 10 : ret = sss_ncache_check_str(ctx, str, ttl);
244 :
245 10 : talloc_free(str);
246 10 : return ret;
247 : }
248 :
249 : typedef int (*ncache_check_byname_fn_t)(struct sss_nc_ctx *, int,
250 : const char *, const char *);
251 :
252 166 : static int sss_cache_check_ent(struct sss_nc_ctx *ctx, int ttl,
253 : struct sss_domain_info *dom, const char *name,
254 : ncache_check_byname_fn_t checker)
255 : {
256 : char *lower;
257 : errno_t ret;
258 :
259 166 : if (dom->case_sensitive == false) {
260 29 : lower = sss_tc_utf8_str_tolower(ctx, name);
261 29 : if (!lower) return ENOMEM;
262 29 : ret = checker(ctx, ttl, dom->name, lower);
263 29 : talloc_free(lower);
264 : } else {
265 137 : ret = checker(ctx, ttl, dom->name, name);
266 : }
267 :
268 166 : return ret;
269 : }
270 :
271 111 : int sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
272 : struct sss_domain_info *dom, const char *name)
273 : {
274 111 : return sss_cache_check_ent(ctx, ttl, dom, name,
275 : sss_ncache_check_user_int);
276 : }
277 :
278 40 : int sss_ncache_check_group(struct sss_nc_ctx *ctx, int ttl,
279 : struct sss_domain_info *dom, const char *name)
280 : {
281 40 : return sss_cache_check_ent(ctx, ttl, dom, name,
282 : sss_ncache_check_group_int);
283 : }
284 :
285 5 : int sss_ncache_check_netgr(struct sss_nc_ctx *ctx, int ttl,
286 : struct sss_domain_info *dom, const char *name)
287 : {
288 5 : return sss_cache_check_ent(ctx, ttl, dom, name,
289 : sss_ncache_check_netgr_int);
290 : }
291 :
292 4 : static int sss_ncache_set_service_int(struct sss_nc_ctx *ctx, bool permanent,
293 : const char *domain, const char *name)
294 : {
295 : char *str;
296 : int ret;
297 :
298 4 : if (!name || !*name) return EINVAL;
299 :
300 4 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_SERVICE_PREFIX, domain, name);
301 4 : if (!str) return ENOMEM;
302 :
303 4 : ret = sss_ncache_set_str(ctx, str, permanent);
304 :
305 4 : talloc_free(str);
306 4 : return ret;
307 : }
308 :
309 2 : int sss_ncache_set_service_name(struct sss_nc_ctx *ctx, bool permanent,
310 : struct sss_domain_info *dom,
311 : const char *name, const char *proto)
312 : {
313 : int ret;
314 2 : char *service_and_protocol = talloc_asprintf(ctx, "%s:%s",
315 : name,
316 : proto ? proto : "<ANY>");
317 2 : if (!service_and_protocol) return ENOMEM;
318 :
319 2 : ret = sss_ncache_set_ent(ctx, permanent, dom,
320 : service_and_protocol,
321 : sss_ncache_set_service_int);
322 2 : talloc_free(service_and_protocol);
323 2 : return ret;
324 : }
325 :
326 5 : int sss_ncache_check_service(struct sss_nc_ctx *ctx, int ttl,
327 : struct sss_domain_info *dom,
328 : const char *name,
329 : const char *proto)
330 : {
331 : int ret;
332 5 : char *service_and_protocol = talloc_asprintf(ctx, "%s:%s",
333 : name,
334 : proto ? proto : "<ANY>");
335 5 : if (!service_and_protocol) return ENOMEM;
336 :
337 5 : ret = sss_cache_check_ent(ctx, ttl, dom, service_and_protocol,
338 : sss_ncache_check_service_int);
339 5 : talloc_free(service_and_protocol);
340 5 : return ret;
341 : }
342 :
343 2 : int sss_ncache_set_service_port(struct sss_nc_ctx *ctx, bool permanent,
344 : struct sss_domain_info *dom,
345 : uint16_t port, const char *proto)
346 : {
347 : int ret;
348 2 : char *service_and_protocol = talloc_asprintf(ctx, "%ul:%s",
349 : port,
350 : proto ? proto : "<ANY>");
351 2 : if (!service_and_protocol) return ENOMEM;
352 :
353 2 : ret = sss_ncache_set_ent(ctx, permanent, dom,
354 : service_and_protocol,
355 : sss_ncache_set_service_int);
356 2 : talloc_free(service_and_protocol);
357 2 : return ret;
358 : }
359 :
360 5 : int sss_ncache_check_service_port(struct sss_nc_ctx *ctx, int ttl,
361 : struct sss_domain_info *dom,
362 : uint16_t port,
363 : const char *proto)
364 : {
365 : int ret;
366 5 : char *service_and_protocol = talloc_asprintf(ctx, "%ul:%s",
367 : port,
368 : proto ? proto : "<ANY>");
369 5 : if (!service_and_protocol) return ENOMEM;
370 :
371 5 : ret = sss_cache_check_ent(ctx, ttl, dom, service_and_protocol,
372 : sss_ncache_check_service_int);
373 5 : talloc_free(service_and_protocol);
374 5 : return ret;
375 : }
376 :
377 :
378 :
379 29 : int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
380 : struct sss_domain_info *dom, uid_t uid)
381 : {
382 : char *str;
383 : int ret;
384 :
385 29 : if (dom != NULL) {
386 0 : str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
387 : uid);
388 : } else {
389 29 : str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
390 : }
391 29 : if (!str) return ENOMEM;
392 :
393 29 : ret = sss_ncache_check_str(ctx, str, ttl);
394 :
395 29 : talloc_free(str);
396 29 : return ret;
397 : }
398 :
399 17 : int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl,
400 : struct sss_domain_info *dom, gid_t gid)
401 : {
402 : char *str;
403 : int ret;
404 :
405 17 : if (dom != NULL) {
406 0 : str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
407 : gid);
408 : } else {
409 17 : str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
410 : }
411 17 : if (!str) return ENOMEM;
412 :
413 17 : ret = sss_ncache_check_str(ctx, str, ttl);
414 :
415 17 : talloc_free(str);
416 17 : return ret;
417 : }
418 :
419 10 : int sss_ncache_check_sid(struct sss_nc_ctx *ctx, int ttl, const char *sid)
420 : {
421 : char *str;
422 : int ret;
423 :
424 10 : str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
425 10 : if (!str) return ENOMEM;
426 :
427 10 : ret = sss_ncache_check_str(ctx, str, ttl);
428 :
429 10 : talloc_free(str);
430 10 : return ret;
431 : }
432 :
433 10 : int sss_ncache_check_cert(struct sss_nc_ctx *ctx, int ttl, const char *cert)
434 : {
435 : char *str;
436 : int ret;
437 :
438 10 : str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
439 10 : if (!str) return ENOMEM;
440 :
441 10 : ret = sss_ncache_check_str(ctx, str, ttl);
442 :
443 10 : talloc_free(str);
444 10 : return ret;
445 : }
446 :
447 :
448 69 : static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
449 : const char *domain, const char *name)
450 : {
451 : char *str;
452 : int ret;
453 :
454 69 : if (!name || !*name) return EINVAL;
455 :
456 69 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
457 69 : if (!str) return ENOMEM;
458 :
459 69 : ret = sss_ncache_set_str(ctx, str, permanent);
460 :
461 69 : talloc_free(str);
462 69 : return ret;
463 : }
464 :
465 56 : static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
466 : const char *domain, const char *name)
467 : {
468 : char *str;
469 : int ret;
470 :
471 56 : if (!name || !*name) return EINVAL;
472 :
473 56 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
474 56 : if (!str) return ENOMEM;
475 :
476 56 : ret = sss_ncache_set_str(ctx, str, permanent);
477 :
478 56 : talloc_free(str);
479 56 : return ret;
480 : }
481 :
482 2 : static int sss_ncache_set_netgr_int(struct sss_nc_ctx *ctx, bool permanent,
483 : const char *domain, const char *name)
484 : {
485 : char *str;
486 : int ret;
487 :
488 2 : if (!name || !*name) return EINVAL;
489 :
490 2 : str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
491 2 : if (!str) return ENOMEM;
492 :
493 2 : ret = sss_ncache_set_str(ctx, str, permanent);
494 :
495 2 : talloc_free(str);
496 2 : return ret;
497 : }
498 :
499 131 : static int sss_ncache_set_ent(struct sss_nc_ctx *ctx, bool permanent,
500 : struct sss_domain_info *dom, const char *name,
501 : ncache_set_byname_fn_t setter)
502 : {
503 : char *lower;
504 : errno_t ret;
505 :
506 131 : if (dom->case_sensitive == false) {
507 26 : lower = sss_tc_utf8_str_tolower(ctx, name);
508 26 : if (!lower) return ENOMEM;
509 26 : ret = setter(ctx, permanent, dom->name, lower);
510 26 : talloc_free(lower);
511 : } else {
512 105 : ret = setter(ctx, permanent, dom->name, name);
513 : }
514 :
515 131 : return ret;
516 : }
517 :
518 :
519 69 : int sss_ncache_set_user(struct sss_nc_ctx *ctx, bool permanent,
520 : struct sss_domain_info *dom, const char *name)
521 : {
522 69 : return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_user_int);
523 : }
524 :
525 56 : int sss_ncache_set_group(struct sss_nc_ctx *ctx, bool permanent,
526 : struct sss_domain_info *dom, const char *name)
527 : {
528 56 : return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_group_int);
529 : }
530 :
531 2 : int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
532 : struct sss_domain_info *dom, const char *name)
533 : {
534 2 : return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_netgr_int);
535 : }
536 :
537 9 : int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
538 : struct sss_domain_info *dom, uid_t uid)
539 : {
540 : char *str;
541 : int ret;
542 :
543 9 : if (dom != NULL) {
544 0 : str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
545 : uid);
546 : } else {
547 9 : str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
548 : }
549 9 : if (!str) return ENOMEM;
550 :
551 9 : ret = sss_ncache_set_str(ctx, str, permanent);
552 :
553 9 : talloc_free(str);
554 9 : return ret;
555 : }
556 :
557 3 : int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
558 : struct sss_domain_info *dom, gid_t gid)
559 : {
560 : char *str;
561 : int ret;
562 :
563 3 : if (dom != NULL) {
564 0 : str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
565 : gid);
566 : } else {
567 3 : str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
568 : }
569 3 : if (!str) return ENOMEM;
570 :
571 3 : ret = sss_ncache_set_str(ctx, str, permanent);
572 :
573 3 : talloc_free(str);
574 3 : return ret;
575 : }
576 :
577 3 : int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid)
578 : {
579 : char *str;
580 : int ret;
581 :
582 3 : str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
583 3 : if (!str) return ENOMEM;
584 :
585 3 : ret = sss_ncache_set_str(ctx, str, permanent);
586 :
587 3 : talloc_free(str);
588 3 : return ret;
589 : }
590 :
591 4 : int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
592 : const char *cert)
593 : {
594 : char *str;
595 : int ret;
596 :
597 4 : str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
598 4 : if (!str) return ENOMEM;
599 :
600 4 : ret = sss_ncache_set_str(ctx, str, permanent);
601 :
602 4 : talloc_free(str);
603 4 : return ret;
604 : }
605 :
606 9 : static int delete_permanent(struct tdb_context *tdb,
607 : TDB_DATA key, TDB_DATA data, void *state)
608 : {
609 : unsigned long long int timestamp;
610 9 : bool remove_key = false;
611 : char *ep;
612 :
613 9 : if (strncmp((char *)key.dptr,
614 : NC_ENTRY_PREFIX, sizeof(NC_ENTRY_PREFIX) - 1) != 0) {
615 : /* not interested in this key */
616 0 : return 0;
617 : }
618 :
619 9 : errno = 0;
620 9 : timestamp = strtoull((const char *)data.dptr, &ep, 10);
621 9 : if (errno != 0 || *ep != '\0') {
622 : /* Malformed entry, remove it */
623 0 : remove_key = true;
624 0 : goto done;
625 : }
626 :
627 9 : if (timestamp == 0) {
628 : /* a 0 timestamp means this is a permanent entry */
629 7 : remove_key = true;
630 : }
631 :
632 : done:
633 9 : if (remove_key) {
634 7 : return tdb_delete(tdb, key);
635 : }
636 :
637 2 : return 0;
638 : }
639 :
640 36 : int sss_ncache_reset_permanent(struct sss_nc_ctx *ctx)
641 : {
642 : int ret;
643 :
644 36 : ret = tdb_traverse(ctx->tdb, delete_permanent, NULL);
645 36 : if (ret < 0)
646 0 : return EIO;
647 :
648 36 : return EOK;
649 : }
650 :
651 36 : errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
652 : struct confdb_ctx *cdb,
653 : struct resp_ctx *rctx)
654 : {
655 : errno_t ret;
656 36 : bool filter_set = false;
657 36 : char **filter_list = NULL;
658 36 : char *name = NULL;
659 36 : struct sss_domain_info *dom = NULL;
660 36 : struct sss_domain_info *domain_list = rctx->domains;
661 36 : char *domainname = NULL;
662 36 : char *conf_path = NULL;
663 36 : TALLOC_CTX *tmpctx = talloc_new(NULL);
664 : int i;
665 :
666 : /* Populate domain-specific negative cache entries */
667 73 : for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
668 37 : conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL,
669 : dom->name);
670 37 : if (!conf_path) {
671 0 : ret = ENOMEM;
672 0 : goto done;
673 : }
674 :
675 37 : talloc_zfree(filter_list);
676 37 : ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
677 : CONFDB_NSS_FILTER_USERS,
678 : &filter_list);
679 37 : if (ret == ENOENT) continue;
680 4 : if (ret != EOK) goto done;
681 4 : filter_set = true;
682 :
683 14 : for (i = 0; (filter_list && filter_list[i]); i++) {
684 20 : ret = sss_parse_name_for_domains(tmpctx, domain_list,
685 10 : rctx->default_domain,
686 10 : filter_list[i],
687 : &domainname, &name);
688 10 : if (ret == EAGAIN) {
689 3 : DEBUG(SSSDBG_MINOR_FAILURE,
690 : "cannot add [%s] to negcache because the required or "
691 : "default domain are not known yet\n", filter_list[i]);
692 7 : } else if (ret != EOK) {
693 0 : DEBUG(SSSDBG_CRIT_FAILURE,
694 : "Invalid name in filterUsers list: [%s] (%d)\n",
695 : filter_list[i], ret);
696 0 : continue;
697 : }
698 :
699 10 : if (domainname && strcmp(domainname, dom->name)) {
700 4 : DEBUG(SSSDBG_CRIT_FAILURE,
701 : "Mismatch between domain name (%s) and name "
702 : "set in FQN (%s), skipping user %s\n",
703 : dom->name, domainname, name);
704 4 : continue;
705 : }
706 :
707 6 : ret = sss_ncache_set_user(ncache, true, dom, name);
708 6 : if (ret != EOK) {
709 0 : DEBUG(SSSDBG_CRIT_FAILURE,
710 : "Failed to store permanent user filter for [%s]"
711 : " (%d [%s])\n", filter_list[i],
712 : ret, strerror(ret));
713 0 : continue;
714 : }
715 : }
716 : }
717 :
718 36 : ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
719 : CONFDB_NSS_FILTER_USERS, &filter_list);
720 36 : if (ret == ENOENT) {
721 34 : if (!filter_set) {
722 32 : filter_list = talloc_array(tmpctx, char *, 2);
723 32 : if (!filter_list) {
724 0 : ret = ENOMEM;
725 0 : goto done;
726 : }
727 32 : filter_list[0] = talloc_strdup(tmpctx, "root");
728 32 : if (!filter_list[0]) {
729 0 : ret = ENOMEM;
730 0 : goto done;
731 : }
732 32 : filter_list[1] = NULL;
733 : }
734 : }
735 2 : else if (ret != EOK) goto done;
736 :
737 78 : for (i = 0; (filter_list && filter_list[i]); i++) {
738 84 : ret = sss_parse_name_for_domains(tmpctx, domain_list,
739 84 : rctx->default_domain, filter_list[i],
740 : &domainname, &name);
741 42 : if (ret == EAGAIN) {
742 3 : DEBUG(SSSDBG_MINOR_FAILURE,
743 : "Cannot add [%s] to negcache because the required or "
744 : "default domain are not known yet\n", filter_list[i]);
745 39 : } else if (ret != EOK) {
746 0 : DEBUG(SSSDBG_CRIT_FAILURE,
747 : "Invalid name in filterUsers list: [%s] (%d)\n",
748 : filter_list[i], ret);
749 0 : continue;
750 : }
751 42 : if (domainname) {
752 9 : dom = responder_get_domain(rctx, domainname);
753 9 : if (!dom) {
754 3 : DEBUG(SSSDBG_CRIT_FAILURE,
755 : "Invalid domain name [%s]\n", domainname);
756 3 : continue;
757 : }
758 :
759 6 : ret = sss_ncache_set_user(ncache, true, dom, name);
760 6 : if (ret != EOK) {
761 0 : DEBUG(SSSDBG_CRIT_FAILURE,
762 : "Failed to store permanent user filter for [%s]"
763 : " (%d [%s])\n", filter_list[i],
764 : ret, strerror(ret));
765 0 : continue;
766 : }
767 : } else {
768 66 : for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
769 33 : ret = sss_ncache_set_user(ncache, true, dom, name);
770 33 : if (ret != EOK) {
771 0 : DEBUG(SSSDBG_CRIT_FAILURE,
772 : "Failed to store permanent user filter for"
773 : " [%s:%s] (%d [%s])\n",
774 : dom->name, filter_list[i],
775 : ret, strerror(ret));
776 0 : continue;
777 : }
778 : }
779 : }
780 : }
781 :
782 36 : filter_set = false;
783 73 : for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
784 37 : conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, dom->name);
785 37 : if (!conf_path) {
786 0 : ret = ENOMEM;
787 0 : goto done;
788 : }
789 :
790 37 : talloc_zfree(filter_list);
791 37 : ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
792 : CONFDB_NSS_FILTER_GROUPS, &filter_list);
793 37 : if (ret == ENOENT) continue;
794 4 : if (ret != EOK) goto done;
795 4 : filter_set = true;
796 :
797 14 : for (i = 0; (filter_list && filter_list[i]); i++) {
798 10 : ret = sss_parse_name(tmpctx, dom->names, filter_list[i],
799 : &domainname, &name);
800 10 : if (ret != EOK) {
801 0 : DEBUG(SSSDBG_CRIT_FAILURE,
802 : "Invalid name in filterGroups list: [%s] (%d)\n",
803 : filter_list[i], ret);
804 0 : continue;
805 : }
806 :
807 10 : if (domainname && strcmp(domainname, dom->name)) {
808 4 : DEBUG(SSSDBG_CRIT_FAILURE,
809 : "Mismatch betwen domain name (%s) and name "
810 : "set in FQN (%s), skipping group %s\n",
811 : dom->name, domainname, name);
812 4 : continue;
813 : }
814 :
815 6 : ret = sss_ncache_set_group(ncache, true, dom, name);
816 6 : if (ret != EOK) {
817 0 : DEBUG(SSSDBG_CRIT_FAILURE,
818 : "Failed to store permanent group filter for [%s]"
819 : " (%d [%s])\n", filter_list[i],
820 : ret, strerror(ret));
821 0 : continue;
822 : }
823 : }
824 : }
825 :
826 36 : ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
827 : CONFDB_NSS_FILTER_GROUPS, &filter_list);
828 36 : if (ret == ENOENT) {
829 34 : if (!filter_set) {
830 32 : filter_list = talloc_array(tmpctx, char *, 2);
831 32 : if (!filter_list) {
832 0 : ret = ENOMEM;
833 0 : goto done;
834 : }
835 32 : filter_list[0] = talloc_strdup(tmpctx, "root");
836 32 : if (!filter_list[0]) {
837 0 : ret = ENOMEM;
838 0 : goto done;
839 : }
840 32 : filter_list[1] = NULL;
841 : }
842 : }
843 2 : else if (ret != EOK) goto done;
844 :
845 78 : for (i = 0; (filter_list && filter_list[i]); i++) {
846 84 : ret = sss_parse_name_for_domains(tmpctx, domain_list,
847 84 : rctx->default_domain, filter_list[i],
848 : &domainname, &name);
849 42 : if (ret == EAGAIN) {
850 3 : DEBUG(SSSDBG_MINOR_FAILURE,
851 : "Cannot add [%s] to negcache because the required or "
852 : "default domain are not known yet\n", filter_list[i]);
853 39 : } else if (ret != EOK) {
854 0 : DEBUG(SSSDBG_CRIT_FAILURE,
855 : "Invalid name in filterGroups list: [%s] (%d)\n",
856 : filter_list[i], ret);
857 0 : continue;
858 : }
859 42 : if (domainname) {
860 9 : dom = responder_get_domain(rctx, domainname);
861 9 : if (!dom) {
862 3 : DEBUG(SSSDBG_CRIT_FAILURE,
863 : "Invalid domain name [%s]\n", domainname);
864 3 : continue;
865 : }
866 :
867 6 : ret = sss_ncache_set_group(ncache, true, dom, name);
868 6 : if (ret != EOK) {
869 0 : DEBUG(SSSDBG_CRIT_FAILURE,
870 : "Failed to store permanent group filter for"
871 : " [%s] (%d [%s])\n", filter_list[i],
872 : ret, strerror(ret));
873 0 : continue;
874 : }
875 : } else {
876 66 : for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
877 33 : ret = sss_ncache_set_group(ncache, true, dom, name);
878 33 : if (ret != EOK) {
879 0 : DEBUG(SSSDBG_CRIT_FAILURE,
880 : "Failed to store permanent group filter for"
881 : " [%s:%s] (%d [%s])\n",
882 : dom->name, filter_list[i],
883 : ret, strerror(ret));
884 0 : continue;
885 : }
886 : }
887 : }
888 : }
889 :
890 36 : ret = EOK;
891 :
892 : done:
893 36 : talloc_free(tmpctx);
894 36 : return ret;
895 : }
896 :
897 : /* Reset permanent negcache after checking the domains */
898 34 : errno_t sss_ncache_reset_repopulate_permanent(struct resp_ctx *rctx,
899 : struct sss_nc_ctx *ncache)
900 : {
901 : int ret;
902 :
903 34 : ret = sss_ncache_reset_permanent(ncache);
904 34 : if (ret == EOK) {
905 34 : ret = sss_ncache_prepopulate(ncache, rctx->cdb, rctx);
906 : }
907 :
908 34 : return ret;
909 : }
|