View | Details | Raw Unified | Return to bug 48054 | Differences between
and this patch

Collapse All | Expand All

(-)a/python/samba/dbchecker.py (-1 / +1 lines)
 Lines 759-765   newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) Link Here 
759
        m = ldb.Message()
759
        m = ldb.Message()
760
        m.dn = obj.dn
760
        m.dn = obj.dn
761
        m['value'] = ldb.MessageElement(forward_vals, ldb.FLAG_MOD_REPLACE, forward_attr)
761
        m['value'] = ldb.MessageElement(forward_vals, ldb.FLAG_MOD_REPLACE, forward_attr)
762
        if self.do_modify(m, ["local_oid:1.3.6.1.4.1.7165.4.3.19.2:1"],
762
        if self.do_modify(m, ["local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS],
763
                "Failed to fix duplicate links in attribute '%s'" % forward_attr):
763
                "Failed to fix duplicate links in attribute '%s'" % forward_attr):
764
            self.report("Fixed duplicate links in attribute '%s'" % (forward_attr))
764
            self.report("Fixed duplicate links in attribute '%s'" % (forward_attr))
765
            duplicate_cache_key = "%s:%s" % (str(obj.dn), forward_attr)
765
            duplicate_cache_key = "%s:%s" % (str(obj.dn), forward_attr)
(-)a/source4/dsdb/pydsdb.c (-2 / +1 lines)
 Lines 1569-1574   void initdsdb(void) Link Here 
1569
	ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME);
1569
	ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME);
1570
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
1570
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
1575
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
1575
- 
1576
NOTE: old (due to rename or delete) DN string component for
1576
NOTE: old (due to rename or delete) DN string component for
1577
objectCategory in object CN=alice,CN=Users,DC=samba,DC=example,DC=com -
1577
objectCategory in object CN=alice,CN=Users,DC=samba,DC=example,DC=com -
1578
<GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>;
1578
<GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>;
1579
  CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=bad,DC=com
1579
  CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=bad,DC=com
1580
Change DN to <GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>;
1580
Change DN to <GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>;
1581
  CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com?
1581
  CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com?
1582
[y/N/all/none] y
1582
[y/N/all/none] y
1583
Failed to fix old DN string on attribute objectCategory : (16,
1583
Failed to fix old DN string on attribute objectCategory : (16,
1584
"attribute 'objectCategory': no matching attribute value while deleting
1584
"attribute 'objectCategory': no matching attribute value while deleting
1585
attribute on 'CN=alice,CN=Users,DC=samba,DC=example,DC=com'")
1585
attribute on 'CN=alice,CN=Users,DC=samba,DC=example,DC=com'")
1586
--
1587
python/samba/dbchecker.py                     | 19 ++++--
1586
python/samba/dbchecker.py                     | 19 ++++--
1588
source4/dsdb/pydsdb.c                         |  1 +
1587
source4/dsdb/pydsdb.c                         |  1 +
1589
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 64 ++++++++++++++++++
1588
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 64 ++++++++++++++++++
1590
source4/dsdb/samdb/samdb.h                    |  3 +
1589
source4/dsdb/samdb/samdb.h                    |  3 +
1591
...-after-dbcheck-oneway-link-corruption.ldif | 19 ++++++
1590
...-after-dbcheck-oneway-link-corruption.ldif | 19 ++++++
1592
...eck-link-output-oneway-link-corruption.txt |  5 ++
1591
...eck-link-output-oneway-link-corruption.txt |  5 ++
1593
testprogs/blackbox/dbcheck-links.sh           | 65 +++++++++++++++++++
1592
testprogs/blackbox/dbcheck-links.sh           | 65 +++++++++++++++++++
1594
7 files changed, 171 insertions(+), 5 deletions(-)
1593
7 files changed, 171 insertions(+), 5 deletions(-)
1595
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif
1594
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif
1596
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt
1595
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt
(-)a/python/samba/dbchecker.py (-5 / +14 lines)
 Lines 650-656   newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) Link Here 
650
        m.dn = dn
650
        m.dn = dn
651
        m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
651
        m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
652
        m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname)
652
        m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname)
653
        if self.do_modify(m, ["show_recycled:1"],
653
        if self.do_modify(m, ["show_recycled:1",
654
                              "local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME],
654
                          "Failed to fix old DN string on attribute %s" % (attrname)):
655
                          "Failed to fix old DN string on attribute %s" % (attrname)):
655
            self.report("Fixed old DN string on attribute %s" % (attrname))
656
            self.report("Fixed old DN string on attribute %s" % (attrname))
656
657
 Lines 1289-1302   newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) Link Here 
1289
                                                      res[0].dn, "SID")
1290
                                                      res[0].dn, "SID")
1290
                continue
1291
                continue
1291
1292
1293
            # Only for non-links, not even forward-only links
1294
            # (otherwise this breaks repl_meta_data):
1295
            #
1292
            # Now we have checked the GUID and SID, offer to fix old
1296
            # Now we have checked the GUID and SID, offer to fix old
1293
            # DN strings as a non-error (for forward links with no
1297
            # DN strings as a non-error (DNs, not links so no
1294
            # backlink).  Samba does not maintain this string
1298
            # backlink).  Samba does not maintain this string
1295
            # otherwise, so we don't increment error_count.
1299
            # otherwise, so we don't increment error_count.
1296
            if reverse_link_name is None:
1300
            if reverse_link_name is None:
1297
                if str(res[0].dn) != str(dsdb_dn.dn):
1301
                if linkID == 0 and str(res[0].dn) != str(dsdb_dn.dn):
1298
                    self.err_dn_string_component_old(obj.dn, attrname, val, dsdb_dn,
1302
                    # Pass in the old/bad DN without the <GUID=...> part,
1299
                                                     res[0].dn)
1303
                    # otherwise the LDB code will correct it on the way through
1304
                    # (Note: we still want to preserve the DSDB DN prefix in the
1305
                    # case of binary DNs)
1306
                    bad_dn = dsdb_dn.prefix + dsdb_dn.dn.get_linearized()
1307
                    self.err_dn_string_component_old(obj.dn, attrname, bad_dn,
1308
                                                     dsdb_dn, res[0].dn)
1300
                continue
1309
                continue
1301
1310
1302
            # check the reverse_link is correct if there should be one
1311
            # check the reverse_link is correct if there should be one
(-)a/source4/dsdb/pydsdb.c (+1 lines)
 Lines 1570-1575   void initdsdb(void) Link Here 
1570
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
1570
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1575
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1575
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
1576
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (+64 lines)
 Lines 3329-3334   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3329
	const struct ldb_message_element *guid_el = NULL;
3329
	const struct ldb_message_element *guid_el = NULL;
3330
	struct ldb_control *sd_propagation_control;
3330
	struct ldb_control *sd_propagation_control;
3331
	struct ldb_control *fix_links_control = NULL;
3331
	struct ldb_control *fix_links_control = NULL;
3332
	struct ldb_control *fix_dn_name_control = NULL;
3332
	struct replmd_private *replmd_private =
3333
	struct replmd_private *replmd_private =
3333
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3334
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3334
3335
 Lines 3387-3392   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3387
		return ldb_next_request(module, req);
3388
		return ldb_next_request(module, req);
3388
	}
3389
	}
3389
3390
3391
	fix_dn_name_control = ldb_request_get_control(req,
3392
					DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
3393
	if (fix_dn_name_control != NULL) {
3394
		struct dsdb_schema *schema = NULL;
3395
		const struct dsdb_attribute *sa = NULL;
3396
3397
		if (req->op.mod.message->num_elements != 2) {
3398
			return ldb_module_operr(module);
3399
		}
3400
3401
		if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) {
3402
			return ldb_module_operr(module);
3403
		}
3404
3405
		if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) {
3406
			return ldb_module_operr(module);
3407
		}
3408
3409
		if (req->op.mod.message->elements[0].num_values != 1) {
3410
			return ldb_module_operr(module);
3411
		}
3412
3413
		if (req->op.mod.message->elements[1].num_values != 1) {
3414
			return ldb_module_operr(module);
3415
		}
3416
3417
		schema = dsdb_get_schema(ldb, req);
3418
		if (schema == NULL) {
3419
			return ldb_module_operr(module);
3420
		}
3421
3422
		if (ldb_attr_cmp(req->op.mod.message->elements[0].name,
3423
				 req->op.mod.message->elements[1].name) != 0) {
3424
			return ldb_module_operr(module);
3425
		}
3426
3427
		sa = dsdb_attribute_by_lDAPDisplayName(schema,
3428
				req->op.mod.message->elements[0].name);
3429
		if (sa == NULL) {
3430
			return ldb_module_operr(module);
3431
		}
3432
3433
		if (sa->dn_format == DSDB_INVALID_DN) {
3434
			return ldb_module_operr(module);
3435
		}
3436
3437
		if (sa->linkID != 0) {
3438
			return ldb_module_operr(module);
3439
		}
3440
3441
		/*
3442
		 * If we are run from dbcheck and we are not updating
3443
		 * a link (as these would need to be sorted and so
3444
		 * can't go via such a simple update, then do not
3445
		 * trigger replicated updates and a new USN from this
3446
		 * change, it wasn't a real change, just a new
3447
		 * (correct) string DN
3448
		 */
3449
3450
		fix_dn_name_control->critical = false;
3451
		return ldb_next_request(module, req);
3452
	}
3453
3390
	ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
3454
	ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
3391
3455
3392
	guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
3456
	guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
(-)a/source4/dsdb/samdb/samdb.h (+3 lines)
 Lines 130-135   struct dsdb_control_password_change { Link Here 
130
/* passed by dbcheck to fix duplicate linked attributes (bug #13095) */
130
/* passed by dbcheck to fix duplicate linked attributes (bug #13095) */
131
#define DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS "1.3.6.1.4.1.7165.4.3.19.2"
131
#define DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS "1.3.6.1.4.1.7165.4.3.19.2"
132
132
133
/* passed by dbcheck to fix the DN strong of a one-way-link (bug #13495) */
134
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
135
133
/* passed when importing plain text password on upgrades */
136
/* passed when importing plain text password on upgrades */
134
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
137
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
135
138
(-)a/source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif (+19 lines)
1
# record 1
2
dn: OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp
3
4
# record 2
5
dn: OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp
6
seeAlso: OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp
7
8
# Referral
9
ref: ldap:///CN=Configuration,DC=release-4-5-0-pre1,DC=samba,DC=corp
10
11
# Referral
12
ref: ldap:///DC=DomainDnsZones,DC=release-4-5-0-pre1,DC=samba,DC=corp
13
14
# Referral
15
ref: ldap:///DC=ForestDnsZones,DC=release-4-5-0-pre1,DC=samba,DC=corp
16
17
# returned 5 records
18
# 2 entries
19
# 3 referrals
(-)a/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt (+5 lines)
1
Checking 228 objects
2
NOTE: old (due to rename or delete) DN string component for seeAlso in object OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp - OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
3
Change DN to <GUID=20600e7c-92bb-492e-9552-f3ed7f8a2cad>;OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp? [YES]
4
Fixed old DN string on attribute seeAlso
5
Checked 228 objects (0 errors)
(-)a/testprogs/blackbox/dbcheck-links.sh (-2 / +65 lines)
 Lines 205-210   check_expected_after_dbcheck_forward_link_corruption() { Link Here 
205
    fi
205
    fi
206
}
206
}
207
207
208
oneway_link_corruption() {
209
    #
210
    # Step1: add  OU "dangling-ou"
211
    #
212
    ldif=$PREFIX_ABS/${RELEASE}/oneway_link_corruption.ldif
213
    cat > $ldif <<EOF
214
dn: OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
215
changetype: add
216
objectclass: organizationalUnit
217
objectGUID: 20600e7c-92bb-492e-9552-f3ed7f8a2cad
218
EOF
219
220
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
221
    if [ "$?" != "0" ]; then
222
	echo "ldbmodify returned:\n$out"
223
	return 1
224
    fi
225
226
    #
227
    # Step2: add  msExchConfigurationContainer "dangling-msexch"
228
    #
229
    ldif=$PREFIX_ABS/${RELEASE}/oneway_link_corruption2.ldif
230
    cat > $ldif <<EOF
231
dn: OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp
232
changetype: add
233
objectclass: organizationalUnit
234
seeAlso: OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
235
EOF
236
237
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif)
238
    if [ "$?" != "0" ]; then
