Branch data Line data Source code
1 : : /*
2 : : SSSD
3 : :
4 : : System Database
5 : :
6 : : Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com>
7 : : Copyright (C) 2008-2011 Stephen Gallagher <ssorce@redhat.com>
8 : :
9 : : This program is free software; you can redistribute it and/or modify
10 : : it under the terms of the GNU General Public License as published by
11 : : the Free Software Foundation; either version 3 of the License, or
12 : : (at your option) any later version.
13 : :
14 : : This program is distributed in the hope that it will be useful,
15 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : : GNU General Public License for more details.
18 : :
19 : : You should have received a copy of the GNU General Public License
20 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : : */
22 : :
23 : : #include "util/util.h"
24 : : #include "util/strtonum.h"
25 : : #include "util/sss_utf8.h"
26 : : #include "db/sysdb_private.h"
27 : : #include "confdb/confdb.h"
28 : : #include <time.h>
29 : :
30 : : #define LDB_MODULES_PATH "LDB_MODULES_PATH"
31 : :
32 : 646 : errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename,
33 : : struct ldb_context **_ldb)
34 : : {
35 : : int ret;
36 : : struct ldb_context *ldb;
37 : : const char *mod_path;
38 : :
39 [ + - ]: 646 : if (_ldb == NULL) {
40 : : return EINVAL;
41 : : }
42 : :
43 : 646 : ldb = ldb_init(mem_ctx, NULL);
44 [ + - ]: 646 : if (!ldb) {
45 : : return EIO;
46 : : }
47 : :
48 : 646 : ret = ldb_set_debug(ldb, ldb_debug_messages, NULL);
49 [ + - ]: 646 : if (ret != LDB_SUCCESS) {
50 : : return EIO;
51 : : }
52 : :
53 : 646 : mod_path = getenv(LDB_MODULES_PATH);
54 [ + - ]: 646 : if (mod_path != NULL) {
55 [ + - ][ + - ]: 646 : DEBUG(9, ("Setting ldb module path to [%s].\n", mod_path));
[ - + ][ # # ]
[ # # ]
56 : 646 : ldb_set_modules_dir(ldb, mod_path);
57 : : }
58 : :
59 : 646 : ret = ldb_connect(ldb, filename, 0, NULL);
60 [ + - ]: 646 : if (ret != LDB_SUCCESS) {
61 : : return EIO;
62 : : }
63 : :
64 : 646 : *_ldb = ldb;
65 : :
66 : 646 : return EOK;
67 : : }
68 : :
69 : 1158 : errno_t sysdb_dn_sanitize(TALLOC_CTX *mem_ctx, const char *input,
70 : : char **sanitized)
71 : : {
72 : : struct ldb_val val;
73 : 1158 : errno_t ret = EOK;
74 : :
75 : 1158 : val.data = (uint8_t *)talloc_strdup(mem_ctx, input);
76 [ + - ]: 1158 : if (!val.data) {
77 : : return ENOMEM;
78 : : }
79 : :
80 : : /* We can't include the trailing NULL because it would
81 : : * be escaped and result in an unterminated string
82 : : */
83 : 1158 : val.length = strlen(input);
84 : :
85 : 1158 : *sanitized = ldb_dn_escape_value(mem_ctx, val);
86 [ - + ]: 1158 : if (!*sanitized) {
87 : 0 : ret = ENOMEM;
88 : : }
89 : :
90 : 1158 : talloc_free(val.data);
91 : : return ret;
92 : : }
93 : :
94 : 24 : struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *sysdb,
95 : : TALLOC_CTX *mem_ctx,
96 : : const char *subtree_name)
97 : : {
98 : : errno_t ret;
99 : : char *clean_subtree;
100 : 24 : struct ldb_dn *dn = NULL;
101 : : TALLOC_CTX *tmp_ctx;
102 : :
103 : 24 : tmp_ctx = talloc_new(NULL);
104 [ + - ]: 24 : if (!tmp_ctx) return NULL;
105 : :
106 : 24 : ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
107 [ - + ]: 24 : if (ret != EOK) {
108 : 0 : talloc_free(tmp_ctx);
109 : : return NULL;
110 : : }
111 : :
112 : 24 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
113 : 24 : clean_subtree, sysdb->domain->name);
114 [ + - ]: 24 : if (dn) {
115 : 24 : talloc_steal(mem_ctx, dn);
116 : : }
117 : 24 : talloc_free(tmp_ctx);
118 : :
119 : : return dn;
120 : : }
121 : :
122 : 71 : struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
123 : : const char *object_name,
124 : : const char *subtree_name)
125 : : {
126 : : errno_t ret;
127 : : TALLOC_CTX *tmp_ctx;
128 : : char *clean_name;
129 : : char *clean_subtree;
130 : 71 : struct ldb_dn *dn = NULL;
131 : :
132 : 71 : tmp_ctx = talloc_new(NULL);
133 [ + - ]: 71 : if (!tmp_ctx) {
134 : : return NULL;
135 : : }
136 : :
137 : 71 : ret = sysdb_dn_sanitize(tmp_ctx, object_name, &clean_name);
138 [ + - ]: 71 : if (ret != EOK) {
139 : : goto done;
140 : : }
141 : :
142 : 71 : ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
143 [ + - ]: 71 : if (ret != EOK) {
144 : : goto done;
145 : : }
146 : :
147 : 71 : dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM, clean_name,
148 : 71 : clean_subtree, sysdb->domain->name);
149 : :
150 : : done:
151 : 71 : talloc_free(tmp_ctx);
152 : : return dn;
153 : : }
154 : :
155 : 348 : struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
156 : : const char *name)
157 : : {
158 : : errno_t ret;
159 : : char *clean_name;
160 : : struct ldb_dn *dn;
161 : :
162 : 348 : ret = sysdb_dn_sanitize(NULL, name, &clean_name);
163 [ + - ]: 348 : if (ret != EOK) {
164 : : return NULL;
165 : : }
166 : :
167 : 348 : dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_USER,
168 : 348 : clean_name, sysdb->domain->name);
169 : 348 : talloc_free(clean_name);
170 : :
171 : : return dn;
172 : : }
173 : :
174 : 328 : struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
175 : : const char *name)
176 : : {
177 : : errno_t ret;
178 : : char *clean_name;
179 : : struct ldb_dn *dn;
180 : :
181 : 328 : ret = sysdb_dn_sanitize(NULL, name, &clean_name);
182 [ + - ]: 328 : if (ret != EOK) {
183 : : return NULL;
184 : : }
185 : :
186 : 328 : dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_GROUP,
187 : 328 : clean_name, sysdb->domain->name);
188 : 328 : talloc_free(clean_name);
189 : :
190 : : return dn;
191 : : }
192 : :
193 : 90 : struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
194 : : const char *name)
195 : : {
196 : : errno_t ret;
197 : : char *clean_name;
198 : : struct ldb_dn *dn;
199 : :
200 : 90 : ret = sysdb_dn_sanitize(NULL, name, &clean_name);
201 [ + - ]: 90 : if (ret != EOK) {
202 : : return NULL;
203 : : }
204 : :
205 : 90 : dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_NETGROUP,
206 : 90 : clean_name, sysdb->domain->name);
207 : 90 : talloc_free(clean_name);
208 : :
209 : : return dn;
210 : : }
211 : :
212 : 0 : struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx)
213 : : {
214 : 0 : return ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_NETGROUP_BASE,
215 : 0 : sysdb->domain->name);
216 : : }
217 : :
218 : 10 : errno_t sysdb_get_rdn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
219 : : const char *_dn, char **_name, char **_val)
220 : : {
221 : : errno_t ret;
222 : : struct ldb_dn *dn;
223 : 10 : const char *attr_name = NULL;
224 : : const struct ldb_val *val;
225 : : TALLOC_CTX *tmp_ctx;
226 : :
227 : : /* We have to create a tmp_ctx here because
228 : : * ldb_dn_new_fmt() fails if mem_ctx is NULL
229 : : */
230 : 10 : tmp_ctx = talloc_new(NULL);
231 [ + - ]: 10 : if (!tmp_ctx) {
232 : : return ENOMEM;
233 : : }
234 : :
235 : 10 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, "%s", _dn);
236 [ + - ]: 10 : if (dn == NULL) {
237 : : ret = ENOMEM;
238 : : goto done;
239 : : }
240 : :
241 [ - + ]: 10 : if (_name) {
242 : 0 : attr_name = ldb_dn_get_rdn_name(dn);
243 [ # # ]: 0 : if (attr_name == NULL) {
244 : : ret = EINVAL;
245 : : goto done;
246 : : }
247 : :
248 : 0 : *_name = talloc_strdup(mem_ctx, attr_name);
249 [ # # ]: 0 : if (!*_name) {
250 : : ret = ENOMEM;
251 : : goto done;
252 : : }
253 : : }
254 : :
255 : 10 : val = ldb_dn_get_rdn_val(dn);
256 [ - + ]: 10 : if (val == NULL) {
257 : 0 : ret = EINVAL;
258 [ # # ]: 0 : if (_name) talloc_free(*_name);
259 : : goto done;
260 : : }
261 : :
262 : 10 : *_val = talloc_strndup(mem_ctx, (char *) val->data, val->length);
263 [ - + ]: 10 : if (!*_val) {
264 : 0 : ret = ENOMEM;
265 [ # # ]: 0 : if (_name) talloc_free(*_name);
266 : : goto done;
267 : : }
268 : :
269 : : ret = EOK;
270 : :
271 : : done:
272 : 10 : talloc_zfree(tmp_ctx);
273 : 10 : return ret;
274 : : }
275 : :
276 : 10 : errno_t sysdb_group_dn_name(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
277 : : const char *_dn, char **_name)
278 : : {
279 : 10 : return sysdb_get_rdn(sysdb, mem_ctx, _dn, NULL, _name);
280 : : }
281 : :
282 : 1 : struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx)
283 : : {
284 : 1 : return ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_DOM_BASE, sysdb->domain->name);
285 : : }
286 : 0 : struct ldb_dn *sysdb_base_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx)
287 : : {
288 : 0 : return ldb_dn_new(mem_ctx, sysdb->ldb, SYSDB_BASE);
289 : : }
290 : :
291 : 0 : struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *sysdb)
292 : : {
293 : 0 : return sysdb->ldb;
294 : : }
295 : :
296 : 0 : struct sss_domain_info *sysdb_ctx_get_domain(struct sysdb_ctx *sysdb)
297 : : {
298 : 0 : return sysdb->domain;
299 : : }
300 : :
301 : 306 : struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *mem_ctx)
302 : : {
303 : 306 : return talloc_zero(mem_ctx, struct sysdb_attrs);
304 : : }
305 : :
306 : 1197 : int sysdb_attrs_get_el_ext(struct sysdb_attrs *attrs, const char *name,
307 : : bool alloc, struct ldb_message_element **el)
308 : : {
309 : 1197 : struct ldb_message_element *e = NULL;
310 : : int i;
311 : :
312 [ + + ]: 2997 : for (i = 0; i < attrs->num; i++) {
313 [ + + ]: 1800 : if (strcasecmp(name, attrs->a[i].name) == 0)
314 : 37 : e = &(attrs->a[i]);
315 : : }
316 : :
317 [ + + ]: 1197 : if (!e && alloc) {
318 : 1097 : e = talloc_realloc(attrs, attrs->a,
319 : : struct ldb_message_element, attrs->num+1);
320 [ + - ]: 1097 : if (!e) return ENOMEM;
321 : 1097 : attrs->a = e;
322 : :
323 : 1097 : e[attrs->num].name = talloc_strdup(e, name);
324 [ + - ]: 1097 : if (!e[attrs->num].name) return ENOMEM;
325 : :
326 : 1097 : e[attrs->num].num_values = 0;
327 : 1097 : e[attrs->num].values = NULL;
328 : 1097 : e[attrs->num].flags = 0;
329 : :
330 : 1097 : e = &(attrs->a[attrs->num]);
331 : 1097 : attrs->num++;
332 : : }
333 : :
334 [ + + ]: 1197 : if (!e) {
335 : : return ENOENT;
336 : : }
337 : :
338 : 1134 : *el = e;
339 : :
340 : 1197 : return EOK;
341 : : }
342 : :
343 : 1134 : int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name,
344 : : struct ldb_message_element **el)
345 : : {
346 : 1134 : return sysdb_attrs_get_el_ext(attrs, name, true, el);
347 : : }
348 : :
349 : 0 : int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name,
350 : : const char **string)
351 : : {
352 : : struct ldb_message_element *el;
353 : : int ret;
354 : :
355 : 0 : ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
356 [ # # ]: 0 : if (ret) {
357 : : return ret;
358 : : }
359 : :
360 [ # # ]: 0 : if (el->num_values != 1) {
361 : : return ERANGE;
362 : : }
363 : :
364 : 0 : *string = (const char *)el->values[0].data;
365 : : return EOK;
366 : : }
367 : :
368 : 0 : int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,
369 : : uint32_t *value)
370 : : {
371 : : struct ldb_message_element *el;
372 : : int ret;
373 : : char *endptr;
374 : : uint32_t val;
375 : :
376 : 0 : ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
377 [ # # ]: 0 : if (ret) {
378 : : return ret;
379 : : }
380 : :
381 [ # # ]: 0 : if (el->num_values != 1) {
382 : : return ERANGE;
383 : : }
384 : :
385 : 0 : errno = 0;
386 : 0 : val = strtouint32((const char *) el->values[0].data, &endptr, 10);
387 [ # # ]: 0 : if (errno != 0) return errno;
388 [ # # ]: 0 : if (*endptr) return EINVAL;
389 : :
390 : 0 : *value = val;
391 : : return EOK;
392 : : }
393 : :
394 : 0 : int sysdb_attrs_get_uint16_t(struct sysdb_attrs *attrs, const char *name,
395 : : uint16_t *value)
396 : : {
397 : : struct ldb_message_element *el;
398 : : int ret;
399 : : char *endptr;
400 : : uint16_t val;
401 : :
402 : 0 : ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
403 [ # # ]: 0 : if (ret) {
404 : : return ret;
405 : : }
406 : :
407 [ # # ]: 0 : if (el->num_values != 1) {
408 : : return ERANGE;
409 : : }
410 : :
411 : 0 : errno = 0;
412 : 0 : val = strtouint16((const char *) el->values[0].data, &endptr, 10);
413 [ # # ]: 0 : if (errno != 0) return errno;
414 [ # # ]: 0 : if (*endptr) return EINVAL;
415 : :
416 : 0 : *value = val;
417 : : return EOK;
418 : : }
419 : :
420 : 63 : errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name,
421 : : bool *value)
422 : : {
423 : : struct ldb_message_element *el;
424 : : int ret;
425 : :
426 : 63 : ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
427 [ - + ]: 63 : if (ret) {
428 : : return ret;
429 : : }
430 : :
431 [ # # ]: 0 : if (el->num_values != 1) {
432 : : return ERANGE;
433 : : }
434 : :
435 [ # # ]: 0 : if (strcmp((const char *)el->values[0].data, "TRUE") == 0)
436 : 0 : *value = true;
437 : : else
438 : 63 : *value = false;
439 : : return EOK;
440 : : }
441 : :
442 : 0 : int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name,
443 : : TALLOC_CTX *mem_ctx, const char ***string)
444 : : {
445 : : struct ldb_message_element *el;
446 : : int ret;
447 : : unsigned int u;
448 : : const char **a;
449 : :
450 : 0 : ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
451 [ # # ]: 0 : if (ret) {
452 : : return ret;
453 : : }
454 : :
455 : 0 : a = talloc_array(mem_ctx, const char *, el->num_values + 1);
456 [ # # ]: 0 : if (a == NULL) {
457 : : return ENOMEM;
458 : : }
459 : :
460 : 0 : memset(a, 0, sizeof(const char *) * (el->num_values + 1));
461 : :
462 [ # # ]: 0 : for(u = 0; u < el->num_values; u++) {
463 : 0 : a[u] = talloc_strndup(a, (const char *)el->values[u].data,
464 : 0 : el->values[u].length);
465 [ # # ]: 0 : if (a[u] == NULL) {
466 : 0 : talloc_free(a);
467 : : return ENOMEM;
468 : : }
469 : : }
470 : :
471 : 0 : *string = a;
472 : : return EOK;
473 : : }
474 : :
475 : 1009 : int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
476 : : const char *name, const struct ldb_val *val)
477 : : {
478 : 1009 : struct ldb_message_element *el = NULL;
479 : : struct ldb_val *vals;
480 : : int ret;
481 : :
482 : 1009 : ret = sysdb_attrs_get_el(attrs, name, &el);
483 [ + - ]: 1009 : if (ret != EOK) {
484 : : return ret;
485 : : }
486 : :
487 : 1009 : vals = talloc_realloc(attrs->a, el->values,
488 : : struct ldb_val, el->num_values+1);
489 [ + - ]: 1009 : if (!vals) return ENOMEM;
490 : :
491 : 1009 : vals[el->num_values] = ldb_val_dup(vals, val);
492 [ - + ][ # # ]: 1009 : if (vals[el->num_values].data == NULL &&
493 : 0 : vals[el->num_values].length != 0) {
494 : : return ENOMEM;
495 : : }
496 : :
497 : 1009 : el->values = vals;
498 : 1009 : el->num_values++;
499 : :
500 : : return EOK;
501 : : }
502 : :
503 : 651 : int sysdb_attrs_add_string(struct sysdb_attrs *attrs,
504 : : const char *name, const char *str)
505 : : {
506 : : struct ldb_val v;
507 : :
508 : 651 : v.data = (uint8_t *)discard_const(str);
509 : 651 : v.length = strlen(str);
510 : :
511 : 651 : return sysdb_attrs_add_val(attrs, name, &v);
512 : : }
513 : :
514 : 76 : int sysdb_attrs_add_bool(struct sysdb_attrs *attrs,
515 : : const char *name, bool value)
516 : : {
517 [ + - ]: 76 : if(value) {
518 : 76 : return sysdb_attrs_add_string(attrs, name, "TRUE");
519 : : }
520 : :
521 : 76 : return sysdb_attrs_add_string(attrs, name, "FALSE");
522 : : }
523 : :
524 : 84 : int sysdb_attrs_steal_string(struct sysdb_attrs *attrs,
525 : : const char *name, char *str)
526 : : {
527 : 84 : struct ldb_message_element *el = NULL;
528 : : struct ldb_val *vals;
529 : : int ret;
530 : :
531 : 84 : ret = sysdb_attrs_get_el(attrs, name, &el);
532 [ + - ]: 84 : if (ret != EOK) {
533 : : return ret;
534 : : }
535 : :
536 : 84 : vals = talloc_realloc(attrs->a, el->values,
537 : : struct ldb_val, el->num_values+1);
538 [ + - ]: 84 : if (!vals) return ENOMEM;
539 : 84 : el->values = vals;
540 : :
541 : : /* now steal and assign the string */
542 : 84 : talloc_steal(el->values, str);
543 : :
544 : 84 : el->values[el->num_values].data = (uint8_t *)str;
545 : 84 : el->values[el->num_values].length = strlen(str);
546 : 84 : el->num_values++;
547 : :
548 : : return EOK;
549 : : }
550 : :
551 : 1 : int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
552 : : const char *name, long value)
553 : : {
554 : : struct ldb_val v;
555 : : char *str;
556 : : int ret;
557 : :
558 : 1 : str = talloc_asprintf(attrs, "%ld", value);
559 [ + - ]: 1 : if (!str) return ENOMEM;
560 : :
561 : 1 : v.data = (uint8_t *)str;
562 : 1 : v.length = strlen(str);
563 : :
564 : 1 : ret = sysdb_attrs_add_val(attrs, name, &v);
565 : 1 : talloc_free(str);
566 : :
567 : : return ret;
568 : : }
569 : :
570 : 46 : int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
571 : : const char *name, uint32_t value)
572 : : {
573 : 46 : unsigned long val = value;
574 : : struct ldb_val v;
575 : : char *str;
576 : : int ret;
577 : :
578 : 46 : str = talloc_asprintf(attrs, "%lu", val);
579 [ + - ]: 46 : if (!str) return ENOMEM;
580 : :
581 : 46 : v.data = (uint8_t *)str;
582 : 46 : v.length = strlen(str);
583 : :
584 : 46 : ret = sysdb_attrs_add_val(attrs, name, &v);
585 : 46 : talloc_free(str);
586 : :
587 : : return ret;
588 : : }
589 : :
590 : 311 : int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
591 : : const char *name, time_t value)
592 : : {
593 : 311 : long long val = value;
594 : : struct ldb_val v;
595 : : char *str;
596 : : int ret;
597 : :
598 : 311 : str = talloc_asprintf(attrs, "%lld", val);
599 [ + - ]: 311 : if (!str) return ENOMEM;
600 : :
601 : 311 : v.data = (uint8_t *)str;
602 : 311 : v.length = strlen(str);
603 : :
604 : 311 : ret = sysdb_attrs_add_val(attrs, name, &v);
605 : 311 : talloc_free(str);
606 : :
607 : : return ret;
608 : : }
609 : :
610 : 0 : int sysdb_attrs_copy_values(struct sysdb_attrs *src,
611 : : struct sysdb_attrs *dst,
612 : : const char *name)
613 : : {
614 : 0 : int ret = EOK;
615 : : int i;
616 : : struct ldb_message_element *src_el;
617 : :
618 : 0 : ret = sysdb_attrs_get_el(src, name, &src_el);
619 [ # # ]: 0 : if (ret != EOK) {
620 : : goto done;
621 : : }
622 : :
623 [ # # ]: 0 : for (i = 0; i < src_el->num_values; i++) {
624 : 0 : ret = sysdb_attrs_add_val(dst, name, &src_el->values[i]);
625 [ # # ]: 0 : if (ret != EOK) {
626 : : goto done;
627 : : }
628 : : }
629 : :
630 : : done:
631 : 0 : return ret;
632 : : }
633 : :
634 : 0 : int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs,
635 : : const char *attr_name,
636 : : const char *domain,
637 : : const char *const *list)
638 : : {
639 : 0 : struct ldb_message_element *el = NULL;
640 : : struct ldb_val *vals;
641 : : int i, j, num;
642 : : char *member;
643 : : int ret;
644 : :
645 : 0 : ret = sysdb_attrs_get_el(attrs, attr_name, &el);
646 [ # # ]: 0 : if (ret) {
647 : : return ret;
648 : : }
649 : :
650 [ # # ]: 0 : for (num = 0; list[num]; num++) /* count */ ;
651 : :
652 : 0 : vals = talloc_realloc(attrs->a, el->values,
653 : : struct ldb_val, el->num_values + num);
654 [ # # ]: 0 : if (!vals) {
655 : : return ENOMEM;
656 : : }
657 : 0 : el->values = vals;
658 : :
659 [ # # ][ # # ]: 0 : DEBUG(9, ("Adding %d members to existing %d ones\n",
[ # # ][ # # ]
[ # # ]
660 : : num, el->num_values));
661 : :
662 [ # # ]: 0 : for (i = 0, j = el->num_values; i < num; i++) {
663 : :
664 : 0 : member = sysdb_user_strdn(el->values, domain, list[i]);
665 [ # # ]: 0 : if (!member) {
666 [ # # ][ # # ]: 0 : DEBUG(4, ("Failed to get user dn for [%s]\n", list[i]));
[ # # ][ # # ]
[ # # ]
667 : 0 : continue;
668 : : }
669 : 0 : el->values[j].data = (uint8_t *)member;
670 : 0 : el->values[j].length = strlen(member);
671 : 0 : j++;
672 : :
673 [ # # ][ # # ]: 0 : DEBUG(7, (" member #%d: [%s]\n", i, member));
[ # # ][ # # ]
[ # # ]
674 : : }
675 : 0 : el->num_values = j;
676 : :
677 : : return EOK;
678 : : }
679 : :
680 : 29 : static char *build_dom_dn_str_escape(TALLOC_CTX *mem_ctx, const char *template,
681 : : const char *domain, const char *name)
682 : : {
683 : : char *ret;
684 : : int l;
685 : :
686 : 29 : l = strcspn(name, ",=\n+<>#;\\\"");
687 [ - + ]: 29 : if (name[l] != '\0') {
688 : : struct ldb_val v;
689 : : char *tmp;
690 : :
691 : 0 : v.data = discard_const_p(uint8_t, name);
692 : 0 : v.length = strlen(name);
693 : :
694 : 0 : tmp = ldb_dn_escape_value(mem_ctx, v);
695 [ # # ]: 0 : if (!tmp) {
696 : : return NULL;
697 : : }
698 : :
699 : 0 : ret = talloc_asprintf(mem_ctx, template, tmp, domain);
700 : 0 : talloc_zfree(tmp);
701 [ # # ]: 0 : if (!ret) {
702 : : return NULL;
703 : : }
704 : :
705 : : return ret;
706 : : }
707 : :
708 : 29 : ret = talloc_asprintf(mem_ctx, template, name, domain);
709 [ + - ]: 29 : if (!ret) {
710 : : return NULL;
711 : : }
712 : :
713 : 29 : return ret;
714 : : }
715 : :
716 : 0 : char *sysdb_user_strdn(TALLOC_CTX *mem_ctx,
717 : : const char *domain, const char *name)
718 : : {
719 : 0 : return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_USER, domain, name);
720 : : }
721 : :
722 : 29 : char *sysdb_group_strdn(TALLOC_CTX *mem_ctx,
723 : : const char *domain, const char *name)
724 : : {
725 : 29 : return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_GROUP, domain, name);
726 : : }
727 : :
728 : : /* TODO: make a more complete and precise mapping */
729 : 855 : int sysdb_error_to_errno(int ldberr)
730 : : {
731 [ - - - - : 855 : switch (ldberr) {
- - + ]
732 : : case LDB_SUCCESS:
733 : : return EOK;
734 : : case LDB_ERR_OPERATIONS_ERROR:
735 : 0 : return EIO;
736 : : case LDB_ERR_NO_SUCH_OBJECT:
737 : 0 : return ENOENT;
738 : : case LDB_ERR_BUSY:
739 : 0 : return EBUSY;
740 : : case LDB_ERR_ENTRY_ALREADY_EXISTS:
741 : 0 : return EEXIST;
742 : : case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
743 : 0 : return EINVAL;
744 : : default:
745 [ # # ][ # # ]: 855 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
746 : : ("LDB returned unexpected error: [%s]\n",
747 : : ldb_strerror(ldberr)));
748 : : return EFAULT;
749 : : }
750 : : }
751 : :
752 : : /* =Transactions========================================================== */
753 : :
754 : 70 : int sysdb_transaction_start(struct sysdb_ctx *sysdb)
755 : : {
756 : : int ret;
757 : :
758 : 70 : ret = ldb_transaction_start(sysdb->ldb);
759 [ - + ]: 70 : if (ret != LDB_SUCCESS) {
760 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
[ # # ][ # # ]
[ # # ]
761 : : }
762 : 70 : return sysdb_error_to_errno(ret);
763 : : }
764 : :
765 : 70 : int sysdb_transaction_commit(struct sysdb_ctx *sysdb)
766 : : {
767 : : int ret;
768 : :
769 : 70 : ret = ldb_transaction_commit(sysdb->ldb);
770 [ - + ]: 70 : if (ret != LDB_SUCCESS) {
771 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
[ # # ][ # # ]
[ # # ]
772 : : }
773 : 70 : return sysdb_error_to_errno(ret);
774 : : }
775 : :
776 : 0 : int sysdb_transaction_cancel(struct sysdb_ctx *sysdb)
777 : : {
778 : : int ret;
779 : :
780 : 0 : ret = ldb_transaction_cancel(sysdb->ldb);
781 [ # # ]: 0 : if (ret != LDB_SUCCESS) {
782 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
[ # # ][ # # ]
[ # # ]
783 : : }
784 : 0 : return sysdb_error_to_errno(ret);
785 : : }
786 : :
787 : : /* =Initialization======================================================== */
788 : :
789 : 643 : int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
790 : : const char *provider, const char *name,
791 : : const char *base_path, char **_ldb_file)
792 : : {
793 : : char *ldb_file;
794 : :
795 : : /* special case for the local domain */
796 [ + - ]: 643 : if (strcasecmp(provider, "local") == 0) {
797 : 643 : ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE,
798 : : base_path);
799 : : } else {
800 : 0 : ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
801 : : base_path, name);
802 : : }
803 [ + - ]: 643 : if (!ldb_file) {
804 : : return ENOMEM;
805 : : }
806 : :
807 : 643 : *_ldb_file = ldb_file;
808 : 643 : return EOK;
809 : : }
810 : :
811 : 6 : errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name)
812 : : {
813 : : struct ldb_message *msg;
814 : : TALLOC_CTX *tmp_ctx;
815 : : int ret;
816 : :
817 : 6 : tmp_ctx = talloc_new(NULL);
818 [ + - ]: 6 : if (tmp_ctx == NULL) {
819 : : ret = ENOMEM;
820 : : goto done;
821 : : }
822 : :
823 : : /* == create base domain object == */
824 : :
825 : 6 : msg = ldb_msg_new(tmp_ctx);
826 [ + - ]: 6 : if (!msg) {
827 : : ret = ENOMEM;
828 : : goto done;
829 : : }
830 : 6 : msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, SYSDB_DOM_BASE, domain_name);
831 [ + - ]: 6 : if (!msg->dn) {
832 : : ret = ENOMEM;
833 : : goto done;
834 : : }
835 : 6 : ret = ldb_msg_add_string(msg, "cn", domain_name);
836 [ + - ]: 6 : if (ret != LDB_SUCCESS) {
837 : : ret = EIO;
838 : : goto done;
839 : : }
840 : : /* do a synchronous add */
841 : 6 : ret = ldb_add(sysdb->ldb, msg);
842 [ - + ]: 6 : if (ret != LDB_SUCCESS) {
843 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) "
[ # # ][ # # ]
[ # # ]
844 : : "for domain %s!\n",
845 : : ret, ldb_errstring(sysdb->ldb),
846 : : domain_name));
847 : : ret = EIO;
848 : : goto done;
849 : : }
850 : 6 : talloc_zfree(msg);
851 : :
852 : : /* == create Users tree == */
853 : :
854 : 6 : msg = ldb_msg_new(tmp_ctx);
855 [ + - ]: 6 : if (!msg) {
856 : : ret = ENOMEM;
857 : : goto done;
858 : : }
859 : 6 : msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
860 : : SYSDB_TMPL_USER_BASE, domain_name);
861 [ + - ]: 6 : if (!msg->dn) {
862 : : ret = ENOMEM;
863 : : goto done;
864 : : }
865 : 6 : ret = ldb_msg_add_string(msg, "cn", "Users");
866 [ + - ]: 6 : if (ret != LDB_SUCCESS) {
867 : : ret = EIO;
868 : : goto done;
869 : : }
870 : : /* do a synchronous add */
871 : 6 : ret = ldb_add(sysdb->ldb, msg);
872 [ - + ]: 6 : if (ret != LDB_SUCCESS) {
873 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) "
[ # # ][ # # ]
[ # # ]
874 : : "for domain %s!\n",
875 : : ret, ldb_errstring(sysdb->ldb),
876 : : domain_name));
877 : : ret = EIO;
878 : : goto done;
879 : : }
880 : 6 : talloc_zfree(msg);
881 : :
882 : : /* == create Groups tree == */
883 : :
884 : 6 : msg = ldb_msg_new(tmp_ctx);
885 [ + - ]: 6 : if (!msg) {
886 : : ret = ENOMEM;
887 : : goto done;
888 : : }
889 : 6 : msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
890 : : SYSDB_TMPL_GROUP_BASE, domain_name);
891 [ + - ]: 6 : if (!msg->dn) {
892 : : ret = ENOMEM;
893 : : goto done;
894 : : }
895 : 6 : ret = ldb_msg_add_string(msg, "cn", "Groups");
896 [ + - ]: 6 : if (ret != LDB_SUCCESS) {
897 : : ret = EIO;
898 : : goto done;
899 : : }
900 : : /* do a synchronous add */
901 : 6 : ret = ldb_add(sysdb->ldb, msg);
902 [ - + ]: 6 : if (ret != LDB_SUCCESS) {
903 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) for "
[ # # ][ # # ]
[ # # ]
904 : : "domain %s!\n",
905 : : ret, ldb_errstring(sysdb->ldb),
906 : : domain_name));
907 : : ret = EIO;
908 : : goto done;
909 : : }
910 : 6 : talloc_zfree(msg);
911 : :
912 : 6 : ret = EOK;
913 : :
914 : : done:
915 : 6 : talloc_zfree(tmp_ctx);
916 : 6 : return ret;
917 : : }
918 : :
919 : 633 : static int remove_sysdb_from_domain(void *mem)
920 : : {
921 : 633 : struct sysdb_ctx *ctx = talloc_get_type(mem, struct sysdb_ctx);
922 : :
923 [ + - ][ + - ]: 633 : if (ctx->domain != NULL && ctx->domain->sysdb == ctx) {
924 : 633 : ctx->domain->sysdb = NULL;
925 : : }
926 : :
927 : 633 : return 0;
928 : : }
929 : :
930 : 643 : errno_t sysdb_add_to_domain(struct sss_domain_info *domain,
931 : : struct sysdb_ctx *ctx)
932 : : {
933 [ - + ]: 643 : if (domain == NULL || ctx == NULL) {
934 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Missing domain or sysdb context.\n"));
[ # # ][ # # ]
[ # # ]
935 : : return EINVAL;
936 : : }
937 : :
938 [ - + ]: 643 : if (domain->sysdb != NULL) {
939 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Sysdb context already set.\n"));
[ # # ][ # # ]
[ # # ]
940 : : return EINVAL;
941 : : }
942 : :
943 : 643 : domain->sysdb = ctx;
944 : :
945 : 643 : talloc_set_destructor((TALLOC_CTX *) ctx, remove_sysdb_from_domain);
946 : :
947 : 643 : return EOK;
948 : : }
949 : :
950 : : /* Compare versions of sysdb, returns ERRNO accordingly */
951 : : static errno_t
952 : 0 : sysdb_version_check(const char *expected,
953 : : const char *received)
954 : : {
955 : : int ret;
956 : : unsigned int exp_major, exp_minor, recv_major, recv_minor;
957 : :
958 : 0 : ret = sscanf(expected, "%u.%u", &exp_major, &exp_minor);
959 [ # # ]: 0 : if (ret != 2) {
960 : : return EINVAL;
961 : : }
962 : 0 : ret = sscanf(received, "%u.%u", &recv_major, &recv_minor);
963 [ # # ]: 0 : if (ret != 2) {
964 : : return EINVAL;
965 : : }
966 : :
967 [ # # ]: 0 : if (recv_major > exp_major) {
968 : : return EUCLEAN;
969 [ # # ]: 0 : } else if (recv_major < exp_major) {
970 : : return EMEDIUMTYPE;
971 : : }
972 : :
973 [ # # ]: 0 : if (recv_minor > exp_minor) {
974 : : return EUCLEAN;
975 [ # # ]: 0 : } else if (recv_minor < exp_minor) {
976 : : return EMEDIUMTYPE;
977 : : }
978 : :
979 : : return EOK;
980 : : }
981 : :
982 : 643 : int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
983 : : struct sss_domain_info *domain,
984 : : const char *db_path,
985 : : bool allow_upgrade,
986 : : struct sysdb_ctx **_ctx)
987 : : {
988 : 643 : TALLOC_CTX *tmp_ctx = NULL;
989 : : struct sysdb_ctx *sysdb;
990 : : const char *base_ldif;
991 : : struct ldb_ldif *ldif;
992 : : struct ldb_message_element *el;
993 : : struct ldb_result *res;
994 : : struct ldb_dn *verdn;
995 : 643 : const char *version = NULL;
996 : : int ret;
997 : :
998 : 643 : sysdb = talloc_zero(mem_ctx, struct sysdb_ctx);
999 [ + - ]: 643 : if (!sysdb) {
1000 : : return ENOMEM;
1001 : : }
1002 : 643 : sysdb->domain = domain;
1003 : :
1004 : : /* The local provider s the only true MPG,
1005 : : * for the other domains, the provider actually unrolls MPGs */
1006 [ + - ]: 643 : if (strcasecmp(domain->provider, "local") == 0) {
1007 : 643 : sysdb->mpg = true;
1008 : : }
1009 : :
1010 : 643 : ret = sysdb_get_db_file(sysdb, domain->provider,
1011 : 643 : domain->name, db_path,
1012 : : &sysdb->ldb_file);
1013 [ + - ]: 643 : if (ret != EOK) {
1014 : : goto done;
1015 : : }
1016 [ + - ][ + - ]: 643 : DEBUG(5, ("DB File for %s: %s\n", domain->name, sysdb->ldb_file));
[ - + ][ # # ]
[ # # ]
1017 : :
1018 : 643 : ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
1019 [ - + ]: 643 : if (ret != EOK) {
1020 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_ldb_connect failed.\n"));
[ # # ][ # # ]
[ # # ]
1021 : : goto done;
1022 : : }
1023 : :
1024 : 643 : tmp_ctx = talloc_new(NULL);
1025 [ + - ]: 643 : if (!tmp_ctx) {
1026 : : ret = ENOMEM;
1027 : : goto done;
1028 : : }
1029 : :
1030 : 643 : verdn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
1031 [ + - ]: 643 : if (!verdn) {
1032 : : ret = EIO;
1033 : : goto done;
1034 : : }
1035 : :
1036 : 643 : ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
1037 : : verdn, LDB_SCOPE_BASE,
1038 : : NULL, NULL);
1039 [ + - ]: 643 : if (ret != LDB_SUCCESS) {
1040 : : ret = EIO;
1041 : : goto done;
1042 : : }
1043 [ + - ]: 643 : if (res->count > 1) {
1044 : : ret = EIO;
1045 : : goto done;
1046 : : }
1047 : :
1048 [ + + ]: 643 : if (res->count == 1) {
1049 : 640 : el = ldb_msg_find_element(res->msgs[0], "version");
1050 [ + - ]: 640 : if (!el) {
1051 : : ret = EIO;
1052 : : goto done;
1053 : : }
1054 : :
1055 [ + - ]: 640 : if (el->num_values != 1) {
1056 : : ret = EINVAL;
1057 : : goto done;
1058 : : }
1059 : 640 : version = talloc_strndup(tmp_ctx,
1060 : 640 : (char *)(el->values[0].data),
1061 : 640 : el->values[0].length);
1062 [ + - ]: 640 : if (!version) {
1063 : : ret = ENOMEM;
1064 : : goto done;
1065 : : }
1066 : :
1067 [ - + ]: 640 : if (strcmp(version, SYSDB_VERSION) == 0) {
1068 : : /* all fine, return */
1069 : : ret = EOK;
1070 : : goto done;
1071 : : }
1072 : :
1073 [ # # ]: 0 : if (!allow_upgrade) {
1074 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE,
[ # # ][ # # ]
[ # # ]
1075 : : ("Wrong DB version (got %s expected %s)\n",
1076 : : version, SYSDB_VERSION));
1077 : 0 : ret = sysdb_version_check(SYSDB_VERSION, version);
1078 : 0 : goto done;
1079 : : }
1080 : :
1081 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CONF_SETTINGS, ("Upgrading DB [%s] from version: %s\n",
[ # # ][ # # ]
[ # # ]
1082 : : domain->name, version));
1083 : :
1084 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_3) == 0) {
[ # # ][ # # ]
1085 : 0 : ret = sysdb_upgrade_03(sysdb, &version);
1086 [ # # ]: 0 : if (ret != EOK) {
1087 : : goto done;
1088 : : }
1089 : : }
1090 : :
1091 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_4) == 0) {
[ # # ][ # # ]
1092 : 0 : ret = sysdb_upgrade_04(sysdb, &version);
1093 [ # # ]: 0 : if (ret != EOK) {
1094 : : goto done;
1095 : : }
1096 : : }
1097 : :
1098 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_5) == 0) {
[ # # ][ # # ]
1099 : 0 : ret = sysdb_upgrade_05(sysdb, &version);
1100 [ # # ]: 0 : if (ret != EOK) {
1101 : : goto done;
1102 : : }
1103 : : }
1104 : :
1105 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_6) == 0) {
[ # # ][ # # ]
1106 : 0 : ret = sysdb_upgrade_06(sysdb, &version);
1107 [ # # ]: 0 : if (ret != EOK) {
1108 : : goto done;
1109 : : }
1110 : : }
1111 : :
1112 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_7) == 0) {
[ # # ][ # # ]
1113 : 0 : ret = sysdb_upgrade_07(sysdb, &version);
1114 [ # # ]: 0 : if (ret != EOK) {
1115 : : goto done;
1116 : : }
1117 : : }
1118 : :
1119 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_8) == 0) {
[ # # ][ # # ]
1120 : 0 : ret = sysdb_upgrade_08(sysdb, &version);
1121 [ # # ]: 0 : if (ret != EOK) {
1122 : : goto done;
1123 : : }
1124 : : }
1125 : :
1126 [ # # ][ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_9) == 0) {
[ # # ][ # # ]
1127 : 0 : ret = sysdb_upgrade_09(sysdb, &version);
1128 [ # # ]: 0 : if (ret != EOK) {
1129 : : goto done;
1130 : : }
1131 : : }
1132 : :
1133 [ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_10) == 0) {
1134 : 0 : ret = sysdb_upgrade_10(sysdb, &version);
1135 [ # # ]: 0 : if (ret != EOK) {
1136 : : goto done;
1137 : : }
1138 : : }
1139 : :
1140 [ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_11) == 0) {
1141 : 0 : ret = sysdb_upgrade_11(sysdb, &version);
1142 [ # # ]: 0 : if (ret != EOK) {
1143 : : goto done;
1144 : : }
1145 : : }
1146 : :
1147 [ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_12) == 0) {
1148 : 0 : ret = sysdb_upgrade_12(sysdb, &version);
1149 [ # # ]: 0 : if (ret != EOK) {
1150 : : goto done;
1151 : : }
1152 : : }
1153 : :
1154 [ # # ]: 0 : if (strcmp(version, SYSDB_VERSION_0_13) == 0) {
1155 : 0 : ret = sysdb_upgrade_13(sysdb, &version);
1156 [ # # ]: 0 : if (ret != EOK) {
1157 : : goto done;
1158 : : }
1159 : : }
1160 : :
1161 : : /* The version should now match SYSDB_VERSION.
1162 : : * If not, it means we didn't match any of the
1163 : : * known older versions. The DB might be
1164 : : * corrupt or generated by a newer version of
1165 : : * SSSD.
1166 : : */
1167 [ # # ]: 0 : if (strcmp(version, SYSDB_VERSION) == 0) {
1168 : : /* The cache has been upgraded.
1169 : : * We need to reopen the LDB to ensure that
1170 : : * any changes made above take effect.
1171 : : */
1172 : 0 : talloc_zfree(sysdb->ldb);
1173 : 0 : ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
1174 [ # # ]: 0 : if (ret != EOK) {
1175 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("sysdb_ldb_connect failed.\n"));
[ # # ][ # # ]
[ # # ]
1176 : : }
1177 : : goto done;
1178 : : }
1179 : :
1180 [ # # ][ # # ]: 0 : DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n",
[ # # ][ # # ]
[ # # ][ # # ]
1181 : : version?version:"not found", SYSDB_VERSION, domain->name));
1182 : 0 : ret = sysdb_version_check(SYSDB_VERSION, version);
1183 : 0 : goto done;
1184 : : }
1185 : :
1186 : : /* SYSDB_BASE does not exists, means db is empty, populate */
1187 : :
1188 : 3 : base_ldif = SYSDB_BASE_LDIF;
1189 [ + + ]: 15 : while ((ldif = ldb_ldif_read_string(sysdb->ldb, &base_ldif))) {
1190 : 12 : ret = ldb_add(sysdb->ldb, ldif->msg);
1191 [ - + ]: 12 : if (ret != LDB_SUCCESS) {
1192 [ # # ][ # # ]: 0 : DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
[ # # ][ # # ]
[ # # ]
1193 : : ret, ldb_errstring(sysdb->ldb), domain->name));
1194 : : ret = EIO;
1195 : : goto done;
1196 : : }
1197 : 12 : ldb_ldif_read_free(sysdb->ldb, ldif);
1198 : : }
1199 : :
1200 : 3 : ret = sysdb_domain_create(sysdb, domain->name);
1201 [ + - ]: 3 : if (ret != EOK) {
1202 : : goto done;
1203 : : }
1204 : :
1205 : : /* The cache has been newly created.
1206 : : * We need to reopen the LDB to ensure that
1207 : : * all of the special values take effect
1208 : : * (such as enabling the memberOf plugin and
1209 : : * the various indexes).
1210 : : */
1211 : 3 : talloc_zfree(sysdb->ldb);
1212 : 3 : ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
1213 [ - + ]: 3 : if (ret != EOK) {
1214 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_ldb_connect failed.\n"));
[ # # ][ # # ]
[ # # ]
1215 : : }
1216 : :
1217 : : done:
1218 : 643 : talloc_free(tmp_ctx);
1219 [ + - ]: 643 : if (ret == EOK) {
1220 : 643 : *_ctx = sysdb;
1221 : : } else {
1222 : 643 : talloc_free(sysdb);
1223 : : }
1224 : : return ret;
1225 : : }
1226 : :
1227 : 0 : int sysdb_init(TALLOC_CTX *mem_ctx,
1228 : : struct confdb_ctx *cdb,
1229 : : const char *alt_db_path,
1230 : : bool allow_upgrade,
1231 : : struct sysdb_ctx_list **_ctx_list)
1232 : : {
1233 : : struct sysdb_ctx_list *ctx_list;
1234 : : struct sss_domain_info *domains, *dom;
1235 : : struct sysdb_ctx *sysdb;
1236 : : int ret;
1237 : :
1238 : 0 : ctx_list = talloc_zero(mem_ctx, struct sysdb_ctx_list);
1239 [ # # ]: 0 : if (!ctx_list) {
1240 : : return ENOMEM;
1241 : : }
1242 : :
1243 [ # # ]: 0 : if (alt_db_path) {
1244 : 0 : ctx_list->db_path = talloc_strdup(ctx_list, alt_db_path);
1245 : : } else {
1246 : 0 : ctx_list->db_path = talloc_strdup(ctx_list, DB_PATH);
1247 : : }
1248 [ # # ]: 0 : if (!ctx_list->db_path) {
1249 : 0 : talloc_zfree(ctx_list);
1250 : : return ENOMEM;
1251 : : }
1252 : :
1253 : : /* open a db for each backend */
1254 : 0 : ret = confdb_get_domains(cdb, &domains);
1255 [ # # ]: 0 : if (ret != EOK) {
1256 : 0 : talloc_zfree(ctx_list);
1257 : : return ret;
1258 : : }
1259 : :
1260 [ # # ]: 0 : if (allow_upgrade) {
1261 : : /* check if we have an old sssd.ldb to upgrade */
1262 : 0 : ret = sysdb_check_upgrade_02(domains, ctx_list->db_path);
1263 [ # # ]: 0 : if (ret != EOK) {
1264 : 0 : talloc_zfree(ctx_list);
1265 : : return ret;
1266 : : }
1267 : : }
1268 : :
1269 [ # # ]: 0 : for (dom = domains; dom; dom = dom->next) {
1270 : :
1271 : 0 : ctx_list->dbs = talloc_realloc(ctx_list, ctx_list->dbs,
1272 : : struct sysdb_ctx *,
1273 : : ctx_list->num_dbs + 1);
1274 [ # # ]: 0 : if (!ctx_list->dbs) {
1275 : 0 : talloc_zfree(ctx_list);
1276 : : return ENOMEM;
1277 : : }
1278 : :
1279 : 0 : ret = sysdb_domain_init_internal(ctx_list, dom,
1280 : 0 : ctx_list->db_path,
1281 : : allow_upgrade, &sysdb);
1282 [ # # ]: 0 : if (ret != EOK) {
1283 : 0 : talloc_zfree(ctx_list);
1284 : : return ret;
1285 : : }
1286 : :
1287 : 0 : ret = sysdb_add_to_domain(dom, sysdb);
1288 [ # # ]: 0 : if (ret != EOK) {
1289 : 0 : talloc_zfree(ctx_list);
1290 : : return ret;
1291 : : }
1292 : :
1293 : 0 : ctx_list->dbs[ctx_list->num_dbs] = sysdb;
1294 : 0 : ctx_list->num_dbs++;
1295 : : }
1296 [ # # ]: 0 : if (ctx_list->num_dbs == 0) {
1297 : : /* what? .. */
1298 : 0 : talloc_zfree(ctx_list);
1299 : : return ENOENT;
1300 : : }
1301 : :
1302 : 0 : *_ctx_list = ctx_list;
1303 : :
1304 : : return EOK;
1305 : : }
1306 : :
1307 : 643 : int sysdb_domain_init(TALLOC_CTX *mem_ctx,
1308 : : struct sss_domain_info *domain,
1309 : : const char *db_path,
1310 : : struct sysdb_ctx **_ctx)
1311 : : {
1312 : 643 : return sysdb_domain_init_internal(mem_ctx, domain,
1313 : : db_path, false, _ctx);
1314 : : }
1315 : :
1316 : 643 : errno_t sysdb_init_domain_and_sysdb(TALLOC_CTX *mem_ctx,
1317 : : struct confdb_ctx *cdb,
1318 : : const char *domain_name,
1319 : : const char *db_path,
1320 : : struct sss_domain_info **_domain,
1321 : : struct sysdb_ctx **_ctx)
1322 : : {
1323 : : int ret;
1324 : : struct sss_domain_info *dom;
1325 : : struct sysdb_ctx *ctx;
1326 : :
1327 : 643 : ret = confdb_get_domain(cdb, domain_name, &dom);
1328 [ - + ]: 643 : if (ret != EOK) {
1329 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Error retrieving domain configuration.\n"));
[ # # ][ # # ]
[ # # ]
1330 : : return ret;
1331 : : }
1332 : :
1333 : 643 : ret = sysdb_domain_init(mem_ctx, dom, db_path, &ctx);
1334 [ - + ]: 643 : if (ret != EOK) {
1335 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Error opening cache database.\n"));
[ # # ][ # # ]
[ # # ]
1336 : : return ret;
1337 : : }
1338 : :
1339 : 643 : ret = sysdb_add_to_domain(dom, ctx);
1340 [ - + ]: 643 : if (ret != EOK) {
1341 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Error storing cache database context.\n"));
[ # # ][ # # ]
[ # # ]
1342 : : return ret;
1343 : : }
1344 : :
1345 : 643 : *_domain = dom;
1346 : 643 : *_ctx = ctx;
1347 : :
1348 : : return EOK;
1349 : : }
1350 : :
1351 : 0 : int sysdb_list_init(TALLOC_CTX *mem_ctx,
1352 : : const char *path,
1353 : : struct sysdb_ctx *sysdb,
1354 : : struct sysdb_ctx_list **_list)
1355 : : {
1356 : : struct sysdb_ctx_list *list;
1357 : : int ret;
1358 : :
1359 : 0 : list = talloc_zero(mem_ctx, struct sysdb_ctx_list);
1360 [ # # ]: 0 : if (!list) {
1361 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_zero failed\n"));
[ # # ][ # # ]
[ # # ]
1362 : : return ENOMEM;
1363 : : }
1364 : :
1365 : 0 : list->db_path = talloc_strdup(list, path);
1366 [ # # ]: 0 : if (!list->db_path) {
1367 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_strdup failed\n"));
[ # # ][ # # ]
[ # # ]
1368 : : ret = ENOMEM;
1369 : : goto fail;
1370 : : }
1371 : :
1372 [ # # ]: 0 : if (sysdb) {
1373 : 0 : list->num_dbs = 1;
1374 : 0 : list->dbs = talloc_array(list, struct sysdb_ctx *, list->num_dbs);
1375 [ # # ]: 0 : if (!list->dbs) {
1376 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_array failed\n"));
[ # # ][ # # ]
[ # # ]
1377 : : ret = ENOMEM;
1378 : : goto fail;
1379 : : }
1380 : :
1381 : 0 : list->dbs[0] = talloc_steal(list, sysdb);
1382 : : }
1383 : :
1384 : 0 : *_list = list;
1385 : 0 : return EOK;
1386 : :
1387 : : fail:
1388 : 0 : talloc_free(list);
1389 : 0 : return ret;
1390 : : }
1391 : :
1392 : 35 : int compare_ldb_dn_comp_num(const void *m1, const void *m2)
1393 : : {
1394 : 35 : struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1),
1395 : : struct ldb_message);
1396 : 35 : struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2),
1397 : : struct ldb_message);
1398 : :
1399 : 35 : return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn);
1400 : : }
1401 : :
1402 : 2 : int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,
1403 : : const char *newname)
1404 : : {
1405 : 2 : struct ldb_message_element *e = NULL;
1406 : : int i;
1407 : : const char *dummy;
1408 : :
1409 [ + - ][ + - ]: 2 : if (attrs == NULL || oldname == NULL || newname == NULL) return EINVAL;
1410 : :
1411 [ + + ]: 7 : for (i = 0; i < attrs->num; i++) {
1412 [ + + ]: 6 : if (strcasecmp(oldname, attrs->a[i].name) == 0) {
1413 : 2 : e = &(attrs->a[i]);
1414 : : }
1415 [ + + ]: 6 : if (strcasecmp(newname, attrs->a[i].name) == 0) {
1416 [ + - ][ + - ]: 1 : DEBUG(3, ("New attribute name [%s] already exists.\n", newname));
[ - + ][ # # ]
[ # # ]
1417 : : return EEXIST;
1418 : : }
1419 : : }
1420 : :
1421 [ + - ]: 1 : if (e != NULL) {
1422 : 1 : dummy = talloc_strdup(attrs, newname);
1423 [ - + ]: 1 : if (dummy == NULL) {
1424 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_strdup failed.\n"));
[ # # ][ # # ]
[ # # ]
1425 : : return ENOMEM;
1426 : : }
1427 : :
1428 : 1 : talloc_free(discard_const(e->name));
1429 : 2 : e->name = dummy;
1430 : : }
1431 : :
1432 : : return EOK;
1433 : : }
1434 : :
1435 : : /* Search for all incidences of attr_name in a list of
1436 : : * sysdb_attrs and add their value to a list
1437 : : *
1438 : : * TODO: Currently only works for single-valued
1439 : : * attributes. Multi-valued attributes will return
1440 : : * only the first entry
1441 : : */
1442 : 1 : errno_t sysdb_attrs_to_list(TALLOC_CTX *mem_ctx,
1443 : : struct sysdb_attrs **attrs,
1444 : : int attr_count,
1445 : : const char *attr_name,
1446 : : char ***_list)
1447 : : {
1448 : : int attr_idx;
1449 : : int i;
1450 : : char **list;
1451 : : char **tmp_list;
1452 : : int list_idx;
1453 : :
1454 : 1 : *_list = NULL;
1455 : :
1456 : : /* Assume that every attrs entry contains the attr_name
1457 : : * This may waste a little memory if some entries don't
1458 : : * have the attribute, but it will save us the trouble
1459 : : * of continuously resizing the array.
1460 : : */
1461 : 1 : list = talloc_array(mem_ctx, char *, attr_count+1);
1462 [ + - ]: 1 : if (!list) {
1463 : : return ENOMEM;
1464 : : }
1465 : :
1466 : : list_idx = 0;
1467 : : /* Loop through all entries in attrs */
1468 [ + + ]: 4 : for (attr_idx = 0; attr_idx < attr_count; attr_idx++) {
1469 : : /* Examine each attribute within the entry */
1470 [ + + ]: 4 : for (i = 0; i < attrs[attr_idx]->num; i++) {
1471 [ + + ]: 3 : if (strcasecmp(attrs[attr_idx]->a[i].name, attr_name) == 0) {
1472 : : /* Attribute name matches the requested name
1473 : : * Copy it to the output list
1474 : : */
1475 : 2 : list[list_idx] = talloc_strdup(
1476 : : list,
1477 : 2 : (const char *)attrs[attr_idx]->a[i].values[0].data);
1478 [ - + ]: 2 : if (!list[list_idx]) {
1479 : 0 : talloc_free(list);
1480 : 0 : return ENOMEM;
1481 : : }
1482 : 2 : list_idx++;
1483 : :
1484 : : /* We only support single-valued attributes
1485 : : * Break here and go on to the next entry
1486 : : */
1487 : 2 : break;
1488 : : }
1489 : : }
1490 : : }
1491 : :
1492 : 1 : list[list_idx] = NULL;
1493 : :
1494 : : /* if list_idx < attr_count, do a realloc to
1495 : : * reclaim unused memory
1496 : : */
1497 [ + - ]: 1 : if (list_idx < attr_count) {
1498 : 1 : tmp_list = talloc_realloc(mem_ctx, list, char *, list_idx+1);
1499 [ - + ]: 1 : if (!tmp_list) {
1500 : 0 : talloc_zfree(list);
1501 : 0 : return ENOMEM;
1502 : : }
1503 : : list = tmp_list;
1504 : : }
1505 : :
1506 : 1 : *_list = list;
1507 : 1 : return EOK;
1508 : : }
1509 : :
1510 : 2 : errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
1511 : : struct ldb_dn *dn,
1512 : : const char *attr_name,
1513 : : bool *value)
1514 : : {
1515 : : TALLOC_CTX *tmp_ctx;
1516 : : struct ldb_result *res;
1517 : : errno_t ret;
1518 : : int lret;
1519 : 2 : const char *attrs[2] = {attr_name, NULL};
1520 : :
1521 : 2 : tmp_ctx = talloc_new(NULL);
1522 [ + - ]: 2 : if (tmp_ctx == NULL) {
1523 : : return ENOMEM;
1524 : : }
1525 : :
1526 : 2 : lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
1527 : : attrs, NULL);
1528 [ - + ]: 2 : if (lret != LDB_SUCCESS) {
1529 : 0 : ret = sysdb_error_to_errno(lret);
1530 : : goto done;
1531 : : }
1532 : :
1533 [ + + ]: 2 : if (res->count == 0) {
1534 : : /* This entry has not been populated in LDB
1535 : : * This is a common case, as unlike LDAP,
1536 : : * LDB does not need to have all of its parent
1537 : : * objects actually exist.
1538 : : * This object in the sysdb exists mostly just
1539 : : * to contain this attribute.
1540 : : */
1541 : 1 : *value = false;
1542 : 1 : ret = EOK;
1543 : 1 : goto done;
1544 [ - + ]: 1 : } else if (res->count != 1) {
1545 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
1546 : : ("Got more than one reply for base search!\n"));
1547 : : ret = EIO;
1548 : : goto done;
1549 : : }
1550 : :
1551 : 1 : *value = ldb_msg_find_attr_as_bool(res->msgs[0], attr_name, false);
1552 : :
1553 : 1 : ret = EOK;
1554 : :
1555 : : done:
1556 : 2 : talloc_free(tmp_ctx);
1557 : : return ret;
1558 : : }
1559 : :
1560 : 1 : errno_t sysdb_set_bool(struct sysdb_ctx *sysdb,
1561 : : struct ldb_dn *dn,
1562 : : const char *cn_value,
1563 : : const char *attr_name,
1564 : : bool value)
1565 : : {
1566 : 1 : TALLOC_CTX *tmp_ctx = NULL;
1567 : 1 : struct ldb_message *msg = NULL;
1568 : 1 : struct ldb_result *res = NULL;
1569 : : errno_t ret;
1570 : : int lret;
1571 : :
1572 [ + - ][ + - ]: 1 : if (dn == NULL || cn_value == NULL || attr_name == NULL) {
1573 : : return EINVAL;
1574 : : }
1575 : :
1576 : 1 : tmp_ctx = talloc_new(NULL);
1577 [ + - ]: 1 : if (tmp_ctx == NULL) {
1578 : : return ENOMEM;
1579 : : }
1580 : :
1581 : 1 : lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
1582 : : NULL, NULL);
1583 [ - + ]: 1 : if (lret != LDB_SUCCESS) {
1584 : 0 : ret = sysdb_error_to_errno(lret);
1585 : : goto done;
1586 : : }
1587 : :
1588 : 1 : msg = ldb_msg_new(tmp_ctx);
1589 [ + - ]: 1 : if (msg == NULL) {
1590 : : ret = ENOMEM;
1591 : : goto done;
1592 : : }
1593 : 1 : msg->dn = dn;
1594 : :
1595 [ + - ]: 1 : if (res->count == 0) {
1596 : 1 : lret = ldb_msg_add_string(msg, "cn", cn_value);
1597 [ - + ]: 1 : if (lret != LDB_SUCCESS) {
1598 : 0 : ret = sysdb_error_to_errno(lret);
1599 : : goto done;
1600 : : }
1601 [ # # ]: 0 : } else if (res->count != 1) {
1602 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
1603 : : ("Got more than one reply for base search!\n"));
1604 : : ret = EIO;
1605 : : goto done;
1606 : : } else {
1607 : 0 : lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
1608 [ # # ]: 0 : if (lret != LDB_SUCCESS) {
1609 : 0 : ret = sysdb_error_to_errno(lret);
1610 : : goto done;
1611 : : }
1612 : : }
1613 : :
1614 [ - + ]: 1 : lret = ldb_msg_add_string(msg, attr_name, value ? "TRUE" : "FALSE");
1615 [ - + ]: 1 : if (lret != LDB_SUCCESS) {
1616 : 0 : ret = sysdb_error_to_errno(lret);
1617 : : goto done;
1618 : : }
1619 : :
1620 [ - + ]: 1 : if (res->count) {
1621 : 0 : lret = ldb_modify(sysdb->ldb, msg);
1622 : : } else {
1623 : 1 : lret = ldb_add(sysdb->ldb, msg);
1624 : : }
1625 : :
1626 : 1 : ret = sysdb_error_to_errno(lret);
1627 : :
1628 : : done:
1629 : 1 : talloc_free(tmp_ctx);
1630 : : return ret;
1631 : : }
1632 : :
1633 : 2 : errno_t sysdb_has_enumerated(struct sysdb_ctx *sysdb,
1634 : : bool *has_enumerated)
1635 : : {
1636 : : errno_t ret;
1637 : : struct ldb_dn *dn;
1638 : : TALLOC_CTX *tmp_ctx;
1639 : :
1640 : :
1641 : 2 : tmp_ctx = talloc_new(NULL);
1642 [ + - ]: 2 : if (!tmp_ctx) {
1643 : : ret = ENOMEM;
1644 : : goto done;
1645 : : }
1646 : :
1647 : 2 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
1648 : : SYSDB_DOM_BASE,
1649 : 2 : sysdb->domain->name);
1650 [ + - ]: 2 : if (!dn) {
1651 : : ret = ENOMEM;
1652 : : goto done;
1653 : : }
1654 : :
1655 : 2 : ret = sysdb_get_bool(sysdb, dn, SYSDB_HAS_ENUMERATED, has_enumerated);
1656 : :
1657 : : done:
1658 : 2 : talloc_free(tmp_ctx);
1659 : 2 : return ret;
1660 : : }
1661 : :
1662 : 1 : errno_t sysdb_set_enumerated(struct sysdb_ctx *sysdb,
1663 : : bool enumerated)
1664 : : {
1665 : : errno_t ret;
1666 : : TALLOC_CTX *tmp_ctx;
1667 : : struct ldb_dn *dn;
1668 : :
1669 : 1 : tmp_ctx = talloc_new(NULL);
1670 [ + - ]: 1 : if (!tmp_ctx) {
1671 : : ret = ENOMEM;
1672 : : goto done;
1673 : : }
1674 : :
1675 : 1 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
1676 : : SYSDB_DOM_BASE,
1677 : 1 : sysdb->domain->name);
1678 [ + - ]: 1 : if (!dn) {
1679 : : ret = ENOMEM;
1680 : : goto done;
1681 : : }
1682 : :
1683 : 1 : ret = sysdb_set_bool(sysdb, dn, sysdb->domain->name,
1684 : : SYSDB_HAS_ENUMERATED, enumerated);
1685 : :
1686 : : done:
1687 : 1 : talloc_free(tmp_ctx);
1688 : 1 : return ret;
1689 : : }
1690 : :
1691 : 0 : errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
1692 : : struct sysdb_attrs *attrs,
1693 : : const char *ldap_attr,
1694 : : const char **_primary)
1695 : : {
1696 : : errno_t ret;
1697 : 0 : char *rdn_attr = NULL;
1698 : 0 : char *rdn_val = NULL;
1699 : : struct ldb_message_element *sysdb_name_el;
1700 : : struct ldb_message_element *orig_dn_el;
1701 : : size_t i;
1702 : 0 : TALLOC_CTX *tmp_ctx = NULL;
1703 : :
1704 : 0 : tmp_ctx = talloc_new(NULL);
1705 [ # # ]: 0 : if (!tmp_ctx) {
1706 : : return ENOMEM;
1707 : : }
1708 : :
1709 : 0 : ret = sysdb_attrs_get_el(attrs,
1710 : : SYSDB_NAME,
1711 : : &sysdb_name_el);
1712 [ # # ][ # # ]: 0 : if (ret != EOK || sysdb_name_el->num_values == 0) {
1713 : : ret = EINVAL;
1714 : : goto done;
1715 : : }
1716 : :
1717 [ # # ]: 0 : if (sysdb_name_el->num_values == 1) {
1718 : : /* Entry contains only one name. Just return that */
1719 : 0 : *_primary = (const char *)sysdb_name_el->values[0].data;
1720 : 0 : ret = EOK;
1721 : 0 : goto done;
1722 : : }
1723 : :
1724 : : /* Multiple values for name. Check whether one matches the RDN */
1725 : :
1726 : 0 : ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
1727 [ # # ]: 0 : if (ret) {
1728 : : goto done;
1729 : : }
1730 [ # # ]: 0 : if (orig_dn_el->num_values == 0) {
1731 [ # # ][ # # ]: 0 : DEBUG(1, ("Original DN is not available.\n"));
[ # # ][ # # ]
[ # # ]
1732 : : ret = EINVAL;
1733 : : goto done;
1734 [ # # ]: 0 : } else if (orig_dn_el->num_values == 1) {
1735 : 0 : ret = sysdb_get_rdn(sysdb, tmp_ctx,
1736 : 0 : (const char *) orig_dn_el->values[0].data,
1737 : : &rdn_attr,
1738 : : &rdn_val);
1739 [ # # ]: 0 : if (ret != EOK) {
1740 [ # # ][ # # ]: 0 : DEBUG(1, ("Could not get rdn from [%s]\n",
[ # # ][ # # ]
[ # # ]
1741 : : (const char *) orig_dn_el->values[0].data));
1742 : : goto done;
1743 : : }
1744 : : } else {
1745 [ # # ][ # # ]: 0 : DEBUG(1, ("Should not have more than one origDN\n"));
[ # # ][ # # ]
[ # # ]
1746 : : ret = EINVAL;
1747 : : goto done;
1748 : : }
1749 : :
1750 : : /* First check whether the attribute name matches */
1751 [ # # ][ # # ]: 0 : DEBUG(8, ("Comparing attribute names [%s] and [%s]\n",
[ # # ][ # # ]
[ # # ]
1752 : : rdn_attr, ldap_attr));
1753 [ # # ]: 0 : if (strcasecmp(rdn_attr, ldap_attr) != 0) {
1754 : : /* Multiple entries, and the RDN attribute doesn't match.
1755 : : * We have no way of resolving this deterministically,
1756 : : * so we'll use the first value as a fallback.
1757 : : */
1758 [ # # ][ # # ]: 0 : DEBUG(3, ("The entry has multiple names and the RDN attribute does "
[ # # ][ # # ]
[ # # ]
1759 : : "not match. Will use the first value as fallback.\n"));
1760 : 0 : *_primary = (const char *)sysdb_name_el->values[0].data;
1761 : 0 : ret = EOK;
1762 : 0 : goto done;
1763 : : }
1764 : :
1765 [ # # ]: 0 : for (i = 0; i < sysdb_name_el->num_values; i++) {
1766 [ # # ]: 0 : if (strcasecmp(rdn_val,
1767 : 0 : (const char *)sysdb_name_el->values[i].data) == 0) {
1768 : : /* This name matches the RDN. Use it */
1769 : : break;
1770 : : }
1771 : : }
1772 [ # # ]: 0 : if (i < sysdb_name_el->num_values) {
1773 : : /* Match was found */
1774 : 0 : *_primary = (const char *)sysdb_name_el->values[i].data;
1775 : : } else {
1776 : : /* If we can't match the name to the RDN, we just have to
1777 : : * throw up our hands. There's no deterministic way to
1778 : : * decide which name is correct.
1779 : : */
1780 [ # # ][ # # ]: 0 : DEBUG(1, ("Cannot save entry. Unable to determine groupname\n"));
[ # # ][ # # ]
[ # # ]
1781 : : ret = EINVAL;
1782 : : goto done;
1783 : : }
1784 : :
1785 : 0 : ret = EOK;
1786 : :
1787 : : done:
1788 [ # # ]: 0 : if (ret != EOK) {
1789 [ # # ][ # # ]: 0 : DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
[ # # ][ # # ]
[ # # ]
1790 : : ret, strerror(ret)));
1791 : : }
1792 : 0 : talloc_free(tmp_ctx);
1793 : : return ret;
1794 : : }
1795 : :
1796 : : /*
1797 : : * An entity with multiple names would have multiple SYSDB_NAME attributes
1798 : : * after being translated into sysdb names using a map.
1799 : : * Given a primary name returned by sysdb_attrs_primary_name(), this function
1800 : : * returns the other SYSDB_NAME attribute values so they can be saved as
1801 : : * SYSDB_NAME_ALIAS into cache.
1802 : : *
1803 : : * If lowercase is set, all aliases are duplicated in lowercase as well.
1804 : : */
1805 : 0 : errno_t sysdb_attrs_get_aliases(TALLOC_CTX *mem_ctx,
1806 : : struct sysdb_attrs *attrs,
1807 : : const char *primary,
1808 : : bool lowercase,
1809 : : const char ***_aliases)
1810 : : {
1811 : 0 : TALLOC_CTX *tmp_ctx = NULL;
1812 : : struct ldb_message_element *sysdb_name_el;
1813 : : size_t i, j, ai;
1814 : : errno_t ret;
1815 : 0 : const char **aliases = NULL;
1816 : : const char *name;
1817 : : char *lower;
1818 : :
1819 [ # # ]: 0 : if (_aliases == NULL) return EINVAL;
1820 : :
1821 : 0 : tmp_ctx = talloc_new(NULL);
1822 [ # # ]: 0 : if (!tmp_ctx) {
1823 : : return ENOMEM;
1824 : : }
1825 : :
1826 : 0 : ret = sysdb_attrs_get_el(attrs,
1827 : : SYSDB_NAME,
1828 : : &sysdb_name_el);
1829 [ # # ][ # # ]: 0 : if (ret != EOK || sysdb_name_el->num_values == 0) {
1830 : : ret = EINVAL;
1831 : : goto done;
1832 : : }
1833 : :
1834 : 0 : aliases = talloc_array(tmp_ctx, const char *,
1835 : : sysdb_name_el->num_values + 1);
1836 [ # # ]: 0 : if (!aliases) {
1837 : : ret = ENOMEM;
1838 : : goto done;
1839 : : }
1840 : :
1841 [ # # ]: 0 : if (lowercase) {
1842 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
1843 : : ("Domain is case-insensitive; will add lowercased aliases\n"));
1844 : : }
1845 : :
1846 : : ai = 0;
1847 [ # # ]: 0 : for (i=0; i < sysdb_name_el->num_values; i++) {
1848 : 0 : name = (const char *)sysdb_name_el->values[i].data;
1849 : :
1850 [ # # ]: 0 : if (lowercase) {
1851 : : /* Domain is case-insensitive. Save the lower-cased version */
1852 : 0 : lower = sss_tc_utf8_str_tolower(tmp_ctx, name);
1853 [ # # ]: 0 : if (!lower) {
1854 : : ret = ENOMEM;
1855 : : goto done;
1856 : : }
1857 : :
1858 [ # # ]: 0 : for (j=0; j < ai; j++) {
1859 [ # # ]: 0 : if (sss_utf8_case_eq((const uint8_t *) aliases[j],
1860 : : (const uint8_t *) lower) == ENOMATCH) {
1861 : : break;
1862 : : }
1863 : : }
1864 : :
1865 [ # # ]: 0 : if (ai == 0 || j < ai) {
1866 : 0 : aliases[ai] = talloc_strdup(aliases, lower);
1867 [ # # ]: 0 : if (!aliases[ai]) {
1868 : : ret = ENOMEM;
1869 : : goto done;
1870 : : }
1871 : 0 : ai++;
1872 : : }
1873 : : } else {
1874 : : /* Domain is case-sensitive. Save it as-is */
1875 [ # # ]: 0 : if (strcmp(primary, name) != 0) {
1876 : 0 : aliases[ai] = talloc_strdup(aliases, name);
1877 [ # # ]: 0 : if (!aliases[ai]) {
1878 : : ret = ENOMEM;
1879 : : goto done;
1880 : : }
1881 : 0 : ai++;
1882 : : }
1883 : : }
1884 : : }
1885 : :
1886 : 0 : aliases[ai] = NULL;
1887 : :
1888 : 0 : ret = EOK;
1889 : :
1890 : : done:
1891 : 0 : *_aliases = talloc_steal(mem_ctx, aliases);
1892 : 0 : talloc_free(tmp_ctx);
1893 : : return ret;
1894 : : }
1895 : :
1896 : 0 : errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
1897 : : TALLOC_CTX *mem_ctx,
1898 : : struct sysdb_attrs **attr_list,
1899 : : size_t attr_count,
1900 : : const char *ldap_attr,
1901 : : char ***name_list)
1902 : : {
1903 : : errno_t ret;
1904 : : size_t i, j;
1905 : : char **list;
1906 : : const char *name;
1907 : :
1908 : : /* Assume that every entry has a primary name */
1909 : 0 : list = talloc_array(mem_ctx, char *, attr_count+1);
1910 [ # # ]: 0 : if (!list) {
1911 : : return ENOMEM;
1912 : : }
1913 : :
1914 : : j = 0;
1915 [ # # ]: 0 : for (i = 0; i < attr_count; i++) {
1916 : 0 : ret = sysdb_attrs_primary_name(sysdb,
1917 : 0 : attr_list[i],
1918 : : ldap_attr,
1919 : : &name);
1920 [ # # ]: 0 : if (ret != EOK) {
1921 [ # # ][ # # ]: 0 : DEBUG(1, ("Could not determine primary name\n"));
[ # # ][ # # ]
[ # # ]
1922 : : /* Skip and continue. Don't advance 'j' */
1923 : 0 : continue;
1924 : : }
1925 : :
1926 : 0 : list[j] = talloc_strdup(list, name);
1927 [ # # ]: 0 : if (!list[j]) {
1928 : : ret = ENOMEM;
1929 : : goto done;
1930 : : }
1931 : :
1932 : 0 : j++;
1933 : : }
1934 : :
1935 : : /* NULL-terminate the list */
1936 : 0 : list[j] = NULL;
1937 : :
1938 : 0 : *name_list = list;
1939 : :
1940 : 0 : ret = EOK;
1941 : :
1942 : : done:
1943 [ # # ]: 0 : if (ret != EOK) {
1944 : 0 : talloc_free(list);
1945 : : }
1946 : : return ret;
1947 : : }
1948 : :
1949 : 0 : errno_t sysdb_get_real_name(TALLOC_CTX *mem_ctx,
1950 : : struct sysdb_ctx *sysdb,
1951 : : const char *name,
1952 : : const char **_cname)
1953 : : {
1954 : : errno_t ret;
1955 : : TALLOC_CTX *tmp_ctx;
1956 : : struct ldb_result *res;
1957 : : const char *cname;
1958 : :
1959 : 0 : tmp_ctx = talloc_new(NULL);
1960 [ # # ]: 0 : if (!tmp_ctx) {
1961 : : return ENOMEM;
1962 : : }
1963 : :
1964 : 0 : ret = sysdb_getpwnam(tmp_ctx, sysdb, name, &res);
1965 [ # # ]: 0 : if (ret != EOK) {
1966 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Cannot canonicalize username\n"));
[ # # ][ # # ]
[ # # ]
1967 : : goto done;
1968 : : }
1969 : :
1970 [ # # ]: 0 : if (res->count == 0) {
1971 : : /* User is not cached yet */
1972 : : ret = ENOENT;
1973 : : goto done;
1974 [ # # ]: 0 : } else if (res->count != 1) {
1975 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
1976 : : ("sysdb_getpwnam returned count: [%d]\n", res->count));
1977 : : ret = EIO;
1978 : : goto done;
1979 : : }
1980 : :
1981 : 0 : cname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
1982 [ # # ]: 0 : if (!cname) {
1983 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no name?\n"));
[ # # ][ # # ]
[ # # ]
1984 : : ret = ENOENT;
1985 : : goto done;
1986 : : }
1987 : :
1988 : 0 : ret = EOK;
1989 : 0 : *_cname = talloc_steal(mem_ctx, cname);
1990 : : done:
1991 : 0 : talloc_free(tmp_ctx);
1992 : : return ret;
1993 : : }
1994 : :
1995 : 0 : errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count,
1996 : : struct ldb_message **msgs,
1997 : : struct sysdb_attrs ***attrs)
1998 : : {
1999 : : int i;
2000 : : struct sysdb_attrs **a;
2001 : :
2002 : 0 : a = talloc_array(mem_ctx, struct sysdb_attrs *, count);
2003 [ # # ]: 0 : if (a == NULL) {
2004 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_array failed.\n"));
[ # # ][ # # ]
[ # # ]
2005 : : return ENOMEM;
2006 : : }
2007 : :
2008 [ # # ]: 0 : for (i = 0; i < count; i++) {
2009 : 0 : a[i] = talloc(a, struct sysdb_attrs);
2010 [ # # ]: 0 : if (a[i] == NULL) {
2011 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc failed.\n"));
[ # # ][ # # ]
[ # # ]
2012 : 0 : talloc_free(a);
2013 : 0 : return ENOMEM;
2014 : : }
2015 : 0 : a[i]->num = msgs[i]->num_elements;
2016 : 0 : a[i]->a = talloc_steal(a[i], msgs[i]->elements);
2017 : : }
2018 : :
2019 : 0 : *attrs = a;
2020 : :
2021 : 0 : return EOK;
2022 : : }
|