Line data Source code
1 : /*
2 : SSSD
3 :
4 : System Database - View and Override related calls
5 :
6 : Copyright (C) 2014 Sumit Bose <sbose@redhat.com>
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 :
25 : /* In general is should not be possible that there is a view container without
26 : * a view name set. But to be on the safe side we return both information
27 : * separately. */
28 23 : static errno_t sysdb_get_view_name_ex(TALLOC_CTX *mem_ctx,
29 : struct sysdb_ctx *sysdb,
30 : char **_view_name,
31 : bool *view_container_exists)
32 : {
33 : errno_t ret;
34 : TALLOC_CTX *tmp_ctx;
35 : const char *tmp_str;
36 : struct ldb_dn *view_base_dn;
37 : struct ldb_result *res;
38 23 : const char *attrs[] = {SYSDB_VIEW_NAME,
39 : NULL};
40 :
41 23 : tmp_ctx = talloc_new(NULL);
42 23 : if (tmp_ctx == NULL) {
43 0 : return ENOMEM;
44 : }
45 :
46 23 : view_base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_BASE);
47 23 : if (view_base_dn == NULL) {
48 0 : ret = EIO;
49 0 : goto done;
50 : }
51 23 : ret = ldb_search(sysdb->ldb, tmp_ctx, &res, view_base_dn, LDB_SCOPE_BASE,
52 : attrs, NULL);
53 23 : if (ret != LDB_SUCCESS) {
54 0 : ret = EIO;
55 0 : goto done;
56 : }
57 :
58 23 : if (res->count > 1) {
59 0 : DEBUG(SSSDBG_OP_FAILURE, "Base search returned [%d] results, "
60 : "expected 1.\n", res->count);
61 0 : ret = EINVAL;
62 0 : goto done;
63 : }
64 :
65 23 : if (res->count == 0) {
66 22 : *view_container_exists = false;
67 22 : ret = ENOENT;
68 22 : goto done;
69 : } else {
70 1 : *view_container_exists = true;
71 1 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_VIEW_NAME,
72 : NULL);
73 1 : if (tmp_str == NULL) {
74 0 : ret = ENOENT;
75 0 : goto done;
76 : }
77 : }
78 :
79 1 : *_view_name = talloc_steal(mem_ctx, discard_const(tmp_str));
80 1 : ret = EOK;
81 :
82 : done:
83 23 : talloc_free(tmp_ctx);
84 23 : return ret;
85 : }
86 :
87 21 : errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
88 : char **view_name)
89 : {
90 : bool view_container_exists;
91 :
92 21 : return sysdb_get_view_name_ex(mem_ctx, sysdb, view_name,
93 : &view_container_exists);
94 : }
95 :
96 2 : errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb,
97 : const char *view_name)
98 : {
99 : errno_t ret;
100 : TALLOC_CTX *tmp_ctx;
101 : char *tmp_str;
102 2 : bool view_container_exists = false;
103 2 : bool add_view_name = false;
104 : struct ldb_message *msg;
105 :
106 2 : tmp_ctx = talloc_new(NULL);
107 2 : if (tmp_ctx == NULL) {
108 0 : return ENOMEM;
109 : }
110 :
111 2 : ret = sysdb_get_view_name_ex(tmp_ctx, sysdb, &tmp_str,
112 : &view_container_exists);
113 2 : if (ret != EOK && ret != ENOENT) {
114 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name_ex failed.\n");
115 0 : goto done;
116 : }
117 :
118 2 : if (ret == EOK) {
119 1 : if (strcmp(tmp_str, view_name) == 0) {
120 : /* view name already known, nothing to do */
121 1 : DEBUG(SSSDBG_TRACE_ALL, "View name already in place.\n");
122 1 : ret = EOK;
123 1 : goto done;
124 : } else {
125 : /* view name changed */
126 0 : DEBUG(SSSDBG_CONF_SETTINGS,
127 : "View name changed from [%s] to [%s].\n", tmp_str, view_name);
128 : }
129 : } else {
130 1 : add_view_name = true;
131 : }
132 :
133 1 : msg = ldb_msg_new(tmp_ctx);
134 1 : if (msg == NULL) {
135 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
136 0 : ret = ENOMEM;
137 0 : goto done;
138 : }
139 :
140 1 : msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_BASE);
141 1 : if (msg->dn == NULL) {
142 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
143 0 : ret = EIO;
144 0 : goto done;
145 : }
146 :
147 1 : ret = ldb_msg_add_empty(msg, SYSDB_VIEW_NAME,
148 : add_view_name ? LDB_FLAG_MOD_ADD
149 : : LDB_FLAG_MOD_REPLACE,
150 : NULL);
151 1 : if (ret != LDB_SUCCESS) {
152 0 : ret = sysdb_error_to_errno(ret);
153 0 : goto done;
154 : }
155 :
156 1 : ret = ldb_msg_add_string(msg, SYSDB_VIEW_NAME, view_name);
157 1 : if (ret != LDB_SUCCESS) {
158 0 : ret = sysdb_error_to_errno(ret);
159 0 : goto done;
160 : }
161 :
162 1 : if (view_container_exists) {
163 0 : ret = ldb_modify(sysdb->ldb, msg);
164 : } else {
165 1 : ret = ldb_add(sysdb->ldb, msg);
166 : }
167 1 : if (ret != LDB_SUCCESS) {
168 0 : DEBUG(SSSDBG_FATAL_FAILURE,
169 : "Failed to %s view container [%s](%d)[%s]\n",
170 : view_container_exists ? "modify" : "add",
171 : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
172 0 : ret = sysdb_error_to_errno(ret);
173 0 : goto done;
174 : }
175 :
176 : done:
177 2 : talloc_free(tmp_ctx);
178 2 : return ret;
179 : }
180 :
181 2 : errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name)
182 : {
183 : struct ldb_dn *dn;
184 : TALLOC_CTX *tmp_ctx;
185 : int ret;
186 :
187 2 : tmp_ctx = talloc_new(NULL);
188 2 : if (tmp_ctx == NULL) {
189 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
190 0 : return ENOMEM;
191 : }
192 :
193 2 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_SEARCH_BASE,
194 : view_name);
195 2 : if (dn == NULL) {
196 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
197 0 : ret = EIO;
198 0 : goto done;
199 : }
200 :
201 2 : ret = sysdb_delete_recursive(sysdb, dn, true);
202 2 : if (ret != EOK) {
203 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
204 0 : goto done;
205 : }
206 :
207 2 : ret = EOK;
208 :
209 : done:
210 2 : talloc_free(tmp_ctx);
211 :
212 2 : return ret;
213 : }
214 :
215 2 : errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb)
216 : {
217 : int ret;
218 : int sret;
219 : TALLOC_CTX *tmp_ctx;
220 2 : bool in_transaction = false;
221 : struct ldb_result *res;
222 : size_t c;
223 : struct ldb_message *msg;
224 : struct ldb_dn *base_dn;
225 :
226 2 : tmp_ctx = talloc_new(NULL);
227 2 : if (tmp_ctx == NULL) {
228 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
229 0 : return ENOMEM;
230 : }
231 :
232 2 : msg = ldb_msg_new(tmp_ctx);
233 2 : if (msg == NULL) {
234 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
235 0 : ret = ENOMEM;
236 0 : goto done;
237 : }
238 :
239 2 : base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
240 2 : if (base_dn == NULL) {
241 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed\n");
242 0 : ret = ENOMEM;
243 0 : goto done;
244 : }
245 :
246 2 : ret = ldb_msg_add_empty(msg, SYSDB_CACHE_EXPIRE, LDB_FLAG_MOD_REPLACE,
247 : NULL);
248 2 : if (ret != LDB_SUCCESS) {
249 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
250 0 : ret = sysdb_error_to_errno(ret);
251 0 : goto done;
252 : }
253 2 : ret = ldb_msg_add_string(msg, SYSDB_CACHE_EXPIRE, "1");
254 2 : if (ret != LDB_SUCCESS) {
255 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
256 0 : ret = sysdb_error_to_errno(ret);
257 0 : goto done;
258 : }
259 :
260 2 : ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
261 2 : if (ret != LDB_SUCCESS) {
262 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
263 0 : ret = sysdb_error_to_errno(ret);
264 0 : goto done;
265 : }
266 :
267 2 : ret = sysdb_transaction_start(sysdb);
268 2 : if (ret != EOK) {
269 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
270 0 : goto done;
271 : }
272 2 : in_transaction = true;
273 :
274 2 : ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
275 : NULL, "%s", SYSDB_UC);
276 2 : if (ret != LDB_SUCCESS) {
277 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
278 0 : ret = sysdb_error_to_errno(ret);
279 0 : goto done;
280 : }
281 :
282 4 : for (c = 0; c < res->count; c++) {
283 2 : msg->dn = res->msgs[c]->dn;
284 :
285 2 : ret = ldb_modify(sysdb->ldb, msg);
286 2 : if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
287 0 : DEBUG(SSSDBG_OP_FAILURE,
288 : "ldb_modify failed: [%s](%d)[%s]\n",
289 : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
290 0 : ret = sysdb_error_to_errno(ret);
291 0 : goto done;
292 : }
293 : }
294 :
295 2 : talloc_free(res);
296 :
297 2 : ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
298 : NULL, "%s", SYSDB_GC);
299 2 : if (ret != LDB_SUCCESS) {
300 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
301 0 : ret = sysdb_error_to_errno(ret);
302 0 : goto done;
303 : }
304 :
305 2 : for (c = 0; c < res->count; c++) {
306 0 : msg->dn = res->msgs[c]->dn;
307 :
308 0 : ret = ldb_modify(sysdb->ldb, msg);
309 0 : if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
310 0 : DEBUG(SSSDBG_OP_FAILURE,
311 : "ldb_modify failed: [%s](%d)[%s]\n",
312 : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
313 0 : ret = sysdb_error_to_errno(ret);
314 0 : goto done;
315 : }
316 : }
317 :
318 2 : ret = EOK;
319 :
320 : done:
321 2 : if (in_transaction) {
322 2 : if (ret == EOK) {
323 2 : sret = sysdb_transaction_commit(sysdb);
324 2 : if (sret != EOK) {
325 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed, " \
326 : "nothing we can do about.\n");
327 0 : ret = sret;
328 : }
329 : } else {
330 0 : sret = sysdb_transaction_cancel(sysdb);
331 0 : if (sret != EOK) {
332 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed, " \
333 : "nothing we can do about.\n");
334 : }
335 : }
336 : }
337 :
338 2 : talloc_free(tmp_ctx);
339 :
340 2 : return ret;
341 : }
342 :
343 : static errno_t
344 0 : add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
345 : struct sysdb_attrs *attrs,
346 : bool add_name,
347 : const char *name_override)
348 : {
349 0 : char *fq_name = NULL;
350 : int ret;
351 :
352 0 : if (strchr(name_override, '@') == NULL) {
353 0 : fq_name = sss_tc_fqname(attrs, domain->names, domain, name_override);
354 0 : if (fq_name == NULL) {
355 0 : DEBUG(SSSDBG_OP_FAILURE, "sss_tc_fqname failed.\n");
356 0 : return ENOMEM;
357 : }
358 :
359 0 : if (!domain->case_sensitive) {
360 0 : ret = sysdb_attrs_add_lc_name_alias(attrs, fq_name);
361 : } else {
362 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS,
363 : fq_name);
364 : }
365 0 : if (ret != EOK) {
366 0 : DEBUG(SSSDBG_OP_FAILURE,
367 : "sysdb_attrs_add_lc_name_alias failed.\n");
368 0 : goto done;
369 : }
370 : }
371 :
372 0 : if (add_name) {
373 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_DEFAULT_OVERRIDE_NAME,
374 : fq_name == NULL ? name_override : fq_name);
375 0 : if (ret != EOK) {
376 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n");
377 0 : goto done;
378 : }
379 : }
380 :
381 0 : if (!domain->case_sensitive) {
382 0 : ret = sysdb_attrs_add_lc_name_alias(attrs, name_override);
383 : } else {
384 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, name_override);
385 : }
386 0 : if (ret != EOK) {
387 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n");
388 0 : goto done;
389 : }
390 :
391 0 : ret = EOK;
392 :
393 : done:
394 0 : talloc_free(fq_name);
395 0 : return ret;
396 : }
397 :
398 29 : errno_t sysdb_store_override(struct sss_domain_info *domain,
399 : const char *view_name,
400 : enum sysdb_member_type type,
401 : struct sysdb_attrs *attrs, struct ldb_dn *obj_dn)
402 : {
403 : TALLOC_CTX *tmp_ctx;
404 : const char *anchor;
405 : int ret;
406 : struct ldb_dn *override_dn;
407 : const char *override_dn_str;
408 : const char *obj_dn_str;
409 29 : const char *obj_attrs[] = { SYSDB_OBJECTCLASS,
410 : SYSDB_OVERRIDE_DN,
411 : NULL};
412 29 : size_t count = 0;
413 : struct ldb_message **msgs;
414 29 : struct ldb_message *msg = NULL;
415 : const char *obj_override_dn;
416 29 : bool add_ref = true;
417 : size_t c;
418 29 : bool in_transaction = false;
419 29 : bool has_override = true;
420 : const char *name_override;
421 :
422 29 : tmp_ctx = talloc_new(NULL);
423 29 : if (tmp_ctx == NULL) {
424 0 : ret = ENOMEM;
425 0 : goto done;
426 : }
427 :
428 29 : if (attrs != NULL) {
429 28 : has_override = true;
430 28 : ret = sysdb_attrs_get_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
431 : &anchor);
432 28 : if (ret != EOK) {
433 1 : DEBUG(SSSDBG_CRIT_FAILURE,
434 : "Missing anchor in override attributes.\n");
435 1 : ret = EINVAL;
436 1 : goto done;
437 : }
438 :
439 27 : override_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
440 : SYSDB_TMPL_OVERRIDE, anchor, view_name);
441 27 : if (override_dn == NULL) {
442 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
443 0 : ret = ENOMEM;
444 0 : goto done;
445 : }
446 : } else {
447 : /* if there is no override for the given object, just store the DN of
448 : * the object iself in the SYSDB_OVERRIDE_DN attribute to indicate
449 : * that it was checked if an override exists and none was found. */
450 1 : has_override = false;
451 1 : override_dn = obj_dn;
452 : }
453 :
454 28 : override_dn_str = ldb_dn_get_linearized(override_dn);
455 28 : obj_dn_str = ldb_dn_get_linearized(obj_dn);
456 28 : if (override_dn_str == NULL || obj_dn_str == NULL) {
457 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
458 0 : ret = ENOMEM;
459 0 : goto done;
460 : }
461 :
462 28 : ret = sysdb_search_entry(tmp_ctx, domain->sysdb, obj_dn, LDB_SCOPE_BASE,
463 : NULL, obj_attrs, &count, &msgs);
464 28 : if (ret != EOK) {
465 0 : if (ret == ENOENT) {
466 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Object to override does not exists.\n");
467 : } else {
468 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
469 : }
470 0 : goto done;
471 : }
472 28 : if (count != 1) {
473 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Base searched returned more than one object.\n");
474 0 : ret = EINVAL;
475 0 : goto done;
476 : }
477 :
478 28 : obj_override_dn = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OVERRIDE_DN,
479 : NULL);
480 28 : if (obj_override_dn != NULL) {
481 2 : if (strcmp(obj_override_dn, override_dn_str) != 0) {
482 0 : DEBUG(SSSDBG_CRIT_FAILURE,
483 : "Existing [%s] and new [%s] override DN do not match.\n",
484 : obj_override_dn, override_dn_str);
485 0 : ret = EINVAL;
486 0 : goto done;
487 : }
488 :
489 2 : add_ref = false;
490 : }
491 :
492 28 : ret = ldb_transaction_start(domain->sysdb->ldb);
493 28 : if (ret != EOK) {
494 0 : return sysdb_error_to_errno(ret);
495 : }
496 28 : in_transaction = true;
497 :
498 28 : if (has_override) {
499 27 : ret = ldb_delete(domain->sysdb->ldb, override_dn);
500 27 : if (ret != EOK) {
501 8 : DEBUG(SSSDBG_TRACE_ALL,
502 : "ldb_delete failed, maybe object did not exist. Ignoring.\n");
503 : }
504 :
505 27 : ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name_override);
506 27 : if (ret == EOK) {
507 0 : ret = add_name_and_aliases_for_name_override(domain, attrs, false,
508 : name_override);
509 0 : if (ret != EOK) {
510 0 : DEBUG(SSSDBG_OP_FAILURE,
511 : "add_name_and_aliases_for_name_override failed.\n");
512 0 : goto done;
513 : }
514 27 : } else if (ret != ENOENT) {
515 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
516 0 : goto done;
517 : }
518 :
519 27 : msg = ldb_msg_new(tmp_ctx);
520 27 : if (msg == NULL) {
521 0 : ret = ENOMEM;
522 0 : goto done;
523 : }
524 :
525 27 : msg->dn = override_dn;
526 :
527 27 : msg->elements = talloc_array(msg, struct ldb_message_element,
528 : attrs->num);
529 27 : if (msg->elements == NULL) {
530 0 : ret = ENOMEM;
531 0 : goto done;
532 : }
533 :
534 78 : for (c = 0; c < attrs->num; c++) {
535 : /* Set num_values to 1 because by default user and group overrides
536 : * use the same attribute name for the GID and this cause SSSD
537 : * machinery to add the same value twice */
538 51 : if (attrs->a[c].num_values > 1
539 0 : && strcmp(attrs->a[c].name, SYSDB_GIDNUM) == 0) {
540 0 : attrs->a[c].num_values = 1;
541 : }
542 51 : msg->elements[c] = attrs->a[c];
543 51 : msg->elements[c].flags = LDB_FLAG_MOD_ADD;
544 : }
545 27 : msg->num_elements = attrs->num;
546 :
547 27 : ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL);
548 27 : if (ret != LDB_SUCCESS) {
549 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
550 0 : ret = sysdb_error_to_errno(ret);
551 0 : goto done;
552 : }
553 :
554 27 : switch(type) {
555 : case SYSDB_MEMBER_USER:
556 15 : ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS,
557 : SYSDB_OVERRIDE_USER_CLASS);
558 15 : break;
559 : case SYSDB_MEMBER_GROUP:
560 12 : ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS,
561 : SYSDB_OVERRIDE_GROUP_CLASS);
562 12 : break;
563 : default:
564 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object type.\n");
565 0 : ret = EINVAL;
566 0 : goto done;
567 : }
568 27 : if (ret != LDB_SUCCESS) {
569 0 : ret = sysdb_error_to_errno(ret);
570 0 : goto done;
571 : }
572 :
573 27 : ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_OBJECT_DN, LDB_FLAG_MOD_ADD,
574 : NULL);
575 27 : if (ret != LDB_SUCCESS) {
576 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
577 0 : ret = sysdb_error_to_errno(ret);
578 0 : goto done;
579 : }
580 :
581 27 : ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_OBJECT_DN, obj_dn_str);
582 27 : if (ret != LDB_SUCCESS) {
583 0 : ret = sysdb_error_to_errno(ret);
584 0 : goto done;
585 : }
586 :
587 27 : ret = ldb_add(domain->sysdb->ldb, msg);
588 27 : if (ret != LDB_SUCCESS) {
589 0 : DEBUG(SSSDBG_CRIT_FAILURE,
590 : "Failed to store override entry: %s(%d)[%s]\n",
591 : ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb));
592 0 : ret = sysdb_error_to_errno(ret);
593 0 : goto done;
594 : }
595 : }
596 :
597 28 : if (add_ref) {
598 26 : talloc_free(msg);
599 26 : msg = ldb_msg_new(tmp_ctx);
600 26 : if (msg == NULL) {
601 0 : ret = ENOMEM;
602 0 : goto done;
603 : }
604 :
605 26 : msg->dn = obj_dn;
606 :
607 26 : ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_ADD,
608 : NULL);
609 26 : if (ret != LDB_SUCCESS) {
610 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
611 0 : ret = sysdb_error_to_errno(ret);
612 0 : goto done;
613 : }
614 :
615 26 : ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_DN, override_dn_str);
616 26 : if (ret != LDB_SUCCESS) {
617 0 : ret = sysdb_error_to_errno(ret);
618 0 : goto done;
619 : }
620 :
621 26 : ret = ldb_modify(domain->sysdb->ldb, msg);
622 26 : if (ret != LDB_SUCCESS) {
623 0 : DEBUG(SSSDBG_CRIT_FAILURE,
624 : "Failed to store override DN: %s(%d)[%s]\n",
625 : ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb));
626 0 : ret = sysdb_error_to_errno(ret);
627 0 : goto done;
628 : }
629 : }
630 :
631 28 : ret = EOK;
632 :
633 : done:
634 29 : if (in_transaction) {
635 28 : if (ret != EOK) {
636 0 : DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret));
637 0 : ldb_transaction_cancel(domain->sysdb->ldb);
638 : } else {
639 28 : ret = ldb_transaction_commit(domain->sysdb->ldb);
640 28 : ret = sysdb_error_to_errno(ret);
641 : }
642 : }
643 :
644 29 : talloc_zfree(tmp_ctx);
645 29 : return ret;
646 : }
647 :
648 0 : static errno_t safe_original_attributes(struct sss_domain_info *domain,
649 : struct sysdb_attrs *attrs,
650 : struct ldb_dn *obj_dn,
651 : const char **allowed_attrs)
652 : {
653 : int ret;
654 : size_t c;
655 : TALLOC_CTX *tmp_ctx;
656 : struct ldb_result *orig_obj;
657 : char *orig_attr_name;
658 0 : struct ldb_message_element *el = NULL;
659 :
660 0 : tmp_ctx = talloc_new(NULL);
661 0 : if (tmp_ctx == NULL) {
662 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
663 0 : return ENOMEM;
664 : }
665 :
666 0 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_obj, obj_dn,
667 : LDB_SCOPE_BASE, NULL, NULL);
668 0 : if (ret != EOK || orig_obj->count != 1) {
669 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Original object not found.\n");
670 0 : goto done;
671 : }
672 :
673 : /* Safe orginal values in attributes prefixed by OriginalAD. */
674 0 : for (c = 0; allowed_attrs[c] != NULL; c++) {
675 0 : el = ldb_msg_find_element(orig_obj->msgs[0], allowed_attrs[c]);
676 0 : if (el != NULL) {
677 0 : orig_attr_name = talloc_asprintf(tmp_ctx, "%s%s",
678 : ORIGINALAD_PREFIX,
679 0 : allowed_attrs[c]);
680 0 : if (orig_attr_name == NULL) {
681 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
682 0 : ret = ENOMEM;
683 0 : goto done;
684 : }
685 :
686 0 : ret = sysdb_attrs_add_val(attrs, orig_attr_name,
687 0 : &el->values[0]);
688 0 : if (ret != EOK) {
689 0 : DEBUG(SSSDBG_OP_FAILURE,
690 : "sysdb_attrs_add_val failed.\n");
691 0 : goto done;
692 : }
693 : } else {
694 0 : DEBUG(SSSDBG_TRACE_ALL,
695 : "Original object does not have [%s] set.\n",
696 : allowed_attrs[c]);
697 : }
698 : }
699 :
700 : /* Add existing aliases to new ones */
701 0 : el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_NAME_ALIAS);
702 0 : if (el != NULL) {
703 0 : for (c = 0; c < el->num_values; c++) {
704 : /* To avoid issue with ldb_modify if e.g. the orginal and the
705 : * override name are the same, we use the *_safe version here. */
706 0 : ret = sysdb_attrs_add_val_safe(attrs, SYSDB_NAME_ALIAS,
707 0 : &el->values[c]);
708 0 : if (ret != EOK) {
709 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n");
710 0 : goto done;
711 : }
712 : }
713 : }
714 :
715 0 : ret = EOK;
716 : done:
717 0 : talloc_free(tmp_ctx);
718 0 : return ret;
719 : }
720 :
721 0 : errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
722 : struct sysdb_attrs *override_attrs,
723 : struct ldb_dn *obj_dn)
724 : {
725 : int ret;
726 : TALLOC_CTX *tmp_ctx;
727 : struct sysdb_attrs *attrs;
728 : size_t c;
729 : size_t d;
730 : size_t num_values;
731 0 : struct ldb_message_element *el = NULL;
732 0 : const char *allowed_attrs[] = { SYSDB_UIDNUM,
733 : SYSDB_GIDNUM,
734 : SYSDB_GECOS,
735 : SYSDB_HOMEDIR,
736 : SYSDB_SHELL,
737 : SYSDB_NAME,
738 : SYSDB_SSH_PUBKEY,
739 : NULL };
740 0 : bool override_attrs_found = false;
741 :
742 0 : if (override_attrs == NULL) {
743 : /* nothing to do */
744 0 : return EOK;
745 : }
746 :
747 0 : tmp_ctx = talloc_new(NULL);
748 0 : if (tmp_ctx == NULL) {
749 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
750 0 : return ENOMEM;
751 : }
752 :
753 0 : attrs = sysdb_new_attrs(tmp_ctx);
754 0 : if (attrs == NULL) {
755 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
756 0 : ret = ENOMEM;
757 0 : goto done;
758 : }
759 :
760 0 : for (c = 0; allowed_attrs[c] != NULL; c++) {
761 0 : ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false,
762 : &el);
763 0 : if (ret == EOK) {
764 0 : override_attrs_found = true;
765 :
766 0 : if (strcmp(allowed_attrs[c], SYSDB_NAME) == 0) {
767 0 : if (el->values[0].data[el->values[0].length] != '\0') {
768 0 : DEBUG(SSSDBG_CRIT_FAILURE,
769 : "String attribute does not end with \\0.\n");
770 0 : ret = EINVAL;
771 0 : goto done;
772 : }
773 :
774 0 : ret = add_name_and_aliases_for_name_override(domain, attrs,
775 : true,
776 0 : (char *) el->values[0].data);
777 0 : if (ret != EOK) {
778 0 : DEBUG(SSSDBG_OP_FAILURE,
779 : "add_name_and_aliases_for_name_override failed.\n");
780 0 : goto done;
781 : }
782 : } else {
783 0 : num_values = el->num_values;
784 : /* Only SYSDB_SSH_PUBKEY is allowed to have multiple values. */
785 0 : if (strcmp(allowed_attrs[c], SYSDB_SSH_PUBKEY) != 0
786 0 : && num_values != 1) {
787 0 : DEBUG(SSSDBG_MINOR_FAILURE,
788 : "Override attribute for [%s] has more [%zd] " \
789 : "than one value, using only the first.\n",
790 : allowed_attrs[c], num_values);
791 0 : num_values = 1;
792 : }
793 :
794 0 : for (d = 0; d < num_values; d++) {
795 0 : ret = sysdb_attrs_add_val(attrs, allowed_attrs[c],
796 0 : &el->values[d]);
797 0 : if (ret != EOK) {
798 0 : DEBUG(SSSDBG_OP_FAILURE,
799 : "sysdb_attrs_add_val failed.\n");
800 0 : goto done;
801 : }
802 0 : DEBUG(SSSDBG_TRACE_ALL,
803 : "Override [%s] with [%.*s] for [%s].\n",
804 : allowed_attrs[c], (int) el->values[d].length,
805 : el->values[d].data, ldb_dn_get_linearized(obj_dn));
806 : }
807 : }
808 0 : } else if (ret != ENOENT) {
809 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el_ext failed.\n");
810 0 : goto done;
811 : }
812 : }
813 :
814 0 : if (override_attrs_found) {
815 0 : ret = safe_original_attributes(domain, attrs, obj_dn, allowed_attrs);
816 0 : if (ret != EOK) {
817 0 : DEBUG(SSSDBG_OP_FAILURE, "safe_original_attributes failed.\n");
818 0 : goto done;
819 : }
820 :
821 0 : ret = sysdb_set_entry_attr(domain->sysdb, obj_dn, attrs, SYSDB_MOD_REP);
822 0 : if (ret != EOK) {
823 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
824 0 : goto done;
825 : }
826 : }
827 :
828 0 : ret = EOK;
829 :
830 : done:
831 0 : talloc_free(tmp_ctx);
832 0 : return ret;
833 : }
834 :
835 :
836 : #define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
837 : #define SYSDB_USER_UID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")("SYSDB_UIDNUM"=%lu))"
838 : #define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
839 : #define SYSDB_GROUP_GID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))"
840 :
841 : enum override_object_type {
842 : OO_TYPE_UNDEF = 0,
843 : OO_TYPE_USER,
844 : OO_TYPE_GROUP
845 : };
846 :
847 0 : static errno_t sysdb_search_override_by_name(TALLOC_CTX *mem_ctx,
848 : struct sss_domain_info *domain,
849 : const char *name,
850 : const char *filter,
851 : const char **attrs,
852 : struct ldb_result **override_obj,
853 : struct ldb_result **orig_obj)
854 : {
855 : TALLOC_CTX *tmp_ctx;
856 : struct ldb_dn *base_dn;
857 : struct ldb_result *override_res;
858 : struct ldb_result *orig_res;
859 : char *sanitized_name;
860 : char *lc_sanitized_name;
861 : const char *src_name;
862 : int ret;
863 : const char *orig_obj_dn;
864 :
865 0 : tmp_ctx = talloc_new(NULL);
866 0 : if (!tmp_ctx) {
867 0 : return ENOMEM;
868 : }
869 :
870 0 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
871 : SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
872 0 : if (base_dn == NULL) {
873 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
874 0 : ret = ENOMEM;
875 0 : goto done;
876 : }
877 :
878 : /* If this is a subdomain we need to use fully qualified names for the
879 : * search as well by default */
880 0 : src_name = sss_get_domain_name(tmp_ctx, name, domain);
881 0 : if (src_name == NULL) {
882 0 : DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_name failed.\n");
883 0 : ret = ENOMEM;
884 0 : goto done;
885 : }
886 :
887 0 : ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain,
888 : &sanitized_name, &lc_sanitized_name);
889 0 : if (ret != EOK) {
890 0 : DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize_for_dom failed.\n");
891 0 : goto done;
892 : }
893 :
894 0 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
895 : LDB_SCOPE_SUBTREE, attrs, filter,
896 : lc_sanitized_name,
897 : sanitized_name, sanitized_name);
898 0 : if (ret != LDB_SUCCESS) {
899 0 : ret = sysdb_error_to_errno(ret);
900 0 : goto done;
901 : }
902 :
903 0 : if (override_res->count == 0) {
904 0 : DEBUG(SSSDBG_TRACE_FUNC, "No user override found for name [%s].\n",
905 : name);
906 0 : ret = ENOENT;
907 0 : goto done;
908 0 : } else if (override_res->count > 1) {
909 0 : DEBUG(SSSDBG_CRIT_FAILURE,
910 : "Found more than one override for name [%s].\n", name);
911 0 : ret = EINVAL;
912 0 : goto done;
913 : }
914 :
915 0 : if (orig_obj != NULL) {
916 0 : orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
917 : SYSDB_OVERRIDE_OBJECT_DN,
918 : NULL);
919 0 : if (orig_obj_dn == NULL) {
920 0 : DEBUG(SSSDBG_CRIT_FAILURE,
921 : "Missing link to original object in override [%s].\n",
922 : ldb_dn_get_linearized(override_res->msgs[0]->dn));
923 0 : ret = EINVAL;
924 0 : goto done;
925 : }
926 :
927 0 : base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
928 0 : if (base_dn == NULL) {
929 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
930 0 : ret = ENOMEM;
931 0 : goto done;
932 : }
933 :
934 0 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
935 : LDB_SCOPE_BASE, attrs, NULL);
936 0 : if (ret != LDB_SUCCESS) {
937 0 : ret = sysdb_error_to_errno(ret);
938 0 : goto done;
939 : }
940 :
941 0 : *orig_obj = talloc_steal(mem_ctx, orig_res);
942 : }
943 :
944 :
945 0 : *override_obj = talloc_steal(mem_ctx, override_res);
946 :
947 0 : ret = EOK;
948 :
949 : done:
950 0 : talloc_zfree(tmp_ctx);
951 0 : return ret;
952 : }
953 :
954 0 : errno_t sysdb_search_user_override_attrs_by_name(TALLOC_CTX *mem_ctx,
955 : struct sss_domain_info *domain,
956 : const char *name,
957 : const char **attrs,
958 : struct ldb_result **override_obj,
959 : struct ldb_result **orig_obj)
960 : {
961 :
962 0 : return sysdb_search_override_by_name(mem_ctx, domain, name,
963 : SYSDB_USER_NAME_OVERRIDE_FILTER,
964 : attrs, override_obj, orig_obj);
965 : }
966 :
967 0 : errno_t sysdb_search_group_override_attrs_by_name(TALLOC_CTX *mem_ctx,
968 : struct sss_domain_info *domain,
969 : const char *name,
970 : const char **attrs,
971 : struct ldb_result **override_obj,
972 : struct ldb_result **orig_obj)
973 : {
974 0 : return sysdb_search_override_by_name(mem_ctx, domain, name,
975 : SYSDB_GROUP_NAME_OVERRIDE_FILTER,
976 : attrs, override_obj, orig_obj);
977 : }
978 :
979 0 : errno_t sysdb_search_user_override_by_name(TALLOC_CTX *mem_ctx,
980 : struct sss_domain_info *domain,
981 : const char *name,
982 : struct ldb_result **override_obj,
983 : struct ldb_result **orig_obj)
984 : {
985 0 : const char *attrs[] = SYSDB_PW_ATTRS;
986 :
987 0 : return sysdb_search_override_by_name(mem_ctx, domain, name,
988 : SYSDB_USER_NAME_OVERRIDE_FILTER,
989 : attrs, override_obj, orig_obj);
990 : }
991 :
992 0 : errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
993 : struct sss_domain_info *domain,
994 : const char *name,
995 : struct ldb_result **override_obj,
996 : struct ldb_result **orig_obj)
997 : {
998 0 : const char *attrs[] = SYSDB_GRSRC_ATTRS;
999 :
1000 0 : return sysdb_search_override_by_name(mem_ctx, domain, name,
1001 : SYSDB_GROUP_NAME_OVERRIDE_FILTER,
1002 : attrs, override_obj, orig_obj);
1003 : }
1004 :
1005 0 : static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx,
1006 : struct sss_domain_info *domain,
1007 : unsigned long int id,
1008 : enum override_object_type type,
1009 : struct ldb_result **override_obj,
1010 : struct ldb_result **orig_obj)
1011 : {
1012 : TALLOC_CTX *tmp_ctx;
1013 : static const char *user_attrs[] = SYSDB_PW_ATTRS;
1014 : static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
1015 : const char **attrs;
1016 : struct ldb_dn *base_dn;
1017 : struct ldb_result *override_res;
1018 : struct ldb_result *orig_res;
1019 : int ret;
1020 : const char *orig_obj_dn;
1021 : const char *filter;
1022 :
1023 0 : tmp_ctx = talloc_new(NULL);
1024 0 : if (!tmp_ctx) {
1025 0 : return ENOMEM;
1026 : }
1027 :
1028 0 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
1029 : SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
1030 0 : if (base_dn == NULL) {
1031 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
1032 0 : ret = ENOMEM;
1033 0 : goto done;
1034 : }
1035 :
1036 0 : switch(type) {
1037 : case OO_TYPE_USER:
1038 0 : filter = SYSDB_USER_UID_OVERRIDE_FILTER;
1039 0 : attrs = user_attrs;
1040 0 : break;
1041 : case OO_TYPE_GROUP:
1042 0 : filter = SYSDB_GROUP_GID_OVERRIDE_FILTER;
1043 0 : attrs = group_attrs;
1044 0 : break;
1045 : default:
1046 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected override object type [%d].\n",
1047 : type);
1048 0 : ret = EINVAL;
1049 0 : goto done;
1050 : }
1051 :
1052 0 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
1053 : LDB_SCOPE_SUBTREE, attrs, filter, id);
1054 0 : if (ret != LDB_SUCCESS) {
1055 0 : ret = sysdb_error_to_errno(ret);
1056 0 : goto done;
1057 : }
1058 :
1059 0 : if (override_res->count == 0) {
1060 0 : DEBUG(SSSDBG_TRACE_FUNC,
1061 : "No user override found for %s with id [%lu].\n",
1062 : (type == OO_TYPE_USER ? "user" : "group"), id);
1063 0 : ret = ENOENT;
1064 0 : goto done;
1065 0 : } else if (override_res->count > 1) {
1066 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1067 : "Found more than one override for id [%lu].\n", id);
1068 0 : ret = EINVAL;
1069 0 : goto done;
1070 : }
1071 :
1072 0 : if (orig_obj != NULL) {
1073 0 : orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
1074 : SYSDB_OVERRIDE_OBJECT_DN,
1075 : NULL);
1076 0 : if (orig_obj_dn == NULL) {
1077 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1078 : "Missing link to original object in override [%s].\n",
1079 : ldb_dn_get_linearized(override_res->msgs[0]->dn));
1080 0 : ret = EINVAL;
1081 0 : goto done;
1082 : }
1083 :
1084 0 : base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
1085 0 : if (base_dn == NULL) {
1086 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
1087 0 : ret = ENOMEM;
1088 0 : goto done;
1089 : }
1090 :
1091 0 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
1092 : LDB_SCOPE_BASE, attrs, NULL);
1093 0 : if (ret != LDB_SUCCESS) {
1094 0 : ret = sysdb_error_to_errno(ret);
1095 0 : goto done;
1096 : }
1097 :
1098 0 : *orig_obj = talloc_steal(mem_ctx, orig_res);
1099 : }
1100 :
1101 :
1102 0 : *override_obj = talloc_steal(mem_ctx, override_res);
1103 :
1104 0 : ret = EOK;
1105 :
1106 : done:
1107 0 : talloc_zfree(tmp_ctx);
1108 0 : return ret;
1109 : }
1110 :
1111 0 : errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx,
1112 : struct sss_domain_info *domain,
1113 : uid_t uid,
1114 : struct ldb_result **override_obj,
1115 : struct ldb_result **orig_obj)
1116 : {
1117 0 : return sysdb_search_override_by_id(mem_ctx, domain, uid, OO_TYPE_USER,
1118 : override_obj, orig_obj);
1119 : }
1120 :
1121 0 : errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
1122 : struct sss_domain_info *domain,
1123 : gid_t gid,
1124 : struct ldb_result **override_obj,
1125 : struct ldb_result **orig_obj)
1126 : {
1127 0 : return sysdb_search_override_by_id(mem_ctx, domain, gid, OO_TYPE_GROUP,
1128 : override_obj, orig_obj);
1129 : }
1130 :
1131 : /**
1132 : * @brief Add override data to the original object
1133 : *
1134 : * @param[in] domain Domain struct, needed to access the cache
1135 : * @oaram[in] obj The original object
1136 : * @param[in] override_obj The object with the override data, may be NULL
1137 : * @param[in] req_attrs List of attributes to be requested, if not set a
1138 : * default list dependig on the object type will be used
1139 : *
1140 : * @return EOK - Override data was added successfully
1141 : * @return ENOMEM - There was insufficient memory to complete the operation
1142 : * @return ENOENT - The original object did not have the SYSDB_OVERRIDE_DN
1143 : * attribute or the value of the attribute points an object
1144 : * which does not exists. Both conditions indicate that the
1145 : * cache must be refreshed.
1146 : */
1147 23 : errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
1148 : struct ldb_message *obj,
1149 : struct ldb_message *override_obj,
1150 : const char **req_attrs)
1151 : {
1152 : int ret;
1153 : const char *override_dn_str;
1154 : struct ldb_dn *override_dn;
1155 : TALLOC_CTX *tmp_ctx;
1156 : struct ldb_result *res;
1157 : struct ldb_message *override;
1158 : uint64_t uid;
1159 : static const char *user_attrs[] = SYSDB_PW_ATTRS;
1160 : static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
1161 : const char **attrs;
1162 : struct attr_map {
1163 : const char *attr;
1164 : const char *new_attr;
1165 23 : } attr_map[] = {
1166 : {SYSDB_UIDNUM, OVERRIDE_PREFIX SYSDB_UIDNUM},
1167 : {SYSDB_GIDNUM, OVERRIDE_PREFIX SYSDB_GIDNUM},
1168 : {SYSDB_GECOS, OVERRIDE_PREFIX SYSDB_GECOS},
1169 : {SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR},
1170 : {SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL},
1171 : {SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME},
1172 : {SYSDB_SSH_PUBKEY, OVERRIDE_PREFIX SYSDB_SSH_PUBKEY},
1173 : {NULL, NULL}
1174 : };
1175 : size_t c;
1176 : size_t d;
1177 : struct ldb_message_element *tmp_el;
1178 :
1179 23 : tmp_ctx = talloc_new(NULL);
1180 23 : if (tmp_ctx == NULL) {
1181 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1182 0 : return ENOMEM;
1183 : }
1184 :
1185 23 : if (override_obj == NULL) {
1186 22 : override_dn_str = ldb_msg_find_attr_as_string(obj,
1187 : SYSDB_OVERRIDE_DN, NULL);
1188 22 : if (override_dn_str == NULL) {
1189 2 : if (is_local_view(domain->view_name)) {
1190 : /* LOCAL view doesn't have to have overrideDN specified. */
1191 1 : ret = EOK;
1192 1 : goto done;
1193 : }
1194 :
1195 1 : DEBUG(SSSDBG_CRIT_FAILURE,
1196 : "Missing override DN for object [%s].\n",
1197 : ldb_dn_get_linearized(obj->dn));
1198 :
1199 1 : ret = ENOENT;
1200 1 : goto done;
1201 : }
1202 :
1203 20 : override_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, override_dn_str);
1204 20 : if (override_dn == NULL) {
1205 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
1206 0 : ret = ENOMEM;
1207 0 : goto done;
1208 : }
1209 :
1210 20 : if (ldb_dn_compare(obj->dn, override_dn) == 0) {
1211 0 : DEBUG(SSSDBG_TRACE_ALL, "Object [%s] has no overrides.\n",
1212 : ldb_dn_get_linearized(obj->dn));
1213 0 : ret = EOK;
1214 0 : goto done;
1215 : }
1216 :
1217 20 : attrs = req_attrs;
1218 20 : if (attrs == NULL) {
1219 20 : uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0);
1220 20 : if (uid == 0) {
1221 : /* No UID hence group object */
1222 10 : attrs = group_attrs;
1223 : } else {
1224 10 : attrs = user_attrs;
1225 : }
1226 : }
1227 :
1228 20 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, override_dn,
1229 : LDB_SCOPE_BASE, attrs, NULL);
1230 20 : if (ret != LDB_SUCCESS) {
1231 0 : ret = sysdb_error_to_errno(ret);
1232 0 : goto done;
1233 : }
1234 :
1235 20 : if (res->count == 1) {
1236 20 : override = res->msgs[0];
1237 0 : } else if (res->count == 0) {
1238 0 : DEBUG(SSSDBG_TRACE_FUNC, "Override object [%s] does not exists.\n",
1239 : override_dn_str);
1240 0 : ret = ENOENT;
1241 0 : goto done;
1242 : } else {
1243 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1244 : "Base search for override object returned [%d] results.\n",
1245 : res->count);
1246 0 : ret = EINVAL;
1247 0 : goto done;
1248 : }
1249 : } else {
1250 1 : override = override_obj;
1251 : }
1252 :
1253 168 : for (c = 0; attr_map[c].attr != NULL; c++) {
1254 147 : tmp_el = ldb_msg_find_element(override, attr_map[c].attr);
1255 147 : if (tmp_el != NULL) {
1256 47 : for (d = 0; d < tmp_el->num_values; d++) {
1257 24 : ret = ldb_msg_add_steal_value(obj, attr_map[c].new_attr,
1258 24 : &tmp_el->values[d]);
1259 24 : if (ret != LDB_SUCCESS) {
1260 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_value failed.\n");
1261 0 : ret = sysdb_error_to_errno(ret);
1262 0 : goto done;
1263 : }
1264 : }
1265 : }
1266 : }
1267 :
1268 21 : ret = EOK;
1269 : done:
1270 23 : talloc_free(tmp_ctx);
1271 :
1272 23 : return ret;
1273 : }
1274 :
1275 10 : errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
1276 : struct ldb_message *obj)
1277 : {
1278 : int ret;
1279 : size_t c;
1280 : struct ldb_message_element *members;
1281 : TALLOC_CTX *tmp_ctx;
1282 : struct ldb_dn *member_dn;
1283 : struct ldb_result *member_obj;
1284 : struct ldb_result *override_obj;
1285 : static const char *member_attrs[] = SYSDB_PW_ATTRS;
1286 : const char *override_dn_str;
1287 : struct ldb_dn *override_dn;
1288 : const char *memberuid;
1289 : const char *orig_name;
1290 : char *orig_domain;
1291 : char *val;
1292 : struct sss_domain_info *orig_dom;
1293 :
1294 10 : members = ldb_msg_find_element(obj, SYSDB_MEMBER);
1295 10 : if (members == NULL || members->num_values == 0) {
1296 10 : DEBUG(SSSDBG_TRACE_ALL, "Group has no members.\n");
1297 10 : return EOK;
1298 : }
1299 :
1300 0 : tmp_ctx = talloc_new(NULL);
1301 0 : if (tmp_ctx == NULL) {
1302 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1303 0 : ret = ENOMEM;
1304 0 : goto done;
1305 : }
1306 :
1307 0 : for (c = 0; c < members->num_values; c++) {
1308 0 : member_dn = ldb_dn_from_ldb_val(tmp_ctx, domain->sysdb->ldb,
1309 0 : &members->values[c]);
1310 0 : if (member_dn == NULL) {
1311 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_from_ldb_val failed.\n");
1312 0 : ret = ENOMEM;
1313 0 : goto done;
1314 : }
1315 :
1316 0 : ret = ldb_search(domain->sysdb->ldb, member_dn, &member_obj, member_dn,
1317 : LDB_SCOPE_BASE, member_attrs, NULL);
1318 0 : if (ret != LDB_SUCCESS) {
1319 0 : ret = sysdb_error_to_errno(ret);
1320 0 : goto done;
1321 : }
1322 :
1323 0 : if (member_obj->count != 1) {
1324 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1325 : "Base search for member object returned [%d] results.\n",
1326 : member_obj->count);
1327 0 : ret = EINVAL;
1328 0 : goto done;
1329 : }
1330 :
1331 0 : if (ldb_msg_find_attr_as_uint64(member_obj->msgs[0],
1332 : SYSDB_UIDNUM, 0) == 0) {
1333 : /* Skip non-POSIX-user members i.e. groups and non-POSIX users */
1334 0 : continue;
1335 : }
1336 :
1337 0 : override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0],
1338 : SYSDB_OVERRIDE_DN, NULL);
1339 0 : if (override_dn_str == NULL) {
1340 0 : if (is_local_view(domain->view_name)) {
1341 : /* LOCAL view doesn't have to have overrideDN specified. */
1342 0 : ret = EOK;
1343 0 : goto done;
1344 : }
1345 :
1346 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1347 : "Missing override DN for object [%s].\n",
1348 : ldb_dn_get_linearized(member_obj->msgs[0]->dn));
1349 0 : ret = ENOENT;
1350 0 : goto done;
1351 : }
1352 :
1353 0 : override_dn = ldb_dn_new(member_obj, domain->sysdb->ldb,
1354 : override_dn_str);
1355 0 : if (override_dn == NULL) {
1356 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
1357 0 : ret = ENOMEM;
1358 0 : goto done;
1359 : }
1360 :
1361 0 : orig_name = ldb_msg_find_attr_as_string(member_obj->msgs[0],
1362 : SYSDB_NAME,
1363 : NULL);
1364 0 : if (orig_name == NULL) {
1365 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
1366 : ldb_dn_get_linearized(member_obj->msgs[0]->dn));
1367 0 : ret = EINVAL;
1368 0 : goto done;
1369 : }
1370 :
1371 0 : memberuid = NULL;
1372 0 : if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) {
1373 0 : DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n",
1374 : ldb_dn_get_linearized(member_obj->msgs[0]->dn));
1375 :
1376 0 : ret = ldb_search(domain->sysdb->ldb, member_obj, &override_obj,
1377 : override_dn, LDB_SCOPE_BASE, member_attrs, NULL);
1378 0 : if (ret != LDB_SUCCESS) {
1379 0 : ret = sysdb_error_to_errno(ret);
1380 0 : goto done;
1381 : }
1382 :
1383 0 : if (override_obj->count != 1) {
1384 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1385 : "Base search for override object returned [%d] results.\n",
1386 : member_obj->count);
1387 0 : ret = EINVAL;
1388 0 : goto done;
1389 : }
1390 :
1391 0 : memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0],
1392 : SYSDB_NAME,
1393 : NULL);
1394 :
1395 0 : if (memberuid != NULL) {
1396 0 : ret = sss_parse_name(tmp_ctx, domain->names, orig_name,
1397 : &orig_domain, NULL);
1398 0 : if (ret != EOK) {
1399 0 : DEBUG(SSSDBG_OP_FAILURE,
1400 : "sss_parse_name failed to split original name [%s].\n",
1401 : orig_name);
1402 0 : goto done;
1403 : }
1404 :
1405 0 : if (orig_domain != NULL) {
1406 0 : orig_dom = find_domain_by_name(get_domains_head(domain),
1407 : orig_domain, true);
1408 0 : if (orig_dom == NULL) {
1409 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1410 : "Cannot find domain with name [%s].\n",
1411 : orig_domain);
1412 0 : ret = EINVAL;
1413 0 : goto done;
1414 : }
1415 0 : memberuid = sss_get_domain_name(tmp_ctx, memberuid,
1416 : orig_dom);
1417 0 : if (memberuid == NULL) {
1418 0 : DEBUG(SSSDBG_OP_FAILURE,
1419 : "sss_get_domain_name failed.\n");
1420 0 : ret = ENOMEM;
1421 0 : goto done;
1422 : }
1423 : }
1424 : }
1425 : }
1426 :
1427 0 : if (memberuid == NULL) {
1428 0 : DEBUG(SSSDBG_TRACE_ALL, "No override name available.\n");
1429 :
1430 0 : memberuid = orig_name;
1431 : }
1432 :
1433 0 : val = talloc_strdup(obj, memberuid);
1434 0 : if (val == NULL) {
1435 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
1436 0 : ret = ENOMEM;
1437 0 : goto done;
1438 : }
1439 :
1440 0 : ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID, val);
1441 0 : if (ret != LDB_SUCCESS) {
1442 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
1443 0 : ret = sysdb_error_to_errno(ret);
1444 0 : goto done;
1445 : }
1446 0 : DEBUG(SSSDBG_TRACE_ALL, "Added [%s] to [%s].\n", memberuid,
1447 : OVERRIDE_PREFIX SYSDB_MEMBERUID);
1448 :
1449 : /* Free all temporary data of the current member to avoid memory usage
1450 : * spikes. All temporary data should be allocated below member_dn. */
1451 0 : talloc_free(member_dn);
1452 : }
1453 :
1454 0 : ret = EOK;
1455 :
1456 : done:
1457 0 : talloc_free(tmp_ctx);
1458 :
1459 0 : return ret;
1460 : }
1461 :
1462 : struct ldb_message_element *
1463 9 : sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
1464 : const struct ldb_message *msg,
1465 : const char *attr_name)
1466 : {
1467 9 : TALLOC_CTX *tmp_ctx = NULL;
1468 : struct ldb_message_element *val;
1469 : char *override_attr_name;
1470 :
1471 9 : if (DOM_HAS_VIEWS(dom)) {
1472 0 : tmp_ctx = talloc_new(NULL);
1473 0 : if (tmp_ctx == NULL) {
1474 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1475 0 : val = NULL;
1476 0 : goto done;
1477 : }
1478 :
1479 0 : override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
1480 : attr_name);
1481 0 : if (override_attr_name == NULL) {
1482 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
1483 0 : val = NULL;
1484 0 : goto done;
1485 : }
1486 :
1487 0 : val = ldb_msg_find_element(msg, override_attr_name);
1488 0 : if (val != NULL) {
1489 0 : goto done;
1490 : }
1491 : }
1492 :
1493 9 : val = ldb_msg_find_element(msg, attr_name);
1494 :
1495 : done:
1496 9 : talloc_free(tmp_ctx);
1497 9 : return val;
1498 : }
1499 :
1500 36 : uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
1501 : const struct ldb_message *msg,
1502 : const char *attr_name,
1503 : uint64_t default_value)
1504 : {
1505 36 : TALLOC_CTX *tmp_ctx = NULL;
1506 : uint64_t val;
1507 : char *override_attr_name;
1508 :
1509 36 : if (DOM_HAS_VIEWS(dom)) {
1510 0 : tmp_ctx = talloc_new(NULL);
1511 0 : if (tmp_ctx == NULL) {
1512 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1513 0 : val = default_value;
1514 0 : goto done;
1515 : }
1516 :
1517 0 : override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
1518 : attr_name);
1519 0 : if (override_attr_name == NULL) {
1520 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
1521 0 : val = default_value;
1522 0 : goto done;
1523 : }
1524 :
1525 0 : if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
1526 0 : val = ldb_msg_find_attr_as_uint64(msg, override_attr_name,
1527 : default_value);
1528 0 : goto done;
1529 : }
1530 : }
1531 :
1532 36 : val = ldb_msg_find_attr_as_uint64(msg, attr_name, default_value);
1533 :
1534 : done:
1535 36 : talloc_free(tmp_ctx);
1536 36 : return val;
1537 : }
1538 :
1539 36 : const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
1540 : const struct ldb_message *msg,
1541 : const char *attr_name,
1542 : const char * default_value)
1543 : {
1544 36 : TALLOC_CTX *tmp_ctx = NULL;
1545 : const char *val;
1546 : char *override_attr_name;
1547 :
1548 36 : if (DOM_HAS_VIEWS(dom)) {
1549 0 : tmp_ctx = talloc_new(NULL);
1550 0 : if (tmp_ctx == NULL) {
1551 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
1552 0 : val = default_value;
1553 0 : goto done;
1554 : }
1555 :
1556 0 : override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
1557 : attr_name);
1558 0 : if (override_attr_name == NULL) {
1559 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
1560 0 : val = default_value;
1561 0 : goto done;
1562 : }
1563 :
1564 0 : if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
1565 0 : val = ldb_msg_find_attr_as_string(msg, override_attr_name,
1566 : default_value);
1567 0 : goto done;
1568 : }
1569 : }
1570 :
1571 36 : val = ldb_msg_find_attr_as_string(msg, attr_name, default_value);
1572 :
1573 : done:
1574 36 : talloc_free(tmp_ctx);
1575 36 : return val;
1576 : }
|