diff options
author | Stefan Metzmacher <metze@samba.org> | 2018-10-12 15:56:18 +0200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2018-11-05 09:33:29 +0100 |
commit | 47745ae56288b836c73516dedb33edc5e324b8dc (patch) | |
tree | 267aebc44dcbabbeb5ea30eb8dd5be0c6af4cd1e | |
parent | 141285407df6cd23ac20ce5eb352983e81ce0969 (diff) | |
download | samba-47745ae56288b836c73516dedb33edc5e324b8dc.tar.gz |
s4:repl_meta_data: add support for DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID
This will be used by dbcheck in the next commits.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 0386307e34097f5d9233c970983c7306d1705a87)
-rw-r--r-- | selftest/knownfail.d/samba4.blackbox.dbcheck-links | 6 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/extended_dn_store.c | 7 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 145 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 12 |
4 files changed, 161 insertions, 9 deletions
diff --git a/selftest/knownfail.d/samba4.blackbox.dbcheck-links b/selftest/knownfail.d/samba4.blackbox.dbcheck-links deleted file mode 100644 index ee207a53ab7..00000000000 --- a/selftest/knownfail.d/samba4.blackbox.dbcheck-links +++ /dev/null @@ -1,6 +0,0 @@ -# The first one fails and all others are follow up failures... -^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_missing_link_sid_corruption -^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.missing_link_sid_clean -^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_clean3 -^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued -^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_equal_or_too_many diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c index a32ab8d6f93..8e5a2ba7ae9 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c @@ -376,6 +376,7 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req unsigned int i, j; struct extended_dn_context *ac; struct ldb_control *fix_links_control = NULL; + struct ldb_control *fix_link_sid_ctrl = NULL; int ret; if (ldb_dn_is_special(req->op.mod.message->dn)) { @@ -400,6 +401,12 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req return ldb_next_request(module, req); } + fix_link_sid_ctrl = ldb_request_get_control(ac->req, + DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID); + if (fix_link_sid_ctrl != NULL) { + return ldb_next_request(module, req); + } + for (i=0; i < req->op.mod.message->num_elements; i++) { const struct ldb_message_element *el = &req->op.mod.message->elements[i]; const struct dsdb_attribute *schema_attr diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 2a3a86ed27e..5bdc57366da 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -112,6 +112,8 @@ struct replmd_replicated_request { bool is_urgent; bool isDeleted; + + bool fix_link_sid; }; static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar); @@ -2481,6 +2483,109 @@ static int replmd_modify_la_add(struct ldb_module *module, return err; } + if (ac->fix_link_sid) { + char *fixed_dnstring = NULL; + struct dom_sid tmp_sid = { 0, }; + DATA_BLOB sid_blob = data_blob_null; + enum ndr_err_code ndr_err; + NTSTATUS status; + int num; + + if (exact == NULL) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + if (dns[i].dsdb_dn->dn_format != DSDB_NORMAL_DN) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + /* + * Only "<GUID=...><SID=...>" is allowed. + * + * We get the GUID to just to find the old + * value and the SID in order to add it + * to the found value. + */ + + num = ldb_dn_get_comp_num(dns[i].dsdb_dn->dn); + if (num != 0) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + num = ldb_dn_get_extended_comp_num(dns[i].dsdb_dn->dn); + if (num != 2) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + status = dsdb_get_extended_dn_sid(exact->dsdb_dn->dn, + &tmp_sid, "SID"); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + /* this is what we expect */ + } else if (NT_STATUS_IS_OK(status)) { + struct GUID_txt_buf guid_str; + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "i[%u] SID NOT MISSING... Attribute %s already " + "exists for target GUID %s, SID %s, DN: %s", + i, el->name, + GUID_buf_string(&exact->guid, + &guid_str), + dom_sid_string(tmp_ctx, &tmp_sid), + dsdb_dn_get_extended_linearized(tmp_ctx, + exact->dsdb_dn, 1)); + talloc_free(tmp_ctx); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } else { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + status = dsdb_get_extended_dn_sid(dns[i].dsdb_dn->dn, + &tmp_sid, "SID"); + if (!NT_STATUS_IS_OK(status)) { + struct GUID_txt_buf guid_str; + ldb_asprintf_errstring(ldb, + "NO SID PROVIDED... Attribute %s already " + "exists for target GUID %s", + el->name, + GUID_buf_string(&exact->guid, + &guid_str)); + talloc_free(tmp_ctx); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + + ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &tmp_sid, + (ndr_push_flags_fn_t)ndr_push_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + ret = ldb_dn_set_extended_component(exact->dsdb_dn->dn, "SID", &sid_blob); + data_blob_free(&sid_blob); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + + fixed_dnstring = dsdb_dn_get_extended_linearized( + new_values, exact->dsdb_dn, 1); + if (fixed_dnstring == NULL) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + /* + * We just replace the existing value... + */ + *exact->v = data_blob_string_const(fixed_dnstring); + + continue; + } + if (exact != NULL) { /* * We are trying to add one that exists, which is only @@ -3306,6 +3411,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) struct ldb_control *sd_propagation_control; struct ldb_control *fix_links_control = NULL; struct ldb_control *fix_dn_name_control = NULL; + struct ldb_control *fix_dn_sid_control = NULL; struct replmd_private *replmd_private = talloc_get_type(ldb_module_get_private(module), struct replmd_private); @@ -3451,6 +3557,44 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_OPERATIONS_ERROR; } + fix_dn_sid_control = ldb_request_get_control(req, + DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID); + if (fix_dn_sid_control != NULL) { + const struct dsdb_attribute *sa = NULL; + + if (msg->num_elements != 1) { + talloc_free(ac); + return ldb_module_operr(module); + } + + if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) { + talloc_free(ac); + return ldb_module_operr(module); + } + + if (msg->elements[0].num_values != 1) { + talloc_free(ac); + return ldb_module_operr(module); + } + + sa = dsdb_attribute_by_lDAPDisplayName(ac->schema, + msg->elements[0].name); + if (sa == NULL) { + talloc_free(ac); + return ldb_module_operr(module); + } + + if (sa->dn_format != DSDB_NORMAL_DN) { + talloc_free(ac); + return ldb_module_operr(module); + } + + fix_dn_sid_control->critical = false; + ac->fix_link_sid = true; + + goto handle_linked_attribs; + } + ldb_msg_remove_attr(msg, "whenChanged"); ldb_msg_remove_attr(msg, "uSNChanged"); @@ -3471,6 +3615,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) return ret; } + handle_linked_attribs: ret = replmd_modify_handle_linked_attribs(module, replmd_private, ac, msg, t, req); if (ret != LDB_SUCCESS) { diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 734d0be26a9..81d8c96437c 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3770,9 +3770,15 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) el = ldb_msg_find_element(ac->msg, "member"); if (el != NULL) { - ret = samldb_member_check(ac); - if (ret != LDB_SUCCESS) { - return ret; + struct ldb_control *fix_link_sid_ctrl = NULL; + + fix_link_sid_ctrl = ldb_request_get_control(ac->req, + DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID); + if (fix_link_sid_ctrl == NULL) { + ret = samldb_member_check(ac); + if (ret != LDB_SUCCESS) { + return ret; + } } } |