diff options
author | Karolin Seeger <kseeger@samba.org> | 2019-12-10 10:25:47 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2019-12-10 10:25:47 +0100 |
commit | e81ef10bbf5579e24a7eaa33a775d3da74dd6dd0 (patch) | |
tree | 9eda32549a0cb2267ba06f6e569fb2b883e6f9ec | |
parent | 91f39dbda151f6a2768b6e5eff59f931f303721f (diff) | |
parent | 7fc8563c2f6381c0389cdbb8c833e9bb89ec068b (diff) | |
download | samba-e81ef10bbf5579e24a7eaa33a775d3da74dd6dd0.tar.gz |
Merge tag 'samba-4.11.3' into v4-11-test
samba: tag release samba-4.11.3
-rw-r--r-- | WHATSNEW.txt | 66 | ||||
-rw-r--r-- | python/samba/netcmd/user.py | 58 | ||||
-rw-r--r-- | python/samba/tests/dcerpc/dnsserver.py | 148 | ||||
-rw-r--r-- | selftest/flapping.d/dnsserver | 2 | ||||
-rw-r--r-- | source4/heimdal/kdc/krb5tgs.c | 58 | ||||
-rw-r--r-- | source4/kdc/mit_samba.c | 5 | ||||
-rw-r--r-- | source4/kdc/sdb_to_kdb.c | 17 | ||||
-rw-r--r-- | source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 21 | ||||
-rw-r--r-- | source4/rpc_server/dnsserver/dnsdata.c | 28 | ||||
-rw-r--r-- | source4/rpc_server/dnsserver/dnsserver.h | 4 | ||||
-rwxr-xr-x | source4/selftest/tests.py | 1 | ||||
-rw-r--r-- | source4/torture/drs/python/samba_tool_drs.py | 3 | ||||
-rwxr-xr-x | testprogs/blackbox/test_s4u_heimdal.sh | 73 |
13 files changed, 417 insertions, 67 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 8c6db3b3034..8bafa38b47c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,4 +1,66 @@ ============================== + Release Notes for Samba 4.11.3 + December 10, 2019 + ============================== + + +This is a security release in order to address the following defects: + +o CVE-2019-14861: Samba AD DC zone-named record Denial of Service in DNS + management server (dnsserver). +o CVE-2019-14870: DelegationNotAllowed not being enforced in protocol transition + on Samba AD DC. + + +======= +Details +======= + +o CVE-2019-14861: + An authenticated user can crash the DCE/RPC DNS management server by creating + records with matching the zone name. + +o CVE-2019-14870: + The DelegationNotAllowed Kerberos feature restriction was not being applied + when processing protocol transition requests (S4U2Self), in the AD DC KDC. + +For more details and workarounds, please refer to the security advisories. + + +Changes since 4.11.2: +--------------------- + +o Andrew Bartlett <abartlet@samba.org> + * BUG 14138: CVE-2019-14861: Fix DNSServer RPC server crash. + +o Isaac Boukris <iboukris@gmail.com> + * BUG 14187: CVE-2019-14870: DelegationNotAllowed not being enforced. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + + ============================== Release Notes for Samba 4.11.2 October 29, 2019 ============================== @@ -69,8 +131,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.11.1 diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py index 121050a26e6..3fd8e6fb7be 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -2642,6 +2642,63 @@ class cmd_user_move(Command): (username, full_new_parent_dn)) +class cmd_user_sensitive(Command): + """Set/unset or show UF_NOT_DELEGATED for an account.""" + + synopsis = "%prog <accountname> [(show|on|off)] [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "credopts": options.CredentialsOptions, + "versionopts": options.VersionOptions, + } + + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", type=str, + metavar="URL", dest="H"), + ] + + takes_args = ["accountname", "cmd"] + + def run(self, accountname, cmd, H=None, credopts=None, sambaopts=None, + versionopts=None): + + if cmd not in ("show", "on", "off"): + raise CommandError("invalid argument: '%s' (choose from 'show', 'on', 'off')" % cmd) + + lp = sambaopts.get_loadparm() + creds = credopts.get_credentials(lp, fallback_machine=True) + sam = SamDB(url=H, session_info=system_session(), + credentials=creds, lp=lp) + + search_filter = "sAMAccountName=%s" % ldb.binary_encode(accountname) + flag = dsdb.UF_NOT_DELEGATED; + + if cmd == "show": + res = sam.search(scope=ldb.SCOPE_SUBTREE, expression=search_filter, + attrs=["userAccountControl"]) + if len(res) == 0: + raise Exception("Unable to find account where '%s'" % search_filter) + + uac = int(res[0].get("userAccountControl")[0]) + + self.outf.write("Account-DN: %s\n" % str(res[0].dn)) + self.outf.write("UF_NOT_DELEGATED: %s\n" % bool(uac & flag)) + + return + + if cmd == "on": + on = True + elif cmd == "off": + on = False + + try: + sam.toggle_userAccountFlags(search_filter, flag, flags_str="Not-Delegated", + on=on, strict=True) + except Exception as err: + raise CommandError(err) + + class cmd_user(SuperCommand): """User management.""" @@ -2660,3 +2717,4 @@ class cmd_user(SuperCommand): subcommands["edit"] = cmd_user_edit() subcommands["show"] = cmd_user_show() subcommands["move"] = cmd_user_move() + subcommands["sensitive"] = cmd_user_sensitive() diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py index 0da9614d066..c6a150c876f 100644 --- a/python/samba/tests/dcerpc/dnsserver.py +++ b/python/samba/tests/dcerpc/dnsserver.py @@ -156,6 +156,154 @@ class DnsserverTests(RpcInterfaceTestCase): None) super(DnsserverTests, self).tearDown() + def test_enum_is_sorted(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0", record_type_str, record_str) + + # This becomes an extra A on the zone itself by server-side magic + self.add_record(self.custom_zone, self.custom_zone, record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "@", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + + def test_enum_is_sorted_with_zone_dup(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0", record_type_str, record_str) + + # This triggers a bug in old Samba + self.add_record(self.custom_zone, self.custom_zone + "1", record_type_str, record_str) + + dn, record = self.get_record_from_db(self.custom_zone, self.custom_zone + "1") + + new_dn = ldb.Dn(self.samdb, str(dn)) + new_dn.set_component(0, "dc", self.custom_zone) + self.samdb.rename(dn, new_dn) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "@", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 7) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + + # Windows doesn't reload the zone fast enough, but doesn't + # have the bug anyway, it will sort last on both names (where + # it should) + if result.rec[6].dnsNodeName.str != (self.custom_zone + "1"): + self.assertEqual(result.rec[6].dnsNodeName.str, self.custom_zone) + + def test_enum_is_sorted_children_prefix_first(self): + """ + Confirm the zone returns the selected prefix first but no more + as Samba is flappy for the full sort + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str) + + # Not expected to be returned + self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "a.b", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + + def test_enum_is_sorted_children(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str) + + # Not expected to be returned + self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "a.b", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + # This test fails against Samba (but passes against Windows), # because Samba does not return the record when we enum records. # Records can be given DNS_RANK_NONE when the zone they are in diff --git a/selftest/flapping.d/dnsserver b/selftest/flapping.d/dnsserver new file mode 100644 index 00000000000..9b33e8522a3 --- /dev/null +++ b/selftest/flapping.d/dnsserver @@ -0,0 +1,2 @@ +# This is not stable in samba due to a bug +^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_enum_is_sorted_children
\ No newline at end of file diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ff7d93138c0..ee3ac3d8f53 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1975,30 +1975,42 @@ server_lookup: if (ret) goto out; + ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, + NULL, &s4u2self_impersonated_clientdb, + &s4u2self_impersonated_client); + if (ret) { + const char *msg; + + /* + * If the client belongs to the same realm as our krbtgt, it + * should exist in the local database. + * + */ + + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + msg = krb5_get_error_message(context, ret); + kdc_log(context, config, 1, + "S2U4Self principal to impersonate %s not found in database: %s", + tpn, msg); + krb5_free_error_message(context, msg); + goto out; + } + + /* Ignore pw_end attributes (as Windows does), + * since S4U2Self is not password authentication. */ + free(s4u2self_impersonated_client->entry.pw_end); + s4u2self_impersonated_client->entry.pw_end = NULL; + + ret = kdc_check_flags(context, config, s4u2self_impersonated_client, tpn, + NULL, NULL, FALSE); + if (ret) + goto out; + /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ if(rspac.data) { krb5_pac p = NULL; krb5_data_free(&rspac); - ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, - NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); - if (ret) { - const char *msg; - - /* - * If the client belongs to the same realm as our krbtgt, it - * should exist in the local database. - * - */ - - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 1, - "S2U4Self principal to impersonate %s not found in database: %s", - tpn, msg); - krb5_free_error_message(context, msg); - goto out; - } ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", @@ -2034,10 +2046,12 @@ server_lookup: /* * If the service isn't trusted for authentication to - * delegation, remove the forward flag. + * delegation or if the impersonate client is disallowed + * forwardable, remove the forwardable flag. */ - if (client->entry.flags.trusted_for_delegation) { + if (client->entry.flags.trusted_for_delegation && + s4u2self_impersonated_client->entry.flags.forwardable) { str = "[forwardable]"; } else { b->kdc_options.forwardable = 0; diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 54dcd545ea1..5a4f6e73e97 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -304,6 +304,11 @@ fetch_referral_principal: sdb_free_entry(&sentry); + if ((kflags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) == 0) { + kentry->attributes &= ~KRB5_KDB_DISALLOW_FORWARDABLE; + kentry->attributes &= ~KRB5_KDB_DISALLOW_PROXIABLE; + } + done: krb5_free_principal(ctx->context, referral_principal); referral_principal = NULL; diff --git a/source4/kdc/sdb_to_kdb.c b/source4/kdc/sdb_to_kdb.c index 1411b0f5f66..2981f180333 100644 --- a/source4/kdc/sdb_to_kdb.c +++ b/source4/kdc/sdb_to_kdb.c @@ -36,18 +36,13 @@ static int SDBFlags_to_kflags(const struct SDBFlags *s, if (s->initial) { *k |= KRB5_KDB_DISALLOW_TGT_BASED; } - /* - * Do not set any disallow rules for forwardable, proxiable, - * renewable, postdate and server. - * - * The KDC will take care setting the flags based on the incoming - * ticket. - */ - if (s->forwardable) { - ; + /* The forwardable and proxiable flags are set according to client and + * server attributes. */ + if (!s->forwardable) { + *k |= KRB5_KDB_DISALLOW_FORWARDABLE; } - if (s->proxiable) { - ; + if (!s->proxiable) { + *k |= KRB5_KDB_DISALLOW_PROXIABLE; } if (s->renewable) { ; diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 993e5dc4e56..b6389f2328a 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1763,6 +1763,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, struct DNS_RPC_RECORDS_ARRAY *recs; char **add_names = NULL; char *rname; + const char *preference_name = NULL; int add_count = 0; int i, ret, len; WERROR status; @@ -1779,6 +1780,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))"); + preference_name = "@"; } else { char *encoded_name = ldb_binary_encode_string(tmp_ctx, name); @@ -1786,6 +1788,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s))(!(dNSTombstoned=TRUE)))", encoded_name, encoded_name); + preference_name = name; } if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); @@ -1799,16 +1802,18 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY); W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx); - /* Sort the names, so that the first record is the parent record */ - ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name, - (ldb_qsort_cmp_fn_t)dns_name_compare); + /* + * Sort the names, so that the records are in order by the child + * component below "name". + * + * A full tree sort is not required, so we pass in "name" so + * we know which level to sort, as only direct children are + * eventually returned + */ + LDB_TYPESAFE_QSORT(res->msgs, res->count, name, dns_name_compare); /* Build a tree of name components from dns name */ - if (strcasecmp(name, z->name) == 0) { - tree = dns_build_tree(tmp_ctx, "@", res); - } else { - tree = dns_build_tree(tmp_ctx, name, res); - } + tree = dns_build_tree(tmp_ctx, preference_name, res); W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx); /* Find the parent record in the tree */ diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c index 2dc098a64a0..47d6f5d5c88 100644 --- a/source4/rpc_server/dnsserver/dnsdata.c +++ b/source4/rpc_server/dnsserver/dnsdata.c @@ -801,10 +801,11 @@ struct dns_tree *dns_build_tree(TALLOC_CTX *mem_ctx, const char *name, struct ld goto failed; } - if (strcmp(ptr, "@") == 0) { - base->data = res->msgs[i]; - continue; - } else if (strcasecmp(ptr, name) == 0) { + /* + * This might be the sub-domain in the zone being + * requested, or @ for the root of the zone + */ + if (strcasecmp(ptr, name) == 0) { base->data = res->msgs[i]; continue; } @@ -1065,8 +1066,8 @@ WERROR dns_fill_records_array(TALLOC_CTX *mem_ctx, } -int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m2, - char *search_name) +int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const *m2, + const char *search_name) { const char *name1, *name2; const char *ptr1, *ptr2; @@ -1077,21 +1078,6 @@ int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m return 0; } - /* '@' record and the search_name record gets preference */ - if (name1[0] == '@') { - return -1; - } - if (search_name && strcasecmp(name1, search_name) == 0) { - return -1; - } - - if (name2[0] == '@') { - return 1; - } - if (search_name && strcasecmp(name2, search_name) == 0) { - return 1; - } - /* Compare the last components of names. * If search_name is not NULL, compare the second last components of names */ ptr1 = strrchr(name1, '.'); diff --git a/source4/rpc_server/dnsserver/dnsserver.h b/source4/rpc_server/dnsserver/dnsserver.h index a8307ef836a..2e46e7c66a4 100644 --- a/source4/rpc_server/dnsserver/dnsserver.h +++ b/source4/rpc_server/dnsserver/dnsserver.h @@ -188,8 +188,8 @@ struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx, struct DNS_ADDR_ int dns_split_name_components(TALLOC_CTX *mem_ctx, const char *name, char ***components); char *dns_split_node_name(TALLOC_CTX *mem_ctx, const char *node_name, const char *zone_name); -int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m2, - char *search_name); +int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const *m2, + const char *search_name); bool dns_record_match(struct dnsp_DnssrvRpcRecord *rec1, struct dnsp_DnssrvRpcRecord *rec2); void dnsp_to_dns_copy(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *dnsp, diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 1772611eb53..2bc4561b87a 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -455,6 +455,7 @@ if have_heimdal_support: plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external", "arcfour-hmac-md5"]) plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4]) plantestsuite("samba4.blackbox.kpasswd(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"]) + plantestsuite("samba4.blackbox.krb5.s4u", "fl2008r2dc:local", [os.path.join(bbdir, "test_s4u_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', configuration]) else: plantestsuite("samba4.blackbox.kinit(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) plantestsuite("samba4.blackbox.kinit(fl2000dc:local)", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) diff --git a/source4/torture/drs/python/samba_tool_drs.py b/source4/torture/drs/python/samba_tool_drs.py index 76cc86f832e..988f1dc7a3c 100644 --- a/source4/torture/drs/python/samba_tool_drs.py +++ b/source4/torture/drs/python/samba_tool_drs.py @@ -210,6 +210,7 @@ class SambaToolDrsTests(drs_base.DrsBaseTestCase): self._disable_inbound_repl(self.dnsname_dc1) self._disable_inbound_repl(self.dnsname_dc2) + self._net_drs_replicate(DC=self.dnsname_dc2, fromDC=self.dnsname_dc1) self._net_drs_replicate(DC=self.dnsname_dc1, fromDC=self.dnsname_dc2) # add an object with link on dc1 @@ -232,7 +233,7 @@ class SambaToolDrsTests(drs_base.DrsBaseTestCase): (obj_1, link_1) = get_num_obj_links(out) - self.assertEqual(obj_1, 2) + self.assertGreaterEqual(obj_1, 2) self.assertEqual(link_1, 1) # pull that change with --local into local db from dc2: shouldn't send link or object diff --git a/testprogs/blackbox/test_s4u_heimdal.sh b/testprogs/blackbox/test_s4u_heimdal.sh new file mode 100755 index 00000000000..0e12c7ec096 --- /dev/null +++ b/testprogs/blackbox/test_s4u_heimdal.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then +cat <<EOF +Usage: test_kinit.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX +EOF +exit 1; +fi + +SERVER=$1 +USERNAME=$2 +PASSWORD=$3 +REALM=$4 +DOMAIN=$5 +PREFIX=$6 +shift 6 +failed=0 + + +samba_tool="$VALGRIND $PYTHON $BINDIR/samba-tool" + +samba4kinit=kinit +if test -x $BINDIR/samba4kinit; then + samba4kinit=$BINDIR/samba4kinit +fi + +samba4kgetcred=kgetcred +if test -x $BINDIR/samba4kgetcred; then + samba4kgetcred=$BINDIR/samba4kgetcred +fi + +. `dirname $0`/subunit.sh +. `dirname $0`/common_test_fns.inc + +ocache="$PREFIX/tmpoutcache" +KRB5CCNAME_PATH="$PREFIX/tmpccache" +KRB5CCNAME="FILE:$KRB5CCNAME_PATH" +export KRB5CCNAME +rm -rf $KRB5CCNAME_PATH + +princ=test_impersonate_princ +impersonator=test_impersonator +target="CIFS/$SERVER.$REALM" + + +testit "add impersonator principal" $samba_tool user add $impersonator $PASSWORD || failed=`expr $failed + 1` +testit "become a service" $samba_tool spn add "HOST/$impersonator" $impersonator || failed=`expr $failed + 1` + +testit "set TrustedToAuthForDelegation" $samba_tool delegation for-any-protocol $impersonator on || failed=`expr $failed + 1` +testit "add msDS-AllowedToDelegateTo" $samba_tool delegation add-service $impersonator $target || failed=`expr $failed + 1` + +testit "add a new principal" $samba_tool user add $princ --random-password || failed=`expr $failed + 1` +testit "set not-delegated flag" $samba_tool user sensitive $princ on || failed=`expr $failed + 1` + + +echo $PASSWORD > $PREFIX/tmppassfile +testit "kinit with password" $samba4kinit -f --password-file=$PREFIX/tmppassfile $impersonator || failed=`expr $failed + 1` + +testit "test S4U2Self with normal user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=${USERNAME} $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy with normal user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +testit "test S4U2Self with sensitive user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit_expect_failure "test S4U2Proxy with sensitive user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +rm -f $ocache +testit "unset not-delegated flag" $samba_tool user sensitive $princ off || failed=`expr $failed + 1` + +testit "test S4U2Self after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + + +rm -f $ocache $PREFIX/tmpccache tmppassfile +exit $failed |