diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/config.mk | 3 | ||||
-rw-r--r-- | source4/dsdb/repl/replicated_objects.c | 299 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.h | 10 |
3 files changed, 311 insertions, 1 deletions
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 206f65d67d..d164dd6919 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -17,7 +17,8 @@ OBJ_FILES = \ common/sidmap.o \ common/flag_mapping.o \ schema/schema_init.o \ - schema/schema_syntax.o + schema/schema_syntax.o \ + repl/replicated_objects.o # # End SUBSYSTEM SAMDB ################################################ diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c new file mode 100644 index 0000000000..9c64381e46 --- /dev/null +++ b/source4/dsdb/repl/replicated_objects.c @@ -0,0 +1,299 @@ +/* + Unix SMB/CIFS mplementation. + Helper functions for applying replicated objects + + Copyright (C) Stefan Metzmacher 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "dsdb/samdb/samdb.h" +#include "lib/ldb/include/ldb_errors.h" +#include "lib/util/dlinklist.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_drsuapi.h" +#include "librpc/gen_ndr/ndr_drsblobs.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, + TALLOC_CTX *mem_ctx, + struct dsdb_extended_replicated_object *out) +{ + NTSTATUS nt_status; + WERROR status; + uint32_t i; + struct ldb_message *msg; + struct replPropertyMetaDataBlob md; + struct ldb_val md_value; + struct drsuapi_DsReplicaObjMetaDataCtr mdc; + struct ldb_val guid_value; + NTTIME whenChanged = 0; + time_t whenChanged_t; + const char *whenChanged_s; + const char *rdn_name; + const struct ldb_val *rdn_value; + const struct dsdb_attribute *rdn_attr; + uint32_t rdn_attid; + struct drsuapi_DsReplicaAttribute *name_a; + struct drsuapi_DsReplicaMetaData *name_d; + struct replPropertyMetaData1 *rdn_m; + struct drsuapi_DsReplicaObjMetaData *rdn_mc; + int ret; + + 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); + + rdn_name = ldb_dn_get_rdn_name(msg->dn); + rdn_attr = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name); + if (!rdn_attr) { + return WERR_FOOBAR; + } + rdn_attid = rdn_attr->attributeID_id; + rdn_value = ldb_dn_get_rdn_val(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); + + for (i=0; i < msg->num_elements; i++) { + status = dsdb_attribute_drsuapi_to_ldb(schema, + &in->object.attribute_ctr.attributes[i], + msg->elements, &msg->elements[i]); + W_ERROR_NOT_OK_RETURN(status); + } + + if (in->object.attribute_ctr.num_attributes != 0 && !in->meta_data_ctr) { + return WERR_FOOBAR; + } + + if (in->object.attribute_ctr.num_attributes != in->meta_data_ctr->count) { + return WERR_FOOBAR; + } + + md.version = 1; + md.reserved = 0; + md.ctr.ctr1.count = in->meta_data_ctr->count; + md.ctr.ctr1.reserved = 0; + md.ctr.ctr1.array = talloc_array(mem_ctx, + struct replPropertyMetaData1, + md.ctr.ctr1.count + 1); + W_ERROR_HAVE_NO_MEMORY(md.ctr.ctr1.array); + + mdc.count = in->meta_data_ctr->count; + mdc.reserved = 0; + mdc.array = talloc_array(mem_ctx, + struct drsuapi_DsReplicaObjMetaData, + mdc.count + 1); + W_ERROR_HAVE_NO_MEMORY(mdc.array); + + for (i=0; i < in->meta_data_ctr->count; i++) { + struct drsuapi_DsReplicaAttribute *a; + struct drsuapi_DsReplicaMetaData *d; + struct replPropertyMetaData1 *m; + struct drsuapi_DsReplicaObjMetaData *mc; + + a = &in->object.attribute_ctr.attributes[i]; + d = &in->meta_data_ctr->meta_data[i]; + m = &md.ctr.ctr1.array[i]; + mc = &mdc.array[i]; + + m->attid = a->attid; + m->version = d->version; + m->orginating_time = d->orginating_time; + m->orginating_invocation_id = d->orginating_invocation_id; + m->orginating_usn = d->orginating_usn; + m->local_usn = 0; + + mc->attribute_name = dsdb_lDAPDisplayName_by_id(schema, a->attid); + mc->version = d->version; + mc->originating_last_changed = d->orginating_time; + mc->originating_dsa_invocation_id= d->orginating_invocation_id; + mc->originating_usn = d->orginating_usn; + mc->local_usn = 0; + + if (d->orginating_time > whenChanged) { + whenChanged = d->orginating_time; + } + + if (a->attid == DRSUAPI_ATTRIBUTE_name) { + name_a = a; + name_d = d; + rdn_m = &md.ctr.ctr1.array[md.ctr.ctr1.count]; + rdn_mc = &mdc.array[mdc.count]; + } + } + + if (!name_d) { + return WERR_FOOBAR; + } + + ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + + nt_status = ndr_push_struct_blob(&guid_value, msg, &in->object.identifier->guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NT_STATUS_IS_OK(nt_status)) { + return ntstatus_to_werror(nt_status); + } + ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + + whenChanged_t = nt_time_to_unix(whenChanged); + whenChanged_s = ldb_timestring(msg, whenChanged_t); + W_ERROR_HAVE_NO_MEMORY(whenChanged_s); + ret = ldb_msg_add_string(msg, "whenChanged", whenChanged_s); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + + rdn_m->attid = rdn_attid; + rdn_m->version = name_d->version; + rdn_m->orginating_time = name_d->orginating_time; + rdn_m->orginating_invocation_id = name_d->orginating_invocation_id; + rdn_m->orginating_usn = name_d->orginating_usn; + rdn_m->local_usn = 0; + md.ctr.ctr1.count++; + + rdn_mc->attribute_name = rdn_attr->lDAPDisplayName; + rdn_mc->version = name_d->version; + rdn_mc->originating_last_changed = name_d->orginating_time; + rdn_mc->originating_dsa_invocation_id = name_d->orginating_invocation_id; + rdn_mc->originating_usn = name_d->orginating_usn; + rdn_mc->local_usn = 0; + mdc.count++; + + nt_status = ndr_push_struct_blob(&md_value, msg, &md, + (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); + if (!NT_STATUS_IS_OK(nt_status)) { + return ntstatus_to_werror(nt_status); + } + ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + + if (lp_parm_bool(-1, "become dc", "dump objects", False)) { + struct ldb_ldif ldif; + fprintf(stdout, "#\n"); + ldif.changetype = LDB_CHANGETYPE_NONE; + ldif.msg = msg; + ldb_ldif_write_file(ldb, stdout, &ldif); + NDR_PRINT_DEBUG(drsuapi_DsReplicaObjMetaDataCtr, &mdc); + } + + out->msg = msg; + return WERR_OK; +} + +WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, + const char *partition_dn, + const struct dsdb_schema *schema, + uint32_t ctr_level, + const struct drsuapi_DsGetNCChangesCtr1 *ctr1, + const struct drsuapi_DsGetNCChangesCtr6 *ctr6, + TALLOC_CTX *mem_ctx, + struct dsdb_extended_replicated_objects **_out) +{ + WERROR status; + struct dsdb_extended_replicated_objects *out; + struct ldb_result *ext_res; + const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr; + uint32_t object_count; + struct drsuapi_DsReplicaObjectListItemEx *first_object; + struct drsuapi_DsReplicaObjectListItemEx *cur; + uint32_t i; + int ret; + + switch (ctr_level) { + case 1: + mapping_ctr = &ctr1->mapping_ctr; + object_count = ctr1->object_count; + first_object = ctr1->first_object; + break; + case 6: + mapping_ctr = &ctr6->mapping_ctr; + object_count = ctr6->object_count; + first_object = ctr6->first_object; + break; + default: + return WERR_INVALID_PARAM; + } + + status = dsdb_verify_oid_mappings(schema, mapping_ctr); + W_ERROR_NOT_OK_RETURN(status); + + out = talloc_zero(mem_ctx, struct dsdb_extended_replicated_objects); + W_ERROR_HAVE_NO_MEMORY(out); + + out->partition_dn = ldb_dn_new(out, ldb, partition_dn); + W_ERROR_HAVE_NO_MEMORY(out->partition_dn); + + out->num_objects = object_count; + out->objects = talloc_array(out, + struct dsdb_extended_replicated_object, + out->num_objects); + W_ERROR_HAVE_NO_MEMORY(out->objects); + + for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { + if (i == out->num_objects) { + return WERR_FOOBAR; + } + + status = dsdb_convert_object(ldb, schema, out, cur, out->objects, &out->objects[i]); + W_ERROR_NOT_OK_RETURN(status); + } + if (i != out->num_objects) { + return WERR_FOOBAR; + } + + /* TODO: handle linked attributes */ + + ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, out, &ext_res); + if (ret != LDB_SUCCESS) { + DEBUG(0,("Failed to apply records: %d\n", + ret)); + talloc_free(out); + return WERR_FOOBAR; + } + talloc_free(ext_res); + + if (_out) { + *_out = out; + } else { + talloc_free(out); + } + + return WERR_OK; +} diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 0fa4d96f04..dc604cce78 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -28,7 +28,10 @@ struct drsuapi_DsNameInfo1; struct drsuapi_DsReplicaObject; struct drsuapi_DsReplicaOIDMapping_Ctr; struct drsuapi_DsReplicaAttribute; +struct drsuapi_DsGetNCChangesCtr1; +struct drsuapi_DsGetNCChangesCtr6; struct ldb_dn; +struct ldb_message; #define DSDB_CONTROL_REPLICATED_OBJECT_OID "1.3.6.1.4.1.7165.4.3.1" struct dsdb_control_replicated_object { @@ -36,8 +39,15 @@ struct dsdb_control_replicated_object { }; #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1" +struct dsdb_extended_replicated_object { + struct ldb_message *msg; +}; + struct dsdb_extended_replicated_objects { struct ldb_dn *partition_dn; + + uint32_t num_objects; + struct dsdb_extended_replicated_object *objects; }; #include "librpc/gen_ndr/security.h" |