diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/repl/replicated_objects.c | 165 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 39 |
2 files changed, 194 insertions, 10 deletions
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c index 4005d0ba93..4002ea8ae0 100644 --- a/source4/dsdb/repl/replicated_objects.c +++ b/source4/dsdb/repl/replicated_objects.c @@ -31,13 +31,12 @@ #include "libcli/auth/libcli_auth.h" #include "param/param.h" -static WERROR dsdb_convert_object(struct ldb_context *ldb, - const struct dsdb_schema *schema, - struct dsdb_extended_replicated_objects *ctr, - const struct drsuapi_DsReplicaObjectListItemEx *in, - const DATA_BLOB *gensec_skey, - TALLOC_CTX *mem_ctx, - struct dsdb_extended_replicated_object *out) +static WERROR dsdb_convert_object_ex(struct ldb_context *ldb, + const struct dsdb_schema *schema, + const struct drsuapi_DsReplicaObjectListItemEx *in, + const DATA_BLOB *gensec_skey, + TALLOC_CTX *mem_ctx, + struct dsdb_extended_replicated_object *out) { NTSTATUS nt_status; enum ndr_err_code ndr_err; @@ -241,7 +240,9 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, return WERR_FOOBAR; } - status = dsdb_convert_object(ldb, schema, out, cur, gensec_skey, out->objects, &out->objects[i]); + status = dsdb_convert_object_ex(ldb, schema, + cur, gensec_skey, + out->objects, &out->objects[i]); W_ERROR_NOT_OK_RETURN(status); } if (i != out->num_objects) { @@ -285,3 +286,151 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, return WERR_OK; } + +static WERROR dsdb_convert_object(struct ldb_context *ldb, + const struct dsdb_schema *schema, + const struct drsuapi_DsReplicaObjectListItem *in, + TALLOC_CTX *mem_ctx, + struct ldb_message **_msg) +{ + WERROR status; + uint32_t i; + struct ldb_message *msg; + + if (!in->object.identifier) { + return WERR_FOOBAR; + } + + if (!in->object.identifier->dn || !in->object.identifier->dn[0]) { + return WERR_FOOBAR; + } + + msg = ldb_msg_new(mem_ctx); + W_ERROR_HAVE_NO_MEMORY(msg); + + msg->dn = ldb_dn_new(msg, ldb, in->object.identifier->dn); + W_ERROR_HAVE_NO_MEMORY(msg->dn); + + msg->num_elements = in->object.attribute_ctr.num_attributes; + msg->elements = talloc_array(msg, struct ldb_message_element, + msg->num_elements); + W_ERROR_HAVE_NO_MEMORY(msg->elements); + + /* + * TODO: + * + * The DsAddEntry() call which creates a nTDSDSA object, + * also adds a servicePrincipalName in the following form + * to the computer account of the new domain controller + * referenced by the "serverReferenece" attribute. + * + * E3514235-4B06-11D1-AB04-00C04FC2DCD2/<new-ntdsdsa-object-guid-as-string>/<domain-dns-name> + * + * also note that the "serverReference" isn't added to the new object! + */ + + for (i=0; i < msg->num_elements; i++) { + struct drsuapi_DsReplicaAttribute *a; + struct ldb_message_element *e; + + a = &in->object.attribute_ctr.attributes[i]; + e = &msg->elements[i]; + + status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e); + W_ERROR_NOT_OK_RETURN(status); + } + + *_msg = msg; + return WERR_OK; +} + +WERROR dsdb_origin_objects_commit(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct drsuapi_DsReplicaObjectListItem *first_object, + uint32_t *_num, + struct drsuapi_DsReplicaObjectIdentifier2 **_ids) +{ + WERROR status; + const struct dsdb_schema *schema; + const struct drsuapi_DsReplicaObjectListItem *cur; + struct ldb_message **objects; + struct drsuapi_DsReplicaObjectIdentifier2 *ids; + uint32_t i; + uint32_t num_objects = 0; + const char * const attrs[] = { + "objectGUID", + "objectSid", + NULL + }; + struct ldb_result *res; + int ret; + + schema = dsdb_get_schema(ldb); + if (!schema) { + return WERR_DS_SCHEMA_NOT_LOADED; + } + + for (cur = first_object; cur; cur = cur->next_object) { + num_objects++; + } + + if (num_objects == 0) { + return WERR_OK; + } + + objects = talloc_array(mem_ctx, struct ldb_message *, + num_objects); + W_ERROR_HAVE_NO_MEMORY(objects); + + for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { + status = dsdb_convert_object(ldb, schema, + cur, objects, &objects[i]); + W_ERROR_NOT_OK_RETURN(status); + } + + ids = talloc_array(mem_ctx, + struct drsuapi_DsReplicaObjectIdentifier2, + num_objects); + W_ERROR_HAVE_NO_MEMORY(objects); + + ret = ldb_transaction_start(ldb); + if (ret != 0) { + goto cancel; + } + + for (i=0; i < num_objects; i++) { + struct dom_sid *sid = NULL; + ret = ldb_add(ldb, objects[i]); + if (ret != 0) { + goto cancel; + } + ret = ldb_search(ldb, objects, &res, objects[i]->dn, + LDB_SCOPE_BASE, attrs, + "(objectClass=*)"); + if (ret != 0) { + goto cancel; + } + ids[i].guid = samdb_result_guid(res->msgs[0], "objectGUID"); + sid = samdb_result_dom_sid(objects, res->msgs[0], "objectSid"); + if (sid) { + ids[i].sid = *sid; + } else { + ZERO_STRUCT(ids[i].sid); + } + } + + ret = ldb_transaction_commit(ldb); + if (ret != 0) { + goto cancel; + } + + talloc_free(objects); + + *_num = num_objects; + *_ids = ids; + return WERR_OK; +cancel: + talloc_free(objects); + ldb_transaction_cancel(ldb); + return WERR_FOOBAR; +} diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index 30096f199e..991b39984b 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -966,14 +966,49 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state return WERR_UNKNOWN_LEVEL; } - /* drsuapi_DsAddEntry */ static WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsAddEntry *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + WERROR status; + struct drsuapi_bind_state *b_state; + struct dcesrv_handle *h; + uint32_t num = 0; + struct drsuapi_DsReplicaObjectIdentifier2 *ids = NULL; + + /* TODO: check which out level the client supports */ + + ZERO_STRUCTP(r->out.ctr); + r->out.level_out = 3; + r->out.ctr->ctr3.level = 1; + r->out.ctr->ctr3.error = talloc_zero(mem_ctx, union drsuapi_DsAddEntryError); + + DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); + b_state = h->data; + + switch (r->in.level) { + case 2: + status = dsdb_origin_objects_commit(b_state->sam_ctx, + mem_ctx, + &r->in.req->req2.first_object, + &num, + &ids); + if (!W_ERROR_IS_OK(status)) { + r->out.ctr->ctr3.error->info1.status = status; + W_ERROR_NOT_OK_RETURN(status); + } + + r->out.ctr->ctr3.count = num; + r->out.ctr->ctr3.objects = ids; + + return WERR_OK; + default: + break; + } + + return WERR_FOOBAR; } |