239
	echo "ldbmodify returned:\n$out"
240
	return 1
241
    fi
242
243
    #
244
    # Step3: rename dangling-ou to dangling-ou2
245
    #
246
    # Because this is a one-way link we don't fix it at runtime
247
    #
248
    out=$(TZ=UTC $ldbrename -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp)
249
    if [ "$?" != "0" ]; then
250
	echo "ldbmodify returned:\n$out"
251
	return 1
252
    fi
253
}
254
255
dbcheck_oneway_link_corruption() {
256
    dbcheck "-oneway-link-corruption" "0" ""
257
    return $?
258
}
259
260
check_expected_after_dbcheck_oneway_link_corruption() {
261
    tmpldif=$PREFIX_ABS/$RELEASE/expected-after-dbcheck-oneway-link-corruption.ldif.tmp
262
    TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(|(ou=dangling-ou)(ou=dangling-ou2)(ou=dangling-from))' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --sorted seeAlso > $tmpldif
263
    diff $tmpldif $release_dir/expected-after-dbcheck-oneway-link-corruption.ldif
264
    if [ "$?" != "0" ]; then
265
	return 1
266
    fi
267
}
268
208
dbcheck_dangling_multi_valued() {
269
dbcheck_dangling_multi_valued() {
209
270
210
    $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --fix --yes
271
    $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --fix --yes
 Lines 276-281   if [ -d $release_dir ]; then Link Here 
276
    testit "dbcheck_forward_link_corruption" dbcheck_forward_link_corruption
337
    testit "dbcheck_forward_link_corruption" dbcheck_forward_link_corruption
277
    testit "check_expected_after_dbcheck_forward_link_corruption" check_expected_after_dbcheck_forward_link_corruption
338
    testit "check_expected_after_dbcheck_forward_link_corruption" check_expected_after_dbcheck_forward_link_corruption
278
    testit "forward_link_corruption_clean" dbcheck_clean
339
    testit "forward_link_corruption_clean" dbcheck_clean
340
    testit "oneway_link_corruption" oneway_link_corruption
341
    testit "dbcheck_oneway_link_corruption" dbcheck_oneway_link_corruption
342
    testit "check_expected_after_dbcheck_oneway_link_corruption" check_expected_after_dbcheck_oneway_link_corruption
343
    testit "oneway_link_corruption_clean" dbcheck_clean
279
    testit "dangling_one_way_link" dangling_one_way_link
344
    testit "dangling_one_way_link" dangling_one_way_link
280
    testit "dbcheck_one_way" dbcheck_one_way
345
    testit "dbcheck_one_way" dbcheck_one_way
281
    testit "dbcheck_clean2" dbcheck_clean
346
    testit "dbcheck_clean2" dbcheck_clean
282
- 
283
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME
347
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME
284
--
285
source4/setup/schema_samba4.ldif | 1 +
348
source4/setup/schema_samba4.ldif | 1 +
286
1 file changed, 1 insertion(+)
349
1 file changed, 1 insertion(+)
(-)a/source4/setup/schema_samba4.ldif (-2 / +1 lines)
 Lines 214-219    Link Here 
214
#Allocated: DSDB_CONTROL_DBCHECK 1.3.6.1.4.1.7165.4.3.19
214
#Allocated: DSDB_CONTROL_DBCHECK 1.3.6.1.4.1.7165.4.3.19
215
#Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1
215
#Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1
216
#Allocated: DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS 1.3.6.1.4.1.7165.4.3.19.2
216
#Allocated: DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS 1.3.6.1.4.1.7165.4.3.19.2
217
#Allocated: DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME 1.3.6.1.4.1.7165.4.3.19.3
217
#Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20
218
#Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20
218
#Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21
219
#Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21
219
#Allocated: DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID 1.3.6.1.4.1.7165.4.3.23
220
#Allocated: DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID 1.3.6.1.4.1.7165.4.3.23
220
- 
221
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME
221
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME
222
--
223
source4/dsdb/samdb/samdb.h | 2 +-
222
source4/dsdb/samdb/samdb.h | 2 +-
224
1 file changed, 1 insertion(+), 1 deletion(-)
223
1 file changed, 1 insertion(+), 1 deletion(-)
(-)a/source4/dsdb/samdb/samdb.h (-3 / +1 lines)
 Lines 130-136   struct dsdb_control_password_change { Link Here 
130
/* passed by dbcheck to fix duplicate linked attributes (bug #13095) */
130
/* passed by dbcheck to fix duplicate linked attributes (bug #13095) */
131
#define DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS "1.3.6.1.4.1.7165.4.3.19.2"
131
#define DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS "1.3.6.1.4.1.7165.4.3.19.2"
132
132
133
/* passed by dbcheck to fix the DN strong of a one-way-link (bug #13495) */
133
/* passed by dbcheck to fix the DN string of a one-way-link (bug #13495) */
134
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
134
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
135
135
136
/* passed when importing plain text password on upgrades */
136
/* passed when importing plain text password on upgrades */
137
- 
138
samba4.blackbox.test_primary_group test
137
samba4.blackbox.test_primary_group test
139
--
140
.../samba4.blackbox.test_primary_group        |  2 +
138
.../samba4.blackbox.test_primary_group        |  2 +
141
source4/selftest/tests.py                     |  2 +
139
source4/selftest/tests.py                     |  2 +
142
testprogs/blackbox/test_primary_group.sh      | 86 +++++++++++++++++++
140
testprogs/blackbox/test_primary_group.sh      | 86 +++++++++++++++++++
143
3 files changed, 90 insertions(+)
141
3 files changed, 90 insertions(+)
144
create mode 100644 selftest/knownfail.d/samba4.blackbox.test_primary_group
142
create mode 100644 selftest/knownfail.d/samba4.blackbox.test_primary_group
145
create mode 100755 testprogs/blackbox/test_primary_group.sh
143
create mode 100755 testprogs/blackbox/test_primary_group.sh
(-)a/selftest/knownfail.d/samba4.blackbox.test_primary_group (+2 lines)
Line 0    Link Here 
1
^samba4.blackbox.test_primary_group.dbcheck.*run1
2
^samba4.blackbox.test_primary_group.dbcheck.*run2
(-)a/source4/selftest/tests.py (+2 lines)
 Lines 406-411   for env in ["ad_member", "s4member", "ad_dc_ntvfs", "chgdcpass"]: Link Here 
406
plantestsuite("samba4.blackbox.samba_tool(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(samba4srcdir, "utils/tests/test_samba_tool.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$DOMAIN', smbclient4])
406
plantestsuite("samba4.blackbox.samba_tool(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(samba4srcdir, "utils/tests/test_samba_tool.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$DOMAIN', smbclient4])
407
plantestsuite("samba4.blackbox.net_rpc_user(ad_dc)", "ad_dc", [os.path.join(bbdir, "test_net_rpc_user.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN'])
407
plantestsuite("samba4.blackbox.net_rpc_user(ad_dc)", "ad_dc", [os.path.join(bbdir, "test_net_rpc_user.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN'])
408
408
409
plantestsuite("samba4.blackbox.test_primary_group", "ad_dc:local", [os.path.join(bbdir, "test_primary_group.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX_ABS'])
410
409
if have_heimdal_support:
411
if have_heimdal_support:
410
    for env in ["ad_dc_ntvfs", "ad_dc"]:
412
    for env in ["ad_dc_ntvfs", "ad_dc"]:
411
        plantestsuite("samba4.blackbox.pkinit(%s:local)" % env, "%s:local" % env, [os.path.join(bbdir, "test_pkinit_heimdal.sh"), '$SERVER', 'pkinit', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX/%s' % env, "aes256-cts-hmac-sha1-96", smbclient4, configuration])
413
        plantestsuite("samba4.blackbox.pkinit(%s:local)" % env, "%s:local" % env, [os.path.join(bbdir, "test_pkinit_heimdal.sh"), '$SERVER', 'pkinit', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX/%s' % env, "aes256-cts-hmac-sha1-96", smbclient4, configuration])
(-)a/testprogs/blackbox/test_primary_group.sh (-2 / +86 lines)
Line 0    Link Here 
0
- 
1
#!/bin/bash
1
--
2
3
if [ $# -lt 5 ]; then
4
cat <<EOF
5
Usage: test_primary_group.sh SERVER USERNAME PASSWORD DOMAIN PREFIX_ABS
6
EOF
7
exit 1;
8
fi
9
10
TMPDIR="$PREFIX_ABS/$(basename $0)"
11
export TMPDIR
12
13
SERVER=$1
14
USERNAME=$2
15
PASSWORD=$3
16
DOMAIN=$4
17
PREFIX_ABS=$5
18
shift 5
19
failed=0
20
21
. `dirname $0`/subunit.sh
22
. `dirname $0`/common_test_fns.inc
23
24
TZ=UTC
25
export TZ
26
27
N=$(date +%H%M%S)
28
29
testuser="testuser$N"
30
testgroup="testgroup$N"
31
32
echo "testuser: $testuser"
33
echo "testgroup: $testgroup"
34
35
testit "mkdir -p '${TMPDIR}'" mkdir -p ${TMPDIR} || failed=`expr $failed + 1`
36
37
testit "create '$testuser'" $VALGRIND $PYTHON $BINDIR/samba-tool user create "$testuser" Password.1 || failed=`expr $failed + 1`
38
testit "add '$testgroup'" $VALGRIND $PYTHON $BINDIR/samba-tool group add "$testgroup" || failed=`expr $failed + 1`
39
testit "addmembers '$testgroup' '$testuser'" $VALGRIND $PYTHON $BINDIR/samba-tool group addmembers "$testgroup" "$testuser" || failed=`expr $failed + 1`
40
41
testit "search1" $VALGRIND $BINDIR/ldbsearch -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 sAMAccountName="$testgroup" objectSid || failed=`expr $failed + 1`
42
ldif="${TMPDIR}/search1.ldif"
43
$VALGRIND $BINDIR/ldbsearch -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 sAMAccountName=$testgroup objectSid > $ldif
44
rid=$(cat $ldif | sed -n 's/^objectSid: S-1-5-21-.*-.*-.*-//p')
45
46
testit "search2" $VALGRIND $BINDIR/ldbsearch -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 sAMAccountName="$testuser" dn || failed=`expr $failed + 1`
47
ldif="${TMPDIR}/search2.ldif"
48
$VALGRIND $BINDIR/ldbsearch -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 sAMAccountName=$testuser dn > $ldif
49
user_dn=$(cat $ldif | sed -n 's/^dn: //p')
50
51
ldif="${TMPDIR}/modify1.ldif"
52
cat > $ldif <<EOF
53
dn: $user_dn
54
changetype: modify
55
replace: primaryGroupID
56
primaryGroupID: $rid
57
EOF
58
testit "Change primaryGroupID to $rid" $VALGRIND $BINDIR/ldbmodify -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 --verbose < $ldif || failed=`expr $failed + 1`
59
60
testit "dbcheck run1" $VALGRIND $PYTHON $BINDIR/samba-tool dbcheck --attrs=member || failed=`expr $failed + 1`
61
62
ldif="${TMPDIR}/modify2.ldif"
63
cat > $ldif <<EOF
64
dn: $user_dn
65
changetype: modify
66
replace: primaryGroupID
67
primaryGroupID: 513
68
EOF
69
testit "Change primaryGroupID to 513" $VALGRIND $BINDIR/ldbmodify  -H ldap://$SERVER_IP -U$USERNAME%$PASSWORD -d0 < $ldif || failed=`expr $failed + 1`
70
71
testit "dbcheck run2" $VALGRIND $PYTHON $BINDIR/samba-tool dbcheck --attrs=member || failed=`expr $failed + 1`
72
73
testit "delete '$testuser'" $VALGRIND $PYTHON $BINDIR/samba-tool user delete "$testuser" || failed=`expr $failed + 1`
74
testit "delete '$testgroup'" $VALGRIND $PYTHON $BINDIR/samba-tool group delete "$testgroup" || failed=`expr $failed + 1`
75
76
#
77
# As we don't support phantom objects and virtual backlinks
78
# the deletion of the user and group cause dangling links,
79
# which are detected like this:
80
#
81
# WARNING: target DN is deleted for member in object
82
#
83
testit_expect_failure "dbcheck run3" $VALGRIND $PYTHON $BINDIR/samba-tool dbcheck --attrs=member --fix --yes || failed=`expr $failed + 1`
84
testit "dbcheck run4" $VALGRIND $PYTHON $BINDIR/samba-tool dbcheck --attrs=member || failed=`expr $failed + 1`
85
86
exit $failed
2
source4/dsdb/pydsdb.c            | 1 +
87
source4/dsdb/pydsdb.c            | 1 +
3
source4/dsdb/samdb/samdb.h       | 3 +++
88
source4/dsdb/samdb/samdb.h       | 3 +++
4
source4/setup/schema_samba4.ldif | 1 +
89
source4/setup/schema_samba4.ldif | 1 +
5
3 files changed, 5 insertions(+)
90
3 files changed, 5 insertions(+)
(-)a/source4/dsdb/pydsdb.c (+1 lines)
 Lines 1571-1576   void initdsdb(void) Link Here 
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1571
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1572
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
1573
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
1574
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1575
	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1575
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1576
	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1576
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
1577
	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
(-)a/source4/dsdb/samdb/samdb.h (+3 lines)
 Lines 133-138   struct dsdb_control_password_change { Link Here 
133
/* passed by dbcheck to fix the DN string of a one-way-link (bug #13495) */
133
/* passed by dbcheck to fix the DN string of a one-way-link (bug #13495) */
134
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
134
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
135
135
136
/* passed by dbcheck to fix the DN SID of a one-way-link (bug #13418) */
137
#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID "1.3.6.1.4.1.7165.4.3.19.4"
138
136
/* passed when importing plain text password on upgrades */
139
/* passed when importing plain text password on upgrades */
137
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
140
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
138
141
(-)a/source4/setup/schema_samba4.ldif (-2 / +1 lines)
 Lines 215-220    Link Here 
215
#Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1
215
#Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1
216
#Allocated: DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS 1.3.6.1.4.1.7165.4.3.19.2
216
#Allocated: DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS 1.3.6.1.4.1.7165.4.3.19.2
217
#Allocated: DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME 1.3.6.1.4.1.7165.4.3.19.3
217
#Allocated: DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME 1.3.6.1.4.1.7165.4.3.19.3
218
#Allocated: DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID 1.3.6.1.4.1.7165.4.3.19.4
218
#Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20
219
#Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20
219
#Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21
220
#Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21
220
#Allocated: DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID 1.3.6.1.4.1.7165.4.3.23
221
#Allocated: DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID 1.3.6.1.4.1.7165.4.3.23
221
- 
222
--
223
python/samba/dbchecker.py | 3 ++-
222
python/samba/dbchecker.py | 3 ++-
224
1 file changed, 2 insertions(+), 1 deletion(-)
223
1 file changed, 2 insertions(+), 1 deletion(-)
(-)a/python/samba/dbchecker.py (-3 / +2 lines)
 Lines 378-387   systemFlags: -1946157056%s""" % (dn, guid_suffix), Link Here 
378
378
379
    def do_modify(self, m, controls, msg, validate=True):
379
    def do_modify(self, m, controls, msg, validate=True):
380
        '''perform a modify with optional verbose output'''
380
        '''perform a modify with optional verbose output'''
381
        controls = controls + ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK]
381
        if self.verbose:
382
        if self.verbose:
382
            self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
383
            self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
384
            self.report("controls: %r" % controls)
383
        try:
385
        try:
384
            controls = controls + ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK]
385
            self.samdb.modify(m, controls=controls, validate=validate)
386
            self.samdb.modify(m, controls=controls, validate=validate)
386
        except Exception, err:
387
        except Exception, err:
387
            if self.in_transaction:
388
            if self.in_transaction:
388
- 
389
--
390
python/samba/dbchecker.py | 42 ++++++++++++++++++++++++++++++++++++++-
389
python/samba/dbchecker.py | 42 ++++++++++++++++++++++++++++++++++++++-
391
1 file changed, 41 insertions(+), 1 deletion(-)
390
1 file changed, 41 insertions(+), 1 deletion(-)
(-)a/python/samba/dbchecker.py (-3 / +41 lines)
 Lines 59-64   class dbcheck(object): Link Here 
59
        self.fix_all_string_dn_component_mismatch = False
59
        self.fix_all_string_dn_component_mismatch = False
60
        self.fix_all_GUID_dn_component_mismatch = False
60
        self.fix_all_GUID_dn_component_mismatch = False
61
        self.fix_all_SID_dn_component_mismatch = False
61
        self.fix_all_SID_dn_component_mismatch = False
62
        self.fix_all_SID_dn_component_missing = False
62
        self.fix_all_old_dn_string_component_mismatch = False
63
        self.fix_all_old_dn_string_component_mismatch = False
63
        self.fix_all_metadata = False
64
        self.fix_all_metadata = False
64
        self.fix_time_metadata = False
65
        self.fix_time_metadata = False
 Lines 673-678   newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) Link Here 
673
                          "Failed to fix incorrect DN %s on attribute %s" % (mismatch_type, attrname)):
674
                          "Failed to fix incorrect DN %s on attribute %s" % (mismatch_type, attrname)):
674
            self.report("Fixed incorrect DN %s on attribute %s" % (mismatch_type, attrname))
675
            self.report("Fixed incorrect DN %s on attribute %s" % (mismatch_type, attrname))
675
676
677
    def err_dn_component_missing_target_sid(self, dn, attrname, val, dsdb_dn, target_sid_blob):
678
        """handle a DN string being incorrect"""
679
        self.report("ERROR: missing DN SID component for %s in object %s - %s" % (attrname, dn, val))
680
681
        if len(dsdb_dn.prefix) != 0:
682
            self.report("Not fixing missing DN SID on DN+BINARY or DN+STRING")
683
            return
684
685
        correct_dn = ldb.Dn(self.samdb, dsdb_dn.dn.extended_str())
686
        correct_dn.set_extended_component("SID", target_sid_blob)
687
688
        if not self.confirm_all('Change DN to %s?' % correct_dn.extended_str(),
689
                                'fix_all_SID_dn_component_missing'):
690
            self.report("Not fixing missing DN SID component")
691
            return
692
693
        target_guid_blob = correct_dn.get_extended_component("GUID")
694
        guid_sid_dn = ldb.Dn(self.samdb, "")
695
        guid_sid_dn.set_extended_component("GUID", target_guid_blob)
696
        guid_sid_dn.set_extended_component("SID", target_sid_blob)
697
698
        m = ldb.Message()
699
        m.dn = dn
700
        m['new_value'] = ldb.MessageElement(guid_sid_dn.extended_str(), ldb.FLAG_MOD_ADD, attrname)
701
        controls = [
702
            "show_recycled:1",
703
            "local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID
704
        ]
705
        if self.do_modify(m, controls,
706
                          "Failed to ADD missing DN SID on attribute %s" % (attrname)):
707
            self.report("Fixed missing DN SID on attribute %s" % (attrname))
708
676
    def err_unknown_attribute(self, obj, attrname):
709
    def err_unknown_attribute(self, obj, attrname):
677
        '''handle an unknown attribute error'''
710
        '''handle an unknown attribute error'''
678
        self.report("ERROR: unknown attribute '%s' in %s" % (attrname, obj.dn))
711
        self.report("ERROR: unknown attribute '%s' in %s" % (attrname, obj.dn))
 Lines 1285-1291   newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) Link Here 
1285
                                                      res[0].dn, "GUID")
1318
                                                      res[0].dn, "GUID")
1286
                continue
1319
                continue
1287
1320
1288
            if res[0].dn.get_extended_component("SID") != dsdb_dn.dn.get_extended_component("SID"):
1321
            target_sid = res[0].dn.get_extended_component("SID")
1322
            link_sid = dsdb_dn.dn.get_extended_component("SID")
1323
            if link_sid is None and target_sid is not None:
1324
                error_count += 1
1325
                self.err_dn_component_missing_target_sid(obj.dn, attrname, val,
1326
                                                         dsdb_dn, target_sid)
1327
                continue
1328
            if link_sid != target_sid:
1289
                error_count += 1
1329
                error_count += 1
1290
                self.err_dn_component_target_mismatch(obj.dn, attrname, val, dsdb_dn,
1330
                self.err_dn_component_target_mismatch(obj.dn, attrname, val, dsdb_dn,
1291
                                                      res[0].dn, "SID")
1331
                                                      res[0].dn, "SID")
1292
- 
1293
<SID=...> on linked attributes
1332
<SID=...> on linked attributes
1294
--
1295
.../knownfail.d/samba4.blackbox.dbcheck-links |   6 +
1333
.../knownfail.d/samba4.blackbox.dbcheck-links |   6 +
1296
...ink-output-missing-link-sid-corruption.txt |   8 ++
1334
...ink-output-missing-link-sid-corruption.txt |   8 ++
1297
testprogs/blackbox/dbcheck-links.sh           | 110 ++++++++++++++++++
1335
testprogs/blackbox/dbcheck-links.sh           | 110 ++++++++++++++++++
1298
3 files changed, 124 insertions(+)
1336
3 files changed, 124 insertions(+)
1299
create mode 100644 selftest/knownfail.d/samba4.blackbox.dbcheck-links
1337
create mode 100644 selftest/knownfail.d/samba4.blackbox.dbcheck-links
1300
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-missing-link-sid-corruption.txt
1338
create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-missing-link-sid-corruption.txt
(-)a/selftest/knownfail.d/samba4.blackbox.dbcheck-links (+6 lines)
1
# The first one fails and all others are follow up failures...
2
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_missing_link_sid_corruption
3
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.missing_link_sid_clean
4
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_clean3
5
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued
6
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_equal_or_too_many
(-)a/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-missing-link-sid-corruption.txt (+8 lines)
1
Change DN to <GUID=0da8f25e-d110-11e8-80b7-3c970ec68461>;<RMD_ADDTIME=123456789000000000>;<RMD_CHANGETIME=123456789000000000>;<RMD_FLAGS=1>;<RMD_INVOCID=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d>;<RMD_LOCAL_USN=3769>;<RMD_ORIGINATING_USN=3769>;<RMD_VERSION=2>;<SID=S-1-5-21-4177067393-1453636373-93818738-771>;CN=missingsidu1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp? [YES]
2
Change DN to <GUID=66eb8f52-d110-11e8-ab9b-3c970ec68461>;<RMD_ADDTIME=123456789000000000>;<RMD_CHANGETIME=123456789000000000>;<RMD_FLAGS=0>;<RMD_INVOCID=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d>;<RMD_LOCAL_USN=3768>;<RMD_ORIGINATING_USN=3768>;<RMD_VERSION=1>;<SID=S-1-5-21-4177067393-1453636373-93818738-772>;CN=missingsidu2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp? [YES]
3
Checked 231 objects (2 errors)
4
Checking 231 objects
5
ERROR: missing DN SID component for member in object CN=missingsidg3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp - <GUID=0da8f25e-d110-11e8-80b7-3c970ec68461>;<RMD_ADDTIME=123456789000000000>;<RMD_CHANGETIME=123456789000000000>;<RMD_FLAGS=1>;<RMD_INVOCID=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d>;<RMD_LOCAL_USN=3769>;<RMD_ORIGINATING_USN=3769>;<RMD_VERSION=2>;CN=missingsidu1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp
6
ERROR: missing DN SID component for member in object CN=missingsidg3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp - <GUID=66eb8f52-d110-11e8-ab9b-3c970ec68461>;<RMD_ADDTIME=123456789000000000>;<RMD_CHANGETIME=123456789000000000>;<RMD_FLAGS=0>;<RMD_INVOCID=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d>;<RMD_LOCAL_USN=3768>;<RMD_ORIGINATING_USN=3768>;<RMD_VERSION=1>;CN=missingsidu2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp
7
Fixed missing DN SID on attribute member
8
Fixed missing DN SID on attribute member
(-)a/testprogs/blackbox/dbcheck-links.sh (-2 / +110 lines)
 Lines 131-136   check_expected_after_duplicate_links() { Link Here 
131
    fi
131
    fi
132
}
132
}
133
133
134
missing_link_sid_corruption() {
135
    # Step1: add user "missingsidu1"
136
    #
137
    ldif=$PREFIX_ABS/${RELEASE}/missing_link_sid_corruption1.ldif
138
    cat > $ldif <<EOF
139
dn: CN=missingsidu1,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
140
changetype: add
141
objectclass: user
142
samaccountname: missingsidu1
143
objectGUID: 0da8f25e-d110-11e8-80b7-3c970ec68461
144
objectSid: S-1-5-21-4177067393-1453636373-93818738-771
145
EOF
146
147
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
148
    if [ "$?" != "0" ]; then
149
	echo "ldbmodify returned:\n$out"
150
	return 1
151
    fi
152
153
    # Step2: add user "missingsidu2"
154
    #
155
    ldif=$PREFIX_ABS/${RELEASE}/missing_link_sid_corruption2.ldif
156
    cat > $ldif <<EOF
157
dn: CN=missingsidu2,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
158
changetype: add
159
objectclass: user
160
samaccountname: missingsidu2
161
objectGUID: 66eb8f52-d110-11e8-ab9b-3c970ec68461
162
objectSid: S-1-5-21-4177067393-1453636373-93818738-772
163
EOF
164
165
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
166
    if [ "$?" != "0" ]; then
167
	echo "ldbmodify returned:\n$out"
168
	return 1
169
    fi
170
171
    # Step3: add group "missingsidg3" and add users as members
172
    #
173
    ldif=$PREFIX_ABS/${RELEASE}/missing_link_sid_corruption3.ldif
174
    cat > $ldif <<EOF
175
dn: CN=missingsidg3,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
176
changetype: add
177
objectclass: group
178
samaccountname: missingsidg3
179
objectGUID: fd992424-d114-11e8-bb36-3c970ec68461
180
objectSid: S-1-5-21-4177067393-1453636373-93818738-773
181
member: CN=missingsidu1,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
182
member: CN=missingsidu2,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
183
EOF
184
185
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
186
    if [ "$?" != "0" ]; then
187
	echo "ldbmodify returned:\n$out"
188
	return 1
189
    fi
190
191
    # Step4: remove one user again, so that we have one deleted link
192
    #
193
    ldif=$PREFIX_ABS/${RELEASE}/missing_link_sid_corruption4.ldif
194
    cat > $ldif <<EOF
195
dn: CN=missingsidg3,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
196
changetype: modify
197
delete: member
198
member: CN=missingsidu1,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp
199
EOF
200
201
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
202
    if [ "$?" != "0" ]; then
203
	echo "ldbmodify returned:\n$out"
204
	return 1
205
    fi
206
207
    #
208
    # Step5: remove the SIDS from the links
209
    #
210
    LDIF1=$(TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb -b 'CN=missingsidg3,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp' -s base --reveal --extended-dn --show-binary member)
211
    DN=$(echo "${LDIF1}" | grep '^dn: ')
212
    MSG=$(echo "${LDIF1}" | grep -v '^dn: ' | grep -v '^#' | grep -v '^$')
213
    ldif=$PREFIX_ABS/${RELEASE}/missing_link_sid_corruption5.ldif
214
    {
215
	echo "${DN}"
216
	echo "changetype: modify"
217
	echo "replace: member"
218
	#echo "${MSG}"
219
	echo "${MSG}" | sed \
220
		-e 's!<SID=S-1-5-21-4177067393-1453636373-93818738-771>;!!g' \
221
		-e 's!<SID=S-1-5-21-4177067393-1453636373-93818738-772>;!!g' \
222
		-e 's!RMD_ADDTIME=[1-9][0-9]*!RMD_ADDTIME=123456789000000000!g' \
223
		-e 's!RMD_CHANGETIME=[1-9][0-9]*!RMD_CHANGETIME=123456789000000000!g' \
224
		| cat
225
    } > $ldif
226
227
    out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-5-0-PRE1,DC%3DSAMBA,DC%3DCORP.ldb $ldif)
228
    if [ "$?" != "0" ]; then
229
	echo "ldbmodify returned:\n$out"
230
	return 1
231
    fi
232
233
    return 0
234
}
235
236
dbcheck_missing_link_sid_corruption() {
237
    dbcheck "-missing-link-sid-corruption" "1" ""
238
    return $?
239
}
240
134
forward_link_corruption() {
241
forward_link_corruption() {
135
    #
242
    #
136
    # Step1: add a duplicate forward link from
243
    # Step1: add a duplicate forward link from
 Lines 344-349   if [ -d $release_dir ]; then Link Here 
344
    testit "dangling_one_way_link" dangling_one_way_link
451
    testit "dangling_one_way_link" dangling_one_way_link
345
    testit "dbcheck_one_way" dbcheck_one_way
452
    testit "dbcheck_one_way" dbcheck_one_way
346
    testit "dbcheck_clean2" dbcheck_clean
453
    testit "dbcheck_clean2" dbcheck_clean
454
    testit "missing_link_sid_corruption" missing_link_sid_corruption
455
    testit "dbcheck_missing_link_sid_corruption" dbcheck_missing_link_sid_corruption
456
    testit "missing_link_sid_clean" dbcheck_clean
347
    testit "dangling_one_way_dn" dangling_one_way_dn
457
    testit "dangling_one_way_dn" dangling_one_way_dn
348
    testit "deleted_one_way_dn" deleted_one_way_dn
458
    testit "deleted_one_way_dn" deleted_one_way_dn
349
    testit "dbcheck_clean3" dbcheck_clean
459
    testit "dbcheck_clean3" dbcheck_clean
350
- 
351
replmd_replicated_request to replmd_modify_handle_linked_attribs()
460
replmd_replicated_request to replmd_modify_handle_linked_attribs()
352
--
353
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 25 ++++++++-----------
461
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 25 ++++++++-----------
354
1 file changed, 10 insertions(+), 15 deletions(-)
462
1 file changed, 10 insertions(+), 15 deletions(-)
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-17 / +10 lines)
 Lines 3116-3123   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
3116
 */
3116
 */
3117
static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
3117
static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
3118
					       struct replmd_private *replmd_private,
3118
					       struct replmd_private *replmd_private,
3119
					       struct replmd_replicated_request *ac,
3119
					       struct ldb_message *msg,
3120
					       struct ldb_message *msg,
3120
					       uint64_t seq_num, time_t t,
3121
					       time_t t,
3121
					       struct ldb_request *parent)
3122
					       struct ldb_request *parent)
3122
{
3123
{
3123
	struct ldb_result *res;
3124
	struct ldb_result *res;
 Lines 3126-3133   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3126
	struct ldb_context *ldb = ldb_module_get_ctx(module);
3127
	struct ldb_context *ldb = ldb_module_get_ctx(module);
3127
	struct ldb_message *old_msg;
3128
	struct ldb_message *old_msg;
3128
3129
3129
	const struct dsdb_schema *schema;
3130
3131
	if (dsdb_functional_level(ldb) == DS_DOMAIN_FUNCTION_2000) {
3130
	if (dsdb_functional_level(ldb) == DS_DOMAIN_FUNCTION_2000) {
3132
		/*
3131
		/*
3133
		 * Nothing special is required for modifying or vanishing links
3132
		 * Nothing special is required for modifying or vanishing links
 Lines 3161-3170   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3161
	if (ret != LDB_SUCCESS) {
3160
	if (ret != LDB_SUCCESS) {
3162
		return ret;
3161
		return ret;
3163
	}
3162
	}
3164
	schema = dsdb_get_schema(ldb, res);
3165
	if (!schema) {
3166
		return LDB_ERR_OPERATIONS_ERROR;
3167
	}
3168
3163
3169
	old_msg = res->msgs[0];
3164
	old_msg = res->msgs[0];
3170
3165
 Lines 3173-3179   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3173
		struct ldb_message_element *old_el, *new_el;
3168
		struct ldb_message_element *old_el, *new_el;
3174
		unsigned int mod_type = LDB_FLAG_MOD_TYPE(el->flags);
3169
		unsigned int mod_type = LDB_FLAG_MOD_TYPE(el->flags);
3175
		const struct dsdb_attribute *schema_attr
3170
		const struct dsdb_attribute *schema_attr
3176
			= dsdb_attribute_by_lDAPDisplayName(schema, el->name);
3171
			= dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name);
3177
		if (!schema_attr) {
3172
		if (!schema_attr) {
3178
			ldb_asprintf_errstring(ldb,
3173
			ldb_asprintf_errstring(ldb,
3179
					       "%s: attribute %s is not a valid attribute in schema",
3174
					       "%s: attribute %s is not a valid attribute in schema",
 Lines 3209-3230   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3209
		switch (mod_type) {
3204
		switch (mod_type) {
3210
		case LDB_FLAG_MOD_REPLACE:
3205
		case LDB_FLAG_MOD_REPLACE:
3211
			ret = replmd_modify_la_replace(module, replmd_private,
3206
			ret = replmd_modify_la_replace(module, replmd_private,
3212
						       schema, msg, el, old_el,
3207
						       ac->schema, msg, el, old_el,
3213
						       schema_attr, seq_num, t,
3208
						       schema_attr, ac->seq_num, t,
3214
						       old_msg->dn,
3209
						       old_msg->dn,
3215
						       parent);
3210
						       parent);
3216
			break;
3211
			break;
3217
		case LDB_FLAG_MOD_DELETE:
3212
		case LDB_FLAG_MOD_DELETE:
3218
			ret = replmd_modify_la_delete(module, replmd_private,
3213
			ret = replmd_modify_la_delete(module, replmd_private,
3219
						      schema, msg, el, old_el,
3214
						      ac->schema, msg, el, old_el,
3220
						      schema_attr, seq_num, t,
3215
						      schema_attr, ac->seq_num, t,
3221
						      old_msg->dn,
3216
						      old_msg->dn,
3222
						      parent);
3217
						      parent);
3223
			break;
3218
			break;
3224
		case LDB_FLAG_MOD_ADD:
3219
		case LDB_FLAG_MOD_ADD:
3225
			ret = replmd_modify_la_add(module, replmd_private,
3220
			ret = replmd_modify_la_add(module, replmd_private,
3226
						   schema, msg, el, old_el,
3221
						   ac->schema, msg, el, old_el,
3227
						   schema_attr, seq_num, t,
3222
						   schema_attr, ac->seq_num, t,
3228
						   old_msg->dn,
3223
						   old_msg->dn,
3229
						   parent);
3224
						   parent);
3230
			break;
3225
			break;
 Lines 3496-3502   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3496
	}
3491
	}
3497
3492
3498
	ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3493
	ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3499
						  msg, ac->seq_num, t, req);
3494
						  ac, msg, t, req);
3500
	if (ret != LDB_SUCCESS) {
3495
	if (ret != LDB_SUCCESS) {
3501
		talloc_free(ac);
3496
		talloc_free(ac);
3502
		return ret;
3497
		return ret;
3503
- 
3504
replmd_replicated_request to replmd_modify_la_add()
3498
replmd_replicated_request to replmd_modify_la_add()
3505
--
3506
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 27 +++++++------------
3499
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 27 +++++++------------
3507
1 file changed, 10 insertions(+), 17 deletions(-)
3500
1 file changed, 10 insertions(+), 17 deletions(-)
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-19 / +10 lines)
 Lines 2398-2409   static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct d Link Here 
2398
 */
2398
 */
2399
static int replmd_modify_la_add(struct ldb_module *module,
2399
static int replmd_modify_la_add(struct ldb_module *module,
2400
				struct replmd_private *replmd_private,
2400
				struct replmd_private *replmd_private,
2401
				const struct dsdb_schema *schema,
2401
				struct replmd_replicated_request *ac,
2402
				struct ldb_message *msg,
2402
				struct ldb_message *msg,
2403
				struct ldb_message_element *el,
2403
				struct ldb_message_element *el,
2404
				struct ldb_message_element *old_el,
2404
				struct ldb_message_element *old_el,
2405
				const struct dsdb_attribute *schema_attr,
2405
				const struct dsdb_attribute *schema_attr,
2406
				uint64_t seq_num,
2407
				time_t t,
2406
				time_t t,
2408
				struct ldb_dn *msg_dn,
2407
				struct ldb_dn *msg_dn,
2409
				struct ldb_request *parent)
2408
				struct ldb_request *parent)
 Lines 2416-2432   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2416
	unsigned old_num_values = old_el ? old_el->num_values : 0;
2415
	unsigned old_num_values = old_el ? old_el->num_values : 0;
2417
	unsigned num_values = 0;
2416
	unsigned num_values = 0;
2418
	unsigned max_num_values;
2417
	unsigned max_num_values;
2419
	const struct GUID *invocation_id;
2420
	struct ldb_context *ldb = ldb_module_get_ctx(module);
2418
	struct ldb_context *ldb = ldb_module_get_ctx(module);
2421
	NTTIME now;
2419
	NTTIME now;
2422
	unix_to_nt_time(&now, t);
2420
	unix_to_nt_time(&now, t);
2423
2421
2424
	invocation_id = samdb_ntds_invocation_id(ldb);
2425
	if (!invocation_id) {
2426
		talloc_free(tmp_ctx);
2427
		return LDB_ERR_OPERATIONS_ERROR;
2428
	}
2429
2430
	/* get the DNs to be added, fully parsed.
2422
	/* get the DNs to be added, fully parsed.
2431
	 *
2423
	 *
2432
	 * We need full parsing because they came off the wire and we don't
2424
	 * We need full parsing because they came off the wire and we don't
 Lines 2522-2536   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2522
			ret = replmd_update_la_val(new_values, exact->v,
2514
			ret = replmd_update_la_val(new_values, exact->v,
2523
						   dns[i].dsdb_dn,
2515
						   dns[i].dsdb_dn,
2524
						   exact->dsdb_dn,
2516
						   exact->dsdb_dn,
2525
						   invocation_id, seq_num,
2517
						   &ac->our_invocation_id,
2526
						   seq_num, now, 0, false);
2518
						   ac->seq_num, ac->seq_num,
2519
						   0, now, false);
2527
			if (ret != LDB_SUCCESS) {
2520
			if (ret != LDB_SUCCESS) {
2528
				talloc_free(tmp_ctx);
2521
				talloc_free(tmp_ctx);
2529
				return ret;
2522
				return ret;
2530
			}
2523
			}
2531
2524
2532
			ret = replmd_add_backlink(module, replmd_private,
2525
			ret = replmd_add_backlink(module, replmd_private,
2533
						  schema,
2526
						  ac->schema,
2534
						  msg_dn,
2527
						  msg_dn,
2535
						  &dns[i].guid, 
2528
						  &dns[i].guid, 
2536
						  true,
2529
						  true,
 Lines 2572-2586   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2572
		}
2565
		}
2573
2566
2574
		ret = replmd_add_backlink(module, replmd_private,
2567
		ret = replmd_add_backlink(module, replmd_private,
2575
					  schema, msg_dn,
2568
					  ac->schema, msg_dn,
2576
					  &dns[i].guid,
2569
					  &dns[i].guid,
2577
					  true, schema_attr,
2570
					  true, schema_attr,
2578
					  parent);
2571
					  parent);
2579
		/* Make the new linked attribute ldb_val. */
2572
		/* Make the new linked attribute ldb_val. */
2580
		ret = replmd_build_la_val(new_values, &new_values[num_values],
2573
		ret = replmd_build_la_val(new_values, &new_values[num_values],
2581
					  dns[i].dsdb_dn, invocation_id,
2574
					  dns[i].dsdb_dn, &ac->our_invocation_id,
2582
					  seq_num, seq_num,
2575
					  ac->seq_num, ac->seq_num,
2583
					  now, 0, false);
2576
					  now, 0, false);
2584
		if (ret != LDB_SUCCESS) {
2577
		if (ret != LDB_SUCCESS) {
2585
			talloc_free(tmp_ctx);
2578
			talloc_free(tmp_ctx);
2586
			return ret;
2579
			return ret;
 Lines 3218-3225   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3218
			break;
3211
			break;
3219
		case LDB_FLAG_MOD_ADD:
3212
		case LDB_FLAG_MOD_ADD:
3220
			ret = replmd_modify_la_add(module, replmd_private,
3213
			ret = replmd_modify_la_add(module, replmd_private,
3221
						   ac->schema, msg, el, old_el,
3214
						   ac, msg, el, old_el,
3222
						   schema_attr, ac->seq_num, t,
3215
						   schema_attr, t,
3223
						   old_msg->dn,
3216
						   old_msg->dn,
3224
						   parent);
3217
						   parent);
3225
			break;
3218
			break;
3226
- 
3227
replmd_modify_la_add()
3219
replmd_modify_la_add()
3228
--
3229
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 2 +-
3220
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 2 +-
3230
1 file changed, 1 insertion(+), 1 deletion(-)
3221
1 file changed, 1 insertion(+), 1 deletion(-)
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-3 / +1 lines)
 Lines 2445-2451   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2445
	max_num_values = old_num_values + el->num_values;
2445
	max_num_values = old_num_values + el->num_values;
2446
	if (max_num_values < old_num_values) {
2446
	if (max_num_values < old_num_values) {
2447
		DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. "
2447
		DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. "
2448
			  "old values: %u, new values: %u, sum: %u",
2448
			  "old values: %u, new values: %u, sum: %u\n",
2449
			  old_num_values, el->num_values, max_num_values));
2449
			  old_num_values, el->num_values, max_num_values));
2450
		talloc_free(tmp_ctx);
2450
		talloc_free(tmp_ctx);
2451
		return LDB_ERR_OPERATIONS_ERROR;
2451
		return LDB_ERR_OPERATIONS_ERROR;
2452
- 
2453
replmd_replicated_request to replmd_modify_la_delete()
2452
replmd_replicated_request to replmd_modify_la_delete()
2454
--
2455
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 27 ++++++++-----------
2453
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 27 ++++++++-----------
2456
1 file changed, 11 insertions(+), 16 deletions(-)
2454
1 file changed, 11 insertions(+), 16 deletions(-)
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-18 / +11 lines)
 Lines 2611-2622   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2611
 */
2611
 */
2612
static int replmd_modify_la_delete(struct ldb_module *module,
2612
static int replmd_modify_la_delete(struct ldb_module *module,
2613
				   struct replmd_private *replmd_private,
2613
				   struct replmd_private *replmd_private,
2614
				   const struct dsdb_schema *schema,
2614
				   struct replmd_replicated_request *ac,
2615
				   struct ldb_message *msg,
2615
				   struct ldb_message *msg,
2616
				   struct ldb_message_element *el,
2616
				   struct ldb_message_element *el,
2617
				   struct ldb_message_element *old_el,
2617
				   struct ldb_message_element *old_el,
2618
				   const struct dsdb_attribute *schema_attr,
2618
				   const struct dsdb_attribute *schema_attr,
2619
				   uint64_t seq_num,
2620
				   time_t t,
2619
				   time_t t,
2621
				   struct ldb_dn *msg_dn,
2620
				   struct ldb_dn *msg_dn,
2622
				   struct ldb_request *parent)
2621
				   struct ldb_request *parent)
 Lines 2630-2645   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2630
	bool vanish_links = false;
2629
	bool vanish_links = false;
2631
	unsigned int num_to_delete = el->num_values;
2630
	unsigned int num_to_delete = el->num_values;
2632
	uint32_t rmd_flags;
2631
	uint32_t rmd_flags;
2633
	const struct GUID *invocation_id;
2634
	NTTIME now;
2632
	NTTIME now;
2635
2633
2636
	unix_to_nt_time(&now, t);
2634
	unix_to_nt_time(&now, t);
2637
2635
2638
	invocation_id = samdb_ntds_invocation_id(ldb);
2639
	if (!invocation_id) {
2640
		return LDB_ERR_OPERATIONS_ERROR;
2641
	}
2642
2643
	if (old_el == NULL || old_el->num_values == 0) {
2636
	if (old_el == NULL || old_el->num_values == 0) {
2644
		/* there is nothing to delete... */
2637
		/* there is nothing to delete... */
2645
		if (num_to_delete == 0) {
2638
		if (num_to_delete == 0) {
 Lines 2703-2709   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2703
				}
2696
				}
2704
			}
2697
			}
2705
			ret = replmd_add_backlink(module, replmd_private,
2698
			ret = replmd_add_backlink(module, replmd_private,
2706
						  schema, msg_dn, &p->guid,
2699
						  ac->schema, msg_dn, &p->guid,
2707
						  false, schema_attr,
2700
						  false, schema_attr,
2708
						  parent);
2701
						  parent);
2709
			if (ret != LDB_SUCCESS) {
2702
			if (ret != LDB_SUCCESS) {
 Lines 2721-2728   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2721
2714
2722
			ret = replmd_update_la_val(old_el->values, p->v,
2715
			ret = replmd_update_la_val(old_el->values, p->v,
2723
						   p->dsdb_dn, p->dsdb_dn,
2716
						   p->dsdb_dn, p->dsdb_dn,
2724
						   invocation_id, seq_num,
2717
						   &ac->our_invocation_id,
2725
						   seq_num, now, 0, true);
2718
						   ac->seq_num, ac->seq_num,
2719
						   now, 0, true);
2726
			if (ret != LDB_SUCCESS) {
2720
			if (ret != LDB_SUCCESS) {
2727
				talloc_free(tmp_ctx);
2721
				talloc_free(tmp_ctx);
2728
				return ret;
2722
				return ret;
 Lines 2784-2790   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2784
			/* remove the backlink */
2778
			/* remove the backlink */
2785
			ret = replmd_add_backlink(module,
2779
			ret = replmd_add_backlink(module,
2786
						  replmd_private,
2780
						  replmd_private,
2787
						  schema, 
2781
						  ac->schema,
2788
						  msg_dn,
2782
						  msg_dn,
2789
						  &p->guid,
2783
						  &p->guid,
2790
						  false, schema_attr,
2784
						  false, schema_attr,
 Lines 2818-2831   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2818
2812
2819
		ret = replmd_update_la_val(old_el->values, exact->v,
2813
		ret = replmd_update_la_val(old_el->values, exact->v,
2820
					   exact->dsdb_dn, exact->dsdb_dn,
2814
					   exact->dsdb_dn, exact->dsdb_dn,
2821
					   invocation_id, seq_num, seq_num,
2815
					   &ac->our_invocation_id,
2816
					   ac->seq_num, ac->seq_num,
2822
					   now, 0, true);
2817
					   now, 0, true);
2823
		if (ret != LDB_SUCCESS) {
2818
		if (ret != LDB_SUCCESS) {
2824
			talloc_free(tmp_ctx);
2819
			talloc_free(tmp_ctx);
2825
			return ret;
2820
			return ret;
2826
		}
2821
		}
2827
		ret = replmd_add_backlink(module, replmd_private,
2822
		ret = replmd_add_backlink(module, replmd_private,
2828
					  schema, msg_dn,
2823
					  ac->schema, msg_dn,
2829
					  &p->guid,
2824
					  &p->guid,
2830
					  false, schema_attr,
2825
					  false, schema_attr,
2831
					  parent);
2826
					  parent);
 Lines 3204-3211   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3204
			break;
3199
			break;
3205
		case LDB_FLAG_MOD_DELETE:
3200
		case LDB_FLAG_MOD_DELETE:
3206
			ret = replmd_modify_la_delete(module, replmd_private,
3201
			ret = replmd_modify_la_delete(module, replmd_private,
3207
						      ac->schema, msg, el, old_el,
3202
						      ac, msg, el, old_el,
3208
						      schema_attr, ac->seq_num, t,
3203
						      schema_attr, t,
3209
						      old_msg->dn,
3204
						      old_msg->dn,
3210
						      parent);
3205
						      parent);
3211
			break;
3206
			break;
3212
- 
3213
replmd_replicated_request to replmd_modify_la_replace()
3207
replmd_replicated_request to replmd_modify_la_replace()
3214
--
3215
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 31 +++++++------------
3208
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 31 +++++++------------
3216
1 file changed, 12 insertions(+), 19 deletions(-)
3209
1 file changed, 12 insertions(+), 19 deletions(-)
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-21 / +12 lines)
 Lines 2870-2881   static int replmd_modify_la_delete(struct ldb_module *module, Link Here 
2870
 */
2870
 */
2871
static int replmd_modify_la_replace(struct ldb_module *module,
2871
static int replmd_modify_la_replace(struct ldb_module *module,
2872
				    struct replmd_private *replmd_private,
2872
				    struct replmd_private *replmd_private,
2873
				    const struct dsdb_schema *schema,
2873
				    struct replmd_replicated_request *ac,
2874
				    struct ldb_message *msg,
2874
				    struct ldb_message *msg,
2875
				    struct ldb_message_element *el,
2875
				    struct ldb_message_element *el,
2876
				    struct ldb_message_element *old_el,
2876
				    struct ldb_message_element *old_el,
2877
				    const struct dsdb_attribute *schema_attr,
2877
				    const struct dsdb_attribute *schema_attr,
2878
				    uint64_t seq_num,
2879
				    time_t t,
2878
				    time_t t,
2880
				    struct ldb_dn *msg_dn,
2879
				    struct ldb_dn *msg_dn,
2881
				    struct ldb_request *parent)
2880
				    struct ldb_request *parent)
 Lines 2884-2890   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
2884
	struct parsed_dn *dns, *old_dns;
2883
	struct parsed_dn *dns, *old_dns;
2885
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
2884
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
2886
	int ret;
2885
	int ret;
2887
	const struct GUID *invocation_id;
2888
	struct ldb_context *ldb = ldb_module_get_ctx(module);
2886
	struct ldb_context *ldb = ldb_module_get_ctx(module);
2889
	struct ldb_val *new_values = NULL;
2887
	struct ldb_val *new_values = NULL;
2890
	const char *ldap_oid = schema_attr->syntax->ldap_oid;
2888
	const char *ldap_oid = schema_attr->syntax->ldap_oid;
 Lines 2895-2905   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
2895
2893
2896
	unix_to_nt_time(&now, t);
2894
	unix_to_nt_time(&now, t);
2897
2895
2898
	invocation_id = samdb_ntds_invocation_id(ldb);
2899
	if (!invocation_id) {
2900
		return LDB_ERR_OPERATIONS_ERROR;
2901
	}
2902
2903
	/*
2896
	/*
2904
	 * The replace operation is unlike the replace and delete cases in that
2897
	 * The replace operation is unlike the replace and delete cases in that
2905
	 * we need to look at every existing link to see whether it is being
2898
	 * we need to look at every existing link to see whether it is being
 Lines 2999-3006   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
2999
				ret = replmd_update_la_val(new_values, old_p->v,
2992
				ret = replmd_update_la_val(new_values, old_p->v,
3000
							   old_p->dsdb_dn,
2993
							   old_p->dsdb_dn,
3001
							   old_p->dsdb_dn,
2994
							   old_p->dsdb_dn,
3002
							   invocation_id,
2995
							   &ac->our_invocation_id,
3003
							   seq_num, seq_num,
2996
							   ac->seq_num, ac->seq_num,
3004
							   now, 0, true);
2997
							   now, 0, true);
3005
				if (ret != LDB_SUCCESS) {
2998
				if (ret != LDB_SUCCESS) {
3006
					talloc_free(tmp_ctx);
2999
					talloc_free(tmp_ctx);
 Lines 3008-3014   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
3008
				}
3001
				}
3009
3002
3010
				ret = replmd_add_backlink(module, replmd_private,
3003
				ret = replmd_add_backlink(module, replmd_private,
3011
							  schema, 
3004
							  ac->schema,
3012
							  msg_dn,
3005
							  msg_dn,
3013
							  &old_p->guid, false,
3006
							  &old_p->guid, false,
3014
							  schema_attr,
3007
							  schema_attr,
 Lines 3033-3040   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
3033
			ret = replmd_update_la_val(new_values, old_p->v,
3026
			ret = replmd_update_la_val(new_values, old_p->v,
3034
						   new_p->dsdb_dn,
3027
						   new_p->dsdb_dn,
3035
						   old_p->dsdb_dn,
3028
						   old_p->dsdb_dn,
3036
						   invocation_id,
3029
						   &ac->our_invocation_id,
3037
						   seq_num, seq_num,
3030
						   ac->seq_num, ac->seq_num,
3038
						   now, 0, false);
3031
						   now, 0, false);
3039
			if (ret != LDB_SUCCESS) {
3032
			if (ret != LDB_SUCCESS) {
3040
				talloc_free(tmp_ctx);
3033
				talloc_free(tmp_ctx);
 Lines 3044-3050   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
3044
			rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
3037
			rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
3045
			if ((rmd_flags & DSDB_RMD_FLAG_DELETED) != 0) {
3038
			if ((rmd_flags & DSDB_RMD_FLAG_DELETED) != 0) {
3046
				ret = replmd_add_backlink(module, replmd_private,
3039
				ret = replmd_add_backlink(module, replmd_private,
3047
							  schema, 
3040
							  ac->schema,
3048
							  msg_dn,
3041
							  msg_dn,
3049
							  &new_p->guid, true,
3042
							  &new_p->guid, true,
3050
							  schema_attr,
3043
							  schema_attr,
 Lines 3066-3080   static int replmd_modify_la_replace(struct ldb_module *module, Link Here 
3066
			ret = replmd_build_la_val(new_values,
3059
			ret = replmd_build_la_val(new_values,
3067
						  new_p->v,
3060
						  new_p->v,
3068
						  new_p->dsdb_dn,
3061
						  new_p->dsdb_dn,
3069
						  invocation_id,
3062
						  &ac->our_invocation_id,
3070
						  seq_num, seq_num,
3063
						  ac->seq_num, ac->seq_num,
3071
						  now, 0, false);
3064
						  now, 0, false);
3072
			if (ret != LDB_SUCCESS) {
3065
			if (ret != LDB_SUCCESS) {
3073
				talloc_free(tmp_ctx);
3066
				talloc_free(tmp_ctx);
3074
				return ret;
3067
				return ret;
3075
			}
3068
			}
3076
			ret = replmd_add_backlink(module, replmd_private,
3069
			ret = replmd_add_backlink(module, replmd_private,
3077
						  schema,
3070
						  ac->schema,
3078
						  msg_dn,
3071
						  msg_dn,
3079
						  &new_p->guid, true,
3072
						  &new_p->guid, true,
3080
						  schema_attr,
3073
						  schema_attr,
 Lines 3192-3199   static int replmd_modify_handle_linked_attribs(struct ldb_module *module, Link Here 
3192
		switch (mod_type) {
3185
		switch (mod_type) {
3193
		case LDB_FLAG_MOD_REPLACE:
3186
		case LDB_FLAG_MOD_REPLACE:
3194
			ret = replmd_modify_la_replace(module, replmd_private,
3187
			ret = replmd_modify_la_replace(module, replmd_private,
3195
						       ac->schema, msg, el, old_el,
3188
						       ac, msg, el, old_el,
3196
						       schema_attr, ac->seq_num, t,
3189
						       schema_attr, t,
3197
						       old_msg->dn,
3190
						       old_msg->dn,
3198
						       parent);
3191
						       parent);
3199
			break;
3192
			break;
3200
- 
3201
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID
3193
DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID
3202
--
3203
.../knownfail.d/samba4.blackbox.dbcheck-links |   6 -
3194
.../knownfail.d/samba4.blackbox.dbcheck-links |   6 -
3204
.../samdb/ldb_modules/extended_dn_store.c     |   7 +
3195
.../samdb/ldb_modules/extended_dn_store.c     |   7 +
3205
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 145 ++++++++++++++++++
3196
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 145 ++++++++++++++++++
3206
source4/dsdb/samdb/ldb_modules/samldb.c       |  12 +-
3197
source4/dsdb/samdb/ldb_modules/samldb.c       |  12 +-
3207
4 files changed, 161 insertions(+), 9 deletions(-)
3198
4 files changed, 161 insertions(+), 9 deletions(-)
3208
delete mode 100644 selftest/knownfail.d/samba4.blackbox.dbcheck-links
3199
delete mode 100644 selftest/knownfail.d/samba4.blackbox.dbcheck-links
(-)a/selftest/knownfail.d/samba4.blackbox.dbcheck-links (-6 lines)
1
# The first one fails and all others are follow up failures...
2
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_missing_link_sid_corruption
3
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.missing_link_sid_clean
4
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_clean3
5
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued
6
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_equal_or_too_many
(-)a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c (+7 lines)
 Lines 376-381   static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req Link Here 
376
	unsigned int i, j;
376
	unsigned int i, j;
377
	struct extended_dn_context *ac;
377
	struct extended_dn_context *ac;
378
	struct ldb_control *fix_links_control = NULL;
378
	struct ldb_control *fix_links_control = NULL;
379
	struct ldb_control *fix_link_sid_ctrl = NULL;
379
	int ret;
380
	int ret;
380
381
381
	if (ldb_dn_is_special(req->op.mod.message->dn)) {
382
	if (ldb_dn_is_special(req->op.mod.message->dn)) {
 Lines 400-405   static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req Link Here 
400
		return ldb_next_request(module, req);
401
		return ldb_next_request(module, req);
401
	}
402
	}
402
403
404
	fix_link_sid_ctrl = ldb_request_get_control(ac->req,
405
					DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
406
	if (fix_link_sid_ctrl != NULL) {
407
		return ldb_next_request(module, req);
408
	}
409
403
	for (i=0; i < req->op.mod.message->num_elements; i++) {
410
	for (i=0; i < req->op.mod.message->num_elements; i++) {
404
		const struct ldb_message_element *el = &req->op.mod.message->elements[i];
411
		const struct ldb_message_element *el = &req->op.mod.message->elements[i];
405
		const struct dsdb_attribute *schema_attr
412
		const struct dsdb_attribute *schema_attr
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (+145 lines)
 Lines 112-117   struct replmd_replicated_request { Link Here 
112
	bool is_urgent;
112
	bool is_urgent;
113
113
114
	bool isDeleted;
114
	bool isDeleted;
115
116
	bool fix_link_sid;
115
};
117
};
116
118
117
static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
119
static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
 Lines 2481-2486   static int replmd_modify_la_add(struct ldb_module *module, Link Here 
2481
			return err;
2483
			return err;
2482
		}
2484
		}
2483
2485
2486
		if (ac->fix_link_sid) {
2487
			char *fixed_dnstring = NULL;
2488
			struct dom_sid tmp_sid = { 0, };
2489
			DATA_BLOB sid_blob = data_blob_null;
2490
			enum ndr_err_code ndr_err;
2491
			NTSTATUS status;
2492
			int num;
2493
2494
			if (exact == NULL) {
2495
				talloc_free(tmp_ctx);
2496
				return ldb_operr(ldb);
2497
			}
2498
2499
			if (dns[i].dsdb_dn->dn_format != DSDB_NORMAL_DN) {
2500
				talloc_free(tmp_ctx);
2501
				return ldb_operr(ldb);
2502
			}
2503
2504
			/*
2505
			 * Only "<GUID=...><SID=...>" is allowed.
2506
			 *
2507
			 * We get the GUID to just to find the old
2508
			 * value and the SID in order to add it
2509
			 * to the found value.
2510
			 */
2511
2512
			num = ldb_dn_get_comp_num(dns[i].dsdb_dn->dn);
2513
			if (num != 0) {
2514
				talloc_free(tmp_ctx);
2515
				return ldb_operr(ldb);
2516
			}
2517
2518
			num = ldb_dn_get_extended_comp_num(dns[i].dsdb_dn->dn);
2519
			if (num != 2) {
2520
				talloc_free(tmp_ctx);
2521
				return ldb_operr(ldb);
2522
			}
2523
2524
			status = dsdb_get_extended_dn_sid(exact->dsdb_dn->dn,
2525
							  &tmp_sid, "SID");
2526
			if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2527
				/* this is what we expect */
2528
			} else if (NT_STATUS_IS_OK(status)) {
2529
				struct GUID_txt_buf guid_str;
2530
				ldb_debug_set(ldb, LDB_DEBUG_FATAL,
2531
						       "i[%u] SID NOT MISSING... Attribute %s already "
2532
						       "exists for target GUID %s, SID %s, DN: %s",
2533
						       i, el->name,
2534
						       GUID_buf_string(&exact->guid,
2535
								       &guid_str),
2536
						       dom_sid_string(tmp_ctx, &tmp_sid),
2537
						       dsdb_dn_get_extended_linearized(tmp_ctx,
2538
							       exact->dsdb_dn, 1));
2539
				talloc_free(tmp_ctx);
2540
				return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2541
			} else {
2542
				talloc_free(tmp_ctx);
2543
				return ldb_operr(ldb);
2544
			}
2545
2546
			status = dsdb_get_extended_dn_sid(dns[i].dsdb_dn->dn,
2547
							  &tmp_sid, "SID");
2548
			if (!NT_STATUS_IS_OK(status)) {
2549
				struct GUID_txt_buf guid_str;
2550
				ldb_asprintf_errstring(ldb,
2551
						       "NO SID PROVIDED... Attribute %s already "
2552
						       "exists for target GUID %s",
2553
						       el->name,
2554
						       GUID_buf_string(&exact->guid,
2555
								       &guid_str));
2556
				talloc_free(tmp_ctx);
2557
				return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2558
			}
2559
2560
			ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &tmp_sid,
2561
						       (ndr_push_flags_fn_t)ndr_push_dom_sid);
2562
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2563
				talloc_free(tmp_ctx);
2564
				return ldb_operr(ldb);
2565
			}
2566
2567
			ret = ldb_dn_set_extended_component(exact->dsdb_dn->dn, "SID", &sid_blob);
2568
			data_blob_free(&sid_blob);
2569
			if (ret != LDB_SUCCESS) {
2570
				talloc_free(tmp_ctx);
2571
				return ret;
2572
			}
2573
2574
			fixed_dnstring = dsdb_dn_get_extended_linearized(
2575
					new_values, exact->dsdb_dn, 1);
2576
			if (fixed_dnstring == NULL) {
2577
				talloc_free(tmp_ctx);
2578
				return ldb_operr(ldb);
2579
			}
2580
2581
			/*
2582
			 * We just replace the existing value...
2583
			 */
2584
			*exact->v = data_blob_string_const(fixed_dnstring);
2585
2586
			continue;
2587
		}
2588
2484
		if (exact != NULL) {
2589
		if (exact != NULL) {
2485
			/*
2590
			/*
2486
			 * We are trying to add one that exists, which is only
2591
			 * We are trying to add one that exists, which is only
 Lines 3306-3311   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3306
	struct ldb_control *sd_propagation_control;
3411
	struct ldb_control *sd_propagation_control;
3307
	struct ldb_control *fix_links_control = NULL;
3412
	struct ldb_control *fix_links_control = NULL;
3308
	struct ldb_control *fix_dn_name_control = NULL;
3413
	struct ldb_control *fix_dn_name_control = NULL;
3414
	struct ldb_control *fix_dn_sid_control = NULL;
3309
	struct replmd_private *replmd_private =
3415
	struct replmd_private *replmd_private =
3310
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3416
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3311
3417
 Lines 3451-3456   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3451
		return LDB_ERR_OPERATIONS_ERROR;
3557
		return LDB_ERR_OPERATIONS_ERROR;
3452
	}
3558
	}
3453
3559
3560
	fix_dn_sid_control = ldb_request_get_control(req,
3561
					DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
3562
	if (fix_dn_sid_control != NULL) {
3563
		const struct dsdb_attribute *sa = NULL;
3564
3565
		if (msg->num_elements != 1) {
3566
			talloc_free(ac);
3567
			return ldb_module_operr(module);
3568
		}
3569
3570
		if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) {
3571
			talloc_free(ac);
3572
			return ldb_module_operr(module);
3573
		}
3574
3575
		if (msg->elements[0].num_values != 1) {
3576
			talloc_free(ac);
3577
			return ldb_module_operr(module);
3578
		}
3579
3580
		sa = dsdb_attribute_by_lDAPDisplayName(ac->schema,
3581
				msg->elements[0].name);
3582
		if (sa == NULL) {
3583
			talloc_free(ac);
3584
			return ldb_module_operr(module);
3585
		}
3586
3587
		if (sa->dn_format != DSDB_NORMAL_DN) {
3588
			talloc_free(ac);
3589
			return ldb_module_operr(module);
3590
		}
3591
3592
		fix_dn_sid_control->critical = false;
3593
		ac->fix_link_sid = true;
3594
3595
		goto handle_linked_attribs;
3596
	}
3597
3454
	ldb_msg_remove_attr(msg, "whenChanged");
3598
	ldb_msg_remove_attr(msg, "whenChanged");
3455
	ldb_msg_remove_attr(msg, "uSNChanged");
3599
	ldb_msg_remove_attr(msg, "uSNChanged");
3456
3600
 Lines 3471-3476   static int replmd_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3471
		return ret;
3615
		return ret;
3472
	}
3616
	}
3473
3617
3618
 handle_linked_attribs:
3474
	ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3619
	ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3475
						  ac, msg, t, req);
3620
						  ac, msg, t, req);
3476
	if (ret != LDB_SUCCESS) {
3621
	if (ret != LDB_SUCCESS) {
(-)a/source4/dsdb/samdb/ldb_modules/samldb.c (-5 / +9 lines)
 Lines 3770-3778   static int samldb_modify(struct ldb_module *module, struct ldb_request *req) Link Here 
3770
3770
3771
	el = ldb_msg_find_element(ac->msg, "member");
3771
	el = ldb_msg_find_element(ac->msg, "member");
3772
	if (el != NULL) {
3772
	if (el != NULL) {
3773
		ret = samldb_member_check(ac);
3773
		struct ldb_control *fix_link_sid_ctrl = NULL;
3774
		if (ret != LDB_SUCCESS) {
3774
3775
			return ret;
3775
		fix_link_sid_ctrl = ldb_request_get_control(ac->req,
3776
					DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
3777
		if (fix_link_sid_ctrl == NULL) {
3778
			ret = samldb_member_check(ac);
3779
			if (ret != LDB_SUCCESS) {
3780
				return ret;
3781
			}
3776
		}
3782
		}
3777
	}
3783
	}
3778
3784
3779
- 
3780
the primaryGroupID field
3785
the primaryGroupID field
3781
--
3782
.../samba4.blackbox.test_primary_group        |  2 --
3786
.../samba4.blackbox.test_primary_group        |  2 --
3783
source4/dsdb/samdb/ldb_modules/samldb.c       | 29 ++++++++++++++-----
3787
source4/dsdb/samdb/ldb_modules/samldb.c       | 29 ++++++++++++++-----
3784
2 files changed, 21 insertions(+), 10 deletions(-)
3788
2 files changed, 21 insertions(+), 10 deletions(-)
3785
delete mode 100644 selftest/knownfail.d/samba4.blackbox.test_primary_group
3789
delete mode 100644 selftest/knownfail.d/samba4.blackbox.test_primary_group
(-)a/selftest/knownfail.d/samba4.blackbox.test_primary_group (-2 lines)
 Lines 1-2    Link Here 
1
^samba4.blackbox.test_primary_group.dbcheck.*run1
2
^samba4.blackbox.test_primary_group.dbcheck.*run2
(-)a/source4/dsdb/samdb/ldb_modules/samldb.c (-10 / +21 lines)
 Lines 1642-1650   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1642
	struct ldb_result *res, *group_res;
1642
	struct ldb_result *res, *group_res;
1643
	struct ldb_message_element *el;
1643
	struct ldb_message_element *el;
1644
	struct ldb_message *msg;
1644
	struct ldb_message *msg;
1645
	uint32_t search_flags =
1646
		DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN;
1645
	uint32_t prev_rid, new_rid, uac;
1647
	uint32_t prev_rid, new_rid, uac;
1646
	struct dom_sid *prev_sid, *new_sid;
1648
	struct dom_sid *prev_sid, *new_sid;
1647
	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1649
	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1650
	const char *new_prim_group_dn_ext_str = NULL;
1651
	struct ldb_dn *user_dn = NULL;
1652
	const char *user_dn_ext_str = NULL;
1648
	int ret;
1653
	int ret;
1649
	const char * const noattrs[] = { NULL };
1654
	const char * const noattrs[] = { NULL };
1650
1655
 Lines 1658-1667   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1658
	/* Fetch information from the existing object */
1663
	/* Fetch information from the existing object */
1659
1664
1660
	ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1665
	ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1661
				    DSDB_FLAG_NEXT_MODULE, ac->req);
1666
				    search_flags, ac->req);
1662
	if (ret != LDB_SUCCESS) {
1667
	if (ret != LDB_SUCCESS) {
1663
		return ret;
1668
		return ret;
1664
	}
1669
	}
1670
	user_dn = res->msgs[0]->dn;
1671
	user_dn_ext_str = ldb_dn_get_extended_linearized(ac, user_dn, 1);
1672
	if (user_dn_ext_str == NULL) {
1673
		return ldb_operr(ldb);
1674
	}
1665
1675
1666
	uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1676
	uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1667
1677
 Lines 1725-1731   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1725
	ret = dsdb_module_search(ac->module, ac, &group_res,
1735
	ret = dsdb_module_search(ac->module, ac, &group_res,
1726
				 ldb_get_default_basedn(ldb),
1736
				 ldb_get_default_basedn(ldb),
1727
				 LDB_SCOPE_SUBTREE,
1737
				 LDB_SCOPE_SUBTREE,
1728
				 noattrs, DSDB_FLAG_NEXT_MODULE,
1738
				 noattrs, search_flags,
1729
				 ac->req,
1739
				 ac->req,
1730
				 "(objectSid=%s)",
1740
				 "(objectSid=%s)",
1731
				 ldap_encode_ndr_dom_sid(ac, prev_sid));
1741
				 ldap_encode_ndr_dom_sid(ac, prev_sid));
 Lines 1745-1751   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1745
	ret = dsdb_module_search(ac->module, ac, &group_res,
1755
	ret = dsdb_module_search(ac->module, ac, &group_res,
1746
				 ldb_get_default_basedn(ldb),
1756
				 ldb_get_default_basedn(ldb),
1747
				 LDB_SCOPE_SUBTREE,
1757
				 LDB_SCOPE_SUBTREE,
1748
				 noattrs, DSDB_FLAG_NEXT_MODULE,
1758
				 noattrs, search_flags,
1749
				 ac->req,
1759
				 ac->req,
1750
				 "(objectSid=%s)",
1760
				 "(objectSid=%s)",
1751
				 ldap_encode_ndr_dom_sid(ac, new_sid));
1761
				 ldap_encode_ndr_dom_sid(ac, new_sid));
 Lines 1758-1768   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1758
		return LDB_ERR_UNWILLING_TO_PERFORM;
1768
		return LDB_ERR_UNWILLING_TO_PERFORM;
1759
	}
1769
	}
1760
	new_prim_group_dn = group_res->msgs[0]->dn;
1770
	new_prim_group_dn = group_res->msgs[0]->dn;
1771
	new_prim_group_dn_ext_str = ldb_dn_get_extended_linearized(ac,
1772
							new_prim_group_dn, 1);
1773
	if (new_prim_group_dn_ext_str == NULL) {
1774
		return ldb_operr(ldb);
1775
	}
1761
1776
1762
	/* We need to be already a normal member of the new primary
1777
	/* We need to be already a normal member of the new primary
1763
	 * group in order to be successful. */
1778
	 * group in order to be successful. */
1764
	el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1779
	el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1765
				  ldb_dn_get_linearized(new_prim_group_dn));
1780
				  new_prim_group_dn_ext_str);
1766
	if (el == NULL) {
1781
	if (el == NULL) {
1767
		return LDB_ERR_UNWILLING_TO_PERFORM;
1782
		return LDB_ERR_UNWILLING_TO_PERFORM;
1768
	}
1783
	}
 Lines 1774-1781   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1774
	}
1789
	}
1775
	msg->dn = new_prim_group_dn;
1790
	msg->dn = new_prim_group_dn;
1776
1791
1777
	ret = samdb_msg_add_delval(ldb, msg, msg, "member",
1792
	ret = samdb_msg_add_delval(ldb, msg, msg, "member", user_dn_ext_str);
1778
				   ldb_dn_get_linearized(ac->msg->dn));
1779
	if (ret != LDB_SUCCESS) {
1793
	if (ret != LDB_SUCCESS) {
1780
		return ret;
1794
		return ret;
1781
	}
1795
	}
 Lines 1793-1800   static int samldb_prim_group_change(struct samldb_ctx *ac) Link Here 
1793
	}
1807
	}
1794
	msg->dn = prev_prim_group_dn;
1808
	msg->dn = prev_prim_group_dn;
1795
1809
1796
	ret = samdb_msg_add_addval(ldb, msg, msg, "member",
1810
	ret = samdb_msg_add_addval(ldb, msg, msg, "member", user_dn_ext_str);
1797
				   ldb_dn_get_linearized(ac->msg->dn));
1798
	if (ret != LDB_SUCCESS) {
1811
	if (ret != LDB_SUCCESS) {
1799
		return ret;
1812
		return ret;
1800
	}
1813
	}
1801
- 
1802
current backlink behaviour
1814
current backlink behaviour
1803
--
1804
.../samdb/ldb_modules/linked_attributes.c     | 18 +++++++++++++-
1815
.../samdb/ldb_modules/linked_attributes.c     | 18 +++++++++++++-
1805
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 24 ++++++++++++++-----
1816
.../dsdb/samdb/ldb_modules/repl_meta_data.c   | 24 ++++++++++++++-----
1806
testprogs/blackbox/test_primary_group.sh      |  6 ++++-
1817
testprogs/blackbox/test_primary_group.sh      |  6 ++++-
1807
3 files changed, 40 insertions(+), 8 deletions(-)
1818
3 files changed, 40 insertions(+), 8 deletions(-)
(-)a/source4/dsdb/samdb/ldb_modules/linked_attributes.c (-1 / +17 lines)
 Lines 25-31    Link Here 
25
 *
25
 *
26
 *  Component: ldb linked_attributes module
26
 *  Component: ldb linked_attributes module
27
 *
27
 *
28
 *  Description: Module to ensure linked attribute pairs remain in sync
28
 *  Description: Module to ensure linked attribute pairs (i.e. forward-links
29
 *  and backlinks) remain in sync.
30
 *
31
 *  Backlinks are 'plain' links (without extra metadata). When the link target
32
 *  object is modified (e.g. renamed), we use the backlinks to keep the link
33
 *  source object updated. Note there are some cases where we can't do this:
34
 *    - one-way links, which don't have a corresponding backlink
35
 *    - two-way deactivated links, i.e. when a user is removed from a group,
36
 *      the forward 'member' link still exists (but is inactive), however, the
37
 *      'memberOf' backlink is deleted.
38
 *  In these cases, we can end up with a dangling forward link which is
39
 *  incorrect (i.e. the target has been renamed or deleted). We have dbcheck
40
 *  rules to detect and fix this, and cope otherwise by filtering at runtime
41
 *  (i.e. in the extended_dn module).
42
 *
43
 *  See also repl_meta_data.c, which handles updating links for deleted
44
 *  objects, as well as link changes received from another DC.
29
 *
45
 *
30
 *  Author: Andrew Bartlett
46
 *  Author: Andrew Bartlett
31
 */
47
 */
(-)a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c (-7 / +10 lines)
 Lines 4367-4372   static int replmd_delete_internals(struct ldb_module *module, struct ldb_request Link Here 
4367
	     - preserved if in above list, or is rDN
4367
	     - preserved if in above list, or is rDN
4368
	  - remove all linked attribs from this object
4368
	  - remove all linked attribs from this object
4369
	  - remove all links from other objects to this object
4369
	  - remove all links from other objects to this object
4370
	    (note we use the backlinks to do this, so we won't find one-way
4371
	     links that still point to this object, or deactivated two-way
4372
	     links, i.e. 'member' after the user has been removed from the
4373
	     group)
4370
	  - add lastKnownParent
4374
	  - add lastKnownParent
4371
	  - update replPropertyMetaData?
4375
	  - update replPropertyMetaData?
4372
4376
 Lines 4488-4499   static int replmd_delete_internals(struct ldb_module *module, struct ldb_request Link Here 
4488
4492
4489
			if (sa->linkID & 1) {
4493
			if (sa->linkID & 1) {
4490
				/*
4494
				/*
4491
				  we have a backlink in this object
4495
				 * we have a backlink in this object
4492
				  that needs to be removed. We're not
4496
				 * that needs to be removed. We're not
4493
				  allowed to remove it directly
4497
				 * allowed to remove it directly
4494
				  however, so we instead setup a
4498
				 * however, so we instead setup a
4495
				  modify to delete the corresponding
4499
				 * modify to delete the corresponding
4496
				  forward link
4500
				 * forward link
4497
				 */
4501
				 */
4498
				ret = replmd_delete_remove_link(module, schema,
4502
				ret = replmd_delete_remove_link(module, schema,
4499
								replmd_private,
4503
								replmd_private,
4500
- 

Return to bug 48054