bool allow_add_guid = false;
bool remove_current_guid = false;
bool is_urgent = false;
+ bool is_schema_nc = false;
struct ldb_message_element *objectclass_el;
struct replmd_private *replmd_private =
talloc_get_type_abort(ldb_module_get_private(module), struct replmd_private);
return LDB_ERR_OPERATIONS_ERROR;
}
+ is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
+
for (i=0; i < msg->num_elements; i++) {
struct ldb_message_element *e = &msg->elements[i];
struct replPropertyMetaData1 *m = &nmd.ctr.ctr1.array[ni];
continue;
}
- m->attid = sa->attributeID_id;
- m->version = 1;
+ m->attid = dsdb_attribute_get_attid(sa, is_schema_nc);
+ m->version = 1;
if (m->attid == 0x20030) {
const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
const char* rdn;
uint64_t *seq_num,
const struct GUID *our_invocation_id,
NTTIME now,
+ bool is_schema_nc,
struct ldb_request *req)
{
uint32_t i;
const struct dsdb_attribute *a;
struct replPropertyMetaData1 *md1;
bool may_skip = false;
+ uint32_t attid;
a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
if (a == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
+ attid = dsdb_attribute_get_attid(a, is_schema_nc);
+
if ((a->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (a->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
return LDB_SUCCESS;
}
}
for (i=0; i<omd->ctr.ctr1.count; i++) {
- if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) break;
+ /*
+ * First check if we find it under the msDS-IntID,
+ * then check if we find it under the OID and
+ * prefixMap ID.
+ *
+ * This allows the administrator to simply re-write
+ * the attributes and so restore replication, which is
+ * likely what they will try to do.
+ */
+ if (attid == omd->ctr.ctr1.array[i].attid) {
+ break;
+ }
+
+ if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) {
+ break;
+ }
}
if (a->linkID != 0 && dsdb_functional_level(ldb) > DS_DOMAIN_FUNCTION_2000) {
md1 = &omd->ctr.ctr1.array[i];
md1->version++;
- md1->attid = a->attributeID_id;
+ md1->attid = attid;
if (md1->attid == 0x20030) {
const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
const char* rdn;
struct ldb_request *req,
const char * const *rename_attrs,
struct ldb_message *msg, uint64_t *seq_num,
- time_t t,
+ time_t t, bool is_schema_nc,
bool *is_urgent, bool *rodc)
{
const struct ldb_val *omd_value;
struct ldb_message_element *old_el;
old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name);
ret = replmd_update_rpmd_element(ldb, msg, &msg->elements[i], old_el, &omd, schema, seq_num,
- our_invocation_id, now, req);
+ our_invocation_id,
+ now, is_schema_nc,
+ req);
if (ret != LDB_SUCCESS) {
return ret;
}
time_t t = time(NULL);
int ret;
bool is_urgent = false, rodc = false;
+ bool is_schema_nc = false;
unsigned int functional_level;
const struct ldb_message_element *guid_el = NULL;
struct ldb_control *sd_propagation_control;
ldb_msg_remove_attr(msg, "whenChanged");
ldb_msg_remove_attr(msg, "uSNChanged");
+ is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
+
ret = replmd_update_rpmd(module, ac->schema, req, NULL,
- msg, &ac->seq_num, t, &is_urgent, &rodc);
+ msg, &ac->seq_num, t, is_schema_nc,
+ &is_urgent, &rodc);
if (rodc && (ret == LDB_ERR_REFERRAL)) {
struct loadparm_context *lp_ctx;
char *referral;
static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct ldb_context *ldb;
- struct replmd_replicated_request *ac;
struct ldb_request *down_req;
struct ldb_message *msg;
const struct dsdb_attribute *rdn_attr;
time_t t = time(NULL);
int ret;
bool is_urgent = false, rodc = false;
+ bool is_schema_nc;
+ struct replmd_replicated_request *ac =
+ talloc_get_type(req->context, struct replmd_replicated_request);
+ struct replmd_private *replmd_private =
+ talloc_get_type(ldb_module_get_private(ac->module),
+ struct replmd_private);
- ac = talloc_get_type(req->context, struct replmd_replicated_request);
ldb = ldb_module_get_ctx(ac->module);
if (ares->error != LDB_SUCCESS) {
msg->dn = ac->req->op.rename.newdn;
+ is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
+
rdn_name = ldb_dn_get_rdn_name(msg->dn);
if (rdn_name == NULL) {
talloc_free(ares);
attrs[4] = NULL;
ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
- msg, &ac->seq_num, t, &is_urgent, &rodc);
+ msg, &ac->seq_num, t,
+ is_schema_nc, &is_urgent, &rodc);
if (rodc && (ret == LDB_ERR_REFERRAL)) {
struct ldb_dn *olddn = ac->req->op.rename.olddn;
struct loadparm_context *lp_ctx;
from samba.samdb import SamDB
from samba.dsdb import DS_DOMAIN_FUNCTION_2003
from samba.tests import delete_force
+from samba.ndr import ndr_unpack
+from samba.dcerpc import drsblobs
parser = optparse.OptionParser("ldap_schema.py [options] <host>")
sambaopts = options.SambaOptions(parser)
# Search for created attribute
res = []
res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE,
- attrs=["lDAPDisplayName","schemaIDGUID"])
+ attrs=["lDAPDisplayName","schemaIDGUID", "msDS-IntID"])
self.assertEquals(len(res), 1)
self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name)
self.assertTrue("schemaIDGUID" in res[0])
+ if "msDS-IntId" in res[0]:
+ msDS_IntId = int(res[0]["msDS-IntId"][0])
+ if msDS_IntId < 0:
+ msDS_IntId += (1 << 32)
+ else:
+ msDS_IntId = None
class_name = "test-Class" + time.strftime("%s", time.gmtime())
class_ldap_display_name = class_name.replace("-", "")
self.ldb.add_ldif(ldif)
# Search for created object
- res = []
- res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["dn"])
- self.assertEquals(len(res), 1)
+ obj_res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["replPropertyMetaData"])
+
+ self.assertEquals(len(obj_res), 1)
+ self.assertTrue("replPropertyMetaData" in obj_res[0])
+ val = obj_res[0]["replPropertyMetaData"][0]
+ repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(val))
+ obj = repl.ctr
+
+ # Windows 2000 functional level won't have this. It is too
+ # hard to work it out from the prefixmap however, so we skip
+ # this test in that case.
+ if msDS_IntId is not None:
+ found = False
+ for o in repl.ctr.array:
+ if o.attid == msDS_IntId:
+ found = True
+ break
+ self.assertTrue(found, "Did not find 0x%08x in replPropertyMetaData" % msDS_IntId)
# Delete the object
delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))