-: 0:Source:src/db/sysdb_ops.c -: 0:Graph:src/db/sysdb_tests-sysdb_ops.gcno -: 0:Data:src/db/sysdb_tests-sysdb_ops.gcda -: 0:Runs:9 -: 0:Programs:7 -: 1:/* -: 2: SSSD -: 3: -: 4: System Database -: 5: -: 6: Copyright (C) Simo Sorce 2008 -: 7: -: 8: This program is free software; you can redistribute it and/or modify -: 9: it under the terms of the GNU General Public License as published by -: 10: the Free Software Foundation; either version 3 of the License, or -: 11: (at your option) any later version. -: 12: -: 13: This program is distributed in the hope that it will be useful, -: 14: but WITHOUT ANY WARRANTY; without even the implied warranty of -: 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -: 16: GNU General Public License for more details. -: 17: -: 18: You should have received a copy of the GNU General Public License -: 19: along with this program. If not, see . -: 20:*/ -: 21: -: 22:#include "util/util.h" -: 23:#include "db/sysdb_private.h" -: 24:#include "db/sysdb_services.h" -: 25:#include "db/sysdb_autofs.h" -: 26:#include "util/crypto/sss_crypto.h" -: 27:#include -: 28: 5238: 29:int add_string(struct ldb_message *msg, int flags, -: 30: const char *attr, const char *value) -: 31:{ -: 32: int ret; -: 33: 5238: 34: ret = ldb_msg_add_empty(msg, attr, flags, NULL); 5238: 35: if (ret == LDB_SUCCESS) { 5238: 36: ret = ldb_msg_add_string(msg, attr, value); 5238: 37: if (ret == LDB_SUCCESS) return EOK; -: 38: } #####: 39: return ENOMEM; -: 40:} -: 41: 3368: 42:int add_ulong(struct ldb_message *msg, int flags, -: 43: const char *attr, unsigned long value) -: 44:{ -: 45: int ret; -: 46: 3368: 47: ret = ldb_msg_add_empty(msg, attr, flags, NULL); 3368: 48: if (ret == LDB_SUCCESS) { 3368: 49: ret = ldb_msg_add_fmt(msg, attr, "%lu", value); 3368: 50: if (ret == LDB_SUCCESS) return EOK; -: 51: } #####: 52: return ENOMEM; -: 53:} -: 54: #####: 55:static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr) -: 56:{ #####: 57: const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr); -: 58: long long int l; -: 59: #####: 60: if (!v || !v->data) { #####: 61: return 0; -: 62: } -: 63: #####: 64: errno = 0; #####: 65: l = strtoll((const char *)v->data, NULL, 10); #####: 66: if (errno) { #####: 67: return (uint32_t)-1; -: 68: } -: 69: #####: 70: if (l < 0 || l > ((uint32_t)(-1))) { #####: 71: return (uint32_t)-1; -: 72: } -: 73: #####: 74: return l; -: 75:} -: 76: 315: 77:static int sss_ldb_modify_permissive(struct ldb_context *ldb, -: 78: struct ldb_message *msg) -: 79:{ -: 80: struct ldb_request *req; 315: 81: int ret = EOK; -: 82: 315: 83: ret = ldb_build_mod_req(&req, ldb, ldb, -: 84: msg, -: 85: NULL, -: 86: NULL, -: 87: ldb_op_default_callback, -: 88: NULL); -: 89: 315: 90: if (ret != LDB_SUCCESS) return ret; -: 91: 315: 92: ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID, -: 93: false, NULL); 315: 94: if (ret != LDB_SUCCESS) { #####: 95: talloc_free(req); #####: 96: return ret; -: 97: } -: 98: 315: 99: ret = ldb_request(ldb, req); 315: 100: if (ret == LDB_SUCCESS) { 315: 101: ret = ldb_wait(req->handle, LDB_WAIT_ALL); -: 102: } -: 103: 315: 104: talloc_free(req); -: 105: 315: 106: return ret; -: 107:} -: 108: -: 109:#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0) -: 110: -: 111: -: 112:/* =Remove-Entry-From-Sysdb=============================================== */ -: 113: 1575: 114:int sysdb_delete_entry(struct sysdb_ctx *sysdb, -: 115: struct ldb_dn *dn, -: 116: bool ignore_not_found) -: 117:{ -: 118: int ret; -: 119: 1575: 120: ret = ldb_delete(sysdb->ldb, dn); 1575: 121: switch (ret) { -: 122: case LDB_SUCCESS: 1575: 123: return EOK; -: 124: case LDB_ERR_NO_SUCH_OBJECT: #####: 125: if (ignore_not_found) { #####: 126: return EOK; -: 127: } -: 128: /* fall through */ -: 129: default: #####: 130: DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n", -: 131: ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb))); #####: 132: return sysdb_error_to_errno(ret); -: 133: } -: 134:} -: 135: -: 136:/* =Remove-Subentries-From-Sysdb=========================================== */ -: 137: 27: 138:int sysdb_delete_recursive(struct sysdb_ctx *sysdb, -: 139: struct ldb_dn *dn, -: 140: bool ignore_not_found) -: 141:{ 27: 142: const char *no_attrs[] = { NULL }; -: 143: struct ldb_message **msgs; -: 144: size_t msgs_count; -: 145: int ret; -: 146: int i; -: 147: TALLOC_CTX *tmp_ctx; -: 148: 27: 149: tmp_ctx = talloc_new(NULL); 27: 150: if (!tmp_ctx) { #####: 151: return ENOMEM; -: 152: } -: 153: 27: 154: ret = ldb_transaction_start(sysdb->ldb); 27: 155: if (ret) { #####: 156: ret = sysdb_error_to_errno(ret); #####: 157: goto done; -: 158: } -: 159: 27: 160: ret = sysdb_search_entry(tmp_ctx, sysdb, dn, -: 161: LDB_SCOPE_SUBTREE, "(distinguishedName=*)", -: 162: no_attrs, &msgs_count, &msgs); 27: 163: if (ret) { #####: 164: if (ignore_not_found && ret == ENOENT) { #####: 165: ret = EOK; -: 166: } #####: 167: if (ret) { #####: 168: DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret))); -: 169: } #####: 170: goto done; -: 171: } -: 172: 27: 173: DEBUG(9, ("Found [%d] items to delete.\n", msgs_count)); -: 174: 27: 175: qsort(msgs, msgs_count, -: 176: sizeof(struct ldb_message *), compare_ldb_dn_comp_num); -: 177: 198: 178: for (i = 0; i < msgs_count; i++) { 171: 179: DEBUG(9 ,("Trying to delete [%s].\n", -: 180: ldb_dn_get_linearized(msgs[i]->dn))); -: 181: 171: 182: ret = sysdb_delete_entry(sysdb, msgs[i]->dn, false); 171: 183: if (ret) { #####: 184: goto done; -: 185: } -: 186: } -: 187: -: 188:done: 27: 189: if (ret == EOK) { 27: 190: ret = ldb_transaction_commit(sysdb->ldb); 27: 191: ret = sysdb_error_to_errno(ret); -: 192: } else { #####: 193: ldb_transaction_cancel(sysdb->ldb); -: 194: } 27: 195: talloc_free(tmp_ctx); 27: 196: return ret; -: 197:} -: 198: -: 199: -: 200:/* =Search-Entry========================================================== */ -: 201: 11641: 202:int sysdb_search_entry(TALLOC_CTX *mem_ctx, -: 203: struct sysdb_ctx *sysdb, -: 204: struct ldb_dn *base_dn, -: 205: int scope, -: 206: const char *filter, -: 207: const char **attrs, -: 208: size_t *msgs_count, -: 209: struct ldb_message ***msgs) -: 210:{ -: 211: struct ldb_result *res; -: 212: int ret; -: 213: 11641: 214: ret = ldb_search(sysdb->ldb, mem_ctx, &res, -: 215: base_dn, scope, attrs, -: 216: filter?"%s":NULL, filter); 11641: 217: if (ret) { #####: 218: return sysdb_error_to_errno(ret); -: 219: } -: 220: 11641: 221: *msgs_count = res->count; 11641: 222: *msgs = talloc_steal(mem_ctx, res->msgs); -: 223: 11641: 224: if (res->count == 0) { 4369: 225: return ENOENT; -: 226: } -: 227: 7272: 228: return EOK; -: 229:} -: 230: -: 231: -: 232:/* =Search-User-by-[UID/NAME]============================================= */ -: 233: 1485: 234:int sysdb_search_user_by_name(TALLOC_CTX *mem_ctx, -: 235: struct sysdb_ctx *sysdb, -: 236: struct sss_domain_info *domain, -: 237: const char *name, -: 238: const char **attrs, -: 239: struct ldb_message **msg) -: 240:{ -: 241: TALLOC_CTX *tmp_ctx; 1485: 242: const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; 1485: 243: struct ldb_message **msgs = NULL; -: 244: struct ldb_dn *basedn; 1485: 245: size_t msgs_count = 0; -: 246: int ret; -: 247: 1485: 248: tmp_ctx = talloc_new(NULL); 1485: 249: if (!tmp_ctx) { #####: 250: return ENOMEM; -: 251: } -: 252: 1485: 253: basedn = sysdb_user_dn(sysdb, tmp_ctx, domain, name); 1485: 254: if (!basedn) { #####: 255: ret = ENOMEM; #####: 256: goto done; -: 257: } -: 258: 1485: 259: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL, -: 260: attrs?attrs:def_attrs, &msgs_count, &msgs); 1485: 261: if (ret) { 1206: 262: goto done; -: 263: } -: 264: 279: 265: *msg = talloc_steal(mem_ctx, msgs[0]); -: 266: -: 267:done: 1485: 268: if (ret == ENOENT) { 1206: 269: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 270: } 279: 271: else if (ret) { #####: 272: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 273: } 1485: 274: talloc_zfree(tmp_ctx); 1485: 275: return ret; -: 276:} -: 277: 531: 278:int sysdb_search_user_by_uid(TALLOC_CTX *mem_ctx, -: 279: struct sysdb_ctx *sysdb, -: 280: struct sss_domain_info *domain, -: 281: uid_t uid, -: 282: const char **attrs, -: 283: struct ldb_message **msg) -: 284:{ -: 285: TALLOC_CTX *tmp_ctx; 531: 286: const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; 531: 287: struct ldb_message **msgs = NULL; -: 288: struct ldb_dn *basedn; 531: 289: size_t msgs_count = 0; -: 290: char *filter; -: 291: int ret; -: 292: 531: 293: tmp_ctx = talloc_new(NULL); 531: 294: if (!tmp_ctx) { #####: 295: return ENOMEM; -: 296: } -: 297: 531: 298: basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 299: SYSDB_TMPL_USER_BASE, domain->name); 531: 300: if (!basedn) { #####: 301: ret = ENOMEM; #####: 302: goto done; -: 303: } -: 304: 531: 305: filter = talloc_asprintf(tmp_ctx, SYSDB_PWUID_FILTER, (unsigned long)uid); 531: 306: if (!filter) { #####: 307: ret = ENOMEM; #####: 308: goto done; -: 309: } -: 310: -: 311: /* Use SUBTREE scope here, not ONELEVEL -: 312: * There is a bug in LDB that makes ONELEVEL searches extremely -: 313: * slow (it ignores indexing) -: 314: */ 531: 315: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter, -: 316: attrs?attrs:def_attrs, &msgs_count, &msgs); 531: 317: if (ret) { 360: 318: goto done; -: 319: } -: 320: 171: 321: *msg = talloc_steal(mem_ctx, msgs[0]); -: 322: -: 323:done: 531: 324: if (ret == ENOENT) { 360: 325: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 326: } 171: 327: else if (ret) { #####: 328: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 329: } -: 330: 531: 331: talloc_zfree(tmp_ctx); 531: 332: return ret; -: 333:} -: 334: -: 335: -: 336:/* =Search-Group-by-[GID/NAME]============================================ */ -: 337: 1251: 338:int sysdb_search_group_by_name(TALLOC_CTX *mem_ctx, -: 339: struct sysdb_ctx *sysdb, -: 340: struct sss_domain_info *domain, -: 341: const char *name, -: 342: const char **attrs, -: 343: struct ldb_message **msg) -: 344:{ -: 345: TALLOC_CTX *tmp_ctx; -: 346: static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL }; 1251: 347: struct ldb_message **msgs = NULL; -: 348: struct ldb_dn *basedn; 1251: 349: size_t msgs_count = 0; -: 350: int ret; -: 351: 1251: 352: tmp_ctx = talloc_new(NULL); 1251: 353: if (!tmp_ctx) { #####: 354: return ENOMEM; -: 355: } -: 356: 1251: 357: basedn = sysdb_group_dn(sysdb, tmp_ctx, domain, name); 1251: 358: if (!basedn) { #####: 359: ret = ENOMEM; #####: 360: goto done; -: 361: } -: 362: 1251: 363: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL, -: 364: attrs?attrs:def_attrs, &msgs_count, &msgs); 1251: 365: if (ret) { 1206: 366: goto done; -: 367: } -: 368: 45: 369: *msg = talloc_steal(mem_ctx, msgs[0]); -: 370: -: 371:done: 1251: 372: if (ret == ENOENT) { 1206: 373: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 374: } 45: 375: else if (ret) { #####: 376: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 377: } 1251: 378: talloc_zfree(tmp_ctx); 1251: 379: return ret; -: 380:} -: 381: 7146: 382:int sysdb_search_group_by_gid(TALLOC_CTX *mem_ctx, -: 383: struct sysdb_ctx *sysdb, -: 384: struct sss_domain_info *domain, -: 385: gid_t gid, -: 386: const char **attrs, -: 387: struct ldb_message **msg) -: 388:{ -: 389: TALLOC_CTX *tmp_ctx; 7146: 390: const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; 7146: 391: struct ldb_message **msgs = NULL; -: 392: struct ldb_dn *basedn; 7146: 393: size_t msgs_count = 0; -: 394: char *filter; -: 395: int ret; -: 396: 7146: 397: tmp_ctx = talloc_new(NULL); 7146: 398: if (!tmp_ctx) { #####: 399: return ENOMEM; -: 400: } -: 401: 7146: 402: basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 403: SYSDB_TMPL_GROUP_BASE, domain->name); 7146: 404: if (!basedn) { #####: 405: ret = ENOMEM; #####: 406: goto done; -: 407: } -: 408: 7146: 409: filter = talloc_asprintf(tmp_ctx, SYSDB_GRGID_FILTER, (unsigned long)gid); 7146: 410: if (!filter) { #####: 411: ret = ENOMEM; #####: 412: goto done; -: 413: } -: 414: -: 415: /* Use SUBTREE scope here, not ONELEVEL -: 416: * There is a bug in LDB that makes ONELEVEL searches extremely -: 417: * slow (it ignores indexing) -: 418: */ 7146: 419: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter, -: 420: attrs?attrs:def_attrs, &msgs_count, &msgs); 7146: 421: if (ret) { 972: 422: goto done; -: 423: } -: 424: 6174: 425: *msg = talloc_steal(mem_ctx, msgs[0]); -: 426: -: 427:done: 7146: 428: if (ret == ENOENT) { 972: 429: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 430: } 6174: 431: else if (ret) { #####: 432: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 433: } -: 434: 7146: 435: talloc_zfree(tmp_ctx); 7146: 436: return ret; -: 437:} -: 438: -: 439: -: 440:/* =Search-Group-by-Name============================================ */ -: 441: 135: 442:int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx, -: 443: struct sysdb_ctx *sysdb, -: 444: struct sss_domain_info *domain, -: 445: const char *name, -: 446: const char **attrs, -: 447: struct ldb_message **msg) -: 448:{ -: 449: TALLOC_CTX *tmp_ctx; -: 450: static const char *def_attrs[] = { SYSDB_NAME, NULL }; 135: 451: struct ldb_message **msgs = NULL; -: 452: struct ldb_dn *basedn; 135: 453: size_t msgs_count = 0; -: 454: int ret; -: 455: 135: 456: tmp_ctx = talloc_new(NULL); 135: 457: if (!tmp_ctx) { #####: 458: return ENOMEM; -: 459: } -: 460: 135: 461: basedn = sysdb_netgroup_dn(sysdb, tmp_ctx, domain, name); 135: 462: if (!basedn) { #####: 463: ret = ENOMEM; #####: 464: goto done; -: 465: } -: 466: 135: 467: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL, -: 468: attrs?attrs:def_attrs, &msgs_count, &msgs); 135: 469: if (ret) { #####: 470: goto done; -: 471: } -: 472: 135: 473: *msg = talloc_steal(mem_ctx, msgs[0]); -: 474: -: 475:done: 135: 476: if (ret == ENOENT) { #####: 477: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 478: } 135: 479: else if (ret) { #####: 480: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 481: } 135: 482: talloc_zfree(tmp_ctx); 135: 483: return ret; -: 484:} -: 485: -: 486:/* =Replace-Attributes-On-Entry=========================================== */ -: 487: 2313: 488:int sysdb_set_entry_attr(struct sysdb_ctx *sysdb, -: 489: struct ldb_dn *entry_dn, -: 490: struct sysdb_attrs *attrs, -: 491: int mod_op) -: 492:{ -: 493: struct ldb_message *msg; -: 494: int i, ret; -: 495: int lret; -: 496: TALLOC_CTX *tmp_ctx; -: 497: 2313: 498: tmp_ctx = talloc_new(NULL); 2313: 499: if (!tmp_ctx) { #####: 500: return ENOMEM; -: 501: } -: 502: 2313: 503: if (!entry_dn || attrs->num == 0) { #####: 504: ret = EINVAL; #####: 505: goto done; -: 506: } -: 507: 2313: 508: msg = ldb_msg_new(tmp_ctx); 2313: 509: if (!msg) { #####: 510: ret = ENOMEM; #####: 511: goto done; -: 512: } -: 513: 2313: 514: msg->dn = entry_dn; -: 515: 2313: 516: msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num); 2313: 517: if (!msg->elements) { #####: 518: ret = ENOMEM; #####: 519: goto done; -: 520: } -: 521: 9333: 522: for (i = 0; i < attrs->num; i++) { 7020: 523: msg->elements[i] = attrs->a[i]; 7020: 524: msg->elements[i].flags = mod_op; -: 525: } -: 526: 2313: 527: msg->num_elements = attrs->num; -: 528: 2313: 529: lret = ldb_modify(sysdb->ldb, msg); 2313: 530: if (lret != LDB_SUCCESS) { #####: 531: DEBUG(SSSDBG_MINOR_FAILURE, -: 532: ("ldb_modify failed: [%s]\n", ldb_strerror(lret))); -: 533: } -: 534: 2313: 535: ret = sysdb_error_to_errno(lret); -: 536: -: 537:done: 2313: 538: if (ret == ENOENT) { #####: 539: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 540: } 2313: 541: else if (ret) { #####: 542: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 543: } 2313: 544: talloc_zfree(tmp_ctx); 2313: 545: return ret; -: 546:} -: 547: -: 548: -: 549:/* =Replace-Attributes-On-User============================================ */ -: 550: 693: 551:int sysdb_set_user_attr(struct sysdb_ctx *sysdb, -: 552: struct sss_domain_info *domain, -: 553: const char *name, -: 554: struct sysdb_attrs *attrs, -: 555: int mod_op) -: 556:{ -: 557: struct ldb_dn *dn; -: 558: TALLOC_CTX *tmp_ctx; -: 559: errno_t ret; -: 560: 693: 561: tmp_ctx = talloc_new(NULL); 693: 562: if (!tmp_ctx) { #####: 563: return ENOMEM; -: 564: } -: 565: 693: 566: dn = sysdb_user_dn(sysdb, tmp_ctx, domain, name); 693: 567: if (!dn) { #####: 568: ret = ENOMEM; #####: 569: goto done; -: 570: } -: 571: 693: 572: ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op); 693: 573: if (ret != EOK) { #####: 574: goto done; -: 575: } -: 576: 693: 577: ret = EOK; -: 578:done: 693: 579: talloc_zfree(tmp_ctx); 693: 580: return ret; -: 581:} -: 582: -: 583: -: 584:/* =Replace-Attributes-On-Group=========================================== */ -: 585: 1485: 586:int sysdb_set_group_attr(struct sysdb_ctx *sysdb, -: 587: struct sss_domain_info *domain, -: 588: const char *name, -: 589: struct sysdb_attrs *attrs, -: 590: int mod_op) -: 591:{ -: 592: struct ldb_dn *dn; -: 593: TALLOC_CTX *tmp_ctx; -: 594: errno_t ret; -: 595: 1485: 596: tmp_ctx = talloc_new(NULL); 1485: 597: if (!tmp_ctx) { #####: 598: ret = ENOMEM; #####: 599: goto done; -: 600: } -: 601: 1485: 602: dn = sysdb_group_dn(sysdb, tmp_ctx, domain, name); 1485: 603: if (!dn) { #####: 604: ret = ENOMEM; #####: 605: goto done; -: 606: } -: 607: 1485: 608: ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op); 1485: 609: if (ret) { #####: 610: goto done; -: 611: } -: 612: 1485: 613: ret = EOK; -: 614:done: 1485: 615: talloc_free(tmp_ctx); 1485: 616: return ret; -: 617:} -: 618: -: 619:/* =Replace-Attributes-On-Netgroup=========================================== */ -: 620: 99: 621:int sysdb_set_netgroup_attr(struct sysdb_ctx *sysdb, -: 622: struct sss_domain_info *domain, -: 623: const char *name, -: 624: struct sysdb_attrs *attrs, -: 625: int mod_op) -: 626:{ -: 627: errno_t ret; -: 628: struct ldb_dn *dn; -: 629: TALLOC_CTX *tmp_ctx; -: 630: 99: 631: tmp_ctx = talloc_new(NULL); 99: 632: if (!tmp_ctx) { #####: 633: return ENOMEM; -: 634: } -: 635: 99: 636: dn = sysdb_netgroup_dn(sysdb, tmp_ctx, domain, name); 99: 637: if (!dn) { #####: 638: ret = ENOMEM; #####: 639: goto done; -: 640: } -: 641: 99: 642: ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op); -: 643: -: 644:done: 99: 645: talloc_free(tmp_ctx); 99: 646: return ret; -: 647:} -: 648: -: 649:/* =Get-New-ID============================================================ */ -: 650: 2: 651:int sysdb_get_new_id(struct sysdb_ctx *sysdb, -: 652: struct sss_domain_info *domain, -: 653: uint32_t *_id) -: 654:{ -: 655: TALLOC_CTX *tmp_ctx; 2: 656: const char *attrs_1[] = { SYSDB_NEXTID, NULL }; 2: 657: const char *attrs_2[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL }; -: 658: struct ldb_dn *base_dn; -: 659: char *filter; 2: 660: uint32_t new_id = 0; -: 661: struct ldb_message **msgs; -: 662: size_t count; -: 663: struct ldb_message *msg; -: 664: uint32_t id; -: 665: int ret; -: 666: int i; -: 667: 2: 668: tmp_ctx = talloc_new(NULL); 2: 669: if (!tmp_ctx) { #####: 670: return ENOMEM; -: 671: } -: 672: 2: 673: base_dn = sysdb_domain_dn(sysdb, tmp_ctx, domain); 2: 674: if (!base_dn) { #####: 675: talloc_zfree(tmp_ctx); #####: 676: return ENOMEM; -: 677: } -: 678: 2: 679: ret = ldb_transaction_start(sysdb->ldb); 2: 680: if (ret) { #####: 681: talloc_zfree(tmp_ctx); #####: 682: ret = sysdb_error_to_errno(ret); #####: 683: return ret; -: 684: } -: 685: 2: 686: ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_BASE, -: 687: SYSDB_NEXTID_FILTER, attrs_1, &count, &msgs); 2: 688: switch (ret) { -: 689: case EOK: #####: 690: new_id = get_attr_as_uint32(msgs[0], SYSDB_NEXTID); #####: 691: if (new_id == (uint32_t)(-1)) { #####: 692: DEBUG(1, ("Invalid Next ID in domain %s\n", domain->name)); #####: 693: ret = ERANGE; #####: 694: goto done; -: 695: } -: 696: #####: 697: if (new_id < domain->id_min) { #####: 698: new_id = domain->id_min; -: 699: } -: 700: #####: 701: if ((domain->id_max != 0) && (new_id > domain->id_max)) { #####: 702: DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n", -: 703: new_id, domain->id_max)); #####: 704: ret = ERANGE; #####: 705: goto done; -: 706: } #####: 707: break; -: 708: -: 709: case ENOENT: -: 710: /* looks like the domain is not initialized yet, use min_id */ 2: 711: new_id = domain->id_min; 2: 712: break; -: 713: -: 714: default: #####: 715: goto done; -: 716: } 2: 717: talloc_zfree(msgs); 2: 718: count = 0; -: 719: -: 720: /* verify the id is actually really free. -: 721: * search all entries with id >= new_id and < max_id */ 2: 722: if (domain->id_max) { #####: 723: filter = talloc_asprintf(tmp_ctx, -: 724: "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))", -: 725: SYSDB_UIDNUM, new_id, -: 726: SYSDB_UIDNUM, domain->id_max, -: 727: SYSDB_GIDNUM, new_id, -: 728: SYSDB_GIDNUM, domain->id_max); -: 729: } -: 730: else { 2: 731: filter = talloc_asprintf(tmp_ctx, -: 732: "(|(%s>=%u)(%s>=%u))", -: 733: SYSDB_UIDNUM, new_id, -: 734: SYSDB_GIDNUM, new_id); -: 735: } 2: 736: if (!filter) { #####: 737: DEBUG(6, ("Error: Out of memory\n")); #####: 738: ret = ENOMEM; #####: 739: goto done; -: 740: } -: 741: 2: 742: ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_SUBTREE, -: 743: filter, attrs_2, &count, &msgs); 2: 744: switch (ret) { -: 745: /* if anything was found, find the maximum and increment past it */ -: 746: case EOK: #####: 747: for (i = 0; i < count; i++) { #####: 748: id = get_attr_as_uint32(msgs[i], SYSDB_UIDNUM); #####: 749: if (id != (uint32_t)(-1)) { #####: 750: if (id > new_id) new_id = id; -: 751: } #####: 752: id = get_attr_as_uint32(msgs[i], SYSDB_GIDNUM); #####: 753: if (id != (uint32_t)(-1)) { #####: 754: if (id > new_id) new_id = id; -: 755: } -: 756: } -: 757: #####: 758: new_id++; -: 759: -: 760: /* check again we are not falling out of range */ #####: 761: if ((domain->id_max != 0) && (new_id > domain->id_max)) { #####: 762: DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n", -: 763: new_id, domain->id_max)); #####: 764: ret = ERANGE; #####: 765: goto done; -: 766: } #####: 767: break; -: 768: -: 769: case ENOENT: 2: 770: break; -: 771: -: 772: default: #####: 773: goto done; -: 774: } -: 775: 2: 776: talloc_zfree(msgs); 2: 777: count = 0; -: 778: -: 779: /* finally store the new next id */ 2: 780: msg = ldb_msg_new(tmp_ctx); 2: 781: if (!msg) { #####: 782: DEBUG(6, ("Error: Out of memory\n")); #####: 783: ret = ENOMEM; #####: 784: goto done; -: 785: } 2: 786: msg->dn = base_dn; -: 787: 2: 788: ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE, 2: 789: SYSDB_NEXTID, new_id + 1); 2: 790: if (ret) { #####: 791: goto done; -: 792: } -: 793: 2: 794: ret = ldb_modify(sysdb->ldb, msg); 2: 795: ret = sysdb_error_to_errno(ret); -: 796: 2: 797: *_id = new_id; -: 798: -: 799:done: 2: 800: if (ret == EOK) { 2: 801: ret = ldb_transaction_commit(sysdb->ldb); 2: 802: ret = sysdb_error_to_errno(ret); -: 803: } else { #####: 804: ldb_transaction_cancel(sysdb->ldb); -: 805: } 2: 806: if (ret) { #####: 807: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 808: } 2: 809: talloc_zfree(tmp_ctx); 2: 810: return ret; -: 811:} -: 812: -: 813: -: 814:/* =Add-Basic-User-NO-CHECKS============================================== */ -: 815: 360: 816:int sysdb_add_basic_user(struct sysdb_ctx *sysdb, -: 817: struct sss_domain_info *domain, -: 818: const char *name, -: 819: uid_t uid, gid_t gid, -: 820: const char *gecos, -: 821: const char *homedir, -: 822: const char *shell) -: 823:{ -: 824: struct ldb_message *msg; -: 825: int ret; -: 826: TALLOC_CTX *tmp_ctx; -: 827: 360: 828: tmp_ctx = talloc_new(NULL); 360: 829: if (!tmp_ctx) { #####: 830: return ENOMEM; -: 831: } -: 832: 360: 833: msg = ldb_msg_new(tmp_ctx); 360: 834: if (!msg) { #####: 835: ret = ENOMEM; #####: 836: goto done; -: 837: } -: 838: -: 839: /* user dn */ 360: 840: msg->dn = sysdb_user_dn(sysdb, msg, domain, name); 360: 841: if (!msg->dn) { #####: 842: ERROR_OUT(ret, ENOMEM, done); -: 843: } -: 844: 360: 845: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS); 360: 846: if (ret) goto done; -: 847: 360: 848: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); 360: 849: if (ret) goto done; -: 850: 360: 851: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid); 360: 852: if (ret) goto done; -: 853: 360: 854: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid); 360: 855: if (ret) goto done; -: 856: -: 857: /* We set gecos to be the same as fullname on user creation, -: 858: * But we will not enforce coherency after that, it's up to -: 859: * admins to decide if they want to keep it in sync if they change -: 860: * one of the 2 */ 360: 861: if (gecos && *gecos) { 351: 862: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos); 351: 863: if (ret) goto done; 351: 864: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos); 351: 865: if (ret) goto done; -: 866: } -: 867: 360: 868: if (homedir && *homedir) { 351: 869: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir); 351: 870: if (ret) goto done; -: 871: } -: 872: 360: 873: if (shell && *shell) { 351: 874: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell); 351: 875: if (ret) goto done; -: 876: } -: 877: -: 878: /* creation time */ 360: 879: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, 360: 880: (unsigned long)time(NULL)); 360: 881: if (ret) goto done; -: 882: 360: 883: ret = ldb_add(sysdb->ldb, msg); 360: 884: ret = sysdb_error_to_errno(ret); -: 885: -: 886:done: 360: 887: if (ret) { #####: 888: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 889: } 360: 890: talloc_zfree(tmp_ctx); 360: 891: return ret; -: 892:} -: 893: -: 894:static errno_t 315: 895:sysdb_remove_ghost_from_group(struct sysdb_ctx *sysdb, -: 896: struct ldb_message *group, -: 897: struct ldb_message_element *alias_el, -: 898: const char *name, -: 899: const char *orig_dn, -: 900: const char *userdn) -: 901:{ -: 902: TALLOC_CTX *tmp_ctx; -: 903: struct ldb_message *msg; -: 904: struct ldb_message_element *orig_members; 315: 905: bool add_member = false; 315: 906: errno_t ret = EOK; -: 907: int i; -: 908: 315: 909: tmp_ctx = talloc_new(NULL); 315: 910: if (!tmp_ctx) { #####: 911: return ENOENT; -: 912: } -: 913: 315: 914: msg = ldb_msg_new(tmp_ctx); 315: 915: if (!msg) { #####: 916: ERROR_OUT(ret, ENOMEM, done); -: 917: } -: 918: 315: 919: msg->dn = group->dn; -: 920: 315: 921: if (orig_dn == NULL) { -: 922: /* We have no way of telling which groups this user belongs to. -: 923: * Add it to all that reference it in the ghost attribute */ 315: 924: add_member = true; -: 925: } else { #####: 926: add_member = false; #####: 927: orig_members = ldb_msg_find_element(group, SYSDB_ORIG_MEMBER); #####: 928: if (orig_members) { #####: 929: for (i = 0; i < orig_members->num_values; i++) { #####: 930: if (strcmp((const char *) orig_members->values[i].data, -: 931: orig_dn) == 0) { -: 932: /* This is a direct member. Add the member attribute */ #####: 933: add_member = true; -: 934: } -: 935: } -: 936: } else { -: 937: /* Nothing to compare the originalDN with. Let's rely on the -: 938: * memberof plugin to do the right thing during initgroups.. -: 939: */ #####: 940: add_member = true; -: 941: } -: 942: } -: 943: 315: 944: if (add_member) { 315: 945: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_MEMBER, userdn); 315: 946: if (ret) goto done; -: 947: } -: 948: 315: 949: ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name); 315: 950: if (ret) goto done; -: 951: -: 952: /* Delete aliases from the ghost attribute as well */ 315: 953: for (i = 0; i < alias_el->num_values; i++) { #####: 954: if (strcmp((const char *)alias_el->values[i].data, name) == 0) { #####: 955: continue; -: 956: } #####: 957: ret = ldb_msg_add_string(msg, SYSDB_GHOST, #####: 958: (char *) alias_el->values[i].data); #####: 959: if (ret != LDB_SUCCESS) { #####: 960: ERROR_OUT(ret, EINVAL, done); -: 961: } -: 962: } -: 963: -: 964: 315: 965: ret = sss_ldb_modify_permissive(sysdb->ldb, msg); 315: 966: ret = sysdb_error_to_errno(ret); 315: 967: if (ret != EOK) { #####: 968: goto done; -: 969: } -: 970: 315: 971: talloc_zfree(msg); -: 972: -: 973: -: 974:done: 315: 975: talloc_free(tmp_ctx); 315: 976: return ret; -: 977:} -: 978: -: 979:static errno_t 351: 980:sysdb_remove_ghostattr_from_groups(struct sysdb_ctx *sysdb, -: 981: struct sss_domain_info *domain, -: 982: const char *orig_dn, -: 983: struct sysdb_attrs *attrs, -: 984: const char *name) -: 985:{ -: 986: TALLOC_CTX *tmp_ctx; -: 987: struct ldb_message **groups; -: 988: struct ldb_message_element *alias_el; -: 989: struct ldb_dn *tmpdn; 351: 990: const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, SYSDB_ORIG_MEMBER, NULL}; -: 991: const char *userdn; -: 992: char *filter; 351: 993: errno_t ret = EOK; 351: 994: size_t group_count = 0; -: 995: int i; -: 996: 351: 997: tmp_ctx = talloc_new(NULL); 351: 998: if (!tmp_ctx) { #####: 999: return ENOENT; -: 1000: } -: 1001: 351: 1002: filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name); 351: 1003: if (!filter) { #####: 1004: ret = ENOMEM; #####: 1005: goto done; -: 1006: } 351: 1007: ret = sysdb_attrs_get_el(attrs, SYSDB_NAME_ALIAS, &alias_el); 351: 1008: if (ret != EOK) { #####: 1009: goto done; -: 1010: } -: 1011: 351: 1012: for (i = 0; i < alias_el->num_values; i++) { #####: 1013: if (strcmp((const char *)alias_el->values[i].data, name) == 0) { #####: 1014: continue; -: 1015: } #####: 1016: filter = talloc_asprintf_append(filter, "(%s=%s)", #####: 1017: SYSDB_GHOST, alias_el->values[i].data); #####: 1018: if (filter == NULL) { #####: 1019: ret = ENOMEM; #####: 1020: goto done; -: 1021: } -: 1022: } -: 1023: 351: 1024: filter = talloc_asprintf_append(filter, ")"); 351: 1025: if (filter == NULL) { #####: 1026: ret = ENOMEM; #####: 1027: goto done; -: 1028: } -: 1029: 351: 1030: tmpdn = sysdb_user_dn(sysdb, tmp_ctx, domain, name); 351: 1031: if (!tmpdn) { #####: 1032: ERROR_OUT(ret, ENOMEM, done); -: 1033: } -: 1034: 351: 1035: userdn = ldb_dn_get_linearized(tmpdn); 351: 1036: if (!userdn) { #####: 1037: ERROR_OUT(ret, EINVAL, done); -: 1038: } -: 1039: 351: 1040: tmpdn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 1041: SYSDB_TMPL_GROUP_BASE, domain->name); 351: 1042: if (!tmpdn) { #####: 1043: ret = ENOMEM; #####: 1044: goto done; -: 1045: } -: 1046: -: 1047: /* We need to find all groups that contain this object as a ghost user -: 1048: * and replace the ghost user by actual member record in direct parents. -: 1049: * Note that this object can be referred to either by its name or any -: 1050: * of its aliases -: 1051: */ 351: 1052: ret = sysdb_search_entry(tmp_ctx, sysdb, tmpdn, LDB_SCOPE_SUBTREE, filter, -: 1053: group_attrs, &group_count, &groups); 351: 1054: if (ret != EOK && ret != ENOENT) { #####: 1055: goto done; -: 1056: } -: 1057: 666: 1058: for (i = 0; i < group_count; i++) { 315: 1059: sysdb_remove_ghost_from_group(sysdb, groups[i], alias_el, name, orig_dn, userdn); -: 1060: } -: 1061: 351: 1062: ret = EOK; -: 1063: -: 1064:done: 351: 1065: talloc_free(tmp_ctx); 351: 1066: return ret; -: 1067:} -: 1068: -: 1069:/* =Add-User-Function===================================================== */ -: 1070: 369: 1071:int sysdb_add_user(struct sysdb_ctx *sysdb, -: 1072: struct sss_domain_info *domain, -: 1073: const char *name, -: 1074: uid_t uid, gid_t gid, -: 1075: const char *gecos, -: 1076: const char *homedir, -: 1077: const char *shell, -: 1078: const char *orig_dn, -: 1079: struct sysdb_attrs *attrs, -: 1080: int cache_timeout, -: 1081: time_t now) -: 1082:{ -: 1083: TALLOC_CTX *tmp_ctx; -: 1084: struct ldb_message *msg; -: 1085: struct sysdb_attrs *id_attrs; -: 1086: uint32_t id; -: 1087: int ret; -: 1088: 369: 1089: if (domain->mpg) { 369: 1090: if (gid != 0) { #####: 1091: DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n")); #####: 1092: return EINVAL; -: 1093: } 369: 1094: gid = uid; -: 1095: } -: 1096: 387: 1097: if (domain->id_max != 0 && uid != 0 && 36: 1098: (uid < domain->id_min || uid > domain->id_max)) { #####: 1099: DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n", -: 1100: uid, domain->id_min, domain->id_max)); #####: 1101: return ERANGE; -: 1102: } -: 1103: 387: 1104: if (domain->id_max != 0 && gid != 0 && 36: 1105: (gid < domain->id_min || gid > domain->id_max)) { #####: 1106: DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n", -: 1107: gid, domain->id_min, domain->id_max)); #####: 1108: return ERANGE; -: 1109: } -: 1110: 369: 1111: tmp_ctx = talloc_new(NULL); 369: 1112: if (!tmp_ctx) { #####: 1113: return ENOMEM; -: 1114: } -: 1115: 369: 1116: ret = ldb_transaction_start(sysdb->ldb); 369: 1117: if (ret) { #####: 1118: ret = sysdb_error_to_errno(ret); #####: 1119: talloc_free(tmp_ctx); #####: 1120: return ret; -: 1121: } -: 1122: 369: 1123: if (domain->mpg) { -: 1124: /* In MPG domains you can't have groups with the same name as users, -: 1125: * search if a group with the same name exists. -: 1126: * Don't worry about users, if we try to add a user with the same -: 1127: * name the operation will fail */ -: 1128: 369: 1129: ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain, -: 1130: name, NULL, &msg); 369: 1131: if (ret != ENOENT) { #####: 1132: if (ret == EOK) ret = EEXIST; #####: 1133: goto done; -: 1134: } -: 1135: } -: 1136: -: 1137: /* check no other user with the same uid exist */ 369: 1138: if (uid != 0) { 369: 1139: ret = sysdb_search_user_by_uid(tmp_ctx, sysdb, domain, -: 1140: uid, NULL, &msg); 369: 1141: if (ret != ENOENT) { 18: 1142: if (ret == EOK) ret = EEXIST; 18: 1143: goto done; -: 1144: } -: 1145: } -: 1146: -: 1147: /* try to add the user */ 351: 1148: ret = sysdb_add_basic_user(sysdb, domain, name, -: 1149: uid, gid, gecos, homedir, shell); 351: 1150: if (ret) goto done; -: 1151: 351: 1152: if (uid == 0) { #####: 1153: ret = sysdb_get_new_id(sysdb, domain, &id); #####: 1154: if (ret) goto done; -: 1155: #####: 1156: id_attrs = sysdb_new_attrs(tmp_ctx); #####: 1157: if (!id_attrs) { #####: 1158: ret = ENOMEM; #####: 1159: goto done; -: 1160: } #####: 1161: ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id); #####: 1162: if (ret) goto done; -: 1163: #####: 1164: if (domain->mpg) { #####: 1165: ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id); #####: 1166: if (ret) goto done; -: 1167: } -: 1168: #####: 1169: ret = sysdb_set_user_attr(sysdb, domain, name, -: 1170: id_attrs, SYSDB_MOD_REP); #####: 1171: goto done; -: 1172: } -: 1173: 351: 1174: if (!attrs) { 90: 1175: attrs = sysdb_new_attrs(tmp_ctx); 90: 1176: if (!attrs) { #####: 1177: ret = ENOMEM; #####: 1178: goto done; -: 1179: } -: 1180: } -: 1181: 351: 1182: if (!now) { 90: 1183: now = time(NULL); -: 1184: } -: 1185: 351: 1186: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 351: 1187: if (ret) goto done; -: 1188: 594: 1189: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1190: ((cache_timeout) ? 243: 1191: (now + cache_timeout) : 0)); 351: 1192: if (ret) goto done; -: 1193: 351: 1194: ret = sysdb_set_user_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); 351: 1195: if (ret) goto done; -: 1196: -: 1197: /* remove all ghost users */ 351: 1198: ret = sysdb_remove_ghostattr_from_groups(sysdb, domain, -: 1199: orig_dn, attrs, name); 351: 1200: if (ret) goto done; -: 1201: 351: 1202: ret = EOK; -: 1203: -: 1204:done: 369: 1205: if (ret == EOK) { 351: 1206: ret = ldb_transaction_commit(sysdb->ldb); 351: 1207: ret = sysdb_error_to_errno(ret); -: 1208: } else { 18: 1209: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); 18: 1210: ldb_transaction_cancel(sysdb->ldb); -: 1211: } 369: 1212: talloc_zfree(tmp_ctx); 369: 1213: return ret; -: 1214:} -: 1215: -: 1216:/* =Add-Basic-Group-NO-CHECKS============================================= */ -: 1217: 1044: 1218:int sysdb_add_basic_group(struct sysdb_ctx *sysdb, -: 1219: struct sss_domain_info *domain, -: 1220: const char *name, gid_t gid) -: 1221:{ -: 1222: struct ldb_message *msg; -: 1223: int ret; -: 1224: TALLOC_CTX *tmp_ctx; -: 1225: 1044: 1226: tmp_ctx = talloc_new(NULL); 1044: 1227: if (!tmp_ctx) { #####: 1228: return ENOMEM; -: 1229: } -: 1230: 1044: 1231: msg = ldb_msg_new(tmp_ctx); 1044: 1232: if (!msg) { #####: 1233: ret = ENOMEM; #####: 1234: goto done; -: 1235: } -: 1236: -: 1237: /* group dn */ 1044: 1238: msg->dn = sysdb_group_dn(sysdb, msg, domain, name); 1044: 1239: if (!msg->dn) { #####: 1240: ERROR_OUT(ret, ENOMEM, done); -: 1241: } -: 1242: 1044: 1243: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS); 1044: 1244: if (ret) goto done; -: 1245: 1044: 1246: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); 1044: 1247: if (ret) goto done; -: 1248: 1044: 1249: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid); 1044: 1250: if (ret) goto done; -: 1251: -: 1252: /* creation time */ 1044: 1253: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, 1044: 1254: (unsigned long)time(NULL)); 1044: 1255: if (ret) goto done; -: 1256: 1044: 1257: ret = ldb_add(sysdb->ldb, msg); 1044: 1258: ret = sysdb_error_to_errno(ret); -: 1259: -: 1260:done: 1044: 1261: if (ret) { #####: 1262: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1263: } 1044: 1264: talloc_zfree(tmp_ctx); 1044: 1265: return ret; -: 1266:} -: 1267: -: 1268: -: 1269:/* =Add-Group-Function==================================================== */ -: 1270: 945: 1271:int sysdb_add_group(struct sysdb_ctx *sysdb, -: 1272: struct sss_domain_info *domain, -: 1273: const char *name, gid_t gid, -: 1274: struct sysdb_attrs *attrs, -: 1275: int cache_timeout, -: 1276: time_t now) -: 1277:{ -: 1278: TALLOC_CTX *tmp_ctx; -: 1279: struct ldb_message *msg; -: 1280: uint32_t id; -: 1281: int ret; -: 1282: bool posix; -: 1283: 954: 1284: if (domain->id_max != 0 && gid != 0 && 18: 1285: (gid < domain->id_min || gid > domain->id_max)) { #####: 1286: DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n", -: 1287: gid, domain->id_min, domain->id_max)); #####: 1288: return ERANGE; -: 1289: } -: 1290: 945: 1291: tmp_ctx = talloc_new(NULL); 945: 1292: if (!tmp_ctx) { #####: 1293: return ENOMEM; -: 1294: } -: 1295: 945: 1296: ret = ldb_transaction_start(sysdb->ldb); 945: 1297: if (ret) { #####: 1298: ret = sysdb_error_to_errno(ret); #####: 1299: talloc_free(tmp_ctx); #####: 1300: return ret; -: 1301: } -: 1302: 945: 1303: if (domain->mpg) { -: 1304: /* In MPG domains you can't have groups with the same name as users, -: 1305: * search if a group with the same name exists. -: 1306: * Don't worry about users, if we try to add a user with the same -: 1307: * name the operation will fail */ -: 1308: 945: 1309: ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain, -: 1310: name, NULL, &msg); 945: 1311: if (ret != ENOENT) { #####: 1312: if (ret == EOK) ret = EEXIST; #####: 1313: goto done; -: 1314: } -: 1315: } -: 1316: -: 1317: /* check no other groups with the same gid exist */ 945: 1318: if (gid != 0) { 945: 1319: ret = sysdb_search_group_by_gid(tmp_ctx, sysdb, domain, -: 1320: gid, NULL, &msg); 945: 1321: if (ret != ENOENT) { 18: 1322: if (ret == EOK) ret = EEXIST; 18: 1323: goto done; -: 1324: } -: 1325: } -: 1326: -: 1327: /* try to add the group */ 927: 1328: ret = sysdb_add_basic_group(sysdb, domain, name, gid); 927: 1329: if (ret) goto done; -: 1330: 927: 1331: if (!attrs) { 90: 1332: attrs = sysdb_new_attrs(tmp_ctx); 90: 1333: if (!attrs) { #####: 1334: ret = ENOMEM; #####: 1335: goto done; -: 1336: } -: 1337: } -: 1338: 927: 1339: ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix); 927: 1340: if (ret == ENOENT) { 927: 1341: posix = true; 927: 1342: ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, true); 927: 1343: if (ret) goto done; #####: 1344: } else if (ret != EOK) { #####: 1345: goto done; -: 1346: } -: 1347: 927: 1348: if (posix && gid == 0) { #####: 1349: ret = sysdb_get_new_id(sysdb, domain, &id); #####: 1350: if (ret) goto done; -: 1351: #####: 1352: ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, id); #####: 1353: if (ret) goto done; -: 1354: } -: 1355: 927: 1356: if (!now) { 90: 1357: now = time(NULL); -: 1358: } -: 1359: 927: 1360: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 927: 1361: if (ret) goto done; -: 1362: 1746: 1363: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1364: ((cache_timeout) ? 819: 1365: (now + cache_timeout) : 0)); 927: 1366: if (ret) goto done; -: 1367: 927: 1368: ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); -: 1369: -: 1370:done: 945: 1371: if (ret == EOK) { 927: 1372: ret = ldb_transaction_commit(sysdb->ldb); 927: 1373: ret = sysdb_error_to_errno(ret); -: 1374: } else { 18: 1375: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); 18: 1376: ldb_transaction_cancel(sysdb->ldb); -: 1377: } 945: 1378: talloc_zfree(tmp_ctx); 945: 1379: return ret; -: 1380:} -: 1381: 117: 1382:int sysdb_add_incomplete_group(struct sysdb_ctx *sysdb, -: 1383: struct sss_domain_info *domain, -: 1384: const char *name, -: 1385: gid_t gid, -: 1386: const char *original_dn, -: 1387: bool posix, -: 1388: time_t now) -: 1389:{ -: 1390: TALLOC_CTX *tmp_ctx; -: 1391: int ret; -: 1392: struct sysdb_attrs *attrs; -: 1393: 117: 1394: tmp_ctx = talloc_new(NULL); 117: 1395: if (!tmp_ctx) { #####: 1396: return ENOMEM; -: 1397: } -: 1398: -: 1399: /* try to add the group */ 117: 1400: ret = sysdb_add_basic_group(sysdb, domain, name, gid); 117: 1401: if (ret) goto done; -: 1402: 117: 1403: attrs = sysdb_new_attrs(tmp_ctx); 117: 1404: if (!attrs) { #####: 1405: ret = ENOMEM; #####: 1406: goto done; -: 1407: } -: 1408: 117: 1409: if (!now) { 117: 1410: now = time(NULL); -: 1411: } -: 1412: 117: 1413: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 117: 1414: if (ret) goto done; -: 1415: 117: 1416: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1417: now-1); 117: 1418: if (ret) goto done; -: 1419: 117: 1420: ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, posix); 117: 1421: if (ret) goto done; -: 1422: 117: 1423: if (original_dn) { 18: 1424: ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, original_dn); 18: 1425: if (ret) goto done; -: 1426: } -: 1427: 117: 1428: ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); -: 1429: -: 1430:done: 117: 1431: if (ret != EOK) { #####: 1432: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1433: } 117: 1434: talloc_zfree(tmp_ctx); 117: 1435: return ret; -: 1436:} -: 1437: -: 1438:/* =Add-Or-Remove-Group-Memeber=========================================== */ -: 1439: -: 1440:/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */ 504: 1441:int sysdb_mod_group_member(struct sysdb_ctx *sysdb, -: 1442: struct ldb_dn *member_dn, -: 1443: struct ldb_dn *group_dn, -: 1444: int mod_op) -: 1445:{ -: 1446: struct ldb_message *msg; -: 1447: const char *dn; -: 1448: int ret; -: 1449: 504: 1450: msg = ldb_msg_new(NULL); 504: 1451: if (!msg) { #####: 1452: ERROR_OUT(ret, ENOMEM, fail); -: 1453: } -: 1454: 504: 1455: msg->dn = group_dn; 504: 1456: ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL); 504: 1457: if (ret != LDB_SUCCESS) { #####: 1458: ERROR_OUT(ret, ENOMEM, fail); -: 1459: } -: 1460: 504: 1461: dn = ldb_dn_get_linearized(member_dn); 504: 1462: if (!dn) { #####: 1463: ERROR_OUT(ret, EINVAL, fail); -: 1464: } -: 1465: 504: 1466: ret = ldb_msg_add_string(msg, SYSDB_MEMBER, dn); 504: 1467: if (ret != LDB_SUCCESS) { #####: 1468: ERROR_OUT(ret, EINVAL, fail); -: 1469: } -: 1470: 504: 1471: ret = ldb_modify(sysdb->ldb, msg); 504: 1472: ret = sysdb_error_to_errno(ret); -: 1473: -: 1474:fail: 504: 1475: if (ret) { #####: 1476: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1477: } 504: 1478: talloc_zfree(msg); 504: 1479: return ret; -: 1480:} -: 1481: -: 1482:/* =Add-Basic-Netgroup-NO-CHECKS============================================= */ -: 1483: 99: 1484:int sysdb_add_basic_netgroup(struct sysdb_ctx *sysdb, -: 1485: struct sss_domain_info *domain, -: 1486: const char *name, const char *description) -: 1487:{ -: 1488: struct ldb_message *msg; -: 1489: int ret; -: 1490: 99: 1491: msg = ldb_msg_new(NULL); 99: 1492: if (!msg) { #####: 1493: return ENOMEM; -: 1494: } -: 1495: -: 1496: /* netgroup dn */ 99: 1497: msg->dn = sysdb_netgroup_dn(sysdb, msg, domain, name); 99: 1498: if (!msg->dn) { #####: 1499: ERROR_OUT(ret, ENOMEM, done); -: 1500: } -: 1501: 99: 1502: ret = add_string(msg, LDB_FLAG_MOD_ADD, -: 1503: SYSDB_OBJECTCLASS, SYSDB_NETGROUP_CLASS); 99: 1504: if (ret) goto done; -: 1505: 99: 1506: ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); 99: 1507: if (ret) goto done; -: 1508: 99: 1509: if (description && *description) { 99: 1510: ret = add_string(msg, LDB_FLAG_MOD_ADD, -: 1511: SYSDB_DESCRIPTION, description); 99: 1512: if (ret) goto done; -: 1513: } -: 1514: -: 1515: /* creation time */ 99: 1516: ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, 99: 1517: (unsigned long) time(NULL)); 99: 1518: if (ret) goto done; -: 1519: 99: 1520: ret = ldb_add(sysdb->ldb, msg); 99: 1521: ret = sysdb_error_to_errno(ret); -: 1522: -: 1523:done: 99: 1524: if (ret) { #####: 1525: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1526: } 99: 1527: talloc_zfree(msg); 99: 1528: return ret; -: 1529:} -: 1530: -: 1531: -: 1532:/* =Add-Netgroup-Function==================================================== */ -: 1533: 9: 1534:int sysdb_add_netgroup(struct sysdb_ctx *sysdb, -: 1535: struct sss_domain_info *domain, -: 1536: const char *name, -: 1537: const char *description, -: 1538: struct sysdb_attrs *attrs, -: 1539: char **missing, -: 1540: int cache_timeout, -: 1541: time_t now) -: 1542:{ -: 1543: TALLOC_CTX *tmp_ctx; -: 1544: int ret; -: 1545: 9: 1546: tmp_ctx = talloc_new(NULL); 9: 1547: if (!tmp_ctx) { #####: 1548: return ENOMEM; -: 1549: } -: 1550: 9: 1551: ret = ldb_transaction_start(sysdb->ldb); 9: 1552: if (ret) { #####: 1553: ret = sysdb_error_to_errno(ret); #####: 1554: talloc_free(tmp_ctx); #####: 1555: return ret; -: 1556: } -: 1557: -: 1558: /* try to add the netgroup */ 9: 1559: ret = sysdb_add_basic_netgroup(sysdb, domain, name, description); 9: 1560: if (ret && ret != EEXIST) goto done; -: 1561: 9: 1562: if (!attrs) { 9: 1563: attrs = sysdb_new_attrs(tmp_ctx); 9: 1564: if (!attrs) { #####: 1565: ret = ENOMEM; #####: 1566: goto done; -: 1567: } -: 1568: } -: 1569: 9: 1570: if (!now) { 9: 1571: now = time(NULL); -: 1572: } -: 1573: 9: 1574: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 9: 1575: if (ret) goto done; -: 1576: 18: 1577: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1578: ((cache_timeout) ? 9: 1579: (now + cache_timeout) : 0)); 9: 1580: if (ret) goto done; -: 1581: 9: 1582: ret = sysdb_set_netgroup_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); -: 1583: 9: 1584: if (missing) { #####: 1585: ret = sysdb_remove_attrs(sysdb, domain, name, -: 1586: SYSDB_MEMBER_NETGROUP, -: 1587: missing); #####: 1588: if (ret != EOK) { #####: 1589: DEBUG(SSSDBG_MINOR_FAILURE, ("Could not remove missing attributes\n")); -: 1590: } -: 1591: } -: 1592: -: 1593:done: 9: 1594: if (ret == EOK) { 9: 1595: ret = ldb_transaction_commit(sysdb->ldb); 9: 1596: ret = sysdb_error_to_errno(ret); -: 1597: } -: 1598: 9: 1599: if (ret != EOK) { #####: 1600: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); #####: 1601: ldb_transaction_cancel(sysdb->ldb); -: 1602: } 9: 1603: talloc_zfree(tmp_ctx); 9: 1604: return ret; -: 1605:} -: 1606: -: 1607:/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */ -: 1608: -: 1609:/* if one of the basic attributes is empty ("") as opposed to NULL, -: 1610: * this will just remove it */ -: 1611: 441: 1612:int sysdb_store_user(struct sysdb_ctx *sysdb, -: 1613: struct sss_domain_info *domain, -: 1614: const char *name, -: 1615: const char *pwd, -: 1616: uid_t uid, gid_t gid, -: 1617: const char *gecos, -: 1618: const char *homedir, -: 1619: const char *shell, -: 1620: const char *orig_dn, -: 1621: struct sysdb_attrs *attrs, -: 1622: char **remove_attrs, -: 1623: uint64_t cache_timeout, -: 1624: time_t now) -: 1625:{ -: 1626: TALLOC_CTX *tmp_ctx; -: 1627: struct ldb_message *msg; -: 1628: int ret; 441: 1629: errno_t sret = EOK; 441: 1630: bool in_transaction = false; -: 1631: 441: 1632: tmp_ctx = talloc_new(NULL); 441: 1633: if (!tmp_ctx) { #####: 1634: return ENOMEM; -: 1635: } -: 1636: 441: 1637: if (!attrs) { 441: 1638: attrs = sysdb_new_attrs(tmp_ctx); 441: 1639: if (!attrs) { #####: 1640: ret = ENOMEM; #####: 1641: goto fail; -: 1642: } -: 1643: } -: 1644: 441: 1645: if (pwd && (domain->legacy_passwords || !*pwd)) { #####: 1646: ret = sysdb_attrs_add_string(attrs, SYSDB_PWD, pwd); #####: 1647: if (ret) goto fail; -: 1648: } -: 1649: 441: 1650: ret = sysdb_transaction_start(sysdb); 441: 1651: if (ret != EOK) { #####: 1652: DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); #####: 1653: goto fail; -: 1654: } -: 1655: 441: 1656: in_transaction = true; -: 1657: 441: 1658: ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain, name, NULL, &msg); 441: 1659: if (ret && ret != ENOENT) { #####: 1660: goto fail; -: 1661: } -: 1662: -: 1663: /* get transaction timestamp */ 441: 1664: if (!now) { 441: 1665: now = time(NULL); -: 1666: } -: 1667: 441: 1668: if (ret == ENOENT) { -: 1669: /* users doesn't exist, turn into adding a user */ 261: 1670: ret = sysdb_add_user(sysdb, domain, name, uid, gid, gecos, homedir, -: 1671: shell, orig_dn, attrs, cache_timeout, now); 261: 1672: if (ret == EEXIST) { -: 1673: /* This may be a user rename. If there is a user with the -: 1674: * same UID, remove it and try to add the basic user again -: 1675: */ 9: 1676: ret = sysdb_delete_user(sysdb, domain, NULL, uid); 9: 1677: if (ret == ENOENT) { -: 1678: /* Not found by UID, return the original EEXIST, -: 1679: * this may be a conflict in MPG domain or something -: 1680: * else */ #####: 1681: ret = EEXIST; #####: 1682: goto fail; 9: 1683: } else if (ret != EOK) { #####: 1684: goto fail; -: 1685: } 9: 1686: DEBUG(SSSDBG_MINOR_FAILURE, -: 1687: ("A user with the same UID [%llu] was removed from the " -: 1688: "cache\n", (unsigned long long) uid)); 9: 1689: ret = sysdb_add_user(sysdb, domain, name, uid, gid, gecos, homedir, -: 1690: shell, orig_dn, attrs, cache_timeout, now); -: 1691: } -: 1692: -: 1693: /* Handle the result of sysdb_add_user */ 261: 1694: if (ret == EOK) { 261: 1695: goto done; -: 1696: } else { #####: 1697: DEBUG(SSSDBG_OP_FAILURE, ("Could not add user\n")); #####: 1698: goto fail; -: 1699: } -: 1700: } -: 1701: -: 1702: /* the user exists, let's just replace attributes when set */ 180: 1703: if (uid) { 180: 1704: ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid); 180: 1705: if (ret) goto fail; -: 1706: } -: 1707: 180: 1708: if (gid) { #####: 1709: ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); #####: 1710: if (ret) goto fail; -: 1711: } -: 1712: 180: 1713: if (uid && !gid && domain->mpg) { 180: 1714: ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, uid); 180: 1715: if (ret) goto fail; -: 1716: } -: 1717: 180: 1718: if (gecos) { 180: 1719: ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos); 180: 1720: if (ret) goto fail; -: 1721: } -: 1722: 180: 1723: if (homedir) { 180: 1724: ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir); 180: 1725: if (ret) goto fail; -: 1726: } -: 1727: 180: 1728: if (shell) { 180: 1729: ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell); 180: 1730: if (ret) goto fail; -: 1731: } -: 1732: 180: 1733: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 180: 1734: if (ret) goto fail; -: 1735: 360: 1736: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1737: ((cache_timeout) ? 180: 1738: (now + cache_timeout) : 0)); 180: 1739: if (ret) goto fail; -: 1740: 180: 1741: ret = sysdb_set_user_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); 180: 1742: if (ret != EOK) goto fail; -: 1743: 180: 1744: if (remove_attrs) { #####: 1745: ret = sysdb_remove_attrs(sysdb, domain, name, -: 1746: SYSDB_MEMBER_USER, -: 1747: remove_attrs); #####: 1748: if (ret != EOK) { #####: 1749: DEBUG(4, ("Could not remove missing attributes\n")); -: 1750: } -: 1751: } -: 1752: -: 1753:done: 441: 1754: ret = sysdb_transaction_commit(sysdb); 441: 1755: if (ret != EOK) { #####: 1756: DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); #####: 1757: goto fail; -: 1758: } -: 1759: 441: 1760: in_transaction = false; -: 1761: -: 1762:fail: 441: 1763: if (in_transaction) { #####: 1764: sret = sysdb_transaction_cancel(sysdb); #####: 1765: if (sret != EOK) { #####: 1766: DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); -: 1767: } -: 1768: } -: 1769: 441: 1770: if (ret) { #####: 1771: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1772: } 441: 1773: talloc_zfree(tmp_ctx); 441: 1774: return ret; -: 1775:} -: 1776: -: 1777:/* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */ -: 1778: -: 1779:/* this function does not check that all user members are actually present */ -: 1780: 846: 1781:int sysdb_store_group(struct sysdb_ctx *sysdb, -: 1782: struct sss_domain_info *domain, -: 1783: const char *name, -: 1784: gid_t gid, -: 1785: struct sysdb_attrs *attrs, -: 1786: uint64_t cache_timeout, -: 1787: time_t now) -: 1788:{ -: 1789: TALLOC_CTX *tmp_ctx; -: 1790: static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, -: 1791: SYSDB_ORIG_MODSTAMP, NULL }; -: 1792: struct ldb_message *msg; 846: 1793: bool new_group = false; -: 1794: int ret; -: 1795: 846: 1796: tmp_ctx = talloc_new(NULL); 846: 1797: if (!tmp_ctx) { #####: 1798: return ENOMEM; -: 1799: } -: 1800: 846: 1801: ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain, -: 1802: name, src_attrs, &msg); 846: 1803: if (ret && ret != ENOENT) { #####: 1804: goto done; -: 1805: } 846: 1806: if (ret == ENOENT) { 837: 1807: new_group = true; -: 1808: } -: 1809: 846: 1810: if (!attrs) { 117: 1811: attrs = sysdb_new_attrs(tmp_ctx); 117: 1812: if (!attrs) { #####: 1813: ret = ENOMEM; #####: 1814: goto done; -: 1815: } -: 1816: } -: 1817: -: 1818: /* get transaction timestamp */ 846: 1819: if (!now) { 846: 1820: now = time(NULL); -: 1821: } -: 1822: -: 1823: /* FIXME: use the remote modification timestamp to know if the -: 1824: * group needs any update */ -: 1825: 846: 1826: if (new_group) { -: 1827: /* group doesn't exist, turn into adding a group */ 837: 1828: ret = sysdb_add_group(sysdb, domain, name, gid, -: 1829: attrs, cache_timeout, now); 837: 1830: if (ret == EEXIST) { -: 1831: /* This may be a group rename. If there is a group with the -: 1832: * same GID, remove it and try to add the basic group again -: 1833: */ 9: 1834: ret = sysdb_delete_group(sysdb, domain, NULL, gid); 9: 1835: if (ret == ENOENT) { -: 1836: /* Not found by GID, return the original EEXIST, -: 1837: * this may be a conflict in MPG domain or something -: 1838: * else */ #####: 1839: return EEXIST; 9: 1840: } else if (ret != EOK) { #####: 1841: goto done; -: 1842: } 9: 1843: DEBUG(SSSDBG_MINOR_FAILURE, -: 1844: ("A group with the same GID [%llu] was removed from the " -: 1845: "cache\n", (unsigned long long) gid)); 9: 1846: ret = sysdb_add_group(sysdb, domain, name, gid, -: 1847: attrs, cache_timeout, now); -: 1848: } 837: 1849: goto done; -: 1850: } -: 1851: -: 1852: /* the group exists, let's just replace attributes when set */ 9: 1853: if (gid) { 9: 1854: ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); 9: 1855: if (ret) goto done; -: 1856: } -: 1857: 9: 1858: ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); 9: 1859: if (ret) goto done; -: 1860: 18: 1861: ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -: 1862: ((cache_timeout) ? 9: 1863: (now + cache_timeout) : 0)); 9: 1864: if (ret) goto done; -: 1865: 9: 1866: ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP); -: 1867: -: 1868:done: 846: 1869: if (ret) { #####: 1870: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 1871: } 846: 1872: talloc_zfree(tmp_ctx); 846: 1873: return ret; -: 1874:} -: 1875: -: 1876: -: 1877:/* =Add-User-to-Group(Native/Legacy)====================================== */ -: 1878:static int 504: 1879:sysdb_group_membership_mod(struct sysdb_ctx *sysdb, -: 1880: struct sss_domain_info *domain, -: 1881: const char *group, -: 1882: const char *member, -: 1883: enum sysdb_member_type type, -: 1884: int modify_op) -: 1885:{ -: 1886: struct ldb_dn *group_dn; -: 1887: struct ldb_dn *member_dn; -: 1888: int ret; 504: 1889: TALLOC_CTX *tmp_ctx = talloc_new(NULL); 504: 1890: if (!tmp_ctx) { #####: 1891: return ENOMEM; -: 1892: } -: 1893: 504: 1894: if (type == SYSDB_MEMBER_USER) { 504: 1895: member_dn = sysdb_user_dn(sysdb, tmp_ctx, domain, member); #####: 1896: } else if (type == SYSDB_MEMBER_GROUP) { #####: 1897: member_dn = sysdb_group_dn(sysdb, tmp_ctx, domain, member); -: 1898: } else { #####: 1899: ret = EINVAL; #####: 1900: goto done; -: 1901: } -: 1902: 504: 1903: if (!member_dn) { #####: 1904: ret = ENOMEM; #####: 1905: goto done; -: 1906: } -: 1907: 504: 1908: group_dn = sysdb_group_dn(sysdb, tmp_ctx, domain, group); 504: 1909: if (!group_dn) { #####: 1910: ret = ENOMEM; #####: 1911: goto done; -: 1912: } -: 1913: 504: 1914: ret = sysdb_mod_group_member(sysdb, member_dn, group_dn, modify_op); -: 1915: -: 1916:done: 504: 1917: talloc_free(tmp_ctx); 504: 1918: return ret; -: 1919:} -: 1920: 387: 1921:int sysdb_add_group_member(struct sysdb_ctx *sysdb, -: 1922: struct sss_domain_info *domain, -: 1923: const char *group, -: 1924: const char *member, -: 1925: enum sysdb_member_type type) -: 1926:{ 387: 1927: return sysdb_group_membership_mod(sysdb, domain, group, -: 1928: member, type, SYSDB_MOD_ADD); -: 1929:} -: 1930: -: 1931:/* =Remove-member-from-Group(Native/Legacy)=============================== */ -: 1932: -: 1933: 117: 1934:int sysdb_remove_group_member(struct sysdb_ctx *sysdb, -: 1935: struct sss_domain_info *domain, -: 1936: const char *group, -: 1937: const char *member, -: 1938: enum sysdb_member_type type) -: 1939:{ 117: 1940: return sysdb_group_membership_mod(sysdb, domain, group, -: 1941: member, type, SYSDB_MOD_DEL); -: 1942:} -: 1943: -: 1944: -: 1945:/* =Password-Caching====================================================== */ -: 1946: 9: 1947:int sysdb_cache_password(struct sysdb_ctx *sysdb, -: 1948: struct sss_domain_info *domain, -: 1949: const char *username, -: 1950: const char *password) -: 1951:{ -: 1952: TALLOC_CTX *tmp_ctx; -: 1953: struct sysdb_attrs *attrs; 9: 1954: char *hash = NULL; -: 1955: char *salt; -: 1956: int ret; -: 1957: 9: 1958: tmp_ctx = talloc_new(NULL); 9: 1959: if (!tmp_ctx) { #####: 1960: return ENOMEM; -: 1961: } -: 1962: 9: 1963: ret = s3crypt_gen_salt(tmp_ctx, &salt); 9: 1964: if (ret) { #####: 1965: DEBUG(4, ("Failed to generate random salt.\n")); #####: 1966: goto fail; -: 1967: } -: 1968: 9: 1969: ret = s3crypt_sha512(tmp_ctx, password, salt, &hash); 9: 1970: if (ret) { #####: 1971: DEBUG(4, ("Failed to create password hash.\n")); #####: 1972: goto fail; -: 1973: } -: 1974: 9: 1975: attrs = sysdb_new_attrs(tmp_ctx); 9: 1976: if (!attrs) { #####: 1977: ERROR_OUT(ret, ENOMEM, fail); -: 1978: } -: 1979: 9: 1980: ret = sysdb_attrs_add_string(attrs, SYSDB_CACHEDPWD, hash); 9: 1981: if (ret) goto fail; -: 1982: -: 1983: /* FIXME: should we use a different attribute for chache passwords ?? */ 9: 1984: ret = sysdb_attrs_add_long(attrs, "lastCachedPasswordChange", -: 1985: (long)time(NULL)); 9: 1986: if (ret) goto fail; -: 1987: 9: 1988: ret = sysdb_attrs_add_uint32(attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0U); 9: 1989: if (ret) goto fail; -: 1990: -: 1991: 9: 1992: ret = sysdb_set_user_attr(sysdb, domain, -: 1993: username, attrs, SYSDB_MOD_REP); 9: 1994: if (ret) { #####: 1995: goto fail; -: 1996: } 9: 1997: talloc_zfree(tmp_ctx); 9: 1998: return EOK; -: 1999: -: 2000:fail: #####: 2001: if (ret) { #####: 2002: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2003: } #####: 2004: talloc_zfree(tmp_ctx); #####: 2005: return ret; -: 2006:} -: 2007: -: 2008:/* =Custom Search================== */ -: 2009: 189: 2010:int sysdb_search_custom(TALLOC_CTX *mem_ctx, -: 2011: struct sysdb_ctx *sysdb, -: 2012: struct sss_domain_info *domain, -: 2013: const char *filter, -: 2014: const char *subtree_name, -: 2015: const char **attrs, -: 2016: size_t *msgs_count, -: 2017: struct ldb_message ***msgs) -: 2018:{ -: 2019: struct ldb_dn *basedn; -: 2020: int ret; -: 2021: 189: 2022: if (filter == NULL || subtree_name == NULL) { #####: 2023: return EINVAL; -: 2024: } -: 2025: 189: 2026: basedn = sysdb_custom_subtree_dn(sysdb, mem_ctx, domain, subtree_name); 189: 2027: if (basedn == NULL) { #####: 2028: DEBUG(1, ("sysdb_custom_subtree_dn failed.\n")); #####: 2029: return ENOMEM; -: 2030: } 189: 2031: if (!ldb_dn_validate(basedn)) { #####: 2032: DEBUG(1, ("Failed to create DN.\n")); #####: 2033: return EINVAL; -: 2034: } -: 2035: 189: 2036: ret = sysdb_search_entry(mem_ctx, sysdb, basedn, -: 2037: LDB_SCOPE_SUBTREE, filter, attrs, -: 2038: msgs_count, msgs); 189: 2039: return ret; -: 2040:} -: 2041: 207: 2042:int sysdb_search_custom_by_name(TALLOC_CTX *mem_ctx, -: 2043: struct sysdb_ctx *sysdb, -: 2044: struct sss_domain_info *domain, -: 2045: const char *object_name, -: 2046: const char *subtree_name, -: 2047: const char **attrs, -: 2048: size_t *_count, -: 2049: struct ldb_message ***_msgs) -: 2050:{ -: 2051: TALLOC_CTX *tmp_ctx; -: 2052: struct ldb_dn *basedn; -: 2053: struct ldb_message **msgs; -: 2054: size_t count; -: 2055: int ret; -: 2056: 207: 2057: if (object_name == NULL || subtree_name == NULL) { #####: 2058: return EINVAL; -: 2059: } -: 2060: 207: 2061: tmp_ctx = talloc_new(NULL); 207: 2062: if (!tmp_ctx) { #####: 2063: return ENOMEM; -: 2064: } -: 2065: 207: 2066: basedn = sysdb_custom_dn(sysdb, tmp_ctx, -: 2067: domain, object_name, subtree_name); 207: 2068: if (basedn == NULL) { #####: 2069: DEBUG(1, ("sysdb_custom_dn failed.\n")); #####: 2070: ret = ENOMEM; #####: 2071: goto done; -: 2072: } 207: 2073: if (!ldb_dn_validate(basedn)) { #####: 2074: DEBUG(1, ("Failed to create DN.\n")); #####: 2075: ret = EINVAL; #####: 2076: goto done; -: 2077: } -: 2078: 207: 2079: ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, -: 2080: LDB_SCOPE_BASE, NULL, attrs, &count, &msgs); 207: 2081: if (ret) { 180: 2082: goto done; -: 2083: } -: 2084: 27: 2085: if (count > 1) { #####: 2086: DEBUG(1, ("More than one result found.\n")); #####: 2087: ret = EFAULT; #####: 2088: goto done; -: 2089: } -: 2090: 27: 2091: *_count = count; 27: 2092: *_msgs = talloc_move(mem_ctx, &msgs); -: 2093: -: 2094:done: 207: 2095: talloc_zfree(tmp_ctx); 207: 2096: return ret; -: 2097:} -: 2098: -: 2099: -: 2100:/* =Custom Store (replaces-existing-data)================== */ -: 2101: 189: 2102:int sysdb_store_custom(struct sysdb_ctx *sysdb, -: 2103: struct sss_domain_info *domain, -: 2104: const char *object_name, -: 2105: const char *subtree_name, -: 2106: struct sysdb_attrs *attrs) -: 2107:{ -: 2108: TALLOC_CTX *tmp_ctx; 189: 2109: const char *search_attrs[] = { "*", NULL }; 189: 2110: size_t resp_count = 0; -: 2111: struct ldb_message **resp; -: 2112: struct ldb_message *msg; -: 2113: struct ldb_message_element *el; 189: 2114: bool add_object = false; -: 2115: int ret; -: 2116: int i; -: 2117: 189: 2118: if (object_name == NULL || subtree_name == NULL) { #####: 2119: return EINVAL; -: 2120: } -: 2121: 189: 2122: ret = ldb_transaction_start(sysdb->ldb); 189: 2123: if (ret) { #####: 2124: return sysdb_error_to_errno(ret); -: 2125: } -: 2126: 189: 2127: tmp_ctx = talloc_new(NULL); 189: 2128: if (!tmp_ctx) { #####: 2129: ret = ENOMEM; #####: 2130: goto done; -: 2131: } -: 2132: 189: 2133: ret = sysdb_search_custom_by_name(tmp_ctx, sysdb, domain, -: 2134: object_name, subtree_name, -: 2135: search_attrs, &resp_count, &resp); 189: 2136: if (ret != EOK && ret != ENOENT) { #####: 2137: goto done; -: 2138: } -: 2139: 189: 2140: if (ret == ENOENT) { 180: 2141: add_object = true; -: 2142: } -: 2143: 189: 2144: msg = ldb_msg_new(tmp_ctx); 189: 2145: if (msg == NULL) { #####: 2146: ret = ENOMEM; #####: 2147: goto done; -: 2148: } -: 2149: 189: 2150: msg->dn = sysdb_custom_dn(sysdb, tmp_ctx, -: 2151: domain, object_name, subtree_name); 189: 2152: if (!msg->dn) { #####: 2153: DEBUG(1, ("sysdb_custom_dn failed.\n")); #####: 2154: ret = ENOMEM; #####: 2155: goto done; -: 2156: } -: 2157: 189: 2158: msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num); 189: 2159: if (!msg->elements) { #####: 2160: ret = ENOMEM; #####: 2161: goto done; -: 2162: } -: 2163: 747: 2164: for (i = 0; i < attrs->num; i++) { 558: 2165: msg->elements[i] = attrs->a[i]; 558: 2166: if (add_object) { 540: 2167: msg->elements[i].flags = LDB_FLAG_MOD_ADD; -: 2168: } else { 18: 2169: el = ldb_msg_find_element(resp[0], attrs->a[i].name); 18: 2170: if (el == NULL) { 9: 2171: msg->elements[i].flags = LDB_FLAG_MOD_ADD; -: 2172: } else { 9: 2173: msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; -: 2174: } -: 2175: } -: 2176: } 189: 2177: msg->num_elements = attrs->num; -: 2178: 189: 2179: if (add_object) { 180: 2180: ret = ldb_add(sysdb->ldb, msg); -: 2181: } else { 9: 2182: ret = ldb_modify(sysdb->ldb, msg); -: 2183: } 189: 2184: if (ret != LDB_SUCCESS) { #####: 2185: DEBUG(1, ("Failed to store custom entry: %s(%d)[%s]\n", -: 2186: ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb))); #####: 2187: ret = sysdb_error_to_errno(ret); -: 2188: } -: 2189: -: 2190:done: 189: 2191: if (ret) { #####: 2192: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); #####: 2193: ldb_transaction_cancel(sysdb->ldb); -: 2194: } else { 189: 2195: ret = ldb_transaction_commit(sysdb->ldb); 189: 2196: ret = sysdb_error_to_errno(ret); -: 2197: } 189: 2198: talloc_zfree(tmp_ctx); 189: 2199: return ret; -: 2200:} -: 2201: -: 2202:/* = Custom Delete======================================= */ -: 2203: 99: 2204:int sysdb_delete_custom(struct sysdb_ctx *sysdb, -: 2205: struct sss_domain_info *domain, -: 2206: const char *object_name, -: 2207: const char *subtree_name) -: 2208:{ -: 2209: TALLOC_CTX *tmp_ctx; -: 2210: struct ldb_dn *dn; -: 2211: int ret; -: 2212: 99: 2213: if (object_name == NULL || subtree_name == NULL) { #####: 2214: return EINVAL; -: 2215: } -: 2216: 99: 2217: tmp_ctx = talloc_new(NULL); 99: 2218: if (!tmp_ctx) { #####: 2219: return ENOMEM; -: 2220: } -: 2221: 99: 2222: dn = sysdb_custom_dn(sysdb, tmp_ctx, -: 2223: domain, object_name, subtree_name); 99: 2224: if (dn == NULL) { #####: 2225: DEBUG(1, ("sysdb_custom_dn failed.\n")); #####: 2226: ret = ENOMEM; #####: 2227: goto done; -: 2228: } -: 2229: 99: 2230: ret = ldb_delete(sysdb->ldb, dn); -: 2231: 99: 2232: switch (ret) { -: 2233: case LDB_SUCCESS: -: 2234: case LDB_ERR_NO_SUCH_OBJECT: 99: 2235: ret = EOK; 99: 2236: break; -: 2237: -: 2238: default: #####: 2239: DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n", -: 2240: ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb))); #####: 2241: ret = sysdb_error_to_errno(ret); #####: 2242: break; -: 2243: } -: 2244: -: 2245:done: 99: 2246: talloc_zfree(tmp_ctx); 99: 2247: return ret; -: 2248:} -: 2249: -: 2250:/* = ASQ search request ======================================== */ -: 2251: 9: 2252:int sysdb_asq_search(TALLOC_CTX *mem_ctx, -: 2253: struct sysdb_ctx *sysdb, -: 2254: struct ldb_dn *base_dn, -: 2255: const char *expression, -: 2256: const char *asq_attribute, -: 2257: const char **attrs, -: 2258: size_t *msgs_count, -: 2259: struct ldb_message ***msgs) -: 2260:{ -: 2261: TALLOC_CTX *tmp_ctx; -: 2262: struct ldb_request *ldb_req; -: 2263: struct ldb_control **ctrl; -: 2264: struct ldb_asq_control *asq_control; -: 2265: struct ldb_result *res; -: 2266: int ret; -: 2267: 9: 2268: tmp_ctx = talloc_new(NULL); 9: 2269: if (!tmp_ctx) { #####: 2270: return ENOMEM; -: 2271: } -: 2272: 9: 2273: ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2); 9: 2274: if (ctrl == NULL) { #####: 2275: ret = ENOMEM; #####: 2276: goto fail; -: 2277: } -: 2278: 9: 2279: ctrl[0] = talloc(ctrl, struct ldb_control); 9: 2280: if (ctrl[0] == NULL) { #####: 2281: ret = ENOMEM; #####: 2282: goto fail; -: 2283: } 9: 2284: ctrl[1] = NULL; -: 2285: 9: 2286: ctrl[0]->oid = LDB_CONTROL_ASQ_OID; 9: 2287: ctrl[0]->critical = 1; -: 2288: 9: 2289: asq_control = talloc(ctrl[0], struct ldb_asq_control); 9: 2290: if (asq_control == NULL) { #####: 2291: ret = ENOMEM; #####: 2292: goto fail; -: 2293: } -: 2294: 9: 2295: asq_control->request = 1; 9: 2296: asq_control->source_attribute = talloc_strdup(asq_control, asq_attribute); 9: 2297: if (asq_control->source_attribute == NULL) { #####: 2298: ret = ENOMEM; #####: 2299: goto fail; -: 2300: } 9: 2301: asq_control->src_attr_len = strlen(asq_control->source_attribute); 9: 2302: ctrl[0]->data = asq_control; -: 2303: 9: 2304: res = talloc_zero(tmp_ctx, struct ldb_result); 9: 2305: if (!res) { #####: 2306: ret = ENOMEM; #####: 2307: goto fail; -: 2308: } -: 2309: 9: 2310: ret = ldb_build_search_req(&ldb_req, sysdb->ldb, tmp_ctx, -: 2311: base_dn, LDB_SCOPE_BASE, -: 2312: expression, attrs, ctrl, -: 2313: res, ldb_search_default_callback, NULL); 9: 2314: if (ret != LDB_SUCCESS) { #####: 2315: ret = sysdb_error_to_errno(ret); #####: 2316: goto fail; -: 2317: } -: 2318: 9: 2319: ret = ldb_request(sysdb->ldb, ldb_req); 9: 2320: if (ret == LDB_SUCCESS) { 9: 2321: ret = ldb_wait(ldb_req->handle, LDB_WAIT_ALL); -: 2322: } 9: 2323: if (ret) { #####: 2324: ret = sysdb_error_to_errno(ret); #####: 2325: goto fail; -: 2326: } -: 2327: 9: 2328: *msgs_count = res->count; 9: 2329: *msgs = talloc_move(mem_ctx, &res->msgs); -: 2330: 9: 2331: talloc_zfree(tmp_ctx); 9: 2332: return EOK; -: 2333: -: 2334:fail: #####: 2335: if (ret == ENOENT) { #####: 2336: DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n")); -: 2337: } #####: 2338: else if (ret) { #####: 2339: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2340: } #####: 2341: talloc_zfree(tmp_ctx); #####: 2342: return ret; -: 2343:} -: 2344: -: 2345:/* =Search-Users-with-Custom-Filter====================================== */ -: 2346: #####: 2347:int sysdb_search_users(TALLOC_CTX *mem_ctx, -: 2348: struct sysdb_ctx *sysdb, -: 2349: struct sss_domain_info *domain, -: 2350: const char *sub_filter, -: 2351: const char **attrs, -: 2352: size_t *msgs_count, -: 2353: struct ldb_message ***msgs) -: 2354:{ -: 2355: TALLOC_CTX *tmp_ctx; -: 2356: struct ldb_dn *basedn; -: 2357: char *filter; -: 2358: int ret; -: 2359: #####: 2360: tmp_ctx = talloc_new(NULL); #####: 2361: if (!tmp_ctx) { #####: 2362: return ENOMEM; -: 2363: } -: 2364: #####: 2365: basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 2366: SYSDB_TMPL_USER_BASE, domain->name); #####: 2367: if (!basedn) { #####: 2368: DEBUG(2, ("Failed to build base dn\n")); #####: 2369: ret = ENOMEM; #####: 2370: goto fail; -: 2371: } -: 2372: #####: 2373: filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_UC, sub_filter); #####: 2374: if (!filter) { #####: 2375: DEBUG(2, ("Failed to build filter\n")); #####: 2376: ret = ENOMEM; #####: 2377: goto fail; -: 2378: } -: 2379: #####: 2380: DEBUG(SSSDBG_TRACE_INTERNAL, -: 2381: ("Search users with filter: %s\n", filter)); -: 2382: #####: 2383: ret = sysdb_search_entry(mem_ctx, sysdb, basedn, -: 2384: LDB_SCOPE_SUBTREE, filter, attrs, -: 2385: msgs_count, msgs); #####: 2386: if (ret) { #####: 2387: goto fail; -: 2388: } -: 2389: #####: 2390: talloc_zfree(tmp_ctx); #####: 2391: return EOK; -: 2392: -: 2393:fail: #####: 2394: if (ret == ENOENT) { #####: 2395: DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n")); -: 2396: } #####: 2397: else if (ret) { #####: 2398: DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2399: } #####: 2400: talloc_zfree(tmp_ctx); #####: 2401: return ret; -: 2402:} -: 2403: -: 2404:/* =Delete-User-by-Name-OR-uid============================================ */ -: 2405: 180: 2406:int sysdb_delete_user(struct sysdb_ctx *sysdb, -: 2407: struct sss_domain_info *domain, -: 2408: const char *name, uid_t uid) -: 2409:{ -: 2410: TALLOC_CTX *tmp_ctx; 180: 2411: const char *attrs[] = {SYSDB_GHOST, NULL}; -: 2412: size_t msg_count; -: 2413: char *filter; -: 2414: struct ldb_message **msgs; -: 2415: struct ldb_message *msg; -: 2416: int ret; -: 2417: int i; -: 2418: 180: 2419: tmp_ctx = talloc_new(NULL); 180: 2420: if (!tmp_ctx) { #####: 2421: return ENOMEM; -: 2422: } -: 2423: 180: 2424: if (name) { 27: 2425: ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain, -: 2426: name, NULL, &msg); -: 2427: } else { 153: 2428: ret = sysdb_search_user_by_uid(tmp_ctx, sysdb, domain, -: 2429: uid, NULL, &msg); -: 2430: } 180: 2431: if (ret == EOK) { 171: 2432: if (name && uid) { -: 2433: /* verify name/gid match */ -: 2434: const char *c_name; -: 2435: uint64_t c_uid; -: 2436: 18: 2437: c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); 18: 2438: c_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); 18: 2439: if (c_name == NULL || c_uid == 0) { #####: 2440: DEBUG(2, ("Attribute is missing but this should never happen!\n")); #####: 2441: ret = EFAULT; #####: 2442: goto fail; -: 2443: } 18: 2444: if (strcmp(name, c_name) || uid != c_uid) { -: 2445: /* this is not the entry we are looking for */ #####: 2446: ret = EINVAL; #####: 2447: goto fail; -: 2448: } -: 2449: } -: 2450: 171: 2451: ret = sysdb_delete_entry(sysdb, msg->dn, false); 171: 2452: if (ret) { #####: 2453: goto fail; -: 2454: } 9: 2455: } else if (ret == ENOENT && name != NULL) { -: 2456: /* Perhaps a ghost user? */ #####: 2457: filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_GHOST, name); #####: 2458: if (filter == NULL) { #####: 2459: ret = ENOMEM; #####: 2460: goto fail; -: 2461: } -: 2462: #####: 2463: ret = sysdb_search_groups(tmp_ctx, sysdb, domain, -: 2464: filter, attrs, &msg_count, &msgs); #####: 2465: if (ret != EOK) { #####: 2466: goto fail; -: 2467: } -: 2468: #####: 2469: for (i = 0; i < msg_count; i++) { #####: 2470: msg = ldb_msg_new(tmp_ctx); #####: 2471: if (!msg) { #####: 2472: ERROR_OUT(ret, ENOMEM, fail); -: 2473: } -: 2474: #####: 2475: msg->dn = msgs[i]->dn; -: 2476: #####: 2477: ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name); #####: 2478: if (ret) goto fail; -: 2479: #####: 2480: ret = ldb_modify(sysdb->ldb, msg); #####: 2481: ret = sysdb_error_to_errno(ret); #####: 2482: if (ret != EOK) { #####: 2483: goto fail; -: 2484: } -: 2485: #####: 2486: talloc_zfree(msg); -: 2487: } -: 2488: } else { -: 2489: goto fail; -: 2490: } -: 2491: -: 2492: 171: 2493: talloc_zfree(tmp_ctx); 171: 2494: return EOK; -: 2495: -: 2496:fail: 9: 2497: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); 9: 2498: talloc_zfree(tmp_ctx); 9: 2499: return ret; -: 2500:} -: 2501: -: 2502: -: 2503:/* =Search-Groups-with-Custom-Filter===================================== */ -: 2504: #####: 2505:int sysdb_search_groups(TALLOC_CTX *mem_ctx, -: 2506: struct sysdb_ctx *sysdb, -: 2507: struct sss_domain_info *domain, -: 2508: const char *sub_filter, -: 2509: const char **attrs, -: 2510: size_t *msgs_count, -: 2511: struct ldb_message ***msgs) -: 2512:{ -: 2513: TALLOC_CTX *tmp_ctx; -: 2514: struct ldb_dn *basedn; -: 2515: char *filter; -: 2516: int ret; -: 2517: #####: 2518: tmp_ctx = talloc_new(NULL); #####: 2519: if (!tmp_ctx) { #####: 2520: return ENOMEM; -: 2521: } -: 2522: #####: 2523: basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 2524: SYSDB_TMPL_GROUP_BASE, domain->name); #####: 2525: if (!basedn) { #####: 2526: DEBUG(2, ("Failed to build base dn\n")); #####: 2527: ret = ENOMEM; #####: 2528: goto fail; -: 2529: } -: 2530: #####: 2531: filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_GC, sub_filter); #####: 2532: if (!filter) { #####: 2533: DEBUG(2, ("Failed to build filter\n")); #####: 2534: ret = ENOMEM; #####: 2535: goto fail; -: 2536: } -: 2537: #####: 2538: DEBUG(SSSDBG_TRACE_INTERNAL, -: 2539: ("Search groups with filter: %s\n", filter)); -: 2540: #####: 2541: ret = sysdb_search_entry(mem_ctx, sysdb, basedn, -: 2542: LDB_SCOPE_SUBTREE, filter, attrs, -: 2543: msgs_count, msgs); #####: 2544: if (ret) { #####: 2545: goto fail; -: 2546: } -: 2547: #####: 2548: talloc_zfree(tmp_ctx); #####: 2549: return EOK; -: 2550: -: 2551:fail: #####: 2552: if (ret == ENOENT) { #####: 2553: DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n")); -: 2554: } #####: 2555: else if (ret) { #####: 2556: DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2557: } #####: 2558: talloc_zfree(tmp_ctx); #####: 2559: return ret; -: 2560:} -: 2561: -: 2562:/* =Delete-Group-by-Name-OR-gid=========================================== */ -: 2563: 954: 2564:int sysdb_delete_group(struct sysdb_ctx *sysdb, -: 2565: struct sss_domain_info *domain, -: 2566: const char *name, gid_t gid) -: 2567:{ -: 2568: TALLOC_CTX *tmp_ctx; -: 2569: struct ldb_message *msg; -: 2570: int ret; -: 2571: 954: 2572: tmp_ctx = talloc_new(NULL); 954: 2573: if (!tmp_ctx) { #####: 2574: return ENOMEM; -: 2575: } -: 2576: 954: 2577: if (name) { 18: 2578: ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain, -: 2579: name, NULL, &msg); -: 2580: } else { 936: 2581: ret = sysdb_search_group_by_gid(tmp_ctx, sysdb, domain, -: 2582: gid, NULL, &msg); -: 2583: } 954: 2584: if (ret) { 27: 2585: goto fail; -: 2586: } -: 2587: 927: 2588: if (name && gid) { -: 2589: /* verify name/gid match */ -: 2590: const char *c_name; -: 2591: uint64_t c_gid; -: 2592: 18: 2593: c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); 18: 2594: c_gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0); 18: 2595: if (c_name == NULL || c_gid == 0) { #####: 2596: DEBUG(2, ("Attribute is missing but this should never happen!\n")); #####: 2597: ret = EFAULT; #####: 2598: goto fail; -: 2599: } 18: 2600: if (strcmp(name, c_name) || gid != c_gid) { -: 2601: /* this is not the entry we are looking for */ #####: 2602: ret = EINVAL; #####: 2603: goto fail; -: 2604: } -: 2605: } -: 2606: 927: 2607: ret = sysdb_delete_entry(sysdb, msg->dn, false); 927: 2608: if (ret) { #####: 2609: goto fail; -: 2610: } -: 2611: 927: 2612: talloc_zfree(tmp_ctx); 927: 2613: return EOK; -: 2614: -: 2615:fail: 27: 2616: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); 27: 2617: talloc_zfree(tmp_ctx); 27: 2618: return ret; -: 2619:} -: 2620: -: 2621:/* =Search-Netgroups-with-Custom-Filter===================================== */ -: 2622: #####: 2623:int sysdb_search_netgroups(TALLOC_CTX *mem_ctx, -: 2624: struct sysdb_ctx *sysdb, -: 2625: struct sss_domain_info *domain, -: 2626: const char *sub_filter, -: 2627: const char **attrs, -: 2628: size_t *msgs_count, -: 2629: struct ldb_message ***msgs) -: 2630:{ -: 2631: TALLOC_CTX *tmp_ctx; -: 2632: struct ldb_dn *basedn; -: 2633: char *filter; -: 2634: int ret; -: 2635: #####: 2636: tmp_ctx = talloc_new(NULL); #####: 2637: if (!tmp_ctx) { #####: 2638: return ENOMEM; -: 2639: } -: 2640: #####: 2641: basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -: 2642: SYSDB_TMPL_NETGROUP_BASE, domain->name); #####: 2643: if (!basedn) { #####: 2644: DEBUG(2, ("Failed to build base dn\n")); #####: 2645: ret = ENOMEM; #####: 2646: goto fail; -: 2647: } -: 2648: #####: 2649: filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_NC, sub_filter); #####: 2650: if (!filter) { #####: 2651: DEBUG(2, ("Failed to build filter\n")); #####: 2652: ret = ENOMEM; #####: 2653: goto fail; -: 2654: } -: 2655: #####: 2656: DEBUG(6, ("Search netgroups with filter: %s\n", filter)); -: 2657: #####: 2658: ret = sysdb_search_entry(mem_ctx, sysdb, basedn, -: 2659: LDB_SCOPE_SUBTREE, filter, attrs, -: 2660: msgs_count, msgs); #####: 2661: if (ret) { #####: 2662: goto fail; -: 2663: } -: 2664: #####: 2665: talloc_zfree(tmp_ctx); #####: 2666: return EOK; -: 2667: -: 2668:fail: #####: 2669: if (ret == ENOENT) { #####: 2670: DEBUG(SSSDBG_TRACE_FUNC, ("Entry not found\n")); -: 2671: } else { #####: 2672: DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2673: } #####: 2674: talloc_zfree(tmp_ctx); #####: 2675: return ret; -: 2676:} -: 2677: -: 2678:/* =Delete-Netgroup-by-Name============================================== */ -: 2679: 45: 2680:int sysdb_delete_netgroup(struct sysdb_ctx *sysdb, -: 2681: struct sss_domain_info *domain, -: 2682: const char *name) -: 2683:{ -: 2684: TALLOC_CTX *tmp_ctx; -: 2685: struct ldb_message *msg; -: 2686: int ret; -: 2687: 45: 2688: if (!name) return EINVAL; -: 2689: 45: 2690: tmp_ctx = talloc_new(NULL); 45: 2691: if (!tmp_ctx) { #####: 2692: return ENOMEM; -: 2693: } -: 2694: 45: 2695: ret = sysdb_search_netgroup_by_name(tmp_ctx, sysdb, domain, -: 2696: name, NULL, &msg); 45: 2697: if (ret != EOK && ret != ENOENT) { #####: 2698: DEBUG(6, ("sysdb_search_netgroup_by_name failed: %d (%s)\n", -: 2699: ret, strerror(ret))); #####: 2700: goto done; 45: 2701: } else if (ret == ENOENT) { #####: 2702: DEBUG(6, ("Netgroup does not exist, nothing to delete\n")); #####: 2703: ret = EOK; #####: 2704: goto done; -: 2705: } -: 2706: 45: 2707: ret = sysdb_delete_entry(sysdb, msg->dn, false); 45: 2708: if (ret != EOK) { #####: 2709: goto done; -: 2710: } -: 2711: -: 2712:done: 45: 2713: if (ret != EOK) { #####: 2714: DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); -: 2715: } 45: 2716: talloc_free(tmp_ctx); 45: 2717: return ret; -: 2718:} -: 2719: -: 2720:/* ========= Authentication against cached password ============ */ -: 2721: -: 2722: 54: 2723:errno_t check_failed_login_attempts(struct confdb_ctx *cdb, -: 2724: struct ldb_message *ldb_msg, -: 2725: uint32_t *failed_login_attempts, -: 2726: time_t *delayed_until) -: 2727:{ -: 2728: int ret; -: 2729: int allowed_failed_login_attempts; -: 2730: int failed_login_delay; -: 2731: time_t last_failed_login; -: 2732: time_t end; -: 2733: TALLOC_CTX *tmp_ctx; -: 2734: 54: 2735: tmp_ctx = talloc_new(NULL); 54: 2736: if (!tmp_ctx) { #####: 2737: return ENOMEM; -: 2738: } -: 2739: 54: 2740: *delayed_until = -1; 54: 2741: *failed_login_attempts = ldb_msg_find_attr_as_uint(ldb_msg, -: 2742: SYSDB_FAILED_LOGIN_ATTEMPTS, 0); 54: 2743: last_failed_login = (time_t) ldb_msg_find_attr_as_int64(ldb_msg, -: 2744: SYSDB_LAST_FAILED_LOGIN, 0); 54: 2745: ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, -: 2746: CONFDB_PAM_FAILED_LOGIN_ATTEMPTS, -: 2747: CONFDB_DEFAULT_PAM_FAILED_LOGIN_ATTEMPTS, -: 2748: &allowed_failed_login_attempts); 54: 2749: if (ret != EOK) { #####: 2750: DEBUG(1, ("Failed to read the number of allowed failed login " -: 2751: "attempts.\n")); #####: 2752: ret = EIO; #####: 2753: goto done; -: 2754: } 54: 2755: ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, -: 2756: CONFDB_PAM_FAILED_LOGIN_DELAY, -: 2757: CONFDB_DEFAULT_PAM_FAILED_LOGIN_DELAY, -: 2758: &failed_login_delay); 54: 2759: if (ret != EOK) { #####: 2760: DEBUG(1, ("Failed to read the failed login delay.\n")); #####: 2761: ret = EIO; #####: 2762: goto done; -: 2763: } 54: 2764: DEBUG(9, ("Failed login attempts [%d], allowed failed login attempts [%d], " -: 2765: "failed login delay [%d].\n", *failed_login_attempts, -: 2766: allowed_failed_login_attempts, failed_login_delay)); -: 2767: 54: 2768: if (allowed_failed_login_attempts) { #####: 2769: if (*failed_login_attempts >= allowed_failed_login_attempts) { #####: 2770: if (failed_login_delay) { #####: 2771: end = last_failed_login + (failed_login_delay * 60); #####: 2772: if (end < time(NULL)) { #####: 2773: DEBUG(7, ("failed_login_delay has passed, " -: 2774: "resetting failed_login_attempts.\n")); #####: 2775: *failed_login_attempts = 0; -: 2776: } else { #####: 2777: DEBUG(7, ("login delayed until %lld.\n", (long long) end)); #####: 2778: *delayed_until = end; #####: 2779: ret = EACCES; #####: 2780: goto done; -: 2781: } -: 2782: } else { #####: 2783: DEBUG(4, ("Too many failed logins.\n")); #####: 2784: ret = EACCES; #####: 2785: goto done; -: 2786: } -: 2787: } -: 2788: } -: 2789: 54: 2790: ret = EOK; -: 2791:done: 54: 2792: talloc_free(tmp_ctx); 54: 2793: return ret; -: 2794:} -: 2795: 54: 2796:int sysdb_cache_auth(struct sysdb_ctx *sysdb, -: 2797: struct sss_domain_info *domain, -: 2798: const char *name, -: 2799: const char *password, -: 2800: struct confdb_ctx *cdb, -: 2801: bool just_check, -: 2802: time_t *_expire_date, -: 2803: time_t *_delayed_until) -: 2804:{ -: 2805: TALLOC_CTX *tmp_ctx; 54: 2806: const char *attrs[] = { SYSDB_NAME, SYSDB_CACHEDPWD, SYSDB_DISABLED, -: 2807: SYSDB_LAST_LOGIN, SYSDB_LAST_ONLINE_AUTH, -: 2808: "lastCachedPasswordChange", -: 2809: "accountExpires", SYSDB_FAILED_LOGIN_ATTEMPTS, -: 2810: SYSDB_LAST_FAILED_LOGIN, NULL }; -: 2811: struct ldb_message *ldb_msg; -: 2812: const char *userhash; -: 2813: char *comphash; 54: 2814: uint64_t lastLogin = 0; -: 2815: int cred_expiration; 54: 2816: uint32_t failed_login_attempts = 0; -: 2817: struct sysdb_attrs *update_attrs; 54: 2818: bool authentication_successful = false; 54: 2819: time_t expire_date = -1; 54: 2820: time_t delayed_until = -1; -: 2821: int ret; -: 2822: 54: 2823: if (name == NULL || *name == '\0') { #####: 2824: DEBUG(1, ("Missing user name.\n")); #####: 2825: return EINVAL; -: 2826: } -: 2827: 54: 2828: if (cdb == NULL) { #####: 2829: DEBUG(1, ("Missing config db context.\n")); #####: 2830: return EINVAL; -: 2831: } -: 2832: 54: 2833: if (sysdb == NULL) { #####: 2834: DEBUG(1, ("Missing sysdb db context.\n")); #####: 2835: return EINVAL; -: 2836: } -: 2837: 54: 2838: if (!domain->cache_credentials) { #####: 2839: DEBUG(3, ("Cached credentials not available.\n")); #####: 2840: return EINVAL; -: 2841: } -: 2842: 54: 2843: tmp_ctx = talloc_new(NULL); 54: 2844: if (!tmp_ctx) { #####: 2845: return ENOMEM; -: 2846: } -: 2847: 54: 2848: ret = ldb_transaction_start(sysdb->ldb); 54: 2849: if (ret) { #####: 2850: talloc_zfree(tmp_ctx); #####: 2851: ret = sysdb_error_to_errno(ret); #####: 2852: return ret; -: 2853: } -: 2854: 54: 2855: ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain, -: 2856: name, attrs, &ldb_msg); 54: 2857: if (ret != EOK) { #####: 2858: DEBUG(1, ("sysdb_search_user_by_name failed [%d][%s].\n", -: 2859: ret, strerror(ret))); #####: 2860: goto done; -: 2861: } -: 2862: -: 2863: /* Check offline_auth_cache_timeout */ 54: 2864: lastLogin = ldb_msg_find_attr_as_uint64(ldb_msg, -: 2865: SYSDB_LAST_ONLINE_AUTH, -: 2866: 0); -: 2867: 54: 2868: ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, -: 2869: CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration); 54: 2870: if (ret != EOK) { #####: 2871: DEBUG(1, ("Failed to read expiration time of offline credentials.\n")); #####: 2872: goto done; -: 2873: } 54: 2874: DEBUG(9, ("Offline credentials expiration is [%d] days.\n", -: 2875: cred_expiration)); -: 2876: 54: 2877: if (cred_expiration) { 27: 2878: expire_date = lastLogin + (cred_expiration * 86400); 27: 2879: if (expire_date < time(NULL)) { #####: 2880: DEBUG(4, ("Cached user entry is too old.\n")); #####: 2881: expire_date = 0; #####: 2882: ret = EACCES; #####: 2883: goto done; -: 2884: } -: 2885: } else { 27: 2886: expire_date = 0; -: 2887: } -: 2888: 54: 2889: ret = check_failed_login_attempts(cdb, ldb_msg, &failed_login_attempts, -: 2890: &delayed_until); 54: 2891: if (ret != EOK) { #####: 2892: DEBUG(1, ("Failed to check login attempts\n")); #####: 2893: goto done; -: 2894: } -: 2895: -: 2896: /* TODO: verify user account (disabled, expired ...) */ -: 2897: 54: 2898: userhash = ldb_msg_find_attr_as_string(ldb_msg, SYSDB_CACHEDPWD, NULL); 54: 2899: if (userhash == NULL || *userhash == '\0') { 18: 2900: DEBUG(4, ("Cached credentials not available.\n")); 18: 2901: ret = ENOENT; 18: 2902: goto done; -: 2903: } -: 2904: 36: 2905: ret = s3crypt_sha512(tmp_ctx, password, userhash, &comphash); 36: 2906: if (ret) { #####: 2907: DEBUG(4, ("Failed to create password hash.\n")); #####: 2908: ret = EFAULT; #####: 2909: goto done; -: 2910: } -: 2911: 36: 2912: update_attrs = sysdb_new_attrs(tmp_ctx); 36: 2913: if (update_attrs == NULL) { #####: 2914: DEBUG(1, ("sysdb_new_attrs failed.\n")); #####: 2915: ret = ENOMEM; #####: 2916: goto done; -: 2917: } -: 2918: 36: 2919: if (strcmp(userhash, comphash) == 0) { -: 2920: /* TODO: probable good point for audit logging */ 18: 2921: DEBUG(4, ("Hashes do match!\n")); 18: 2922: authentication_successful = true; -: 2923: 18: 2924: if (just_check) { #####: 2925: ret = EOK; #####: 2926: goto done; -: 2927: } -: 2928: 18: 2929: ret = sysdb_attrs_add_time_t(update_attrs, -: 2930: SYSDB_LAST_LOGIN, time(NULL)); 18: 2931: if (ret != EOK) { #####: 2932: DEBUG(3, ("sysdb_attrs_add_time_t failed, " -: 2933: "but authentication is successful.\n")); #####: 2934: ret = EOK; #####: 2935: goto done; -: 2936: } -: 2937: 18: 2938: ret = sysdb_attrs_add_uint32(update_attrs, -: 2939: SYSDB_FAILED_LOGIN_ATTEMPTS, 0U); 18: 2940: if (ret != EOK) { #####: 2941: DEBUG(3, ("sysdb_attrs_add_uint32 failed, " -: 2942: "but authentication is successful.\n")); #####: 2943: ret = EOK; #####: 2944: goto done; -: 2945: } -: 2946: -: 2947: -: 2948: } else { 18: 2949: DEBUG(4, ("Authentication failed.\n")); 18: 2950: authentication_successful = false; -: 2951: 18: 2952: ret = sysdb_attrs_add_time_t(update_attrs, -: 2953: SYSDB_LAST_FAILED_LOGIN, -: 2954: time(NULL)); 18: 2955: if (ret != EOK) { #####: 2956: DEBUG(3, ("sysdb_attrs_add_time_t failed\n.")); #####: 2957: goto done; -: 2958: } -: 2959: 18: 2960: ret = sysdb_attrs_add_uint32(update_attrs, -: 2961: SYSDB_FAILED_LOGIN_ATTEMPTS, -: 2962: ++failed_login_attempts); 18: 2963: if (ret != EOK) { #####: 2964: DEBUG(3, ("sysdb_attrs_add_uint32 failed.\n")); #####: 2965: goto done; -: 2966: } -: 2967: } -: 2968: 36: 2969: ret = sysdb_set_user_attr(sysdb, domain, -: 2970: name, update_attrs, LDB_FLAG_MOD_REPLACE); 36: 2971: if (ret) { #####: 2972: DEBUG(1, ("Failed to update Login attempt information!\n")); -: 2973: } -: 2974: -: 2975:done: 54: 2976: if (_expire_date != NULL) { 54: 2977: *_expire_date = expire_date; -: 2978: } 54: 2979: if (_delayed_until != NULL) { 54: 2980: *_delayed_until = delayed_until; -: 2981: } 54: 2982: if (ret) { 18: 2983: ldb_transaction_cancel(sysdb->ldb); -: 2984: } else { 36: 2985: ret = ldb_transaction_commit(sysdb->ldb); 36: 2986: ret = sysdb_error_to_errno(ret); 36: 2987: if (ret) { #####: 2988: DEBUG(2, ("Failed to commit transaction!\n")); -: 2989: } -: 2990: } 54: 2991: if (authentication_successful) { 18: 2992: ret = EOK; -: 2993: } else { 36: 2994: if (ret == EOK) { 18: 2995: ret = EINVAL; -: 2996: } -: 2997: } 54: 2998: talloc_free(tmp_ctx); 54: 2999: return ret; -: 3000:} -: 3001: 27: 3002:errno_t sysdb_update_members(struct sysdb_ctx *sysdb, -: 3003: struct sss_domain_info *domain, -: 3004: const char *member, -: 3005: enum sysdb_member_type type, -: 3006: const char *const *add_groups, -: 3007: const char *const *del_groups) -: 3008:{ -: 3009: errno_t ret; -: 3010: errno_t sret; -: 3011: int i; 27: 3012: bool in_transaction = false; -: 3013: 27: 3014: TALLOC_CTX *tmp_ctx = talloc_new(NULL); 27: 3015: if(!tmp_ctx) { #####: 3016: return ENOMEM; -: 3017: } -: 3018: 27: 3019: ret = sysdb_transaction_start(sysdb); 27: 3020: if (ret != EOK) { #####: 3021: DEBUG(0, ("Failed to start update transaction\n")); #####: 3022: goto done; -: 3023: } -: 3024: 27: 3025: in_transaction = true; -: 3026: 27: 3027: if (add_groups) { -: 3028: /* Add the user to all add_groups */ 45: 3029: for (i = 0; add_groups[i]; i++) { 27: 3030: ret = sysdb_add_group_member(sysdb, domain, 27: 3031: add_groups[i], member, type); 27: 3032: if (ret != EOK) { #####: 3033: DEBUG(1, ("Could not add member [%s] to group [%s]. " -: 3034: "Skipping.\n", member, add_groups[i])); -: 3035: /* Continue on, we should try to finish the rest */ -: 3036: } -: 3037: } -: 3038: } -: 3039: 27: 3040: if (del_groups) { -: 3041: /* Remove the user from all del_groups */ 45: 3042: for (i = 0; del_groups[i]; i++) { 27: 3043: ret = sysdb_remove_group_member(sysdb, domain, 27: 3044: del_groups[i], member, type); 27: 3045: if (ret != EOK) { #####: 3046: DEBUG(1, ("Could not remove member [%s] from group [%s]. " -: 3047: "Skipping\n", member, del_groups[i])); -: 3048: /* Continue on, we should try to finish the rest */ -: 3049: } -: 3050: } -: 3051: } -: 3052: 27: 3053: ret = sysdb_transaction_commit(sysdb); 27: 3054: if (ret != EOK) { #####: 3055: DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); #####: 3056: goto done; -: 3057: } -: 3058: 27: 3059: in_transaction = false; -: 3060: -: 3061:done: 27: 3062: if (in_transaction) { #####: 3063: sret = sysdb_transaction_cancel(sysdb); #####: 3064: if (sret != EOK) { #####: 3065: DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); -: 3066: } -: 3067: } 27: 3068: talloc_free(tmp_ctx); 27: 3069: return ret; -: 3070:} -: 3071: #####: 3072:errno_t sysdb_remove_attrs(struct sysdb_ctx *sysdb, -: 3073: struct sss_domain_info *domain, -: 3074: const char *name, -: 3075: enum sysdb_member_type type, -: 3076: char **remove_attrs) -: 3077:{ -: 3078: errno_t ret; #####: 3079: errno_t sret = EOK; #####: 3080: bool in_transaction = false; -: 3081: struct ldb_message *msg; -: 3082: int lret; -: 3083: size_t i; -: 3084: #####: 3085: msg = ldb_msg_new(NULL); #####: 3086: if (!msg) return ENOMEM; -: 3087: #####: 3088: switch(type) { -: 3089: case SYSDB_MEMBER_USER: #####: 3090: msg->dn = sysdb_user_dn(sysdb, msg, domain, name); #####: 3091: break; -: 3092: -: 3093: case SYSDB_MEMBER_GROUP: #####: 3094: msg->dn = sysdb_group_dn(sysdb, msg, domain, name); #####: 3095: break; -: 3096: -: 3097: case SYSDB_MEMBER_NETGROUP: #####: 3098: msg->dn = sysdb_netgroup_dn(sysdb, msg, domain, name); #####: 3099: break; -: 3100: -: 3101: case SYSDB_MEMBER_SERVICE: #####: 3102: msg->dn = sysdb_svc_dn(sysdb, msg, domain->name, name); #####: 3103: break; -: 3104: } #####: 3105: if (!msg->dn) { #####: 3106: ret = ENOMEM; #####: 3107: goto done; -: 3108: } -: 3109: #####: 3110: ret = sysdb_transaction_start(sysdb); #####: 3111: if (ret != EOK) { #####: 3112: DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); #####: 3113: goto done; -: 3114: } -: 3115: #####: 3116: in_transaction = true; -: 3117: #####: 3118: for (i = 0; remove_attrs[i]; i++) { -: 3119: /* SYSDB_MEMBEROF is exclusively handled by the memberof plugin */ #####: 3120: if (strcasecmp(remove_attrs[i], SYSDB_MEMBEROF) == 0) { #####: 3121: continue; -: 3122: } #####: 3123: DEBUG(8, ("Removing attribute [%s] from [%s]\n", -: 3124: remove_attrs[i], name)); #####: 3125: lret = ldb_msg_add_empty(msg, remove_attrs[i], -: 3126: LDB_FLAG_MOD_DELETE, NULL); #####: 3127: if (lret != LDB_SUCCESS) { #####: 3128: ret = sysdb_error_to_errno(lret); #####: 3129: goto done; -: 3130: } -: 3131: -: 3132: /* We need to do individual modifies so that we can -: 3133: * skip unknown attributes. Otherwise, any nonexistent -: 3134: * attribute in the sysdb will cause other removals to -: 3135: * fail. -: 3136: */ #####: 3137: lret = ldb_modify(sysdb->ldb, msg); #####: 3138: if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_ATTRIBUTE) { #####: 3139: ret = sysdb_error_to_errno(lret); #####: 3140: goto done; -: 3141: } -: 3142: -: 3143: /* Remove this attribute and move on to the next one */ #####: 3144: ldb_msg_remove_attr(msg, remove_attrs[i]); -: 3145: } -: 3146: #####: 3147: ret = sysdb_transaction_commit(sysdb); #####: 3148: if (ret != EOK) { #####: 3149: DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); #####: 3150: goto done; -: 3151: } -: 3152: #####: 3153: in_transaction = false; -: 3154: #####: 3155: ret = EOK; -: 3156:done: #####: 3157: if (in_transaction) { #####: 3158: sret = sysdb_transaction_cancel(sysdb); #####: 3159: if (sret != EOK) { #####: 3160: DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); -: 3161: } -: 3162: } #####: 3163: talloc_free(msg); #####: 3164: return ret; -: 3165:}