#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "auth/auth.h"
#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
+#include "rpc_server/dcerpc_server_proto.h"
+#include "../libcli/drsuapi/drsuapi.h"
+#include "../libcli/security/dom_sid.h"
/*
- drsuapi_DsGetNCChanges
+ drsuapi_DsGetNCChanges for one object
*/
static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItemEx *obj,
struct ldb_message *msg,
struct ldb_context *sam_ctx,
struct ldb_dn *ncRoot_dn,
- struct dsdb_schema *schema)
+ struct dsdb_schema *schema,
+ DATA_BLOB *session_key)
{
const struct ldb_val *md_value;
int i;
struct ldb_dn *obj_dn;
+ struct replPropertyMetaDataBlob md;
+ struct dom_sid *sid;
+ uint32_t rid = 0;
if (ldb_dn_compare(ncRoot_dn, msg->dn) == 0) {
obj->is_nc_prefix = true;
obj->meta_data_ctr = talloc(obj, struct drsuapi_DsReplicaMetaDataCtr);
md_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
if (md_value) {
- struct replPropertyMetaDataBlob md;
enum ndr_err_code ndr_err;
ndr_err = ndr_pull_struct_blob(md_value, obj,
lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), &md,
} else {
obj->meta_data_ctr->meta_data = talloc(obj, struct drsuapi_DsReplicaMetaData);
obj->meta_data_ctr->count = 0;
+ ZERO_STRUCT(md);
}
obj->object.identifier = talloc(obj, struct drsuapi_DsReplicaObjectIdentifier);
obj_dn = ldb_msg_find_attr_as_dn(sam_ctx, obj, msg, "distinguishedName");
obj->object.identifier->dn = ldb_dn_get_linearized(obj_dn);
- obj->object.identifier->guid = GUID_zero();
- ZERO_STRUCT(obj->object.identifier->sid);
-
- obj->object.attribute_ctr.num_attributes = msg->num_elements;
- /* Exclude non-replicate attributes from the responce.*/
- for (i=0; i<msg->num_elements; i++) {
- const struct dsdb_attribute *sa;
- sa = dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
- if (sa && sa->systemFlags & SYSTEM_FLAG_CR_NTDS_NC) {
- ldb_msg_remove_attr(msg, msg->elements[i].name);
- obj->object.attribute_ctr.num_attributes--;
- }
+ obj->object.identifier->guid = samdb_result_guid(msg, "objectGUID");
+ sid = samdb_result_dom_sid(obj, msg, "objectSid");
+ if (sid) {
+ dom_sid_split_rid(NULL, sid, NULL, &rid);
+ obj->object.identifier->sid = *sid;
+ } else {
+ ZERO_STRUCT(obj->object.identifier->sid);
}
+
+ obj->object.attribute_ctr.num_attributes = obj->meta_data_ctr->count;
obj->object.attribute_ctr.attributes = talloc_array(obj, struct drsuapi_DsReplicaAttribute,
- obj->object.attribute_ctr.num_attributes);
+ obj->object.attribute_ctr.num_attributes);
+
+ /*
+ * Note that the meta_data array and the attributes array must
+ * be the same size and in the same order
+ */
for (i=0; i<obj->object.attribute_ctr.num_attributes; i++) {
- dsdb_attribute_ldb_to_drsuapi(sam_ctx, schema,&msg->elements[i], obj,
- &obj->object.attribute_ctr.attributes[i]);
+ const struct dsdb_attribute *sa;
+ struct ldb_message_element *el;
+ WERROR werr;
+
+ sa = dsdb_attribute_by_attributeID_id(schema, md.ctr.ctr1.array[i].attid);
+ if (!sa) {
+ DEBUG(0,("Unable to find attributeID %u in schema\n", md.ctr.ctr1.array[i].attid));
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ el = ldb_msg_find_element(msg, sa->lDAPDisplayName);
+ if (el == NULL) {
+ DEBUG(0,("No element '%s' for attributeID %u in message\n",
+ sa->lDAPDisplayName, md.ctr.ctr1.array[i].attid));
+ ZERO_STRUCT(obj->object.attribute_ctr.attributes[i]);
+ obj->object.attribute_ctr.attributes[i].attid = md.ctr.ctr1.array[i].attid;
+ } else {
+ werr = dsdb_attribute_ldb_to_drsuapi(sam_ctx, schema, el, obj,
+ &obj->object.attribute_ctr.attributes[i]);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,("Unable to convert %s to DRS object - %s\n",
+ sa->lDAPDisplayName, win_errstr(werr)));
+ return werr;
+ }
+
+ /* some attributes needs to be encrypted
+ before being sent */
+ werr = drsuapi_encrypt_attribute(obj, session_key, rid,
+ &obj->object.attribute_ctr.attributes[i]);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,("Unable to encrypt %s in DRS object - %s\n",
+ sa->lDAPDisplayName, win_errstr(werr)));
+ return werr;
+ }
+ }
+ }
+
+ return WERR_OK;
+}
+
+static int replmd_drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
+ const struct drsuapi_DsReplicaCursor2 *c2)
+{
+ return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
+}
+
+static WERROR get_nc_changes_udv(struct drsuapi_DsReplicaCursor2CtrEx *udv,
+ struct ldb_message *msg,
+ struct ldb_context *sam_ctx)
+{
+ uint32_t it_value;
+
+ it_value = ldb_msg_find_attr_as_uint(msg, "instanceType", 0);
+ if ((it_value & INSTANCE_TYPE_IS_NC_HEAD) == INSTANCE_TYPE_IS_NC_HEAD) {
+ const struct ldb_val *ouv_value;
+ struct drsuapi_DsReplicaCursor2 *tmp_cursor;
+ uint64_t highest_commited_usn;
+ NTTIME now;
+ time_t t = time(NULL);
+
+ int ret = ldb_sequence_number(sam_ctx, LDB_SEQ_HIGHEST_SEQ, &highest_commited_usn);
+ if (ret != LDB_SUCCESS) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ tmp_cursor = talloc(udv, struct drsuapi_DsReplicaCursor2);
+ tmp_cursor->source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
+ tmp_cursor->highest_usn = highest_commited_usn;
+ unix_to_nt_time(&now, t);
+ tmp_cursor->last_sync_success = now;
+
+ ouv_value = ldb_msg_find_ldb_val(msg, "replUpToDateVector");
+ if (ouv_value) {
+ struct replUpToDateVectorBlob ouv;
+ enum ndr_err_code ndr_err;
+
+ ndr_err = ndr_pull_struct_blob(ouv_value, udv,
+ lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), &ouv,
+ (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ if (ouv.version != 2) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ udv->count = ouv.ctr.ctr2.count + 1;
+ udv->cursors = talloc_steal(udv, ouv.ctr.ctr2.cursors);
+ udv->cursors = talloc_realloc(udv, udv->cursors, struct drsuapi_DsReplicaCursor2, udv->count);
+ if (!udv->cursors) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ udv->cursors[udv->count - 1] = *tmp_cursor;
+
+ qsort(udv->cursors, udv->count,
+ sizeof(struct drsuapi_DsReplicaCursor2),
+ (comparison_fn_t)replmd_drsuapi_DsReplicaCursor2_compare);
+ } else {
+ udv->count = 1;
+ udv->cursors = talloc_steal(udv, tmp_cursor);
+ }
}
return WERR_OK;
int i;
struct dsdb_schema *schema;
struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
- time_t t = time(NULL);
- NTTIME now;
struct drsuapi_DsReplicaObjectListItemEx *currentObject;
+ NTSTATUS status;
+ DATA_BLOB session_key;
+ const char *attrs[] = { "*", "parentGUID", NULL };
/*
- * connect to the samdb
+ * connect to the samdb. TODO: We need to check that the caller
+ * has the rights to do this. This exposes all attributes,
+ * including all passwords.
*/
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
+ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
if (!sam_ctx) {
return WERR_FOOBAR;
}
return WERR_DS_DRA_BAD_NC;
}
- DEBUG(4,("DsGetNSChanges with uSHChanged >= %llu\n",
+ DEBUG(4,("DsGetNSChanges with uSNChanged >= %llu\n",
(unsigned long long)r->in.req->req8.highwatermark.highest_usn));
+ /* we need the session key for encrypting password attributes */
+ status = dcesrv_inherited_session_key(dce_call->conn, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,(__location__ ": Failed to get session key\n"));
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
/* Construct response. */
ncRoot_dn = ldb_dn_new(mem_ctx, sam_ctx, ncRoot->dn);
ret = drsuapi_search_with_extended_dn(sam_ctx, mem_ctx, &site_res,
- ncRoot_dn, LDB_SCOPE_SUBTREE, NULL,
+ ncRoot_dn, LDB_SCOPE_SUBTREE, attrs,
"(&(uSNChanged>=%llu)(objectClass=*))",
(unsigned long long)r->in.req->req8.highwatermark.highest_usn);
if (ret != LDB_SUCCESS) {
r->out.ctr->ctr6.old_highwatermark = r->in.req->req8.highwatermark;
r->out.ctr->ctr6.new_highwatermark = r->in.req->req8.highwatermark;
+ r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx);
+ r->out.ctr->ctr6.uptodateness_vector->version = 2;
+ r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0;
+ r->out.ctr->ctr6.uptodateness_vector->reserved2 = 0;
+
r->out.ctr->ctr6.first_object = talloc(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
currentObject = r->out.ctr->ctr6.first_object;
r->out.ctr->ctr6.new_highwatermark.highest_usn = uSN;
}
- werr = get_nc_changes_build_object(currentObject, site_res->msgs[i], sam_ctx, ncRoot_dn, schema);
+ werr = get_nc_changes_build_object(currentObject, site_res->msgs[i], sam_ctx, ncRoot_dn,
+ schema, &session_key);
if (!W_ERROR_IS_OK(werr)) {
+ r->out.ctr->ctr6.first_object = NULL;
return werr;
}
+
+ werr = get_nc_changes_udv(r->out.ctr->ctr6.uptodateness_vector, site_res->msgs[i], sam_ctx);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
if (i == (site_res->count-1)) {
break;
}
- currentObject->next_object = talloc(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
+ currentObject->next_object = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
currentObject = currentObject->next_object;
}
- r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx);
-
- r->out.ctr->ctr6.uptodateness_vector->version = 2;
- r->out.ctr->ctr6.uptodateness_vector->count = 1;
- r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0;
- r->out.ctr->ctr6.uptodateness_vector->reserved2 = 0;
- r->out.ctr->ctr6.uptodateness_vector->cursors = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2);
-
- r->out.ctr->ctr6.uptodateness_vector->cursors[0].source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
- r->out.ctr->ctr6.uptodateness_vector->cursors[0].highest_usn = r->out.ctr->ctr6.new_highwatermark.highest_usn;
- unix_to_nt_time(&now, t);
- r->out.ctr->ctr6.uptodateness_vector->cursors[0].last_sync_success = now;
-
return WERR_OK;
}