diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-09-09 12:29:01 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-09-09 12:36:51 +1000 |
commit | dca7afb799477a34f704c04397a6afa1ee6b9973 (patch) | |
tree | d091f9089b3ffb5518958a8b920a9526f34e6e0d /source4/rpc_server | |
parent | 3cb1caf0ef9fa7b3e96f2ff1d878357bef3a60d3 (diff) | |
download | samba-dca7afb799477a34f704c04397a6afa1ee6b9973.tar.gz samba-dca7afb799477a34f704c04397a6afa1ee6b9973.tar.bz2 samba-dca7afb799477a34f704c04397a6afa1ee6b9973.zip |
s4: fixed format of repsTo in samdb
Metze pointed out what the windows tool ldp.exe will examine repsTo
attributes on remote DCs, so we do in fact need to use the same format
that windows uses. This patch changes the server side implementation
of UpdateRefs to use the windows format
Diffstat (limited to 'source4/rpc_server')
-rw-r--r-- | source4/rpc_server/drsuapi/updaterefs.c | 122 |
1 files changed, 70 insertions, 52 deletions
diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c index 5bf2f2251f..4a888099c0 100644 --- a/source4/rpc_server/drsuapi/updaterefs.c +++ b/source4/rpc_server/drsuapi/updaterefs.c @@ -30,6 +30,11 @@ #include "librpc/gen_ndr/ndr_drsblobs.h" #include "auth/auth.h" +struct repsTo { + uint32_t count; + struct repsFromToBlob *r; +}; + /* load the repsTo structure for a given partition GUID */ @@ -39,8 +44,9 @@ static WERROR uref_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, st struct ldb_dn *dn; const char *attrs[] = { "repsTo", NULL }; struct ldb_result *res; - const struct ldb_val *v; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + int i; + struct ldb_message_element *el; if (dsdb_find_dn_by_guid(sam_ctx, tmp_ctx, GUID_string(tmp_ctx, guid), &dn) != LDB_SUCCESS) { DEBUG(0,("drsuapi_addref: failed to find partition with GUID %s\n", @@ -58,16 +64,27 @@ static WERROR uref_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, st return WERR_DS_DRA_INTERNAL_ERROR; } - v = ldb_msg_find_ldb_val(res->msgs[0], "repsTo"); - if (v == NULL) { - /* treat as empty empty */ - ZERO_STRUCTP(reps); - reps->version = REPSTO_VERSION1; - } else { + ZERO_STRUCTP(reps); + + el = ldb_msg_find_element(res->msgs[0], "repsTo"); + if (el == NULL) { + talloc_free(tmp_ctx); + return WERR_OK; + } + + reps->count = el->num_values; + reps->r = talloc_array(mem_ctx, struct repsFromToBlob, reps->count); + if (reps->r == NULL) { + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + for (i=0; i<reps->count; i++) { enum ndr_err_code ndr_err; - ndr_err = ndr_pull_struct_blob(v, mem_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), - reps, - (ndr_pull_flags_fn_t)ndr_pull_repsTo); + ndr_err = ndr_pull_struct_blob(&el->values[i], + mem_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), + &reps->r[i], + (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); return WERR_DS_DRA_INTERNAL_ERROR; @@ -86,11 +103,10 @@ static WERROR uref_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, st struct repsTo *reps) { struct ldb_dn *dn; - struct ldb_val v; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - enum ndr_err_code ndr_err; struct ldb_message *msg; struct ldb_message_element *el; + int i; if (dsdb_find_dn_by_guid(sam_ctx, tmp_ctx, GUID_string(tmp_ctx, guid), &dn) != LDB_SUCCESS) { DEBUG(0,("drsuapi_addref: failed to find partition with GUID %s\n", @@ -99,20 +115,31 @@ static WERROR uref_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, st return WERR_DS_DRA_BAD_NC; } - ndr_err = ndr_push_struct_blob(&v, tmp_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), - reps, - (ndr_push_flags_fn_t)ndr_push_repsTo); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - goto failed; - } - msg = ldb_msg_new(tmp_ctx); msg->dn = dn; if (ldb_msg_add_empty(msg, "repsTo", LDB_FLAG_MOD_REPLACE, &el) != LDB_SUCCESS) { goto failed; } - el->num_values = 1; - el->values = &v; + + el->values = talloc_array(msg, struct ldb_val, reps->count); + if (!el->values) { + goto failed; + } + + for (i=0; i<reps->count; i++) { + struct ldb_val v; + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob(&v, tmp_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), + &reps->r[i], + (ndr_push_flags_fn_t)ndr_push_repsFromToBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + goto failed; + } + + el->num_values++; + el->values[i] = v; + } if (ldb_modify(sam_ctx, msg) != LDB_SUCCESS) { DEBUG(0,("Failed to store repsTo - %s\n", ldb_errstring(sam_ctx))); @@ -132,30 +159,24 @@ failed: add a replication destination for a given partition GUID */ static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, - struct GUID *guid, struct repsToDest *dest) + struct GUID *guid, struct repsFromTo1 *dest) { struct repsTo reps; WERROR werr; - struct repsTov1 *rv1; werr = uref_loadreps(sam_ctx, mem_ctx, guid, &reps); if (!W_ERROR_IS_OK(werr)) { return werr; } - if (reps.version != REPSTO_VERSION1) { - DEBUG(0,("Wrong version number %u on disk\n", - reps.version)); - return WERR_DS_DRA_INTERNAL_ERROR; - } - - rv1 = &reps.ctr.r; - rv1->reps = talloc_realloc(mem_ctx, rv1->reps, struct repsToDest, rv1->count+1); - if (rv1->reps == NULL) { + reps.r = talloc_realloc(mem_ctx, reps.r, struct repsFromToBlob, reps.count+1); + if (reps.r == NULL) { return WERR_DS_DRA_INTERNAL_ERROR; } - rv1->reps[rv1->count] = *dest; - rv1->count++; + ZERO_STRUCT(reps.r[reps.count]); + reps.r[reps.count].version = 1; + reps.r[reps.count].ctr.ctr1 = *dest; + reps.count++; werr = uref_savereps(sam_ctx, mem_ctx, guid, &reps); if (!W_ERROR_IS_OK(werr)) { @@ -173,7 +194,6 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, { struct repsTo reps; WERROR werr; - struct repsTov1 *rv1; int i; werr = uref_loadreps(sam_ctx, mem_ctx, guid, &reps); @@ -181,19 +201,12 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return werr; } - if (reps.version != REPSTO_VERSION1) { - DEBUG(0,("Wrong version number %u on disk\n", reps.version)); - return WERR_DS_DRA_INTERNAL_ERROR; - } - - rv1 = &reps.ctr.r; - - for (i=0; i<rv1->count; i++) { - if (GUID_compare(dest_guid, &rv1->reps[i].dest_guid) == 0) { - if (i+1 < rv1->count) { - memmove(&rv1->reps[i], &rv1->reps[i+1], sizeof(rv1->reps[i])*(rv1->count-(i+1))); + for (i=0; i<reps.count; i++) { + if (GUID_compare(dest_guid, &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) { + if (i+1 < reps.count) { + memmove(&reps.r[i], &reps.r[i+1], sizeof(reps.r[i])*(reps.count-(i+1))); } - rv1->count--; + reps.count--; } } @@ -248,16 +261,21 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA } if (req->options & DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE) { - struct repsToDest dest; + struct repsFromTo1 dest; + struct repsFromTo1OtherInfo oi; + + ZERO_STRUCT(dest); + ZERO_STRUCT(oi); - dest.dest_dsa_dns_name = req->dest_dsa_dns_name; - dest.dest_guid = req->dest_dsa_guid; - dest.options = req->options; + oi.dns_name = req->dest_dsa_dns_name; + dest.other_info = &oi; + dest.source_dsa_obj_guid = req->dest_dsa_guid; + dest.replica_flags = req->options; werr = uref_add_dest(sam_ctx, mem_ctx, &req->naming_context->guid, &dest); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("Failed to delete repsTo for %s\n", - GUID_string(dce_call, &dest.dest_guid))); + GUID_string(dce_call, &dest.source_dsa_obj_guid))); goto failed; } } |