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