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