/* see if two DNs match, comparing first by GUID, then by SID, and finally by string components */ static int samba_dn_extended_match(struct ldb_context *ldb, const struct ldb_val *v1, const struct ldb_val *v2, bool *matched) { TALLOC_CTX *tmp_ctx; struct ldb_dn *dn1, *dn2; const struct ldb_val *guid1, *guid2, *sid1, *sid2; uint32_t rmd_flags1, rmd_flags2; tmp_ctx = talloc_new(ldb); dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1); dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2); if (!dn1 || !dn2) { /* couldn't parse as DN's */ talloc_free(tmp_ctx); (*matched) = false; return LDB_SUCCESS; } rmd_flags1 = dsdb_dn_rmd_flags(dn1); rmd_flags2 = dsdb_dn_rmd_flags(dn2); if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) != (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) { /* only match if they have the same deletion status */ talloc_free(tmp_ctx); (*matched) = false; return LDB_SUCCESS; } guid1 = ldb_dn_get_extended_component(dn1, "GUID"); guid2 = ldb_dn_get_extended_component(dn2, "GUID"); if (guid1 && guid2) { (*matched) = (data_blob_cmp(guid1, guid2) == 0); talloc_free(tmp_ctx); return LDB_SUCCESS; } sid1 = ldb_dn_get_extended_component(dn1, "SID"); sid2 = ldb_dn_get_extended_component(dn2, "SID"); if (sid1 && sid2) { (*matched) = (data_blob_cmp(sid1, sid2) == 0); talloc_free(tmp_ctx); return LDB_SUCCESS; } (*matched) = (ldb_dn_compare(dn1, dn2) == 0); talloc_free(tmp_ctx); return LDB_SUCCESS; }
static bool torture_ldb_dn_extended(struct torture_context *torture) { TALLOC_CTX *mem_ctx = talloc_new(torture); struct ldb_context *ldb; struct ldb_dn *dn, *dn2; DATA_BLOB sid_blob = strhex_to_data_blob(mem_ctx, hex_sid); DATA_BLOB guid_blob = strhex_to_data_blob(mem_ctx, hex_guid); const char *dn_str = "cn=admin,cn=users,dc=samba,dc=org"; torture_assert(torture, ldb = ldb_init(mem_ctx, torture->ev), "Failed to init ldb"); torture_assert_int_equal(torture, ldb_register_samba_handlers(ldb), 0, "Failed to register Samba handlers"); ldb_set_utf8_fns(ldb, NULL, wrap_casefold); /* Check behaviour of a normal DN */ torture_assert(torture, dn = ldb_dn_new(mem_ctx, ldb, dn_str), "Failed to create a 'normal' DN"); torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'normal' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == false, "Should not find plain DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") == NULL, "Should not find an SID on plain DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") == NULL, "Should not find an GUID on plain DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "WKGUID") == NULL, "Should not find an WKGUID on plain DN"); /* Now make an extended DN */ torture_assert(torture, dn = ldb_dn_new_fmt(mem_ctx, ldb, "<GUID=%s>;<SID=%s>;%s", guid, sid, dn_str), "Failed to create an 'extended' DN"); torture_assert(torture, dn2 = ldb_dn_copy(mem_ctx, dn), "Failed to copy the 'extended' DN"); talloc_free(dn); dn = dn2; torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'extended' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == true, "Should find extended DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") != NULL, "Should find an SID on extended DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") != NULL, "Should find an GUID on extended DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "SID"), sid_blob, "Extended DN SID incorect"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "GUID"), guid_blob, "Extended DN GUID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), dn_str, "linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_casefold(dn), strupper_talloc(mem_ctx, dn_str), "casefolded DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_component_name(dn, 0), "cn", "componet zero incorrect"); torture_assert_data_blob_equal(torture, *ldb_dn_get_component_val(dn, 0), data_blob_string_const("admin"), "componet zero incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 1), talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", guid, sid, dn_str), "Clear extended linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 0), talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", hex_guid, hex_sid, dn_str), "HEX extended linearized DN incorrect"); torture_assert(torture, ldb_dn_remove_child_components(dn, 1) == true, "Failed to remove DN child"); torture_assert(torture, ldb_dn_has_extended(dn) == false, "Extended DN flag should be cleared after child element removal"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") == NULL, "Should not find an SID on DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") == NULL, "Should not find an GUID on DN"); /* TODO: test setting these in the other order, and ensure it still comes out 'GUID first' */ torture_assert_int_equal(torture, ldb_dn_set_extended_component(dn, "GUID", &guid_blob), 0, "Failed to set a GUID on DN"); torture_assert_int_equal(torture, ldb_dn_set_extended_component(dn, "SID", &sid_blob), 0, "Failed to set a SID on DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "SID"), sid_blob, "Extended DN SID incorect"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "GUID"), guid_blob, "Extended DN GUID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), "cn=users,dc=samba,dc=org", "linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 1), talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", guid, sid, "cn=users,dc=samba,dc=org"), "Clear extended linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 0), talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", hex_guid, hex_sid, "cn=users,dc=samba,dc=org"), "HEX extended linearized DN incorrect"); /* Now check a 'just GUID' DN (clear format) */ torture_assert(torture, dn = ldb_dn_new_fmt(mem_ctx, ldb, "<GUID=%s>", guid), "Failed to create an 'extended' DN"); torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'extended' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == true, "Should find extended DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") == NULL, "Should not find an SID on this DN"); torture_assert_int_equal(torture, ldb_dn_get_comp_num(dn), 0, "Should not find an 'normal' componet on this DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") != NULL, "Should find an GUID on this DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "GUID"), guid_blob, "Extended DN GUID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), "", "linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 1), talloc_asprintf(mem_ctx, "<GUID=%s>", guid), "Clear extended linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 0), talloc_asprintf(mem_ctx, "<GUID=%s>", hex_guid), "HEX extended linearized DN incorrect"); /* Now check a 'just GUID' DN (HEX format) */ torture_assert(torture, dn = ldb_dn_new_fmt(mem_ctx, ldb, "<GUID=%s>", hex_guid), "Failed to create an 'extended' DN"); torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'extended' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == true, "Should find extended DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") == NULL, "Should not find an SID on this DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") != NULL, "Should find an GUID on this DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "GUID"), guid_blob, "Extended DN GUID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), "", "linearized DN incorrect"); /* Now check a 'just SID' DN (clear format) */ torture_assert(torture, dn = ldb_dn_new_fmt(mem_ctx, ldb, "<SID=%s>", sid), "Failed to create an 'extended' DN"); torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'extended' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == true, "Should find extended DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") == NULL, "Should not find an SID on this DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") != NULL, "Should find an SID on this DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "SID"), sid_blob, "Extended DN SID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), "", "linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 1), talloc_asprintf(mem_ctx, "<SID=%s>", sid), "Clear extended linearized DN incorrect"); torture_assert_str_equal(torture, ldb_dn_get_extended_linearized(mem_ctx, dn, 0), talloc_asprintf(mem_ctx, "<SID=%s>", hex_sid), "HEX extended linearized DN incorrect"); /* Now check a 'just SID' DN (HEX format) */ torture_assert(torture, dn = ldb_dn_new_fmt(mem_ctx, ldb, "<SID=%s>", hex_sid), "Failed to create an 'extended' DN"); torture_assert(torture, ldb_dn_validate(dn), "Failed to validate 'extended' DN"); torture_assert(torture, ldb_dn_has_extended(dn) == true, "Should find extended DN to be 'extended'"); torture_assert(torture, ldb_dn_get_extended_component(dn, "GUID") == NULL, "Should not find an SID on this DN"); torture_assert(torture, ldb_dn_get_extended_component(dn, "SID") != NULL, "Should find an SID on this DN"); torture_assert_data_blob_equal(torture, *ldb_dn_get_extended_component(dn, "SID"), sid_blob, "Extended DN SID incorect"); torture_assert_str_equal(torture, ldb_dn_get_linearized(dn), "", "linearized DN incorrect"); talloc_free(mem_ctx); return true; }
static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct ldb_message_element *in, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaAttribute *out) { uint32_t i; DATA_BLOB *blobs; if (attr->attributeID_id == 0xFFFFFFFF) { return WERR_FOOBAR; } out->attid = attr->attributeID_id; out->value_ctr.num_values = in->num_values; out->value_ctr.values = talloc_array(mem_ctx, struct drsuapi_DsAttributeValue, in->num_values); W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values); blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values); W_ERROR_HAVE_NO_MEMORY(blobs); for (i=0; i < in->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; enum ndr_err_code ndr_err; const DATA_BLOB *guid_blob, *sid_blob; struct ldb_dn *dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); out->value_ctr.values[i].blob = &blobs[i]; dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]); W_ERROR_HAVE_NO_MEMORY(dn); guid_blob = ldb_dn_get_extended_component(dn, "GUID"); ZERO_STRUCT(id3); if (guid_blob) { ndr_err = ndr_pull_struct_blob_all(guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, (ndr_pull_flags_fn_t)ndr_pull_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } sid_blob = ldb_dn_get_extended_component(dn, "SID"); if (sid_blob) { ndr_err = ndr_pull_struct_blob_all(sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } id3.dn = ldb_dn_get_linearized(dn); ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } talloc_free(tmp_ctx); } return WERR_OK; }