Line data Source code
1 : /*
2 : SSSD
3 :
4 : System Database
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 "db/sysdb_private.h"
24 : #include "confdb/confdb.h"
25 : #include <time.h>
26 : #include <ctype.h>
27 :
28 : /* users */
29 :
30 158 : int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
31 : struct sss_domain_info *domain,
32 : const char *name,
33 : struct ldb_result **_res)
34 : {
35 : TALLOC_CTX *tmp_ctx;
36 : static const char *attrs[] = SYSDB_PW_ATTRS;
37 : struct ldb_dn *base_dn;
38 : struct ldb_result *res;
39 : char *sanitized_name;
40 : char *lc_sanitized_name;
41 : const char *src_name;
42 : int ret;
43 :
44 158 : tmp_ctx = talloc_new(NULL);
45 158 : if (!tmp_ctx) {
46 0 : return ENOMEM;
47 : }
48 :
49 158 : base_dn = sysdb_user_base_dn(tmp_ctx, domain);
50 158 : if (!base_dn) {
51 0 : ret = ENOMEM;
52 0 : goto done;
53 : }
54 :
55 : /* If this is a subdomain we need to use fully qualified names for the
56 : * search as well by default */
57 158 : src_name = sss_get_domain_name(tmp_ctx, name, domain);
58 158 : if (!src_name) {
59 0 : ret = ENOMEM;
60 0 : goto done;
61 : }
62 :
63 158 : ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain,
64 : &sanitized_name, &lc_sanitized_name);
65 158 : if (ret != EOK) {
66 0 : goto done;
67 : }
68 :
69 158 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
70 : LDB_SCOPE_SUBTREE, attrs, SYSDB_PWNAM_FILTER,
71 : lc_sanitized_name,
72 : sanitized_name, sanitized_name);
73 158 : if (ret) {
74 0 : ret = sysdb_error_to_errno(ret);
75 0 : goto done;
76 : }
77 :
78 158 : *_res = talloc_steal(mem_ctx, res);
79 :
80 : done:
81 158 : talloc_zfree(tmp_ctx);
82 158 : return ret;
83 : }
84 :
85 72 : errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
86 : struct sss_domain_info *domain,
87 : const char *name,
88 : struct ldb_result **res)
89 : {
90 : int ret;
91 72 : struct ldb_result *orig_obj = NULL;
92 72 : struct ldb_result *override_obj = NULL;
93 : TALLOC_CTX *tmp_ctx;
94 :
95 72 : tmp_ctx = talloc_new(NULL);
96 72 : if (tmp_ctx == NULL) {
97 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
98 0 : return ENOMEM;
99 : }
100 :
101 : /* If there are views we first have to search the overrides for matches */
102 72 : if (DOM_HAS_VIEWS(domain)) {
103 0 : ret = sysdb_search_user_override_by_name(tmp_ctx, domain, name,
104 : &override_obj, &orig_obj);
105 0 : if (ret != EOK && ret != ENOENT) {
106 0 : DEBUG(SSSDBG_OP_FAILURE,
107 : "sysdb_search_override_by_name failed.\n");
108 0 : goto done;
109 : }
110 : }
111 :
112 : /* If there are no views or nothing was found in the overrides the
113 : * original objects are searched. */
114 72 : if (orig_obj == NULL) {
115 72 : ret = sysdb_getpwnam(tmp_ctx, domain, name, &orig_obj);
116 72 : if (ret != EOK) {
117 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwnam failed.\n");
118 0 : goto done;
119 : }
120 : }
121 :
122 : /* If there are views we have to check if override values must be added to
123 : * the original object. */
124 72 : if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
125 0 : ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
126 0 : override_obj == NULL ? NULL : override_obj->msgs[0],
127 : NULL);
128 0 : if (ret != EOK && ret != ENOENT) {
129 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
130 0 : goto done;
131 : }
132 :
133 0 : if (ret == ENOENT) {
134 0 : *res = talloc_zero(mem_ctx, struct ldb_result);
135 0 : if (*res == NULL) {
136 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
137 0 : ret = ENOMEM;
138 : } else {
139 0 : ret = EOK;
140 : }
141 0 : goto done;
142 : }
143 : }
144 :
145 72 : *res = talloc_steal(mem_ctx, orig_obj);
146 72 : ret = EOK;
147 :
148 : done:
149 72 : talloc_free(tmp_ctx);
150 72 : return ret;
151 : }
152 :
153 43 : int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
154 : struct sss_domain_info *domain,
155 : uid_t uid,
156 : struct ldb_result **_res)
157 : {
158 : TALLOC_CTX *tmp_ctx;
159 43 : unsigned long int ul_uid = uid;
160 : static const char *attrs[] = SYSDB_PW_ATTRS;
161 : struct ldb_dn *base_dn;
162 : struct ldb_result *res;
163 : int ret;
164 :
165 43 : tmp_ctx = talloc_new(NULL);
166 43 : if (!tmp_ctx) {
167 0 : return ENOMEM;
168 : }
169 :
170 43 : base_dn = sysdb_user_base_dn(tmp_ctx, domain);
171 43 : if (!base_dn) {
172 0 : ret = ENOMEM;
173 0 : goto done;
174 : }
175 :
176 43 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
177 : LDB_SCOPE_SUBTREE, attrs, SYSDB_PWUID_FILTER, ul_uid);
178 43 : if (ret) {
179 0 : ret = sysdb_error_to_errno(ret);
180 0 : goto done;
181 : }
182 :
183 43 : *_res = talloc_steal(mem_ctx, res);
184 :
185 : done:
186 43 : talloc_zfree(tmp_ctx);
187 43 : return ret;
188 : }
189 :
190 30 : errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
191 : struct sss_domain_info *domain,
192 : uid_t uid,
193 : struct ldb_result **res)
194 : {
195 : int ret;
196 30 : struct ldb_result *orig_obj = NULL;
197 30 : struct ldb_result *override_obj = NULL;
198 : TALLOC_CTX *tmp_ctx;
199 :
200 30 : tmp_ctx = talloc_new(NULL);
201 30 : if (tmp_ctx == NULL) {
202 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
203 0 : return ENOMEM;
204 : }
205 :
206 : /* If there are views we first have to search the overrides for matches */
207 30 : if (DOM_HAS_VIEWS(domain)) {
208 0 : ret = sysdb_search_user_override_by_uid(tmp_ctx, domain, uid,
209 : &override_obj, &orig_obj);
210 0 : if (ret != EOK && ret != ENOENT) {
211 0 : DEBUG(SSSDBG_OP_FAILURE,
212 : "sysdb_search_user_override_by_uid failed.\n");
213 0 : goto done;
214 : }
215 : }
216 :
217 : /* If there are no views or nothing was found in the overrides the
218 : * original objects are searched. */
219 30 : if (orig_obj == NULL) {
220 30 : ret = sysdb_getpwuid(tmp_ctx, domain, uid, &orig_obj);
221 30 : if (ret != EOK) {
222 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwuid failed.\n");
223 0 : goto done;
224 : }
225 : }
226 :
227 : /* If there are views we have to check if override values must be added to
228 : * the original object. */
229 30 : if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
230 0 : ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
231 0 : override_obj == NULL ? NULL : override_obj->msgs[0],
232 : NULL);
233 0 : if (ret != EOK && ret != ENOENT) {
234 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
235 0 : goto done;
236 : }
237 :
238 0 : if (ret == ENOENT) {
239 0 : *res = talloc_zero(mem_ctx, struct ldb_result);
240 0 : if (*res == NULL) {
241 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
242 0 : ret = ENOMEM;
243 : } else {
244 0 : ret = EOK;
245 : }
246 0 : goto done;
247 : }
248 : }
249 :
250 30 : *res = talloc_steal(mem_ctx, orig_obj);
251 30 : ret = EOK;
252 :
253 : done:
254 30 : talloc_free(tmp_ctx);
255 30 : return ret;
256 : }
257 :
258 38 : static char *enum_filter(TALLOC_CTX *mem_ctx,
259 : const char *base_filter,
260 : const char *name_filter,
261 : const char *addtl_filter)
262 : {
263 : char *filter;
264 38 : TALLOC_CTX *tmp_ctx = NULL;
265 :
266 38 : tmp_ctx = talloc_new(NULL);
267 38 : if (tmp_ctx == NULL) {
268 0 : return NULL;
269 : }
270 :
271 38 : if (name_filter == NULL && addtl_filter == NULL) {
272 6 : filter = talloc_strdup(tmp_ctx, base_filter);
273 : } else {
274 32 : filter = talloc_asprintf(tmp_ctx, "(&%s", base_filter);
275 :
276 32 : if (filter != NULL && name_filter != NULL) {
277 32 : filter = talloc_asprintf_append(filter, "(%s=%s)",
278 : SYSDB_NAME, name_filter);
279 : }
280 :
281 32 : if (filter != NULL && addtl_filter != NULL) {
282 16 : filter = talloc_asprintf_append(filter, "%s", addtl_filter);
283 : }
284 :
285 32 : if (filter != NULL) {
286 32 : filter = talloc_asprintf_append(filter, ")");
287 : }
288 : }
289 :
290 38 : if (filter) {
291 38 : talloc_steal(mem_ctx, filter);
292 : }
293 :
294 38 : talloc_free(tmp_ctx);
295 38 : return filter;
296 : }
297 :
298 23 : int sysdb_getpwupn(TALLOC_CTX *mem_ctx,
299 : struct sss_domain_info *domain,
300 : const char *upn,
301 : struct ldb_result **_res)
302 : {
303 : TALLOC_CTX *tmp_ctx;
304 : struct ldb_result *res;
305 : static const char *attrs[] = SYSDB_PW_ATTRS;
306 : errno_t ret;
307 :
308 23 : tmp_ctx = talloc_new(NULL);
309 23 : if (tmp_ctx == NULL) {
310 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
311 0 : return ENOMEM;
312 : }
313 :
314 23 : ret = sysdb_search_user_by_upn_res(tmp_ctx, domain, upn, attrs, &res);
315 23 : if (ret != EOK && ret != ENOENT) {
316 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn_res() failed.\n");
317 0 : goto done;
318 : }
319 :
320 23 : *_res = talloc_steal(mem_ctx, res);
321 :
322 : done:
323 23 : talloc_free(tmp_ctx);
324 23 : return ret;
325 : }
326 :
327 20 : int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
328 : struct sss_domain_info *domain,
329 : const char *name_filter,
330 : const char *addtl_filter,
331 : struct ldb_result **_res)
332 : {
333 : TALLOC_CTX *tmp_ctx;
334 : static const char *attrs[] = SYSDB_PW_ATTRS;
335 20 : char *filter = NULL;
336 : struct ldb_dn *base_dn;
337 : struct ldb_result *res;
338 : int ret;
339 :
340 20 : tmp_ctx = talloc_new(NULL);
341 20 : if (!tmp_ctx) {
342 0 : return ENOMEM;
343 : }
344 :
345 20 : base_dn = sysdb_user_base_dn(tmp_ctx, domain);
346 20 : if (!base_dn) {
347 0 : ret = ENOMEM;
348 0 : goto done;
349 : }
350 :
351 20 : filter = enum_filter(tmp_ctx, SYSDB_PWENT_FILTER,
352 : name_filter, addtl_filter);
353 20 : if (filter == NULL) {
354 0 : ret = ENOMEM;
355 0 : goto done;
356 : }
357 20 : DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter);
358 :
359 20 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
360 : LDB_SCOPE_SUBTREE, attrs, "%s", filter);
361 20 : if (ret) {
362 0 : ret = sysdb_error_to_errno(ret);
363 0 : goto done;
364 : }
365 :
366 20 : *_res = talloc_steal(mem_ctx, res);
367 :
368 : done:
369 20 : talloc_zfree(tmp_ctx);
370 20 : return ret;
371 : }
372 :
373 2 : int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
374 : struct sss_domain_info *domain,
375 : struct ldb_result **_res)
376 : {
377 2 : return sysdb_enumpwent_filter(mem_ctx, domain, NULL, 0, _res);
378 : }
379 :
380 12 : int sysdb_enumpwent_filter_with_views(TALLOC_CTX *mem_ctx,
381 : struct sss_domain_info *domain,
382 : const char *name_filter,
383 : const char *addtl_filter,
384 : struct ldb_result **_res)
385 : {
386 : TALLOC_CTX *tmp_ctx;
387 : struct ldb_result *res;
388 : size_t c;
389 : int ret;
390 :
391 12 : tmp_ctx = talloc_new(NULL);
392 12 : if (tmp_ctx == NULL) {
393 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
394 0 : return ENOMEM;
395 : }
396 :
397 12 : ret = sysdb_enumpwent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res);
398 12 : if (ret != EOK) {
399 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumpwent failed.\n");
400 0 : goto done;
401 : }
402 :
403 12 : if (DOM_HAS_VIEWS(domain)) {
404 16 : for (c = 0; c < res->count; c++) {
405 10 : ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
406 : NULL);
407 : /* enumeration assumes that the cache is up-to-date, hence we do not
408 : * need to handle ENOENT separately. */
409 10 : if (ret != EOK) {
410 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
411 0 : goto done;
412 : }
413 : }
414 : }
415 :
416 12 : *_res = talloc_steal(mem_ctx, res);
417 :
418 : done:
419 12 : talloc_zfree(tmp_ctx);
420 12 : return ret;
421 : }
422 :
423 1 : int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
424 : struct sss_domain_info *domain,
425 : struct ldb_result **_res)
426 : {
427 1 : return sysdb_enumpwent_filter_with_views(mem_ctx, domain, NULL, NULL, _res);
428 : }
429 :
430 : /* groups */
431 :
432 85 : static int mpg_convert(struct ldb_message *msg)
433 : {
434 : struct ldb_message_element *el;
435 85 : struct ldb_val *val = NULL;
436 : int i;
437 :
438 85 : el = ldb_msg_find_element(msg, "objectClass");
439 85 : if (!el) return EINVAL;
440 :
441 : /* see if this is a user to convert to a group */
442 160 : for (i = 0; i < el->num_values; i++) {
443 85 : val = &(el->values[i]);
444 170 : if (strncasecmp(SYSDB_USER_CLASS,
445 85 : (char *)val->data, val->length) == 0) {
446 10 : break;
447 : }
448 : }
449 : /* no, leave as is */
450 85 : if (i == el->num_values) return EOK;
451 :
452 : /* yes, convert */
453 10 : val->data = (uint8_t *)talloc_strdup(msg, SYSDB_GROUP_CLASS);
454 10 : if (val->data == NULL) return ENOMEM;
455 10 : val->length = strlen(SYSDB_GROUP_CLASS);
456 :
457 10 : return EOK;
458 : }
459 :
460 108 : static int mpg_res_convert(struct ldb_result *res)
461 : {
462 : int ret;
463 : int i;
464 :
465 193 : for (i = 0; i < res->count; i++) {
466 85 : ret = mpg_convert(res->msgs[i]);
467 85 : if (ret) {
468 0 : return ret;
469 : }
470 : }
471 108 : return EOK;
472 : }
473 :
474 33 : int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
475 : struct sss_domain_info *domain,
476 : const char *name,
477 : struct ldb_result **res)
478 : {
479 : TALLOC_CTX *tmp_ctx;
480 : int ret;
481 33 : struct ldb_result *orig_obj = NULL;
482 33 : struct ldb_result *override_obj = NULL;
483 : struct ldb_message_element *el;
484 :
485 33 : tmp_ctx = talloc_new(NULL);
486 33 : if (!tmp_ctx) {
487 0 : return ENOMEM;
488 : }
489 :
490 : /* If there are views we first have to search the overrides for matches */
491 33 : if (DOM_HAS_VIEWS(domain)) {
492 0 : ret = sysdb_search_group_override_by_name(tmp_ctx, domain, name,
493 : &override_obj, &orig_obj);
494 0 : if (ret != EOK && ret != ENOENT) {
495 0 : DEBUG(SSSDBG_OP_FAILURE,
496 : "sysdb_search_group_override_by_name failed.\n");
497 0 : goto done;
498 : }
499 : }
500 :
501 : /* If there are no views or nothing was found in the overrides the
502 : * original objects are searched. */
503 33 : if (orig_obj == NULL) {
504 33 : ret = sysdb_getgrnam(tmp_ctx, domain, name, &orig_obj);
505 33 : if (ret != EOK) {
506 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrnam failed.\n");
507 0 : goto done;
508 : }
509 : }
510 :
511 : /* If there are views we have to check if override values must be added to
512 : * the original object. */
513 33 : if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
514 0 : if (!is_local_view(domain->view_name)) {
515 0 : el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
516 0 : if (el != NULL && el->num_values != 0) {
517 0 : DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
518 : "entries which must be resolved before overrides can be "
519 : "applied.\n",
520 : ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
521 0 : ret = ENOENT;
522 0 : goto done;
523 : }
524 : }
525 :
526 0 : ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
527 0 : override_obj == NULL ? NULL : override_obj ->msgs[0],
528 : NULL);
529 0 : if (ret != EOK) {
530 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
531 0 : goto done;
532 : }
533 :
534 0 : ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]);
535 0 : if (ret != EOK) {
536 0 : DEBUG(SSSDBG_OP_FAILURE,
537 : "sysdb_add_group_member_overrides failed.\n");
538 0 : goto done;
539 : }
540 : }
541 :
542 33 : *res = talloc_steal(mem_ctx, orig_obj);
543 33 : ret = EOK;
544 :
545 : done:
546 33 : if (ret == ENOENT) {
547 0 : DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n");
548 0 : *res = talloc_zero(mem_ctx, struct ldb_result);
549 0 : if (*res == NULL) {
550 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
551 0 : ret = ENOMEM;
552 : } else {
553 0 : ret = EOK;
554 : }
555 : }
556 :
557 33 : talloc_free(tmp_ctx);
558 33 : return ret;
559 : }
560 :
561 57 : int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
562 : struct sss_domain_info *domain,
563 : const char *name,
564 : struct ldb_result **_res)
565 : {
566 : TALLOC_CTX *tmp_ctx;
567 : static const char *attrs[] = SYSDB_GRSRC_ATTRS;
568 : const char *fmt_filter;
569 : char *sanitized_name;
570 : struct ldb_dn *base_dn;
571 : struct ldb_result *res;
572 : const char *src_name;
573 : char *lc_sanitized_name;
574 : int ret;
575 :
576 57 : tmp_ctx = talloc_new(NULL);
577 57 : if (!tmp_ctx) {
578 0 : return ENOMEM;
579 : }
580 :
581 57 : if (domain->mpg) {
582 24 : fmt_filter = SYSDB_GRNAM_MPG_FILTER;
583 24 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
584 : SYSDB_DOM_BASE, domain->name);
585 : } else {
586 33 : fmt_filter = SYSDB_GRNAM_FILTER;
587 33 : base_dn = sysdb_group_base_dn(tmp_ctx, domain);
588 : }
589 57 : if (!base_dn) {
590 0 : ret = ENOMEM;
591 0 : goto done;
592 : }
593 :
594 : /* If this is a subomain we need to use fully qualified names for the
595 : * search as well by default */
596 57 : src_name = sss_get_domain_name(tmp_ctx, name, domain);
597 57 : if (!src_name) {
598 0 : ret = ENOMEM;
599 0 : goto done;
600 : }
601 :
602 57 : ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain,
603 : &sanitized_name, &lc_sanitized_name);
604 57 : if (ret != EOK) {
605 0 : goto done;
606 : }
607 :
608 57 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
609 : LDB_SCOPE_SUBTREE, attrs, fmt_filter,
610 : lc_sanitized_name, sanitized_name, sanitized_name);
611 57 : if (ret) {
612 0 : ret = sysdb_error_to_errno(ret);
613 0 : goto done;
614 : }
615 :
616 57 : ret = mpg_res_convert(res);
617 57 : if (ret) {
618 0 : goto done;
619 : }
620 :
621 57 : *_res = talloc_steal(mem_ctx, res);
622 :
623 : done:
624 57 : talloc_zfree(tmp_ctx);
625 57 : return ret;
626 : }
627 :
628 23 : int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
629 : struct sss_domain_info *domain,
630 : gid_t gid,
631 : struct ldb_result **res)
632 : {
633 : TALLOC_CTX *tmp_ctx;
634 : int ret;
635 23 : struct ldb_result *orig_obj = NULL;
636 23 : struct ldb_result *override_obj = NULL;
637 : struct ldb_message_element *el;
638 :
639 23 : tmp_ctx = talloc_new(NULL);
640 23 : if (!tmp_ctx) {
641 0 : return ENOMEM;
642 : }
643 :
644 : /* If there are views we first have to search the overrides for matches */
645 23 : if (DOM_HAS_VIEWS(domain)) {
646 0 : ret = sysdb_search_group_override_by_gid(tmp_ctx, domain, gid,
647 : &override_obj, &orig_obj);
648 0 : if (ret != EOK && ret != ENOENT) {
649 0 : DEBUG(SSSDBG_OP_FAILURE,
650 : "sysdb_search_group_override_by_gid failed.\n");
651 0 : goto done;
652 : }
653 : }
654 :
655 : /* If there are no views or nothing was found in the overrides the
656 : * original objects are searched. */
657 23 : if (orig_obj == NULL) {
658 23 : ret = sysdb_getgrgid(tmp_ctx, domain, gid, &orig_obj);
659 23 : if (ret != EOK) {
660 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrgid failed.\n");
661 0 : goto done;
662 : }
663 : }
664 :
665 : /* If there are views we have to check if override values must be added to
666 : * the original object. */
667 23 : if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
668 0 : if (!is_local_view(domain->view_name)) {
669 0 : el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
670 0 : if (el != NULL && el->num_values != 0) {
671 0 : DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
672 : "entries which must be resolved before overrides can be "
673 : "applied.\n",
674 : ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
675 0 : ret = ENOENT;
676 0 : goto done;
677 : }
678 : }
679 :
680 0 : ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
681 0 : override_obj == NULL ? NULL : override_obj ->msgs[0],
682 : NULL);
683 0 : if (ret != EOK) {
684 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
685 0 : goto done;
686 : }
687 :
688 0 : ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]);
689 0 : if (ret != EOK) {
690 0 : DEBUG(SSSDBG_OP_FAILURE,
691 : "sysdb_add_group_member_overrides failed.\n");
692 0 : goto done;
693 : }
694 : }
695 :
696 23 : *res = talloc_steal(mem_ctx, orig_obj);
697 23 : ret = EOK;
698 :
699 : done:
700 23 : if (ret == ENOENT) {
701 0 : DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n");
702 0 : *res = talloc_zero(mem_ctx, struct ldb_result);
703 0 : if (*res == NULL) {
704 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
705 0 : ret = ENOMEM;
706 : } else {
707 0 : ret = EOK;
708 : }
709 : }
710 :
711 23 : talloc_free(tmp_ctx);
712 23 : return ret;
713 : }
714 :
715 33 : int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
716 : struct sss_domain_info *domain,
717 : gid_t gid,
718 : struct ldb_result **_res)
719 : {
720 : TALLOC_CTX *tmp_ctx;
721 33 : unsigned long int ul_gid = gid;
722 : static const char *attrs[] = SYSDB_GRSRC_ATTRS;
723 : const char *fmt_filter;
724 : struct ldb_dn *base_dn;
725 : struct ldb_result *res;
726 : int ret;
727 :
728 33 : tmp_ctx = talloc_new(NULL);
729 33 : if (!tmp_ctx) {
730 0 : return ENOMEM;
731 : }
732 :
733 33 : if (domain->mpg) {
734 10 : fmt_filter = SYSDB_GRGID_MPG_FILTER;
735 10 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
736 : SYSDB_DOM_BASE, domain->name);
737 : } else {
738 23 : fmt_filter = SYSDB_GRGID_FILTER;
739 23 : base_dn = sysdb_group_base_dn(tmp_ctx, domain);
740 : }
741 33 : if (!base_dn) {
742 0 : ret = ENOMEM;
743 0 : goto done;
744 : }
745 :
746 33 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
747 : LDB_SCOPE_SUBTREE, attrs, fmt_filter, ul_gid);
748 33 : if (ret) {
749 0 : ret = sysdb_error_to_errno(ret);
750 0 : goto done;
751 : }
752 :
753 33 : ret = mpg_res_convert(res);
754 33 : if (ret) {
755 0 : goto done;
756 : }
757 :
758 33 : *_res = talloc_steal(mem_ctx, res);
759 :
760 : done:
761 33 : talloc_zfree(tmp_ctx);
762 33 : return ret;
763 : }
764 :
765 18 : int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
766 : struct sss_domain_info *domain,
767 : const char *name_filter,
768 : const char *addtl_filter,
769 : struct ldb_result **_res)
770 : {
771 : TALLOC_CTX *tmp_ctx;
772 : static const char *attrs[] = SYSDB_GRSRC_ATTRS;
773 18 : const char *filter = NULL;
774 : const char *base_filter;
775 : struct ldb_dn *base_dn;
776 : struct ldb_result *res;
777 : int ret;
778 :
779 18 : tmp_ctx = talloc_new(NULL);
780 18 : if (!tmp_ctx) {
781 0 : return ENOMEM;
782 : }
783 :
784 18 : if (domain->mpg) {
785 14 : base_filter = SYSDB_GRENT_MPG_FILTER;
786 14 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
787 : SYSDB_DOM_BASE, domain->name);
788 : } else {
789 4 : base_filter = SYSDB_GRENT_FILTER;
790 4 : base_dn = sysdb_group_base_dn(tmp_ctx, domain);
791 : }
792 18 : if (!base_dn) {
793 0 : ret = ENOMEM;
794 0 : goto done;
795 : }
796 :
797 18 : filter = enum_filter(tmp_ctx, base_filter,
798 : name_filter, addtl_filter);
799 18 : if (filter == NULL) {
800 0 : ret = ENOMEM;
801 0 : goto done;
802 : }
803 18 : DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter);
804 :
805 18 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
806 : LDB_SCOPE_SUBTREE, attrs, "%s", filter);
807 18 : if (ret) {
808 0 : ret = sysdb_error_to_errno(ret);
809 0 : goto done;
810 : }
811 :
812 18 : ret = mpg_res_convert(res);
813 18 : if (ret) {
814 0 : goto done;
815 : }
816 :
817 18 : *_res = talloc_steal(mem_ctx, res);
818 :
819 : done:
820 18 : talloc_zfree(tmp_ctx);
821 18 : return ret;
822 : }
823 :
824 2 : int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
825 : struct sss_domain_info *domain,
826 : struct ldb_result **_res)
827 : {
828 2 : return sysdb_enumgrent_filter(mem_ctx, domain, NULL, 0, _res);
829 : }
830 :
831 10 : int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx,
832 : struct sss_domain_info *domain,
833 : const char *name_filter,
834 : const char *addtl_filter,
835 : struct ldb_result **_res)
836 : {
837 : TALLOC_CTX *tmp_ctx;
838 : struct ldb_result *res;
839 : size_t c;
840 : int ret;
841 :
842 10 : tmp_ctx = talloc_new(NULL);
843 10 : if (tmp_ctx == NULL) {
844 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
845 0 : return ENOMEM;
846 : }
847 :
848 10 : ret = sysdb_enumgrent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res);
849 10 : if (ret != EOK) {
850 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumgrent failed.\n");
851 0 : goto done;
852 : }
853 :
854 10 : if (DOM_HAS_VIEWS(domain)) {
855 16 : for (c = 0; c < res->count; c++) {
856 10 : ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
857 : NULL);
858 : /* enumeration assumes that the cache is up-to-date, hence we do not
859 : * need to handle ENOENT separately. */
860 10 : if (ret != EOK) {
861 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
862 0 : goto done;
863 : }
864 :
865 10 : ret = sysdb_add_group_member_overrides(domain, res->msgs[c]);
866 10 : if (ret != EOK) {
867 0 : DEBUG(SSSDBG_OP_FAILURE,
868 : "sysdb_add_group_member_overrides failed.\n");
869 0 : goto done;
870 : }
871 : }
872 : }
873 :
874 :
875 10 : *_res = talloc_steal(mem_ctx, res);
876 :
877 : done:
878 10 : talloc_zfree(tmp_ctx);
879 10 : return ret;
880 : }
881 :
882 1 : int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
883 : struct sss_domain_info *domain,
884 : struct ldb_result **_res)
885 : {
886 1 : return sysdb_enumgrent_filter_with_views(mem_ctx, domain, NULL, NULL, _res);
887 : }
888 :
889 11 : int sysdb_initgroups(TALLOC_CTX *mem_ctx,
890 : struct sss_domain_info *domain,
891 : const char *name,
892 : struct ldb_result **_res)
893 : {
894 : TALLOC_CTX *tmp_ctx;
895 : struct ldb_result *res;
896 : struct ldb_dn *user_dn;
897 : struct ldb_request *req;
898 : struct ldb_control **ctrl;
899 : struct ldb_asq_control *control;
900 : static const char *attrs[] = SYSDB_INITGR_ATTRS;
901 : int ret;
902 :
903 11 : tmp_ctx = talloc_new(NULL);
904 11 : if (!tmp_ctx) {
905 0 : return ENOMEM;
906 : }
907 :
908 11 : ret = sysdb_getpwnam(tmp_ctx, domain, name, &res);
909 11 : if (ret != EOK) {
910 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam failed: [%d][%s]\n",
911 : ret, strerror(ret));
912 0 : goto done;
913 : }
914 :
915 11 : if (res->count == 0) {
916 : /* User is not cached yet */
917 0 : *_res = talloc_steal(mem_ctx, res);
918 0 : ret = EOK;
919 0 : goto done;
920 :
921 11 : } else if (res->count != 1) {
922 0 : ret = EIO;
923 0 : DEBUG(SSSDBG_CRIT_FAILURE,
924 : "sysdb_getpwnam returned count: [%d]\n", res->count);
925 0 : goto done;
926 : }
927 :
928 : /* no need to steal the dn, we are not freeing the result */
929 11 : user_dn = res->msgs[0]->dn;
930 :
931 : /* note we count on the fact that the default search callback
932 : * will just keep appending values. This is by design and can't
933 : * change so it is ok to already have a result (from the getpwnam)
934 : * even before we call the next search */
935 :
936 11 : ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2);
937 11 : if (!ctrl) {
938 0 : ret = ENOMEM;
939 0 : goto done;
940 : }
941 11 : ctrl[1] = NULL;
942 11 : ctrl[0] = talloc(ctrl, struct ldb_control);
943 11 : if (!ctrl[0]) {
944 0 : ret = ENOMEM;
945 0 : goto done;
946 : }
947 11 : ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
948 11 : ctrl[0]->critical = 1;
949 11 : control = talloc(ctrl[0], struct ldb_asq_control);
950 11 : if (!control) {
951 0 : ret = ENOMEM;
952 0 : goto done;
953 : }
954 11 : control->request = 1;
955 11 : control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR);
956 11 : if (!control->source_attribute) {
957 0 : ret = ENOMEM;
958 0 : goto done;
959 : }
960 11 : control->src_attr_len = strlen(control->source_attribute);
961 11 : ctrl[0]->data = control;
962 :
963 11 : ret = ldb_build_search_req(&req, domain->sysdb->ldb, tmp_ctx,
964 : user_dn, LDB_SCOPE_BASE,
965 : SYSDB_INITGR_FILTER, attrs, ctrl,
966 : res, ldb_search_default_callback,
967 : NULL);
968 11 : if (ret != LDB_SUCCESS) {
969 0 : ret = sysdb_error_to_errno(ret);
970 0 : goto done;
971 : }
972 :
973 11 : ret = ldb_request(domain->sysdb->ldb, req);
974 11 : if (ret == LDB_SUCCESS) {
975 11 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
976 : }
977 11 : if (ret != LDB_SUCCESS) {
978 0 : ret = sysdb_error_to_errno(ret);
979 0 : goto done;
980 : }
981 :
982 11 : *_res = talloc_steal(mem_ctx, res);
983 :
984 : done:
985 11 : talloc_zfree(tmp_ctx);
986 11 : return ret;
987 : }
988 :
989 0 : int sysdb_initgroups_by_upn(TALLOC_CTX *mem_ctx,
990 : struct sss_domain_info *domain,
991 : const char *upn,
992 : struct ldb_result **_res)
993 : {
994 : TALLOC_CTX *tmp_ctx;
995 : struct ldb_message *msg;
996 : struct ldb_result *res;
997 : const char *sysdb_name;
998 : static const char *attrs[] = SYSDB_INITGR_ATTRS;
999 : size_t i;
1000 : errno_t ret;
1001 :
1002 0 : tmp_ctx = talloc_new(NULL);
1003 0 : if (tmp_ctx == NULL) {
1004 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
1005 0 : return ENOMEM;
1006 : }
1007 :
1008 0 : ret = sysdb_search_user_by_upn(tmp_ctx, domain, upn, attrs, &msg);
1009 0 : if (ret != EOK && ret != ENOENT) {
1010 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn() failed.\n");
1011 0 : goto done;
1012 : }
1013 :
1014 0 : res = talloc_zero(tmp_ctx, struct ldb_result);
1015 0 : if (res == NULL) {
1016 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero() failed.\n");
1017 0 : ret = ENOMEM;
1018 0 : goto done;
1019 : }
1020 :
1021 0 : if (ret == ENOENT) {
1022 0 : res->count = 0;
1023 0 : res->msgs = NULL;
1024 : } else {
1025 0 : sysdb_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1026 0 : if (sysdb_name == NULL) {
1027 0 : DEBUG(SSSDBG_OP_FAILURE, "Sysdb entry does not have a name.\n");
1028 0 : return EINVAL;
1029 : }
1030 :
1031 0 : ret = sysdb_initgroups(tmp_ctx, domain, sysdb_name, &res);
1032 0 : if (ret == EOK && DOM_HAS_VIEWS(domain)) {
1033 0 : for (i = 0; i < res->count; i++) {
1034 0 : ret = sysdb_add_overrides_to_object(domain, res->msgs[i],
1035 : NULL, NULL);
1036 0 : if (ret != EOK) {
1037 0 : DEBUG(SSSDBG_OP_FAILURE,
1038 : "sysdb_add_overrides_to_object() failed.\n");
1039 0 : return ret;
1040 : }
1041 : }
1042 : }
1043 : }
1044 :
1045 0 : *_res = talloc_steal(mem_ctx, res);
1046 0 : ret = EOK;
1047 :
1048 : done:
1049 0 : talloc_free(tmp_ctx);
1050 0 : return ret;
1051 : }
1052 :
1053 9 : int sysdb_initgroups_with_views(TALLOC_CTX *mem_ctx,
1054 : struct sss_domain_info *domain,
1055 : const char *name,
1056 : struct ldb_result **_res)
1057 : {
1058 : TALLOC_CTX *tmp_ctx;
1059 : struct ldb_result *res;
1060 : struct ldb_dn *user_dn;
1061 : struct ldb_request *req;
1062 : struct ldb_control **ctrl;
1063 : struct ldb_asq_control *control;
1064 : static const char *attrs[] = SYSDB_INITGR_ATTRS;
1065 : int ret;
1066 : size_t c;
1067 :
1068 9 : tmp_ctx = talloc_new(NULL);
1069 9 : if (!tmp_ctx) {
1070 0 : return ENOMEM;
1071 : }
1072 :
1073 9 : ret = sysdb_getpwnam_with_views(tmp_ctx, domain, name, &res);
1074 9 : if (ret != EOK) {
1075 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam failed: [%d][%s]\n",
1076 : ret, strerror(ret));
1077 0 : goto done;
1078 : }
1079 :
1080 9 : if (res->count == 0) {
1081 : /* User is not cached yet */
1082 3 : *_res = talloc_steal(mem_ctx, res);
1083 3 : ret = EOK;
1084 3 : goto done;
1085 :
1086 6 : } else if (res->count != 1) {
1087 0 : ret = EIO;
1088 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1089 : "sysdb_getpwnam returned count: [%d]\n", res->count);
1090 0 : goto done;
1091 : }
1092 :
1093 : /* no need to steal the dn, we are not freeing the result */
1094 6 : user_dn = res->msgs[0]->dn;
1095 :
1096 : /* note we count on the fact that the default search callback
1097 : * will just keep appending values. This is by design and can't
1098 : * change so it is ok to already have a result (from the getpwnam)
1099 : * even before we call the next search */
1100 :
1101 6 : ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2);
1102 6 : if (!ctrl) {
1103 0 : ret = ENOMEM;
1104 0 : goto done;
1105 : }
1106 6 : ctrl[1] = NULL;
1107 6 : ctrl[0] = talloc(ctrl, struct ldb_control);
1108 6 : if (!ctrl[0]) {
1109 0 : ret = ENOMEM;
1110 0 : goto done;
1111 : }
1112 6 : ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
1113 6 : ctrl[0]->critical = 1;
1114 6 : control = talloc(ctrl[0], struct ldb_asq_control);
1115 6 : if (!control) {
1116 0 : ret = ENOMEM;
1117 0 : goto done;
1118 : }
1119 6 : control->request = 1;
1120 6 : control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR);
1121 6 : if (!control->source_attribute) {
1122 0 : ret = ENOMEM;
1123 0 : goto done;
1124 : }
1125 6 : control->src_attr_len = strlen(control->source_attribute);
1126 6 : ctrl[0]->data = control;
1127 :
1128 6 : ret = ldb_build_search_req(&req, domain->sysdb->ldb, tmp_ctx,
1129 : user_dn, LDB_SCOPE_BASE,
1130 : SYSDB_INITGR_FILTER, attrs, ctrl,
1131 : res, ldb_search_default_callback,
1132 : NULL);
1133 6 : if (ret != LDB_SUCCESS) {
1134 0 : ret = sysdb_error_to_errno(ret);
1135 0 : goto done;
1136 : }
1137 :
1138 6 : ret = ldb_request(domain->sysdb->ldb, req);
1139 6 : if (ret == LDB_SUCCESS) {
1140 6 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1141 : }
1142 6 : if (ret != LDB_SUCCESS) {
1143 0 : ret = sysdb_error_to_errno(ret);
1144 0 : goto done;
1145 : }
1146 :
1147 6 : if (DOM_HAS_VIEWS(domain)) {
1148 : /* Skip user entry because it already has override values added */
1149 0 : for (c = 1; c < res->count; c++) {
1150 0 : ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
1151 : NULL);
1152 0 : if (ret != EOK) {
1153 0 : DEBUG(SSSDBG_OP_FAILURE,
1154 : "sysdb_add_overrides_to_object failed.\n");
1155 0 : goto done;
1156 : }
1157 : }
1158 : }
1159 :
1160 6 : *_res = talloc_steal(mem_ctx, res);
1161 :
1162 : done:
1163 9 : talloc_zfree(tmp_ctx);
1164 9 : return ret;
1165 : }
1166 :
1167 24 : int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
1168 : struct sss_domain_info *domain,
1169 : const char *name,
1170 : const char **attributes,
1171 : struct ldb_result **_res)
1172 : {
1173 : TALLOC_CTX *tmp_ctx;
1174 : struct ldb_dn *base_dn;
1175 : struct ldb_result *res;
1176 : const char *src_name;
1177 : char *sanitized_name;
1178 : char *lc_sanitized_name;
1179 : int ret;
1180 :
1181 24 : tmp_ctx = talloc_new(NULL);
1182 24 : if (!tmp_ctx) {
1183 0 : return ENOMEM;
1184 : }
1185 :
1186 24 : base_dn = sysdb_user_base_dn(tmp_ctx, domain);
1187 24 : if (!base_dn) {
1188 0 : ret = ENOMEM;
1189 0 : goto done;
1190 : }
1191 :
1192 : /* If this is a subdomain we need to use fully qualified names for the
1193 : * search as well by default */
1194 24 : src_name = sss_get_domain_name(tmp_ctx, name, domain);
1195 24 : if (!src_name) {
1196 0 : ret = ENOMEM;
1197 0 : goto done;
1198 : }
1199 :
1200 24 : ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain,
1201 : &sanitized_name, &lc_sanitized_name);
1202 24 : if (ret != EOK) {
1203 0 : goto done;
1204 : }
1205 :
1206 24 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
1207 : LDB_SCOPE_SUBTREE, attributes,
1208 : SYSDB_PWNAM_FILTER, lc_sanitized_name, sanitized_name,
1209 : sanitized_name);
1210 24 : if (ret) {
1211 0 : ret = sysdb_error_to_errno(ret);
1212 0 : goto done;
1213 : }
1214 :
1215 24 : *_res = talloc_steal(mem_ctx, res);
1216 :
1217 : done:
1218 24 : talloc_zfree(tmp_ctx);
1219 24 : return ret;
1220 : }
1221 :
1222 0 : int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
1223 : struct sss_domain_info *domain,
1224 : const char *name,
1225 : const char **attributes,
1226 : struct ldb_result **_res)
1227 : {
1228 : int ret;
1229 0 : struct ldb_result *orig_obj = NULL;
1230 0 : struct ldb_result *override_obj = NULL;
1231 0 : const char **attrs = NULL;
1232 0 : const char *mandatory_override_attrs[] = {SYSDB_OVERRIDE_DN,
1233 : SYSDB_OVERRIDE_OBJECT_DN,
1234 : NULL};
1235 : TALLOC_CTX *tmp_ctx;
1236 :
1237 0 : tmp_ctx = talloc_new(NULL);
1238 0 : if (tmp_ctx == NULL) {
1239 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1240 0 : return ENOMEM;
1241 : }
1242 :
1243 0 : attrs = attributes;
1244 :
1245 : /* If there are views we first have to search the overrides for matches */
1246 0 : if (DOM_HAS_VIEWS(domain)) {
1247 0 : ret = add_strings_lists(tmp_ctx, attributes, mandatory_override_attrs,
1248 : false, discard_const(&attrs));
1249 0 : if (ret != EOK) {
1250 0 : DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n");
1251 0 : goto done;
1252 : }
1253 :
1254 0 : ret = sysdb_search_user_override_attrs_by_name(tmp_ctx, domain, name,
1255 : attrs, &override_obj, &orig_obj);
1256 0 : if (ret != EOK && ret != ENOENT) {
1257 0 : DEBUG(SSSDBG_OP_FAILURE,
1258 : "sysdb_search_user_override_attrs_by_name failed.\n");
1259 0 : return ret;
1260 : }
1261 : }
1262 :
1263 : /* If there are no views or nothing was found in the overrides the
1264 : * original objects are searched. */
1265 0 : if (orig_obj == NULL) {
1266 0 : ret = sysdb_get_user_attr(tmp_ctx, domain, name, attrs, &orig_obj);
1267 0 : if (ret != EOK) {
1268 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_user_attr failed.\n");
1269 0 : return ret;
1270 : }
1271 : }
1272 :
1273 : /* If there are views we have to check if override values must be added to
1274 : * the original object. */
1275 0 : if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
1276 0 : ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
1277 0 : override_obj == NULL ? NULL : override_obj ->msgs[0],
1278 : attrs);
1279 0 : if (ret != EOK && ret != ENOENT) {
1280 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
1281 0 : return ret;
1282 : }
1283 :
1284 0 : if (ret == ENOENT) {
1285 0 : *_res = talloc_zero(mem_ctx, struct ldb_result);
1286 0 : if (*_res == NULL) {
1287 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
1288 0 : ret = ENOMEM;
1289 : } else {
1290 0 : ret = EOK;
1291 : }
1292 0 : goto done;
1293 : }
1294 : }
1295 :
1296 0 : *_res = talloc_steal(mem_ctx, orig_obj);
1297 0 : ret = EOK;
1298 :
1299 : done:
1300 0 : talloc_free(tmp_ctx);
1301 0 : return ret;
1302 : }
1303 :
1304 : /* This function splits a three-tuple into three strings
1305 : * It assumes that any whitespace between the parentheses
1306 : * and commas are intentional and does not attempt to
1307 : * strip them out. Leading and trailing whitespace is
1308 : * ignored.
1309 : *
1310 : * This behavior is compatible with nss_ldap's
1311 : * implementation.
1312 : */
1313 0 : static errno_t sysdb_netgr_split_triple(TALLOC_CTX *mem_ctx,
1314 : const char *triple,
1315 : char **hostname,
1316 : char **username,
1317 : char **domainname)
1318 : {
1319 : errno_t ret;
1320 : TALLOC_CTX *tmp_ctx;
1321 0 : const char *p = triple;
1322 : const char *p_host;
1323 : const char *p_user;
1324 : const char *p_domain;
1325 : size_t len;
1326 :
1327 0 : char *host = NULL;
1328 0 : char *user = NULL;
1329 0 : char *domain = NULL;
1330 :
1331 : /* Pre-set the values to NULL here so if they are not
1332 : * copied, we don't return garbage below.
1333 : */
1334 0 : *hostname = NULL;
1335 0 : *username = NULL;
1336 0 : *domainname = NULL;
1337 :
1338 0 : tmp_ctx = talloc_new(NULL);
1339 0 : if (!tmp_ctx) {
1340 0 : return ENOMEM;
1341 : }
1342 :
1343 : /* Remove any leading whitespace */
1344 0 : while (*p && isspace(*p)) p++;
1345 :
1346 0 : if (*p != '(') {
1347 : /* Triple must start and end with parentheses */
1348 0 : ret = EINVAL;
1349 0 : goto done;
1350 : }
1351 0 : p++;
1352 0 : p_host = p;
1353 :
1354 : /* Find the first comma */
1355 0 : while (*p && *p != ',') p++;
1356 :
1357 0 : if (!*p) {
1358 : /* No comma was found: parse error */
1359 0 : ret = EINVAL;
1360 0 : goto done;
1361 : }
1362 :
1363 0 : len = p - p_host;
1364 :
1365 0 : if (len > 0) {
1366 : /* Copy the host string */
1367 0 : host = talloc_strndup(tmp_ctx, p_host, len);
1368 0 : if (!host) {
1369 0 : ret = ENOMEM;
1370 0 : goto done;
1371 : }
1372 : }
1373 0 : p++;
1374 0 : p_user = p;
1375 :
1376 : /* Find the second comma */
1377 0 : while (*p && *p != ',') p++;
1378 :
1379 0 : if (!*p) {
1380 : /* No comma was found: parse error */
1381 0 : ret = EINVAL;
1382 0 : goto done;
1383 : }
1384 :
1385 0 : len = p - p_user;
1386 :
1387 0 : if (len > 0) {
1388 : /* Copy the user string */
1389 0 : user = talloc_strndup(tmp_ctx, p_user, len);
1390 0 : if (!user) {
1391 0 : ret = ENOMEM;
1392 0 : goto done;
1393 : }
1394 : }
1395 0 : p++;
1396 0 : p_domain = p;
1397 :
1398 : /* Find the closing parenthesis */
1399 0 : while (*p && *p != ')') p++;
1400 0 : if (*p != ')') {
1401 : /* No trailing parenthesis: parse error */
1402 0 : ret = EINVAL;
1403 0 : goto done;
1404 : }
1405 :
1406 0 : len = p - p_domain;
1407 :
1408 0 : if (len > 0) {
1409 : /* Copy the domain string */
1410 0 : domain = talloc_strndup(tmp_ctx, p_domain, len);
1411 0 : if (!domain) {
1412 0 : ret = ENOMEM;
1413 0 : goto done;
1414 : }
1415 : }
1416 0 : p++;
1417 :
1418 : /* skip trailing whitespace */
1419 0 : while (*p && isspace(*p)) p++;
1420 :
1421 0 : if (*p) {
1422 : /* Extra data after the closing parenthesis
1423 : * is a parse error
1424 : */
1425 0 : ret = EINVAL;
1426 0 : goto done;
1427 : }
1428 :
1429 : /* Return any non-NULL values */
1430 0 : if (host) {
1431 0 : *hostname = talloc_steal(mem_ctx, host);
1432 : }
1433 :
1434 0 : if (user) {
1435 0 : *username = talloc_steal(mem_ctx, user);
1436 : }
1437 :
1438 0 : if (domain) {
1439 0 : *domainname = talloc_steal(mem_ctx, domain);
1440 : }
1441 :
1442 0 : ret = EOK;
1443 :
1444 : done:
1445 0 : talloc_free(tmp_ctx);
1446 0 : return ret;
1447 : }
1448 :
1449 0 : errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx,
1450 : struct ldb_result *res,
1451 : struct sysdb_netgroup_ctx ***entries)
1452 : {
1453 : errno_t ret;
1454 0 : size_t size = 0;
1455 0 : size_t c = 0;
1456 : char *triple_str;
1457 : TALLOC_CTX *tmp_ctx;
1458 0 : struct sysdb_netgroup_ctx **tmp_entry = NULL;
1459 : struct ldb_message_element *el;
1460 : int i, j;
1461 :
1462 0 : if(!res || res->count == 0) {
1463 0 : return ENOENT;
1464 : }
1465 :
1466 0 : tmp_ctx = talloc_new(NULL);
1467 0 : if (!tmp_ctx) {
1468 0 : return ENOMEM;
1469 : }
1470 :
1471 0 : for (i=0; i < res->count; i++) {
1472 0 : el = ldb_msg_find_element(res->msgs[i], SYSDB_NETGROUP_TRIPLE);
1473 0 : if (el != NULL) {
1474 0 : size += el->num_values;
1475 : }
1476 0 : el = ldb_msg_find_element(res->msgs[i], SYSDB_NETGROUP_MEMBER);
1477 0 : if (el != NULL) {
1478 0 : size += el->num_values;
1479 : }
1480 : }
1481 :
1482 0 : tmp_entry = talloc_array(tmp_ctx, struct sysdb_netgroup_ctx *, size + 1);
1483 0 : if (tmp_entry == NULL) {
1484 0 : ret = ENOMEM;
1485 0 : goto done;
1486 : }
1487 :
1488 0 : if (size != 0) {
1489 0 : for (i=0; i < res->count; i++) {
1490 0 : el = ldb_msg_find_element(res->msgs[i], SYSDB_NETGROUP_TRIPLE);
1491 0 : if (el != NULL) {
1492 : /* Copy in all of the entries */
1493 0 : for(j = 0; j < el->num_values; j++) {
1494 0 : triple_str = talloc_strndup(tmp_ctx,
1495 0 : (const char *)el->values[j].data,
1496 0 : el->values[j].length);
1497 0 : if (!triple_str) {
1498 0 : ret = ENOMEM;
1499 0 : goto done;
1500 : }
1501 :
1502 0 : tmp_entry[c] = talloc_zero(tmp_entry,
1503 : struct sysdb_netgroup_ctx);
1504 0 : if (!tmp_entry[c]) {
1505 0 : ret = ENOMEM;
1506 0 : goto done;
1507 : }
1508 :
1509 0 : tmp_entry[c]->type = SYSDB_NETGROUP_TRIPLE_VAL;
1510 0 : ret = sysdb_netgr_split_triple(tmp_entry[c],
1511 : triple_str,
1512 0 : &tmp_entry[c]->value.triple.hostname,
1513 0 : &tmp_entry[c]->value.triple.username,
1514 0 : &tmp_entry[c]->value.triple.domainname);
1515 0 : if (ret != EOK) {
1516 0 : DEBUG(SSSDBG_IMPORTANT_INFO,
1517 : "Cannot split netgroup triple [%s], "
1518 : "this attribute will be skipped \n",
1519 : triple_str);
1520 0 : continue;
1521 : }
1522 :
1523 0 : c++;
1524 : }
1525 : }
1526 0 : el = ldb_msg_find_element(res->msgs[i], SYSDB_NETGROUP_MEMBER);
1527 0 : if (el != NULL) {
1528 0 : for(j = 0; j < el->num_values; j++) {
1529 0 : tmp_entry[c] = talloc_zero(tmp_entry,
1530 : struct sysdb_netgroup_ctx);
1531 0 : if (!tmp_entry[c]) {
1532 0 : ret = ENOMEM;
1533 0 : goto done;
1534 : }
1535 :
1536 0 : tmp_entry[c]->type = SYSDB_NETGROUP_GROUP_VAL;
1537 0 : tmp_entry[c]->value.groupname = talloc_strndup(tmp_entry[c],
1538 0 : (const char *)el->values[j].data,
1539 0 : el->values[j].length);
1540 0 : if (tmp_entry[c]->value.groupname == NULL) {
1541 0 : ret = ENOMEM;
1542 0 : goto done;
1543 : }
1544 :
1545 0 : c++;
1546 : }
1547 : }
1548 : }
1549 : }
1550 :
1551 : /* Add NULL terminator */
1552 0 : tmp_entry[c] = NULL;
1553 :
1554 0 : *entries = talloc_steal(mem_ctx, tmp_entry);
1555 0 : ret = EOK;
1556 :
1557 : done:
1558 0 : talloc_free(tmp_ctx);
1559 0 : return ret;
1560 : }
1561 :
1562 2 : errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx,
1563 : struct sss_domain_info *domain,
1564 : const char *netgroup,
1565 : struct ldb_result **res)
1566 : {
1567 : TALLOC_CTX *tmp_ctx;
1568 : static const char *attrs[] = SYSDB_NETGR_ATTRS;
1569 : struct ldb_dn *base_dn;
1570 2 : struct ldb_result *result = NULL;
1571 : char *sanitized_netgroup;
1572 : char *lc_sanitized_netgroup;
1573 : char *netgroup_dn;
1574 : errno_t ret;
1575 :
1576 2 : tmp_ctx = talloc_new(NULL);
1577 2 : if (!tmp_ctx) {
1578 0 : return ENOMEM;
1579 : }
1580 :
1581 2 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
1582 : SYSDB_TMPL_NETGROUP_BASE,
1583 : domain->name);
1584 2 : if (!base_dn) {
1585 0 : ret = ENOMEM;
1586 0 : goto done;
1587 : }
1588 :
1589 2 : ret = sss_filter_sanitize_for_dom(tmp_ctx, netgroup, domain,
1590 : &sanitized_netgroup,
1591 : &lc_sanitized_netgroup);
1592 2 : if (ret != EOK) {
1593 0 : goto done;
1594 : }
1595 :
1596 2 : netgroup_dn = talloc_asprintf(tmp_ctx, SYSDB_TMPL_NETGROUP,
1597 : sanitized_netgroup, domain->name);
1598 2 : if (!netgroup_dn) {
1599 0 : ret = ENOMEM;
1600 0 : goto done;
1601 : }
1602 :
1603 2 : SSS_LDB_SEARCH(ret, domain->sysdb->ldb, tmp_ctx, &result, base_dn,
1604 : LDB_SCOPE_SUBTREE, attrs,
1605 : SYSDB_NETGR_TRIPLES_FILTER, lc_sanitized_netgroup,
1606 : sanitized_netgroup, sanitized_netgroup,
1607 : netgroup_dn);
1608 :
1609 2 : if (ret == EOK || ret == ENOENT) {
1610 2 : *res = talloc_steal(mem_ctx, result);
1611 : }
1612 :
1613 : done:
1614 2 : talloc_zfree(tmp_ctx);
1615 2 : return ret;
1616 : }
1617 :
1618 11 : int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx,
1619 : struct sss_domain_info *domain,
1620 : const char *netgrname,
1621 : const char **attributes,
1622 : struct ldb_result **res)
1623 : {
1624 : TALLOC_CTX *tmp_ctx;
1625 : struct ldb_dn *base_dn;
1626 : struct ldb_result *result;
1627 : char *sanitized_netgroup;
1628 : char *lc_sanitized_netgroup;
1629 : int ret;
1630 :
1631 11 : tmp_ctx = talloc_new(NULL);
1632 11 : if (!tmp_ctx) {
1633 0 : return ENOMEM;
1634 : }
1635 :
1636 11 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
1637 : SYSDB_TMPL_NETGROUP_BASE, domain->name);
1638 11 : if (!base_dn) {
1639 0 : ret = ENOMEM;
1640 0 : goto done;
1641 : }
1642 :
1643 11 : ret = sss_filter_sanitize_for_dom(tmp_ctx, netgrname, domain,
1644 : &sanitized_netgroup,
1645 : &lc_sanitized_netgroup);
1646 11 : if (ret != EOK) {
1647 0 : goto done;
1648 : }
1649 :
1650 11 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &result, base_dn,
1651 : LDB_SCOPE_SUBTREE, attributes,
1652 : SYSDB_NETGR_FILTER,
1653 : lc_sanitized_netgroup,
1654 : sanitized_netgroup,
1655 : sanitized_netgroup);
1656 11 : if (ret) {
1657 0 : ret = sysdb_error_to_errno(ret);
1658 0 : goto done;
1659 : }
1660 :
1661 11 : *res = talloc_steal(mem_ctx, result);
1662 : done:
1663 11 : talloc_zfree(tmp_ctx);
1664 11 : return ret;
1665 : }
1666 :
1667 0 : errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
1668 : struct sss_domain_info *dom,
1669 : enum sysdb_member_type mtype,
1670 : const char *name,
1671 : char ***_direct_parents)
1672 : {
1673 : errno_t ret;
1674 : const char *dn;
1675 : char *sanitized_dn;
1676 : struct ldb_dn *basedn;
1677 : static const char *group_attrs[] = { SYSDB_NAME, NULL };
1678 : const char *member_filter;
1679 0 : size_t direct_sysdb_count = 0;
1680 0 : struct ldb_message **direct_sysdb_groups = NULL;
1681 0 : char **direct_parents = NULL;
1682 0 : TALLOC_CTX *tmp_ctx = NULL;
1683 : int i, pi;
1684 : const char *tmp_str;
1685 :
1686 0 : tmp_ctx = talloc_new(NULL);
1687 0 : if (!tmp_ctx) return ENOMEM;
1688 :
1689 0 : if (mtype == SYSDB_MEMBER_USER) {
1690 0 : dn = sysdb_user_strdn(tmp_ctx, dom->name, name);
1691 0 : } else if (mtype == SYSDB_MEMBER_GROUP) {
1692 0 : dn = sysdb_group_strdn(tmp_ctx, dom->name, name);
1693 : } else {
1694 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unknown member type\n");
1695 0 : ret = EINVAL;
1696 0 : goto done;
1697 : }
1698 :
1699 0 : if (!dn) {
1700 0 : ret = ENOMEM;
1701 0 : goto done;
1702 : }
1703 :
1704 0 : ret = sss_filter_sanitize(tmp_ctx, dn, &sanitized_dn);
1705 0 : if (ret != EOK) {
1706 0 : goto done;
1707 : }
1708 :
1709 0 : member_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(%s=%s))",
1710 : SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS,
1711 : SYSDB_MEMBER, sanitized_dn);
1712 0 : if (!member_filter) {
1713 0 : ret = ENOMEM;
1714 0 : goto done;
1715 : }
1716 :
1717 0 : basedn = sysdb_group_base_dn(tmp_ctx, dom);
1718 0 : if (!basedn) {
1719 0 : ret = ENOMEM;
1720 0 : goto done;
1721 : }
1722 :
1723 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1724 : "searching sysdb with filter [%s]\n", member_filter);
1725 :
1726 0 : ret = sysdb_search_entry(tmp_ctx, dom->sysdb, basedn,
1727 : LDB_SCOPE_SUBTREE, member_filter, group_attrs,
1728 : &direct_sysdb_count, &direct_sysdb_groups);
1729 0 : if (ret == ENOENT) {
1730 0 : direct_sysdb_count = 0;
1731 0 : } else if (ret != EOK) {
1732 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed: [%d]: %s\n",
1733 : ret, strerror(ret));
1734 0 : goto done;
1735 : }
1736 :
1737 : /* EOK */
1738 : /* Get the list of sysdb groups by name */
1739 0 : direct_parents = talloc_array(tmp_ctx, char *, direct_sysdb_count+1);
1740 0 : if (!direct_parents) {
1741 0 : ret = ENOMEM;
1742 0 : goto done;
1743 : }
1744 :
1745 0 : pi = 0;
1746 0 : for(i = 0; i < direct_sysdb_count; i++) {
1747 0 : tmp_str = ldb_msg_find_attr_as_string(direct_sysdb_groups[i],
1748 : SYSDB_NAME, NULL);
1749 0 : if (!tmp_str) {
1750 : /* This should never happen, but if it does, just continue */
1751 0 : continue;
1752 : }
1753 :
1754 0 : direct_parents[pi] = talloc_strdup(direct_parents, tmp_str);
1755 0 : if (!direct_parents[pi]) {
1756 0 : DEBUG(SSSDBG_CRIT_FAILURE, "A group with no name?\n");
1757 0 : ret = EIO;
1758 0 : goto done;
1759 : }
1760 0 : pi++;
1761 : }
1762 0 : direct_parents[pi] = NULL;
1763 :
1764 0 : DEBUG(SSSDBG_TRACE_LIBS, "%s is a member of %zu sysdb groups\n",
1765 : name, direct_sysdb_count);
1766 0 : *_direct_parents = talloc_steal(mem_ctx, direct_parents);
1767 0 : ret = EOK;
1768 : done:
1769 0 : talloc_free(tmp_ctx);
1770 0 : return ret;
1771 : }
1772 :
1773 5 : errno_t sysdb_get_real_name(TALLOC_CTX *mem_ctx,
1774 : struct sss_domain_info *domain,
1775 : const char *name_or_upn_or_sid,
1776 : const char **_cname)
1777 : {
1778 : errno_t ret;
1779 : TALLOC_CTX *tmp_ctx;
1780 : struct ldb_result *res;
1781 : const char *cname;
1782 : struct ldb_message *msg;
1783 :
1784 5 : tmp_ctx = talloc_new(NULL);
1785 5 : if (!tmp_ctx) {
1786 0 : return ENOMEM;
1787 : }
1788 :
1789 5 : ret = sysdb_getpwnam(tmp_ctx, domain, name_or_upn_or_sid, &res);
1790 5 : if (ret != EOK) {
1791 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot canonicalize username\n");
1792 0 : goto done;
1793 : }
1794 :
1795 5 : if (res->count == 0) {
1796 4 : ret = sysdb_search_user_by_upn(tmp_ctx, domain, name_or_upn_or_sid,
1797 : NULL, &msg);
1798 4 : if (ret == ENOENT) {
1799 3 : ret = sysdb_search_user_by_sid_str(tmp_ctx, domain,
1800 : name_or_upn_or_sid, NULL, &msg);
1801 3 : if (ret == ENOENT) {
1802 2 : ret = sysdb_search_object_by_uuid(tmp_ctx, domain,
1803 : name_or_upn_or_sid, NULL,
1804 : &res);
1805 2 : if (ret == EOK && res->count == 1) {
1806 1 : msg = res->msgs[0];
1807 1 : } else if (ret != ENOENT) {
1808 0 : DEBUG(SSSDBG_OP_FAILURE,
1809 : "sysdb_search_object_by_uuid failed or returned "
1810 : "more than one result [%d][%s].\n",
1811 : ret, sss_strerror(ret));
1812 0 : ret = ENOENT;
1813 0 : goto done;
1814 : }
1815 : }
1816 : }
1817 4 : if (ret != EOK) {
1818 : /* User cannot be found in cache */
1819 1 : DEBUG(SSSDBG_OP_FAILURE, "Cannot find user [%s] in cache\n",
1820 : name_or_upn_or_sid);
1821 1 : goto done;
1822 : }
1823 1 : } else if (res->count == 1) {
1824 1 : msg = res->msgs[0];
1825 : } else {
1826 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1827 : "sysdb_getpwnam returned count: [%d]\n", res->count);
1828 0 : ret = EIO;
1829 0 : goto done;
1830 : }
1831 :
1832 4 : cname = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1833 4 : if (!cname) {
1834 0 : DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
1835 0 : ret = ENOENT;
1836 0 : goto done;
1837 : }
1838 :
1839 4 : ret = EOK;
1840 4 : *_cname = talloc_steal(mem_ctx, cname);
1841 : done:
1842 5 : talloc_free(tmp_ctx);
1843 5 : return ret;
1844 : }
|