s4/drs: when we don't find an attribute use zero values
[Samba/aatanasov.git] / source4 / rpc_server / drsuapi / getncchanges.c
blob6e65e3185b2eb0df8cefe808569be1d6cd12f6ae
1 /*
2 Unix SMB/CIFS implementation.
4 implement the DRSUpdateRefs call
6 Copyright (C) Anatoliy Atanasov 2009
7 Copyright (C) Andrew Tridgell 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_drsuapi.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "rpc_server/common/common.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "lib/ldb/include/ldb_errors.h"
29 #include "param/param.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "auth/auth.h"
32 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
34 /*
35 drsuapi_DsGetNCChanges
37 static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItemEx *obj,
38 struct ldb_message *msg,
39 struct ldb_context *sam_ctx,
40 struct ldb_dn *ncRoot_dn,
41 struct dsdb_schema *schema)
43 const struct ldb_val *md_value;
44 int i;
45 struct ldb_dn *obj_dn;
46 struct replPropertyMetaDataBlob md;
48 if (ldb_dn_compare(ncRoot_dn, msg->dn) == 0) {
49 obj->is_nc_prefix = true;
50 obj->parent_object_guid = NULL;
51 } else {
52 obj->is_nc_prefix = false;
53 obj->parent_object_guid = talloc(obj, struct GUID);
54 *obj->parent_object_guid = samdb_result_guid(msg, "parentGUID");
56 obj->next_object = NULL;
58 obj->meta_data_ctr = talloc(obj, struct drsuapi_DsReplicaMetaDataCtr);
59 md_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
60 if (md_value) {
61 enum ndr_err_code ndr_err;
62 ndr_err = ndr_pull_struct_blob(md_value, obj,
63 lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), &md,
64 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
65 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
66 return WERR_DS_DRA_INTERNAL_ERROR;
69 if (md.version != 1) {
70 return WERR_DS_DRA_INTERNAL_ERROR;
73 obj->meta_data_ctr->count = md.ctr.ctr1.count;
74 obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count);
75 for (i=0; i<md.ctr.ctr1.count; i++) {
76 obj->meta_data_ctr->meta_data[i].originating_change_time = md.ctr.ctr1.array[i].originating_change_time;
77 obj->meta_data_ctr->meta_data[i].version = md.ctr.ctr1.array[i].version;
78 obj->meta_data_ctr->meta_data[i].originating_invocation_id = md.ctr.ctr1.array[i].originating_invocation_id;
79 obj->meta_data_ctr->meta_data[i].originating_usn = md.ctr.ctr1.array[i].originating_usn;
81 } else {
82 obj->meta_data_ctr->meta_data = talloc(obj, struct drsuapi_DsReplicaMetaData);
83 obj->meta_data_ctr->count = 0;
84 ZERO_STRUCT(md);
86 obj->object.identifier = talloc(obj, struct drsuapi_DsReplicaObjectIdentifier);
87 obj_dn = ldb_msg_find_attr_as_dn(sam_ctx, obj, msg, "distinguishedName");
88 obj->object.identifier->dn = ldb_dn_get_linearized(obj_dn);
89 obj->object.identifier->guid = GUID_zero();
90 ZERO_STRUCT(obj->object.identifier->sid);
92 obj->object.attribute_ctr.num_attributes = obj->meta_data_ctr->count;
93 obj->object.attribute_ctr.attributes = talloc_array(obj, struct drsuapi_DsReplicaAttribute,
94 obj->object.attribute_ctr.num_attributes);
97 * Note that the meta_data array and the attributes array must
98 * be the same size and in the same order
100 for (i=0; i<obj->object.attribute_ctr.num_attributes; i++) {
101 const struct dsdb_attribute *sa;
102 struct ldb_message_element *el;
103 WERROR werr;
105 sa = dsdb_attribute_by_attributeID_id(schema, md.ctr.ctr1.array[i].attid);
106 if (!sa) {
107 DEBUG(0,("Unable to find attributeID %u in schema\n", md.ctr.ctr1.array[i].attid));
108 return WERR_DS_DRA_INTERNAL_ERROR;
111 el = ldb_msg_find_element(msg, sa->lDAPDisplayName);
112 if (el == NULL) {
113 DEBUG(0,("No element '%s' for attributeID %u in message\n",
114 sa->lDAPDisplayName, md.ctr.ctr1.array[i].attid));
115 ZERO_STRUCT(obj->object.attribute_ctr.attributes[i]);
116 obj->object.attribute_ctr.attributes[i].attid = md.ctr.ctr1.array[i].attid;
117 } else {
118 werr = dsdb_attribute_ldb_to_drsuapi(sam_ctx, schema, el, obj,
119 &obj->object.attribute_ctr.attributes[i]);
120 if (!W_ERROR_IS_OK(werr)) {
121 DEBUG(0,("Unable to convert %s to DRS object - %s\n",
122 sa->lDAPDisplayName, win_errstr(werr)));
123 return werr;
128 return WERR_OK;
132 drsuapi_DsGetNCChanges
134 WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
135 struct drsuapi_DsGetNCChanges *r)
137 struct ldb_result *site_res;
138 struct drsuapi_DsReplicaObjectIdentifier *ncRoot;
139 struct ldb_context *sam_ctx;
140 struct ldb_dn *ncRoot_dn;
141 int ret;
142 int i;
143 struct dsdb_schema *schema;
144 struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
145 time_t t = time(NULL);
146 NTTIME now;
147 struct drsuapi_DsReplicaObjectListItemEx *currentObject;
150 * connect to the samdb
152 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
153 if (!sam_ctx) {
154 return WERR_FOOBAR;
157 /* Check request revision. */
158 if (r->in.level != 8) {
159 return WERR_REVISION_MISMATCH;
162 /* Perform access checks. */
163 if (r->in.req->req8.naming_context == NULL) {
164 return WERR_DS_DRA_INVALID_PARAMETER;
167 ncRoot = r->in.req->req8.naming_context;
168 if (ncRoot == NULL) {
169 return WERR_DS_DRA_BAD_NC;
172 DEBUG(4,("DsGetNSChanges with uSNChanged >= %llu\n",
173 (unsigned long long)r->in.req->req8.highwatermark.highest_usn));
175 /* Construct response. */
176 ncRoot_dn = ldb_dn_new(mem_ctx, sam_ctx, ncRoot->dn);
177 ret = drsuapi_search_with_extended_dn(sam_ctx, mem_ctx, &site_res,
178 ncRoot_dn, LDB_SCOPE_SUBTREE, NULL,
179 "(&(uSNChanged>=%llu)(objectClass=*))",
180 (unsigned long long)r->in.req->req8.highwatermark.highest_usn);
181 if (ret != LDB_SUCCESS) {
182 return WERR_DS_DRA_INTERNAL_ERROR;
185 *r->out.level_out = 6;
186 r->out.ctr->ctr6.naming_context = talloc(mem_ctx, struct drsuapi_DsReplicaObjectIdentifier);
187 *r->out.ctr->ctr6.naming_context = *ncRoot;
188 /* TODO: linked attributes*/
189 r->out.ctr->ctr6.linked_attributes_count = 0;
190 r->out.ctr->ctr6.linked_attributes = NULL;
192 r->out.ctr->ctr6.object_count = 0;
193 r->out.ctr->ctr6.more_data = false;
194 r->out.ctr->ctr6.uptodateness_vector = NULL;
196 /* Prefix mapping */
197 schema = dsdb_get_schema(sam_ctx);
198 if (!schema) {
199 DEBUG(0,("No schema in sam_ctx\n"));
200 return WERR_DS_DRA_INTERNAL_ERROR;
203 dsdb_get_oid_mappings_drsuapi(schema, true, mem_ctx, &ctr);
204 r->out.ctr->ctr6.mapping_ctr = *ctr;
206 r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID(sam_ctx));
207 r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
209 r->out.ctr->ctr6.old_highwatermark = r->in.req->req8.highwatermark;
210 r->out.ctr->ctr6.new_highwatermark = r->in.req->req8.highwatermark;
212 r->out.ctr->ctr6.first_object = talloc(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
213 currentObject = r->out.ctr->ctr6.first_object;
215 for(i=0; i<site_res->count; i++) {
216 int uSN;
217 WERROR werr;
219 uSN = ldb_msg_find_attr_as_int(site_res->msgs[i], "uSNChanged", -1);
220 r->out.ctr->ctr6.object_count++;
221 if (uSN > r->out.ctr->ctr6.new_highwatermark.highest_usn) {
222 r->out.ctr->ctr6.new_highwatermark.highest_usn = uSN;
225 werr = get_nc_changes_build_object(currentObject, site_res->msgs[i], sam_ctx, ncRoot_dn, schema);
226 if (!W_ERROR_IS_OK(werr)) {
227 r->out.ctr->ctr6.first_object = NULL;
228 return werr;
230 if (i == (site_res->count-1)) {
231 break;
233 currentObject->next_object = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
234 currentObject = currentObject->next_object;
237 r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx);
239 r->out.ctr->ctr6.uptodateness_vector->version = 2;
240 r->out.ctr->ctr6.uptodateness_vector->count = 1;
241 r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0;
242 r->out.ctr->ctr6.uptodateness_vector->reserved2 = 0;
243 r->out.ctr->ctr6.uptodateness_vector->cursors = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2);
245 r->out.ctr->ctr6.uptodateness_vector->cursors[0].source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
246 r->out.ctr->ctr6.uptodateness_vector->cursors[0].highest_usn = r->out.ctr->ctr6.new_highwatermark.highest_usn;
247 unix_to_nt_time(&now, t);
248 r->out.ctr->ctr6.uptodateness_vector->cursors[0].last_sync_success = now;
250 return WERR_OK;