The Samba-Bugzilla – Attachment 10874 Details for
Bug 11142
KDC does not support enterprise UPNs properly
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
4.2 patch cherry-picked from master
krb5-upn-4.2-with-bug.patch (text/plain), 369.94 KB, created by
Andrew Bartlett
on 2015-03-15 20:46:44 UTC
(
hide
)
Description:
4.2 patch cherry-picked from master
Filename:
MIME Type:
Creator:
Andrew Bartlett
Created:
2015-03-15 20:46:44 UTC
Size:
369.94 KB
patch
obsolete
>From 82f6e867e0b701f60de912629fa4b6da966b1de4 Mon Sep 17 00:00:00 2001 >From: Michael Brown <michael@netdirect.ca> >Date: Thu, 21 Nov 2013 10:48:33 -0500 >Subject: [PATCH 01/60] Add missing parameters to drs_Replicate in rodc.py > >* rodc.py: destination_dsa_guid parameter was neglected > in drs_Replicate call >* rodc.py: cancel the local_samdb transaction on error > >Change-Id: I962315a26ec48dc8774bb41db760387a3469c919 >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11145 > >Autobuild-User(master): Garming Sam <garming@samba.org> >Autobuild-Date(master): Thu Oct 23 03:05:00 CEST 2014 on sn-devel-104 > >(cherry picked from commit 88f9f50024b624319267ffa3684044d4e20e85c7) >--- > python/samba/netcmd/rodc.py | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > >diff --git a/python/samba/netcmd/rodc.py b/python/samba/netcmd/rodc.py >index 2dc6112..4404b7b 100644 >--- a/python/samba/netcmd/rodc.py >+++ b/python/samba/netcmd/rodc.py >@@ -91,11 +91,13 @@ class cmd_rodc_preload(Command): > destination_dsa_guid = misc.GUID(local_samdb.get_ntds_GUID()) > > local_samdb.transaction_start() >- repl = drs_Replicate("ncacn_ip_tcp:%s[seal,print]" % server, lp, creds, local_samdb) >+ repl = drs_Replicate("ncacn_ip_tcp:%s[seal,print]" % server, lp, creds, >+ local_samdb, destination_dsa_guid) > try: > repl.replicate(dn, source_dsa_invocation_id, destination_dsa_guid, > exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) > except Exception, e: >+ local_samdb.transaction_cancel() > raise CommandError("Error replicating DN %s" % dn, e) > local_samdb.transaction_commit() > >-- >2.1.4 > > >From 8f76c45292ba43a50c1d3f69140ad70d6af546e0 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 2 Oct 2014 13:02:48 +0200 >Subject: [PATCH 02/60] torture: add torture_assert_int_not_equal > >Signed-off-by: Michael Adam <obnox@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit fae589be2af8efe36713536203ae715d29d78b5b) >--- > lib/torture/torture.h | 10 ++++++++++ > 1 file changed, 10 insertions(+) > >diff --git a/lib/torture/torture.h b/lib/torture/torture.h >index 3a08042..e6f323a 100644 >--- a/lib/torture/torture.h >+++ b/lib/torture/torture.h >@@ -414,6 +414,16 @@ void torture_result(struct torture_context *test, > } \ > } while(0) > >+#define torture_assert_int_not_equal(torture_ctx,got,not_expected,cmt)\ >+ do { int __got = (got), __not_expected = (not_expected); \ >+ if (__got == __not_expected) { \ >+ torture_result(torture_ctx, TORTURE_FAIL, \ >+ __location__": "#got" was %d (0x%X), expected a different number: %s", \ >+ __got, __got, cmt); \ >+ return false; \ >+ } \ >+ } while(0) >+ > #define torture_assert_u64_equal(torture_ctx,got,expected,cmt)\ > do { uint64_t __got = (got), __expected = (expected); \ > if (__got != __expected) { \ >-- >2.1.4 > > >From 01f63ecbfefe5dd328b127260e32a63ad020b5ee Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 27 Feb 2014 09:29:36 +0100 >Subject: [PATCH 03/60] s4:kdc: comment out unused code in db-glue.c > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit e5e5c223531e1935ba3c30b6439bdc0afd53a88d) >--- > source4/kdc/db-glue.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index b0c3e7a..00b58fd 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -1362,10 +1362,10 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context, > } else { > int lret; > char *short_princ; >- const char *realm; >+ /* const char *realm; */ > /* server as client principal case, but we must not lookup userPrincipalNames */ > *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); >- realm = krb5_principal_get_realm(context, principal); >+ /* realm = krb5_principal_get_realm(context, principal); */ > > /* TODO: Check if it is our realm, otherwise give referral */ > >-- >2.1.4 > > >From c295eda467bf67dbb843eeb344ad023dc7c18757 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 15 Dec 2014 16:48:27 +0100 >Subject: [PATCH 04/60] s4:kdc: add aes key support for trusted domains >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >We have a look at "msDS-SupportedEncryptionTypes" and >= DS_DOMAIN_FUNCTION_2008 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Günther Deschner <gd@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Fri Dec 19 15:39:40 CET 2014 on sn-devel-104 > >(cherry picked from commit 8dd37327b02eaea33915a9cd206667981b8df872) >--- > source4/kdc/db-glue.c | 185 ++++++++++++++++++++++++++++++++++++++++---------- > 1 file changed, 148 insertions(+), 37 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index 00b58fd..caeb1b2 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -858,17 +858,27 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; > const char *dnsdomain; > const char *realm = lpcfg_realm(lp_ctx); >- DATA_BLOB password_utf16; >- struct samr_Password password_hash; >+ DATA_BLOB password_utf16 = data_blob_null; >+ DATA_BLOB password_utf8 = data_blob_null; >+ struct samr_Password _password_hash; >+ const struct samr_Password *password_hash = NULL; > const struct ldb_val *password_val; > struct trustAuthInOutBlob password_blob; > struct samba_kdc_entry *p; > bool use_previous; > uint32_t current_kvno; >+ uint32_t num_keys = 0; > enum ndr_err_code ndr_err; > int ret, trust_direction_flags; > unsigned int i; > struct AuthenticationInformationArray *auth_array; >+ uint32_t supported_enctypes = ENCTYPE_ARCFOUR_HMAC; >+ >+ if (dsdb_functional_level(kdc_db_ctx->samdb) >= DS_DOMAIN_FUNCTION_2008) { >+ supported_enctypes = ldb_msg_find_attr_as_uint(msg, >+ "msDS-SupportedEncryptionTypes", >+ supported_enctypes); >+ } > > p = talloc(mem_ctx, struct samba_kdc_entry); > if (!p) { >@@ -895,6 +905,29 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > &entry_ex->entry.created_by.principal, > realm, "kadmin", NULL); > >+ entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); >+ if (entry_ex->entry.principal == NULL) { >+ krb5_clear_error_message(context); >+ ret = ENOMEM; >+ goto out; >+ } >+ >+ ret = copy_Principal(principal, entry_ex->entry.principal); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } >+ >+ /* >+ * While we have copied the client principal, tests >+ * show that Win2k3 returns the 'corrected' realm, not >+ * the client-specified realm. This code attempts to >+ * replace the client principal's realm with the one >+ * we determine from our records >+ */ >+ >+ krb5_principal_set_realm(context, entry_ex->entry.principal, realm); >+ > entry_ex->entry.valid_start = NULL; > > trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0); >@@ -910,13 +943,15 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > } > > if (!password_val || !(trust_direction_flags & direction)) { >- ret = ENOENT; >+ krb5_clear_error_message(context); >+ ret = HDB_ERR_NOENTRY; > goto out; > } > > ndr_err = ndr_pull_struct_blob(password_val, mem_ctx, &password_blob, > (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob); > if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ krb5_clear_error_message(context); > ret = EINVAL; > goto out; > } >@@ -952,7 +987,8 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > } else { > DEBUG(1,(__location__ ": Request for unknown kvno %u - current kvno is %u\n", > kvno, current_kvno)); >- ret = ENOENT; >+ krb5_clear_error_message(context); >+ ret = HDB_ERR_NOENTRY; > goto out; > } > >@@ -971,38 +1007,124 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > > for (i=0; i < auth_array->count; i++) { > if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) { >+ bool ok; >+ > password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password, > auth_array->array[i].AuthInfo.clear.size); >- /* In the future, generate all sorts of >- * hashes, but for now we can't safely convert >- * the random strings windows uses into >- * utf8 */ >+ if (password_utf16.length == 0) { >+ break; >+ } >+ >+ if (supported_enctypes & ENCTYPE_ARCFOUR_HMAC) { >+ mdfour(_password_hash.hash, password_utf16.data, password_utf16.length); >+ if (password_hash == NULL) { >+ num_keys += 1; >+ } >+ password_hash = &_password_hash; >+ } > >- /* but as it is utf16 already, we can get the NT password/arcfour-hmac-md5 key */ >- mdfour(password_hash.hash, password_utf16.data, password_utf16.length); >+ if (!(supported_enctypes & (ENC_HMAC_SHA1_96_AES128|ENC_HMAC_SHA1_96_AES256))) { >+ break; >+ } >+ >+ ok = convert_string_talloc(mem_ctx, >+ CH_UTF16MUNGED, CH_UTF8, >+ password_utf16.data, >+ password_utf16.length, >+ (void *)&password_utf8.data, >+ &password_utf8.length); >+ if (!ok) { >+ krb5_clear_error_message(context); >+ ret = ENOMEM; >+ goto out; >+ } >+ >+ if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { >+ num_keys += 1; >+ } >+ if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { >+ num_keys += 1; >+ } > break; > } else if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) { >- password_hash = auth_array->array[i].AuthInfo.nt4owf.password; >- break; >+ if (supported_enctypes & ENCTYPE_ARCFOUR_HMAC) { >+ password_hash = &auth_array->array[i].AuthInfo.nt4owf.password; >+ num_keys += 1; >+ } > } > } > >- if (i < auth_array->count) { >- Key key; >- /* Must have found a cleartext or MD4 password */ >- entry_ex->entry.keys.val = calloc(1, sizeof(Key)); >+ /* Must have found a cleartext or MD4 password */ >+ if (num_keys == 0) { >+ DEBUG(1,(__location__ ": no usable key found\n")); >+ krb5_clear_error_message(context); >+ ret = HDB_ERR_NOENTRY; >+ goto out; >+ } > >- key.mkvno = 0; >- key.salt = NULL; /* No salt for this enc type */ >+ entry_ex->entry.keys.val = calloc(num_keys, sizeof(Key)); >+ if (entry_ex->entry.keys.val == NULL) { >+ krb5_clear_error_message(context); >+ ret = ENOMEM; >+ goto out; >+ } > >- if (entry_ex->entry.keys.val == NULL) { >- ret = ENOMEM; >+ if (password_utf8.length != 0) { >+ Key key = {}; >+ krb5_const_principal salt_principal = principal; >+ krb5_salt salt; >+ krb5_data cleartext_data; >+ >+ cleartext_data.data = password_utf8.data; >+ cleartext_data.length = password_utf8.length; >+ >+ ret = krb5_get_pw_salt(context, >+ salt_principal, >+ &salt); >+ if (ret != 0) { > goto out; > } > >+ if (supported_enctypes & ENCTYPE_AES256_CTS_HMAC_SHA1_96) { >+ ret = krb5_string_to_key_data_salt(context, >+ ENCTYPE_AES256_CTS_HMAC_SHA1_96, >+ cleartext_data, >+ salt, >+ &key.key); >+ if (ret != 0) { >+ krb5_free_salt(context, salt); >+ goto out; >+ } >+ >+ entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; >+ entry_ex->entry.keys.len++; >+ } >+ >+ if (supported_enctypes & ENCTYPE_AES128_CTS_HMAC_SHA1_96) { >+ ret = krb5_string_to_key_data_salt(context, >+ ENCTYPE_AES128_CTS_HMAC_SHA1_96, >+ cleartext_data, >+ salt, >+ &key.key); >+ if (ret != 0) { >+ krb5_free_salt(context, salt); >+ goto out; >+ } >+ >+ entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; >+ entry_ex->entry.keys.len++; >+ } >+ >+ krb5_free_salt(context, salt); >+ } >+ >+ if (password_hash != NULL) { >+ Key key = {}; >+ > ret = krb5_keyblock_init(context, > ENCTYPE_ARCFOUR_HMAC, >- password_hash.hash, sizeof(password_hash.hash), >+ password_hash->hash, >+ sizeof(password_hash->hash), > &key.key); > if (ret != 0) { > goto out; >@@ -1012,21 +1134,6 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > entry_ex->entry.keys.len++; > } > >- entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); >- >- ret = copy_Principal(principal, entry_ex->entry.principal); >- if (ret) { >- krb5_clear_error_message(context); >- goto out; >- } >- >- /* While we have copied the client principal, tests >- * show that Win2k3 returns the 'corrected' realm, not >- * the client-specified realm. This code attempts to >- * replace the client principal's realm with the one >- * we determine from our records */ >- >- krb5_principal_set_realm(context, entry_ex->entry.principal, realm); > entry_ex->entry.flags = int2HDBFlags(0); > entry_ex->entry.flags.immutable = 1; > entry_ex->entry.flags.invalid = 0; >@@ -1307,7 +1414,11 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context, > principal, direction, > realm_dn, flags, kvno, msg, entry_ex); > if (ret != 0) { >- krb5_warnx(context, "samba_kdc_fetch: trust_message2entry failed"); >+ krb5_warnx(context, "samba_kdc_fetch: trust_message2entry failed for %s", >+ ldb_dn_get_linearized(msg->dn)); >+ krb5_set_error_message(context, ret, "samba_kdc_fetch: " >+ "trust_message2entry failed for %s", >+ ldb_dn_get_linearized(msg->dn)); > } > return ret; > } >-- >2.1.4 > > >From a8242f46adf39e3eedb86416eb145be93f1ba54a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 20 Jan 2015 10:52:22 +0000 >Subject: [PATCH 05/60] s4:kdc/db-glue: fix supported_enctypes > samba_kdc_trust_message2entry() > >This avoids writing invalid memory, because num_keys was calculated >in a wrong way... > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 01c02340c1700aeb16d167be45f6de8d96a91802) >--- > source4/kdc/db-glue.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index caeb1b2..37e2f9e 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -872,7 +872,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > int ret, trust_direction_flags; > unsigned int i; > struct AuthenticationInformationArray *auth_array; >- uint32_t supported_enctypes = ENCTYPE_ARCFOUR_HMAC; >+ uint32_t supported_enctypes = ENC_RC4_HMAC_MD5; > > if (dsdb_functional_level(kdc_db_ctx->samdb) >= DS_DOMAIN_FUNCTION_2008) { > supported_enctypes = ldb_msg_find_attr_as_uint(msg, >@@ -1015,7 +1015,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > break; > } > >- if (supported_enctypes & ENCTYPE_ARCFOUR_HMAC) { >+ if (supported_enctypes & ENC_RC4_HMAC_MD5) { > mdfour(_password_hash.hash, password_utf16.data, password_utf16.length); > if (password_hash == NULL) { > num_keys += 1; >@@ -1047,7 +1047,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > } > break; > } else if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) { >- if (supported_enctypes & ENCTYPE_ARCFOUR_HMAC) { >+ if (supported_enctypes & ENC_RC4_HMAC_MD5) { > password_hash = &auth_array->array[i].AuthInfo.nt4owf.password; > num_keys += 1; > } >@@ -1085,7 +1085,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > goto out; > } > >- if (supported_enctypes & ENCTYPE_AES256_CTS_HMAC_SHA1_96) { >+ if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { > ret = krb5_string_to_key_data_salt(context, > ENCTYPE_AES256_CTS_HMAC_SHA1_96, > cleartext_data, >@@ -1100,7 +1100,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > entry_ex->entry.keys.len++; > } > >- if (supported_enctypes & ENCTYPE_AES128_CTS_HMAC_SHA1_96) { >+ if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { > ret = krb5_string_to_key_data_salt(context, > ENCTYPE_AES128_CTS_HMAC_SHA1_96, > cleartext_data, >-- >2.1.4 > > >From 8d329eefdf2d564cec00db23f979b82818c94dec Mon Sep 17 00:00:00 2001 >From: Garming Sam <garming@catalyst.net.nz> >Date: Tue, 16 Dec 2014 14:54:14 +1300 >Subject: [PATCH 06/60] test: improve kinit kerberos tests > >For enterprise and windows style kinit, a UPN is now configured. > >There are now additional smbclient calls and added cache removals >to make the tests more robust. > >Change-Id: I7c58ae4c9f303ca74a52878aa5dce2cc5f7d6742 >Pair-programmed-with: Andrew Bartlett <abartlet@samba.org> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 64f5984273fac19282fa1dd77c773840030a4ccb) >--- > testprogs/blackbox/test_kinit.sh | 44 ++++++++++++++++++++++++++++++++++------ > 1 file changed, 38 insertions(+), 6 deletions(-) > >diff --git a/testprogs/blackbox/test_kinit.sh b/testprogs/blackbox/test_kinit.sh >index 6ec1eaf..cc235c2 100755 >--- a/testprogs/blackbox/test_kinit.sh >+++ b/testprogs/blackbox/test_kinit.sh >@@ -71,16 +71,25 @@ enctype="-e $ENCTYPE" > PWSETCONFIG="-H ldap://$SERVER -U$USERNAME%$PASSWORD" > export PWSETCONFIG > >-KRB5CCNAME="$PREFIX/tmpccache" >+KRB5CCNAME_PATH="$PREFIX/tmpccache" >+KRB5CCNAME="FILE:$KRB5CCNAME_PATH" >+ADMIN_KRB5CCNAME="FILE:$KRB5CCNAME_PATH" > export KRB5CCNAME >+rm -rf $KRB5CCNAME_PATH > > testit "reset password policies beside of minimum password age of 0 days" $VALGRIND $samba_tool domain passwordsettings $PWSETCONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=0 --max-pwd-age=default || failed=`expr $failed + 1` > > echo $PASSWORD > $PREFIX/tmppassfile > #testit "kinit with keytab" $samba4kinit $enctype --keytab=$PREFIX/dc/private/secrets.keytab $SERVER\$@$REALM || failed=`expr $failed + 1` > testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $USERNAME@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >+ > testit "kinit with password (enterprise style)" $samba4kinit $enctype --enterprise --password-file=$PREFIX/tmppassfile --request-pac $USERNAME@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >+ > testit "kinit with password (windows style)" $samba4kinit $enctype --renewable --windows --password-file=$PREFIX/tmppassfile --request-pac $USERNAME@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >+ > testit "kinit renew ticket" $samba4kinit $enctype --request-pac -R > > test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >@@ -99,17 +108,21 @@ dn: cn=nettestuser,cn=users,$BASEDN > changetype: modify > add: servicePrincipalName > servicePrincipalName: host/nettestuser >+replace: userPrincipalName >+userPrincipalName: nettest@$REALM > EOF > >-testit "modify servicePrincipalName" $VALGRIND $ldbmodify -H ldap://$SERVER $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1` >+testit "modify servicePrincipalName and userPrincpalName" $VALGRIND $ldbmodify -H ldap://$SERVER $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1` > > testit "set user password with kerberos ccache" $VALGRIND $samba_tool user setpassword nettestuser --newpassword=$USERPASS $CONFIGURATION -k yes $@ || failed=`expr $failed + 1` > > testit "enable user with kerberos cache" $VALGRIND $enableaccount nettestuser -H ldap://$SERVER -k yes $@ || failed=`expr $failed + 1` > >-KRB5CCNAME="$PREFIX/tmpuserccache" >+KRB5CCNAME_PATH="$PREFIX/tmpuserccache" >+KRB5CCNAME="FILE:$KRB5CCNAME_PATH" > export KRB5CCNAME > >+rm -f $KRB5CCNAME_PATH > testit "kinit with user password" $samba4kinit $enctype --password-file=$PREFIX/tmpuserpassfile --request-pac nettestuser@$REALM || failed=`expr $failed + 1` > > test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >@@ -118,11 +131,25 @@ NEWUSERPASS=testPaSS@34% > testit "change user password with 'samba-tool user password' (rpc)" $VALGRIND $samba_tool user password -W$DOMAIN -Unettestuser%$USERPASS $CONFIGURATION -k no --newpassword=$NEWUSERPASS $@ || failed=`expr $failed + 1` > > echo $NEWUSERPASS > $PREFIX/tmpuserpassfile >+rm -f $KRB5CCNAME_PATH > testit "kinit with user password" $samba4kinit $enctype --password-file=$PREFIX/tmpuserpassfile --request-pac nettestuser@$REALM || failed=`expr $failed + 1` > > test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` > > >+rm -f $KRB5CCNAME_PATH >+testit "kinit with password (NT-Principal style) using UPN" $samba4kinit $enctype --password-file=$PREFIX/tmpuserpassfile --request-pac nettest@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache from enterprise UPN" 'ls' -k yes || failed=`expr $failed + 1` >+ >+rm -f $KRB5CCNAME_PATH >+testit "kinit with password (enterprise style) using UPN" $samba4kinit $enctype --enterprise --password-file=$PREFIX/tmpuserpassfile --request-pac nettest@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache from enterprise UPN" 'ls' -k yes || failed=`expr $failed + 1` >+ >+rm -f $KRB5CCNAME_PATH >+testit "kinit with password (windows style) using UPN" $samba4kinit $enctype --renewable --windows --password-file=$PREFIX/tmpuserpassfile --request-pac nettest@$REALM || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache from windows UPN" 'ls' -k yes || failed=`expr $failed + 1` >+ >+ > USERPASS=$NEWUSERPASS > NEWUSERPASS=testPaSS@56% > echo $NEWUSERPASS > $PREFIX/tmpuserpassfile >@@ -139,6 +166,7 @@ EOF > > testit "change user password with kpasswd" $texpect $PREFIX/tmpkpasswdscript $samba4kpasswd nettestuser@$REALM || failed=`expr $failed + 1` > >+rm -f $KRB5CCNAME_PATH > testit "kinit with user password" $samba4kinit $enctype --password-file=$PREFIX/tmpuserpassfile --request-pac nettestuser@$REALM || failed=`expr $failed + 1` > > NEWUSERPASS=testPaSS@78% >@@ -154,8 +182,9 @@ send ${NEWUSERPASS}\n > expect Success > EOF > >-testit "set user password with kpasswd" $texpect $PREFIX/tmpkpasswdscript $samba4kpasswd --cache=$PREFIX/tmpccache nettestuser@$REALM || failed=`expr $failed + 1` >+testit "set user password with kpasswd" $texpect $PREFIX/tmpkpasswdscript $samba4kpasswd --cache=$ADMIN_KRB5CCNAME nettestuser@$REALM || failed=`expr $failed + 1` > >+rm -f $KRB5CCNAME_PATH > testit "kinit with user password" $samba4kinit $enctype --password-file=$PREFIX/tmpuserpassfile --request-pac nettestuser@$REALM || failed=`expr $failed + 1` > > test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` >@@ -210,16 +239,19 @@ testit "kinit with user password" $samba4kinit $enctype --password-file=$PREFIX/ > > test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` > >-KRB5CCNAME="$PREFIX/tmpccache" >+KRB5CCNAME_PATH="$PREFIX/tmpccache" >+KRB5CCNAME="FILE:$KRB5CCNAME_PATH" > export KRB5CCNAME > >+rm -rf $KRB5CCNAME_PATH >+ > lowerrealm=$(echo $REALM | tr '[A-Z]' '[a-z]') > test_smbclient "Test login with user kerberos lowercase realm" 'ls' -k yes -Unettestuser@$lowerrealm%$NEWUSERPASS || failed=`expr $failed + 1` > test_smbclient "Test login with user kerberos lowercase realm 2" 'ls' -k yes -Unettestuser@$REALM%$NEWUSERPASS --realm=$lowerrealm || failed=`expr $failed + 1` > > testit "del user with kerberos ccache" $VALGRIND $samba_tool user delete nettestuser $CONFIGURATION -k yes $@ || failed=`expr $failed + 1` > >-rm -f $KRB5CCNAME >+rm -f $KRB5CCNAME_PATH > testit "kinit with machineaccountccache script" $machineaccountccache $CONFIGURATION $KRB5CCNAME || failed=`expr $failed + 1` > test_smbclient "Test machine account login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` > >-- >2.1.4 > > >From 6c02b27098855471a3875e2a152afa47f2018eeb Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 5 Jan 2015 14:54:45 +1300 >Subject: [PATCH 07/60] torture: Start a new testsuite for krb5 and KDC > behaviour > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 9a0aa6f6f7217399eaac34aa8ac82b49d953175a) >--- > source4/auth/kerberos/krb5_init_context.c | 123 +++++++++++++++++++++--------- > source4/auth/kerberos/krb5_init_context.h | 6 ++ > source4/selftest/tests.py | 4 + > source4/torture/krb5/kdc.c | 118 ++++++++++++++++++++++++++++ > source4/torture/krb5/wscript_build | 11 +++ > source4/torture/wscript_build | 1 + > 6 files changed, 226 insertions(+), 37 deletions(-) > create mode 100644 source4/torture/krb5/kdc.c > create mode 100644 source4/torture/krb5/wscript_build > >diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c >index 4404b67..e8a1a6c 100644 >--- a/source4/auth/kerberos/krb5_init_context.c >+++ b/source4/auth/kerberos/krb5_init_context.c >@@ -210,46 +210,31 @@ static void smb_krb5_socket_handler(struct tevent_context *ev, struct tevent_fd > } > } > >-krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, >- void *data, >- krb5_krbhst_info *hi, >- time_t timeout, >- const krb5_data *send_buf, >- krb5_data *recv_buf) >+static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, >+ struct tevent_context *ev, >+ krb5_krbhst_info *hi, >+ struct addrinfo *ai, >+ krb5_send_to_kdc_func func, >+ void *data, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf) > { > krb5_error_code ret; > NTSTATUS status; > const char *name; >- struct addrinfo *ai, *a; >+ struct addrinfo *a; > struct smb_krb5_socket *smb_krb5; > > DATA_BLOB send_blob; > >- struct tevent_context *ev; > TALLOC_CTX *tmp_ctx = talloc_new(NULL); > if (!tmp_ctx) { > return ENOMEM; > } > >- if (!data) { >- /* If no event context was available, then create one for this loop */ >- ev = samba_tevent_context_init(tmp_ctx); >- if (!ev) { >- talloc_free(tmp_ctx); >- return ENOMEM; >- } >- } else { >- ev = talloc_get_type_abort(data, struct tevent_context); >- } >- > send_blob = data_blob_const(send_buf->data, send_buf->length); > >- ret = krb5_krbhst_get_addrinfo(context, hi, &ai); >- if (ret) { >- talloc_free(tmp_ctx); >- return ret; >- } >- > for (a = ai; a; a = a->ai_next) { > struct socket_address *remote_addr; > smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket); >@@ -359,18 +344,20 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, > return EINVAL; > } > >- /* After each and every event loop, reset the >- * send_to_kdc pointers to what they were when >- * we entered this loop. That way, if a >- * nested event has invalidated them, we put >- * it back before we return to the heimdal >- * code */ >- ret = krb5_set_send_to_kdc_func(context, >- smb_krb5_send_and_recv_func, >- data); >- if (ret != 0) { >- talloc_free(tmp_ctx); >- return ret; >+ if (func) { >+ /* After each and every event loop, reset the >+ * send_to_kdc pointers to what they were when >+ * we entered this loop. That way, if a >+ * nested event has invalidated them, we put >+ * it back before we return to the heimdal >+ * code */ >+ ret = krb5_set_send_to_kdc_func(context, >+ func, >+ data); >+ if (ret != 0) { >+ talloc_free(tmp_ctx); >+ return ret; >+ } > } > } > if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) { >@@ -407,6 +394,68 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, > } > return KRB5_KDC_UNREACH; > } >+ >+krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, >+ void *data, >+ krb5_krbhst_info *hi, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf) >+{ >+ krb5_error_code ret; >+ struct addrinfo *ai; >+ >+ struct tevent_context *ev; >+ TALLOC_CTX *tmp_ctx = talloc_new(NULL); >+ if (!tmp_ctx) { >+ return ENOMEM; >+ } >+ >+ if (!data) { >+ /* If no event context was available, then create one for this loop */ >+ ev = samba_tevent_context_init(tmp_ctx); >+ if (!ev) { >+ talloc_free(tmp_ctx); >+ return ENOMEM; >+ } >+ } else { >+ ev = talloc_get_type_abort(data, struct tevent_context); >+ } >+ >+ ret = krb5_krbhst_get_addrinfo(context, hi, &ai); >+ if (ret) { >+ talloc_free(tmp_ctx); >+ return ret; >+ } >+ return smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf); >+} >+ >+krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, >+ void *data, /* struct addrinfo */ >+ krb5_krbhst_info *hi, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf) >+{ >+ struct addrinfo *ai = data; >+ >+ struct tevent_context *ev; >+ TALLOC_CTX *tmp_ctx = talloc_new(NULL); >+ if (!tmp_ctx) { >+ return ENOMEM; >+ } >+ >+ /* If no event context was available, then create one for this loop */ >+ ev = samba_tevent_context_init(tmp_ctx); >+ if (!ev) { >+ talloc_free(tmp_ctx); >+ return ENOMEM; >+ } >+ >+ /* No need to pass in send_and_recv functions, we won't nest on this private event loop */ >+ return smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL, >+ timeout, send_buf, recv_buf); >+} > #endif > > krb5_error_code >diff --git a/source4/auth/kerberos/krb5_init_context.h b/source4/auth/kerberos/krb5_init_context.h >index 3c32069..6c997c5 100644 >--- a/source4/auth/kerberos/krb5_init_context.h >+++ b/source4/auth/kerberos/krb5_init_context.h >@@ -45,6 +45,12 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, > time_t timeout, > const krb5_data *send_buf, > krb5_data *recv_buf); >+krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, >+ void *data, /* struct addrinfo */ >+ krb5_krbhst_info *hi, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf); > krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context, > struct tevent_context *ev, > struct tevent_context **previous_ev); >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 8d03b40..1b54d25 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -546,6 +546,10 @@ for env in ['vampire_dc', 'promoted_dc']: > for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"]: > plantestsuite("samba.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) > >+for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc"]: >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN']) >+ >+ > # TODO: Verifying the databases really should be a part of the > # environment teardown. > # check the databases are all OK. PLEASE LEAVE THIS AS THE LAST TEST >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >new file mode 100644 >index 0000000..9dcee40 >--- /dev/null >+++ b/source4/torture/krb5/kdc.c >@@ -0,0 +1,118 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ Validate the krb5 pac generation routines >+ >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2015 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+#include "system/kerberos.h" >+#include "torture/smbtorture.h" >+#include "torture/winbind/proto.h" >+#include "auth/credentials/credentials.h" >+#include "lib/cmdline/popt_common.h" >+#include "source4/auth/kerberos/kerberos.h" >+#include "source4/auth/kerberos/kerberos_util.h" >+#include "lib/util/util_net.h" >+ >+static bool torture_krb5_init_context(struct torture_context *tctx, >+ struct smb_krb5_context **smb_krb5_context) >+{ >+ const char *host = torture_setting_string(tctx, "host", NULL); >+ krb5_error_code k5ret; >+ bool ok; >+ struct addrinfo *server; >+ >+ k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context); >+ torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed"); >+ >+ ok = interpret_string_addr_internal(&server, host, AI_NUMERICHOST); >+ torture_assert(tctx, ok, "Failed to parse target server"); >+ >+ set_sockaddr_port(server->ai_addr, 88); >+ >+ k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, >+ smb_krb5_send_and_recv_func_forced, >+ server); >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed"); >+ return true; >+} >+ >+static bool torture_krb5_as_req_1(struct torture_context *tctx) >+{ >+ krb5_error_code k5ret; >+ bool ok; >+ krb5_creds my_creds; >+ krb5_principal principal; >+ struct smb_krb5_context *smb_krb5_context; >+ enum credentials_obtained obtained; >+ const char *error_string; >+ const char *password = cli_credentials_get_password(cmdline_credentials); >+ >+ ok = torture_krb5_init_context(tctx, &smb_krb5_context); >+ torture_assert(tctx, ok, "torture_krb5_init_context failed"); >+ >+ k5ret = principal_from_credentials(tctx, cmdline_credentials, smb_krb5_context, &principal, &obtained, &error_string); >+ torture_assert_int_equal(tctx, k5ret, 0, error_string); >+ >+ k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, >+ password, NULL, NULL, 0, >+ NULL, NULL); >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(smb_krb5_context->krb5_context, >+ my_creds.client), KRB5_NT_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ >+ torture_assert(tctx, krb5_principal_compare(smb_krb5_context->krb5_context, >+ principal, my_creds.client), >+ "krb5_get_init_creds_password returned a different principal"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(smb_krb5_context->krb5_context, >+ my_creds.server), KRB5_NT_SRV_INST, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ >+ torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >+ my_creds.server, 0), >+ "krbtgt", >+ "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]"); >+ >+ k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds); >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed"); >+ >+ return true; >+} >+ >+NTSTATUS torture_krb5_init(void); >+NTSTATUS torture_krb5_init(void) >+{ >+ struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "krb5"); >+ struct torture_suite *kdc_suite = torture_suite_create(suite, "kdc"); >+ suite->description = talloc_strdup(suite, "Kerberos tests"); >+ kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests"); >+ >+ torture_suite_add_simple_test(kdc_suite, "as-req-1", >+ torture_krb5_as_req_1); >+ >+ torture_suite_add_suite(suite, kdc_suite); >+ >+ torture_register_suite(suite); >+ return NT_STATUS_OK; >+} >diff --git a/source4/torture/krb5/wscript_build b/source4/torture/krb5/wscript_build >new file mode 100644 >index 0000000..963c3a3 >--- /dev/null >+++ b/source4/torture/krb5/wscript_build >@@ -0,0 +1,11 @@ >+#!/usr/bin/env python >+if bld.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): >+ bld.SAMBA_MODULE('TORTURE_KRB5', >+ source='kdc.c', >+ autoproto='proto.h', >+ subsystem='smbtorture', >+ init_function='torture_krb5_init', >+ deps='authkrb5 popt POPT_CREDENTIALS torture KERBEROS_UTIL', >+ internal_module=True >+ ) >+ >diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build >index c13e7d4..0ef2c23 100755 >--- a/source4/torture/wscript_build >+++ b/source4/torture/wscript_build >@@ -90,6 +90,7 @@ bld.SAMBA_MODULE('TORTURE_AUTH', > ) > > bld.RECURSE('local') >+bld.RECURSE('krb5') > > bld.SAMBA_MODULE('TORTURE_NBENCH', > source='nbench/nbio.c nbench/nbench.c', >-- >2.1.4 > > >From c2ecdf083d72bd49d1490444bb529b789086e10f Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 5 Jan 2015 16:07:42 +1300 >Subject: [PATCH 08/60] torture: Run new testsuite for krb5 and KDC behaviour > with machine account also > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 378bb04835a377699a8ff254c0ec633ac63a41de) >--- > source4/selftest/tests.py | 5 ++++- > source4/torture/krb5/kdc.c | 16 +++++++++++----- > 2 files changed, 15 insertions(+), 6 deletions(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 1b54d25..cf44dc5 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -547,7 +547,10 @@ for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"] > plantestsuite("samba.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) > > for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc"]: >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN']) >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ "samba4.krb5.kdc with specified account") >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER', "-k", "yes", '-P', '--workgroup=$DOMAIN'], >+ "samba4.krb5.kdc with machine account") > > > # TODO: Verifying the databases really should be a part of the >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index 9dcee40..c9014cf 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -53,7 +53,8 @@ static bool torture_krb5_init_context(struct torture_context *tctx, > return true; > } > >-static bool torture_krb5_as_req_1(struct torture_context *tctx) >+static bool torture_krb5_as_req_creds(struct torture_context *tctx, >+ struct cli_credentials *credentials) > { > krb5_error_code k5ret; > bool ok; >@@ -62,12 +63,12 @@ static bool torture_krb5_as_req_1(struct torture_context *tctx) > struct smb_krb5_context *smb_krb5_context; > enum credentials_obtained obtained; > const char *error_string; >- const char *password = cli_credentials_get_password(cmdline_credentials); >+ const char *password = cli_credentials_get_password(credentials); > > ok = torture_krb5_init_context(tctx, &smb_krb5_context); > torture_assert(tctx, ok, "torture_krb5_init_context failed"); > >- k5ret = principal_from_credentials(tctx, cmdline_credentials, smb_krb5_context, &principal, &obtained, &error_string); >+ k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context, &principal, &obtained, &error_string); > torture_assert_int_equal(tctx, k5ret, 0, error_string); > > k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, >@@ -100,6 +101,11 @@ static bool torture_krb5_as_req_1(struct torture_context *tctx) > return true; > } > >+static bool torture_krb5_as_req_cmdline(struct torture_context *tctx) >+{ >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials); >+} >+ > NTSTATUS torture_krb5_init(void); > NTSTATUS torture_krb5_init(void) > { >@@ -108,8 +114,8 @@ NTSTATUS torture_krb5_init(void) > suite->description = talloc_strdup(suite, "Kerberos tests"); > kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests"); > >- torture_suite_add_simple_test(kdc_suite, "as-req-1", >- torture_krb5_as_req_1); >+ torture_suite_add_simple_test(kdc_suite, "as-req-cmdline", >+ torture_krb5_as_req_cmdline); > > torture_suite_add_suite(suite, kdc_suite); > >-- >2.1.4 > > >From 5d66ea1d9b000aa283fd8f91a4474f6aebe5b05d Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 5 Jan 2015 16:32:23 +1300 >Subject: [PATCH 09/60] torture: Additionally run testsuite for krb5 and KDC > behaviour with unprivileged accounts > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit ff240c84e471fb6e83f663fef6b0ec7f257832e2) >--- > selftest/target/Samba4.pm | 21 +++++++++++++++++++++ > source4/selftest/tests.py | 4 ++++ > 2 files changed, 25 insertions(+) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 342de58..568d27a 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -773,6 +773,27 @@ sub provision_raw_step2($$$) > return undef; > } > >+ my $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") >+ . " user add --configfile=$ctx->{smb_conf} testallowed $ctx->{password}"; >+ unless (system($samba_tool_cmd) == 0) { >+ warn("Unable to add testallowed user: \n$samba_tool_cmd\n"); >+ return undef; >+ } >+ >+ $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") >+ . " user add --configfile=$ctx->{smb_conf} testdenied $ctx->{password}"; >+ unless (system($samba_tool_cmd) == 0) { >+ warn("Unable to add testdenied user: \n$samba_tool_cmd\n"); >+ return undef; >+ } >+ >+ $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") >+ . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' testallowed"; >+ unless (system($samba_tool_cmd) == 0) { >+ warn("Unable to add testallowed user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n"); >+ return undef; >+ } >+ > return $ret; > } > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index cf44dc5..d1b7bfd 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -549,6 +549,10 @@ for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"] > for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc"]: > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with specified account") >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-Utestdenied@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") > plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER', "-k", "yes", '-P', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with machine account") > >-- >2.1.4 > > >From 2716687484aae7da179702ebf19767edb27ede5c Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 5 Jan 2015 16:48:08 +1300 >Subject: [PATCH 10/60] torture: Additionally run testsuite for krb5 and KDC > behaviour against all the DC envs > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit fc84d35c4eaf50ca8139b1210201be12d89a0b3e) >--- > source4/selftest/tests.py | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index d1b7bfd..3b849f8 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -546,14 +546,14 @@ for env in ['vampire_dc', 'promoted_dc']: > for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"]: > plantestsuite("samba.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) > >-for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc"]: >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with specified account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER', "-k", "yes", '-Utestdenied@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") >- plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER', "-k", "yes", '-P', '--workgroup=$DOMAIN'], >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with machine account") > > >-- >2.1.4 > > >From aec9c6e7d81089fc7c882c74754875e088eed3a4 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 5 Jan 2015 17:48:50 +1300 >Subject: [PATCH 11/60] torture: Decode expected packets and test KDC behaviour > for wrong passwords > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 672ade3876877ad30e4367f0cd01e660b0def8cd) >--- > source4/torture/krb5/kdc.c | 173 ++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 164 insertions(+), 9 deletions(-) > >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index c9014cf..c9a1a60 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -30,31 +30,170 @@ > #include "source4/auth/kerberos/kerberos_util.h" > #include "lib/util/util_net.h" > >+enum torture_krb5_test { >+ TORTURE_KRB5_TEST_PLAIN, >+ TORTURE_KRB5_TEST_BREAK_PW >+}; >+ >+struct torture_krb5_context { >+ struct torture_context *tctx; >+ struct addrinfo *server; >+ enum torture_krb5_test test; >+ int packet_count; >+ AS_REQ as_req; >+ AS_REP as_rep; >+}; >+ >+static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf) >+{ >+ size_t used; >+ switch (test_context->test) >+ { >+ case TORTURE_KRB5_TEST_PLAIN: >+ case TORTURE_KRB5_TEST_BREAK_PW: >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0, >+ "decode_AS_REQ failed"); >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno"); >+ break; >+ } >+ return true; >+} >+ >+static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ KRB_ERROR error; >+ size_t used; >+ switch (test_context->test) >+ { >+ case TORTURE_KRB5_TEST_PLAIN: >+ if (test_context->packet_count == 0) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) >+ && (test_context->packet_count == 1)) { >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno"); >+ free_AS_REP(&test_context->as_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ break; >+ case TORTURE_KRB5_TEST_BREAK_PW: >+ if (test_context->packet_count == 0) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if (test_context->packet_count == 1) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_FAILED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ break; >+ } >+ return true; >+} >+ >+static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context, >+ void *data, /* struct torture_krb5_context */ >+ krb5_krbhst_info *hi, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf) >+{ >+ krb5_error_code k5ret; >+ bool ok; >+ >+ struct torture_krb5_context *test_context >+ = talloc_get_type_abort(data, struct torture_krb5_context); >+ >+ ok = torture_krb5_pre_send_test(test_context, send_buf); >+ if (ok == false) { >+ return EINVAL; >+ } >+ >+ k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, >+ hi, timeout, send_buf, recv_buf); >+ >+ ok = torture_krb5_post_recv_test(test_context, recv_buf); >+ if (ok == false) { >+ return EINVAL; >+ } >+ >+ test_context->packet_count++; >+ >+ return k5ret; >+} >+ >+static int test_context_destructor(struct torture_krb5_context *test_context) >+{ >+ freeaddrinfo(test_context->server); >+ return 0; >+} >+ >+ > static bool torture_krb5_init_context(struct torture_context *tctx, >+ enum torture_krb5_test test, > struct smb_krb5_context **smb_krb5_context) > { > const char *host = torture_setting_string(tctx, "host", NULL); > krb5_error_code k5ret; > bool ok; >- struct addrinfo *server; >+ >+ struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context); >+ torture_assert(tctx, test_context != NULL, "Failed to allocate"); >+ >+ test_context->test = test; >+ test_context->tctx = tctx; > > k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context); > torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed"); > >- ok = interpret_string_addr_internal(&server, host, AI_NUMERICHOST); >+ ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST); > torture_assert(tctx, ok, "Failed to parse target server"); > >- set_sockaddr_port(server->ai_addr, 88); >+ talloc_set_destructor(test_context, test_context_destructor); >+ >+ set_sockaddr_port(test_context->server->ai_addr, 88); > > k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, >- smb_krb5_send_and_recv_func_forced, >- server); >+ smb_krb5_send_and_recv_func_override, >+ test_context); > torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed"); > return true; > } > > static bool torture_krb5_as_req_creds(struct torture_context *tctx, >- struct cli_credentials *credentials) >+ struct cli_credentials *credentials, >+ enum torture_krb5_test test) > { > krb5_error_code k5ret; > bool ok; >@@ -65,16 +204,24 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > const char *error_string; > const char *password = cli_credentials_get_password(credentials); > >- ok = torture_krb5_init_context(tctx, &smb_krb5_context); >+ ok = torture_krb5_init_context(tctx, test, &smb_krb5_context); > torture_assert(tctx, ok, "torture_krb5_init_context failed"); > > k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context, &principal, &obtained, &error_string); > torture_assert_int_equal(tctx, k5ret, 0, error_string); > >+ if (test == TORTURE_KRB5_TEST_BREAK_PW) { >+ password = "NOT the password"; >+ } > k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, > password, NULL, NULL, 0, > NULL, NULL); >- torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); >+ if (test == TORTURE_KRB5_TEST_BREAK_PW) { >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed"); >+ return true; >+ } else { >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); >+ } > > torture_assert_int_equal(tctx, > krb5_principal_get_type(smb_krb5_context->krb5_context, >@@ -103,7 +250,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > > static bool torture_krb5_as_req_cmdline(struct torture_context *tctx) > { >- return torture_krb5_as_req_creds(tctx, cmdline_credentials); >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PLAIN); >+} >+ >+static bool torture_krb5_as_req_break_pw(struct torture_context *tctx) >+{ >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_BREAK_PW); > } > > NTSTATUS torture_krb5_init(void); >@@ -117,6 +269,9 @@ NTSTATUS torture_krb5_init(void) > torture_suite_add_simple_test(kdc_suite, "as-req-cmdline", > torture_krb5_as_req_cmdline); > >+ torture_suite_add_simple_test(kdc_suite, "as-req-break-pw", >+ torture_krb5_as_req_break_pw); >+ > torture_suite_add_suite(suite, kdc_suite); > > torture_register_suite(suite); >-- >2.1.4 > > >From 4fd2e7cccaf12f5f9f515fc6243c71089cc776b0 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 6 Jan 2015 13:24:04 +1300 >Subject: [PATCH 12/60] torture: Extend KDC test to cover more options and > modes > >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit a07598db9cefcad4accd9e189c748a5bed630cf6) >--- > selftest/knownfail | 4 ++ > source4/torture/krb5/kdc.c | 154 ++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 151 insertions(+), 7 deletions(-) > >diff --git a/selftest/knownfail b/selftest/knownfail >index af7e7fd..5fc05a0 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -296,3 +296,7 @@ > ^samba.blackbox.wbinfo\(s3member:local\).wbinfo -G check for sane mapping\(s3member:local\) > ^samba.ntlm_auth.\(dc:local\).ntlm_auth against winbindd with failed require-membership-of > ^samba.ntlm_auth.\(dc:local\).ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server against winbind with failed require-membership-of >+# >+# Differences in our KDC compared to windows >+# >+^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally >\ No newline at end of file >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index c9a1a60..edf1ecd 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -32,7 +32,10 @@ > > enum torture_krb5_test { > TORTURE_KRB5_TEST_PLAIN, >- TORTURE_KRB5_TEST_BREAK_PW >+ TORTURE_KRB5_TEST_WIN2K, >+ TORTURE_KRB5_TEST_PAC_REQUEST, >+ TORTURE_KRB5_TEST_BREAK_PW, >+ TORTURE_KRB5_TEST_CLOCK_SKEW, > }; > > struct torture_krb5_context { >@@ -50,7 +53,10 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > switch (test_context->test) > { > case TORTURE_KRB5_TEST_PLAIN: >+ case TORTURE_KRB5_TEST_WIN2K: >+ case TORTURE_KRB5_TEST_PAC_REQUEST: > case TORTURE_KRB5_TEST_BREAK_PW: >+ case TORTURE_KRB5_TEST_CLOCK_SKEW: > torture_assert_int_equal(test_context->tctx, > decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0, > "decode_AS_REQ failed"); >@@ -68,6 +74,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > switch (test_context->test) > { > case TORTURE_KRB5_TEST_PLAIN: >+ case TORTURE_KRB5_TEST_WIN2K: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, > decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >@@ -95,6 +102,43 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); > free_AS_REQ(&test_context->as_req); > break; >+ case TORTURE_KRB5_TEST_PAC_REQUEST: >+ if (test_context->packet_count == 0) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if (test_context->packet_count == 1) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) >+ && (test_context->packet_count == 2)) { >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno"); >+ free_AS_REP(&test_context->as_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ break; > case TORTURE_KRB5_TEST_BREAK_PW: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, >@@ -118,6 +162,29 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); > free_AS_REQ(&test_context->as_req); > break; >+ case TORTURE_KRB5_TEST_CLOCK_SKEW: >+ if (test_context->packet_count == 0) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if (test_context->packet_count == 1) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_AP_ERR_SKEW - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ break; > } > return true; > } >@@ -203,24 +270,73 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > enum credentials_obtained obtained; > const char *error_string; > const char *password = cli_credentials_get_password(credentials); >+ krb5_get_init_creds_opt *krb_options = NULL; > > ok = torture_krb5_init_context(tctx, test, &smb_krb5_context); > torture_assert(tctx, ok, "torture_krb5_init_context failed"); > >- k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context, &principal, &obtained, &error_string); >+ k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context, >+ &principal, &obtained, &error_string); > torture_assert_int_equal(tctx, k5ret, 0, error_string); > >- if (test == TORTURE_KRB5_TEST_BREAK_PW) { >+ switch (test) >+ { >+ case TORTURE_KRB5_TEST_PLAIN: >+ break; >+ >+ case TORTURE_KRB5_TEST_WIN2K: >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >+ 0, "krb5_get_init_creds_opt_alloc failed"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, krb_options, true), >+ 0, "krb5_get_init_creds_opt_set_win2k failed"); >+ break; >+ >+ case TORTURE_KRB5_TEST_PAC_REQUEST: >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >+ 0, "krb5_get_init_creds_opt_alloc failed"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context, krb_options, true), >+ 0, "krb5_get_init_creds_opt_set_pac_request failed"); >+ break; >+ >+ case TORTURE_KRB5_TEST_BREAK_PW: > password = "NOT the password"; >+ break; >+ >+ case TORTURE_KRB5_TEST_CLOCK_SKEW: >+ torture_assert_int_equal(tctx, >+ krb5_set_real_time(smb_krb5_context->krb5_context, time(NULL) + 3600, 0), >+ 0, "krb5_set_real_time failed"); >+ break; >+ >+ break; > } > k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, > password, NULL, NULL, 0, >- NULL, NULL); >- if (test == TORTURE_KRB5_TEST_BREAK_PW) { >+ NULL, krb_options); >+ krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); >+ >+ switch (test) >+ { >+ case TORTURE_KRB5_TEST_PLAIN: >+ case TORTURE_KRB5_TEST_WIN2K: >+ case TORTURE_KRB5_TEST_PAC_REQUEST: >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); >+ break; >+ >+ case TORTURE_KRB5_TEST_BREAK_PW: > torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed"); > return true; >- } else { >- torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); >+ >+ case TORTURE_KRB5_TEST_CLOCK_SKEW: >+ torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_SKEW, "krb5_get_init_creds_password should have failed"); >+ return true; >+ > } > > torture_assert_int_equal(tctx, >@@ -253,11 +369,26 @@ static bool torture_krb5_as_req_cmdline(struct torture_context *tctx) > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PLAIN); > } > >+static bool torture_krb5_as_req_win2k(struct torture_context *tctx) >+{ >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_WIN2K); >+} >+ >+static bool torture_krb5_as_req_pac_request(struct torture_context *tctx) >+{ >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PAC_REQUEST); >+} >+ > static bool torture_krb5_as_req_break_pw(struct torture_context *tctx) > { > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_BREAK_PW); > } > >+static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx) >+{ >+ return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_CLOCK_SKEW); >+} >+ > NTSTATUS torture_krb5_init(void); > NTSTATUS torture_krb5_init(void) > { >@@ -269,9 +400,18 @@ NTSTATUS torture_krb5_init(void) > torture_suite_add_simple_test(kdc_suite, "as-req-cmdline", > torture_krb5_as_req_cmdline); > >+ torture_suite_add_simple_test(kdc_suite, "as-req-win2k", >+ torture_krb5_as_req_win2k); >+ >+ torture_suite_add_simple_test(kdc_suite, "as-req-pac-request", >+ torture_krb5_as_req_pac_request); >+ > torture_suite_add_simple_test(kdc_suite, "as-req-break-pw", > torture_krb5_as_req_break_pw); > >+ torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew", >+ torture_krb5_as_req_clock_skew); >+ > torture_suite_add_suite(suite, kdc_suite); > > torture_register_suite(suite); >-- >2.1.4 > > >From d6c7df3ecf41cde4a2f903424b4461731c59cbe5 Mon Sep 17 00:00:00 2001 >From: Nicolas Williams <nico@cryptonector.com> >Date: Wed, 17 Dec 2014 16:55:34 +1300 >Subject: [PATCH 13/60] heimdal: Fix bug in KDC handling of enterprise > principals > >The useful change in Samba from this commit is that we gain >validation of the enterprise principal name. > >(commit message by Andrew Bartlett) > >Cherry-pick of Heimdal commit c76ec8ec6a507a6f34ca80c11e5297146acff83f > >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit fe99c420b21933e0dc11a5c4193e9af4cbfc574e) >--- > source4/heimdal/kdc/misc.c | 73 ++++++++++++++++++++++++---------------------- > 1 file changed, 38 insertions(+), 35 deletions(-) > >diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c >index 1b2c440..749c67c 100644 >--- a/source4/heimdal/kdc/misc.c >+++ b/source4/heimdal/kdc/misc.c >@@ -48,41 +48,36 @@ _kdc_db_fetch(krb5_context context, > krb5_error_code ret = HDB_ERR_NOENTRY; > int i; > unsigned kvno = 0; >+ krb5_principal enterprise_principal = NULL; >+ krb5_const_principal princ; >+ >+ *h = NULL; > > if (kvno_ptr) { > kvno = *kvno_ptr; > flags |= HDB_F_KVNO_SPECIFIED; > } > >- ent = calloc (1, sizeof (*ent)); >- if (ent == NULL) { >- krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); >- return ENOMEM; >+ ent = calloc(1, sizeof (*ent)); >+ if (ent == NULL) >+ return krb5_enomem(context); >+ >+ if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ if (principal->name.name_string.len != 1) { >+ ret = KRB5_PARSE_MALFORMED; >+ krb5_set_error_message(context, ret, >+ "malformed request: " >+ "enterprise name with %d name components", >+ principal->name.name_string.len); >+ goto out; >+ } >+ ret = krb5_parse_name(context, principal->name.name_string.val[0], >+ &enterprise_principal); >+ if (ret) >+ goto out; > } > >- for(i = 0; i < config->num_db; i++) { >- krb5_principal enterprise_principal = NULL; >- if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) >- && principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >- if (principal->name.name_string.len != 1) { >- ret = KRB5_PARSE_MALFORMED; >- krb5_set_error_message(context, ret, >- "malformed request: " >- "enterprise name with %d name components", >- principal->name.name_string.len); >- free(ent); >- return ret; >- } >- ret = krb5_parse_name(context, principal->name.name_string.val[0], >- &enterprise_principal); >- if (ret) { >- free(ent); >- return ret; >- } >- >- principal = enterprise_principal; >- } >- >+ for (i = 0; i < config->num_db; i++) { > ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0); > if (ret) { > const char *msg = krb5_get_error_message(context, ret); >@@ -91,26 +86,34 @@ _kdc_db_fetch(krb5_context context, > continue; > } > >+ if (config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) >+ princ = principal; >+ else if (enterprise_principal) >+ princ = enterprise_principal; >+ > ret = config->db[i]->hdb_fetch_kvno(context, > config->db[i], >- principal, >+ princ, > flags | HDB_F_DECRYPT, > kvno, > ent); >- >- krb5_free_principal(context, enterprise_principal); >- > config->db[i]->hdb_close(context, config->db[i]); >- if(ret == 0) { >+ >+ if (ret == 0) { > if (db) > *db = config->db[i]; > *h = ent; >- return 0; >+ ent = NULL; >+ goto out; > } > } >+ >+ ret = HDB_ERR_NOENTRY; >+ krb5_set_error_message(context, ret, "no such entry found in hdb"); >+ >+out: >+ krb5_free_principal(context, enterprise_principal); > free(ent); >- krb5_set_error_message(context, ret, >- "no such entry found in hdb"); > return ret; > } > >-- >2.1.4 > > >From bee970edf66d4374f837c6f534ceff264b314a2a Mon Sep 17 00:00:00 2001 >From: Nicolas Williams <nico@cryptonector.com> >Date: Wed, 17 Dec 2014 16:57:40 +1300 >Subject: [PATCH 14/60] heimdal: Really bug in KDC handling of enterprise > princs > >The value of this commit to Samba is to continue to match Heimdal's >upstream code in this area. Because we set HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL >there is no runtime difference. > >(commit message by Andrew Bartlett) > >Cherry-pick of Heimdal commit 9aa7883ff2efb3e0a60016c9090c577acfd0779f > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit da4ac71eaba84fa6227b7d9f3adb204003ceaa70) >--- > source4/heimdal/kdc/misc.c | 5 ++--- > 1 file changed, 2 insertions(+), 3 deletions(-) > >diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c >index 749c67c..869c676 100644 >--- a/source4/heimdal/kdc/misc.c >+++ b/source4/heimdal/kdc/misc.c >@@ -86,9 +86,8 @@ _kdc_db_fetch(krb5_context context, > continue; > } > >- if (config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) >- princ = principal; >- else if (enterprise_principal) >+ princ = principal; >+ if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) && enterprise_principal) > princ = enterprise_principal; > > ret = config->db[i]->hdb_fetch_kvno(context, >-- >2.1.4 > > >From ea85322e42e7c262bccb8dca113ec3947c0c60d5 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 21 Jan 2015 11:45:45 +1300 >Subject: [PATCH 15/60] heimdal: Ensure that HDB_ERR_NOT_FOUND_HERE, critical > for the RODC, is not overwritten > >This change ensures that our RODC will correctly proxy when asked to provide >a ticket for a service or user where the keys are not on this RODC. > >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 891c4c6a403cc0904c37caaf500bb3a4e3a646c7) >--- > source4/heimdal/kdc/misc.c | 23 +++++++++++++++++++---- > 1 file changed, 19 insertions(+), 4 deletions(-) > >diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c >index 869c676..4ef5439 100644 >--- a/source4/heimdal/kdc/misc.c >+++ b/source4/heimdal/kdc/misc.c >@@ -98,18 +98,33 @@ _kdc_db_fetch(krb5_context context, > ent); > config->db[i]->hdb_close(context, config->db[i]); > >- if (ret == 0) { >+ switch (ret) { >+ case 0: > if (db) > *db = config->db[i]; > *h = ent; > ent = NULL; > goto out; >+ >+ case HDB_ERR_NOENTRY: >+ /* Check the other databases */ >+ continue; >+ >+ default: >+ /* >+ * This is really important, because errors like >+ * HDB_ERR_NOT_FOUND_HERE (used to indicate to Samba that >+ * the RODC on which this code is running does not have >+ * the key we need, and so a proxy to the KDC is required) >+ * have specific meaning, and need to be propogated up. >+ */ >+ goto out; > } > } > >- ret = HDB_ERR_NOENTRY; >- krb5_set_error_message(context, ret, "no such entry found in hdb"); >- >+ if (ret == HDB_ERR_NOENTRY) { >+ krb5_set_error_message(context, ret, "no such entry found in hdb"); >+ } > out: > krb5_free_principal(context, enterprise_principal); > free(ent); >-- >2.1.4 > > >From 758bed64ce36e2e9ade0793f346c2665edbe3e70 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 17 Dec 2014 17:02:53 +1300 >Subject: [PATCH 16/60] kdc: Fix enterpise principal name handling > >Based on a patch by Samuel Cabrero <scabrero@zentyal.com> > >This ensures we write the correct (implict, samAccountName) based UPN into >the ticket, rather than the userPrincipalName, which will have a different >realm. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 86021a081fa7973d00ac3665296ffcfc9e834fb0) >--- > source4/kdc/db-glue.c | 33 +++++++++++++++++++++++---------- > source4/kdc/hdb-samba4.c | 2 +- > 2 files changed, 24 insertions(+), 11 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index 37e2f9e..fae2703 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -628,6 +628,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); > if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { > krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >+ } else if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); > } else { > ret = copy_Principal(principal, entry_ex->entry.principal); > if (ret) { >@@ -1216,18 +1218,29 @@ static krb5_error_code samba_kdc_lookup_client(krb5_context context, > struct ldb_message **msg) { > NTSTATUS nt_status; > char *principal_string; >- krb5_error_code ret; > >- ret = krb5_unparse_name(context, principal, &principal_string); >- >- if (ret != 0) { >- return ret; >+ if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ principal_string = smb_krb5_principal_get_comp_string(mem_ctx, context, >+ principal, 0); >+ if (principal_string == NULL) { >+ return ENOMEM; >+ } >+ nt_status = sam_get_results_principal(kdc_db_ctx->samdb, >+ mem_ctx, principal_string, attrs, >+ realm_dn, msg); >+ TALLOC_FREE(principal_string); >+ } else { >+ krb5_error_code ret; >+ ret = krb5_unparse_name(context, principal, &principal_string); >+ if (ret != 0) { >+ return ret; >+ } >+ nt_status = sam_get_results_principal(kdc_db_ctx->samdb, >+ mem_ctx, principal_string, attrs, >+ realm_dn, msg); >+ free(principal_string); > } > >- nt_status = sam_get_results_principal(kdc_db_ctx->samdb, >- mem_ctx, principal_string, attrs, >- realm_dn, msg); >- free(principal_string); > if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { > return HDB_ERR_NOENTRY; > } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) { >@@ -1236,7 +1249,7 @@ static krb5_error_code samba_kdc_lookup_client(krb5_context context, > return EINVAL; > } > >- return ret; >+ return 0; > } > > static krb5_error_code samba_kdc_fetch_client(krb5_context context, >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 47d59d4a..52ddb5e 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -207,7 +207,7 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, > > (*db)->hdb_master_key_set = 0; > (*db)->hdb_db = NULL; >- (*db)->hdb_capability_flags = 0; >+ (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL; > > nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx); > if (!NT_STATUS_IS_OK(nt_status)) { >-- >2.1.4 > > >From af171d07de37ea53d9560fd36b16eb951cf53af8 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 18 Dec 2014 17:23:43 +1300 >Subject: [PATCH 17/60] sefltest: Add test for enterprise UPN in a different > domain > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit c1280569a97be772549debbecb374c53a6cdf796) >--- > testprogs/blackbox/test_kinit.sh | 23 ++++++++++++++++++----- > 1 file changed, 18 insertions(+), 5 deletions(-) > >diff --git a/testprogs/blackbox/test_kinit.sh b/testprogs/blackbox/test_kinit.sh >index cc235c2..db17e86 100755 >--- a/testprogs/blackbox/test_kinit.sh >+++ b/testprogs/blackbox/test_kinit.sh >@@ -68,8 +68,8 @@ test_smbclient() { > > enctype="-e $ENCTYPE" > >-PWSETCONFIG="-H ldap://$SERVER -U$USERNAME%$PASSWORD" >-export PWSETCONFIG >+ADMIN_LDBMODIFY_CONFIG="-H ldap://$SERVER -U$USERNAME%$PASSWORD" >+export ADMIN_LDBMODIFY_CONFIG > > KRB5CCNAME_PATH="$PREFIX/tmpccache" > KRB5CCNAME="FILE:$KRB5CCNAME_PATH" >@@ -77,7 +77,7 @@ ADMIN_KRB5CCNAME="FILE:$KRB5CCNAME_PATH" > export KRB5CCNAME > rm -rf $KRB5CCNAME_PATH > >-testit "reset password policies beside of minimum password age of 0 days" $VALGRIND $samba_tool domain passwordsettings $PWSETCONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=0 --max-pwd-age=default || failed=`expr $failed + 1` >+testit "reset password policies beside of minimum password age of 0 days" $VALGRIND $samba_tool domain passwordsettings $ADMIN_LDBMODIFY_CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=0 --max-pwd-age=default || failed=`expr $failed + 1` > > echo $PASSWORD > $PREFIX/tmppassfile > #testit "kinit with keytab" $samba4kinit $enctype --keytab=$PREFIX/dc/private/secrets.keytab $SERVER\$@$REALM || failed=`expr $failed + 1` >@@ -149,6 +149,19 @@ rm -f $KRB5CCNAME_PATH > testit "kinit with password (windows style) using UPN" $samba4kinit $enctype --renewable --windows --password-file=$PREFIX/tmpuserpassfile --request-pac nettest@$REALM || failed=`expr $failed + 1` > test_smbclient "Test login with user kerberos ccache from windows UPN" 'ls' -k yes || failed=`expr $failed + 1` > >+cat > $PREFIX/tmpldbmodify <<EOF >+dn: cn=nettestuser,cn=users,$BASEDN >+changetype: modify >+replace: userPrincipalName >+userPrincipalName: nettest@$REALM.org >+EOF >+ >+testit "modify userPrincipalName to be a different domain" $VALGRIND $ldbmodify $ADMIN_LDBMODIFY_CONFIG $PREFIX/tmpldbmodify $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1` >+ >+rm -f $KRB5CCNAME_PATH >+testit "kinit with password (enterprise style) using UPN" $samba4kinit $enctype --enterprise --password-file=$PREFIX/tmpuserpassfile --request-pac nettest@$REALM.org || failed=`expr $failed + 1` >+test_smbclient "Test login with user kerberos ccache from enterprise UPN, different domain" 'ls' -k yes || failed=`expr $failed + 1` >+ > > USERPASS=$NEWUSERPASS > NEWUSERPASS=testPaSS@56% >@@ -216,7 +229,7 @@ EOF > USERPASS=$NEWUSERPASS > NEWUSERPASS=testPaSS@911% > >-testit "modify pwdLastSet" $VALGRIND $ldbmodify $PWSETCONFIG $PREFIX/tmpldbmodify $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1` >+testit "modify pwdLastSet" $VALGRIND $ldbmodify $ADMIN_LDBMODIFY_CONFIG $PREFIX/tmpldbmodify $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1` > > cat > $PREFIX/tmppasswordchange <<EOF > expect nettestuser@${REALM}'s Password: >@@ -255,7 +268,7 @@ rm -f $KRB5CCNAME_PATH > testit "kinit with machineaccountccache script" $machineaccountccache $CONFIGURATION $KRB5CCNAME || failed=`expr $failed + 1` > test_smbclient "Test machine account login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1` > >-testit "reset password policies" $VALGRIND $samba_tool domain passwordsettings $PWSETCONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1` >+testit "reset password policies" $VALGRIND $samba_tool domain passwordsettings $ADMIN_LDBMODIFY_CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1` > > rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache tmpkpasswdscript > exit $failed >-- >2.1.4 > > >From 6fa6b0246a6ff2cf1d71f907b9b7733d4dd18a5e Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 21 Jan 2015 15:57:40 +1300 >Subject: [PATCH 18/60] torture: Extend krb5.kdc test to confirm correct RODC > proxy behaviour > >The RODC should answer some requests locally, and others it should defer to the main DC. > >We can tell which KDC we talk do by the KVNO of the encrypted parts that are returned >to the KDC. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 03d07ed58bb4ebad41260a35f8952a18c8cf3e6d) >--- > selftest/target/Samba4.pm | 11 +++++++++++ > source4/selftest/tests.py | 12 ++++++++---- > source4/torture/krb5/kdc.c | 19 ++++++++++++++++++- > 3 files changed, 37 insertions(+), 5 deletions(-) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 568d27a..721a7f5 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -1515,6 +1515,17 @@ sub provision_rodc($$$) > return undef; > } > >+ # This ensures deterministic behaviour for tests that want to have the testallowed >+ # user password verified on the RODC >+ $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; >+ $cmd .= "$samba_tool rodc preload testallowed $ret->{CONFIGURATION}"; >+ $cmd .= " --server=$dcvars->{DC_SERVER}"; >+ >+ unless (system($cmd) == 0) { >+ warn("RODC join failed\n$cmd"); >+ return undef; >+ } >+ > # we overwrite the kdc after the RODC join > # so that use the RODC as kdc and test > # the proxy code >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 3b849f8..4c4c0b3 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -549,13 +549,17 @@ for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"] > for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with specified account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >- "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], > "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") >- plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN'], >- "samba4.krb5.kdc with machine account") >+ if env == "rodc": >+ extra_options = ['--option=torture:expect_rodc=true'] >+ else: >+ extra_options = [] > >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN'] + extra_options, >+ "samba4.krb5.kdc with machine account") >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'] + extra_options, >+ "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > > # TODO: Verifying the databases really should be a part of the > # environment teardown. >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index edf1ecd..4f76001 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -96,7 +96,24 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, > "decode_AS_REP failed"); > torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->as_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >+ torture_assert_int_not_equal(test_context->tctx, >+ *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Did not get a RODC number in the KVNO"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO"); >+ } > free_AS_REP(&test_context->as_rep); > } > torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); >-- >2.1.4 > > >From fd1c26426ed959991e3f4a08901fefc9286d1a56 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 21 Jan 2015 17:27:09 +1300 >Subject: [PATCH 19/60] torture-krb5: Add tests for combinations of enterprise, > cannon, and different input principals > >This combinational test confirms the interactions between a number of differnet >kerberos flags and principal types. > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 170ee3071b7b51af0b6a89b7abf944ec3b08c014) >--- > selftest/target/Samba.pm | 8 +- > source4/selftest/tests.py | 8 +- > source4/torture/krb5/kdc-canon.c | 401 +++++++++++++++++++++++++++++++++++++ > source4/torture/krb5/kdc.c | 3 +- > source4/torture/krb5/wscript_build | 2 +- > 5 files changed, 415 insertions(+), 7 deletions(-) > create mode 100644 source4/torture/krb5/kdc-canon.c > >diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm >index ccc63f3..2b7343d 100644 >--- a/selftest/target/Samba.pm >+++ b/selftest/target/Samba.pm >@@ -124,7 +124,8 @@ sub mk_krb5_conf($$) > sub mk_realms_stanza($$$$) > { > my ($realm, $dnsname, $domain, $kdc_ipv4) = @_; >- >+ my $lc_domain = lc($domain); >+ > my $realms_stanza = " > $realm = { > kdc = $kdc_ipv4:88 >@@ -141,6 +142,11 @@ sub mk_realms_stanza($$$$) > admin_server = $kdc_ipv4:88 > default_domain = $dnsname > } >+ $lc_domain = { >+ kdc = $kdc_ipv4:88 >+ admin_server = $kdc_ipv4:88 >+ default_domain = $dnsname >+ } > > "; > return $realms_stanza; >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 4c4c0b3..f207b1a 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -547,18 +547,18 @@ for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"] > plantestsuite("samba.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) > > for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'], > "samba4.krb5.kdc with specified account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied@$REALM%$PASSWORD', '--workgroup=$DOMAIN'], >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'], > "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") > if env == "rodc": > extra_options = ['--option=torture:expect_rodc=true'] > else: > extra_options = [] > >- plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with machine account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed@$REALM%$PASSWORD', '--workgroup=$DOMAIN'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > > # TODO: Verifying the databases really should be a part of the >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >new file mode 100644 >index 0000000..53a3b6a >--- /dev/null >+++ b/source4/torture/krb5/kdc-canon.c >@@ -0,0 +1,401 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ Validate the krb5 pac generation routines >+ >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2015 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+#include "system/kerberos.h" >+#include "torture/smbtorture.h" >+#include "torture/krb5/proto.h" >+#include "auth/credentials/credentials.h" >+#include "lib/cmdline/popt_common.h" >+#include "source4/auth/kerberos/kerberos.h" >+#include "source4/auth/kerberos/kerberos_util.h" >+#include "lib/util/util_net.h" >+ >+#define TEST_CANONICALIZE 0x0000001 >+#define TEST_ENTERPRISE 0x0000002 >+#define TEST_UPPER_REALM 0x0000004 >+#define TEST_UPPER_USERNAME 0x0000008 >+#define TEST_NETBIOS_REALM 0x0000010 >+#define TEST_ALL 0x000001F >+ >+struct test_data { >+ struct smb_krb5_context *smb_krb5_context; >+ const char *realm; >+ const char *real_realm; >+ const char *username; >+ bool canonicalize; >+ bool enterprise; >+ bool upper_realm; >+ bool upper_username; >+}; >+ >+struct torture_krb5_context { >+ struct torture_context *tctx; >+ struct addrinfo *server; >+ struct test_data *test_data; >+ int packet_count; >+ AS_REQ as_req; >+ AS_REP as_rep; >+}; >+ >+static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+{ >+ krb5_error_code k5ret; >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0, >+ "decode_AS_REQ failed"); >+ >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno"); >+ if (test_context->test_data->canonicalize || test_context->test_data->enterprise) { >+ torture_assert(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, "krb5 libs did not set canonicalize!"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ } >+ >+ if (test_context->test_data->enterprise) { >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.cname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, "krb5 libs did not pass principal as enterprise!"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.cname->name_type, KRB5_NT_PRINCIPAL, "krb5 libs unexpectedly set principal as enterprise!"); >+ } >+ >+ /* Force off canonicalize that was forced on by the krb5 libs */ >+ if (test_context->test_data->canonicalize == false && test_context->test_data->enterprise) { >+ test_context->as_req.req_body.kdc_options.canonicalize = false; >+ } >+ >+ ASN1_MALLOC_ENCODE(AS_REQ, modified_send_buf->data, modified_send_buf->length, >+ &test_context->as_req, &used, k5ret); >+ torture_assert_int_equal(test_context->tctx, >+ k5ret, 0, >+ "encode_AS_REQ failed"); >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "re-encode length mismatch"); >+ return true; >+} >+ >+static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ KRB_ERROR error; >+ size_t used; >+ if (test_context->packet_count == 0) { >+ torture_assert_int_equal(test_context->tctx, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) >+ && (test_context->packet_count == 1)) { >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ free_KRB_ERROR(&error); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->as_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >+ torture_assert_int_not_equal(test_context->tctx, >+ *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Did not get a RODC number in the KVNO"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO"); >+ } >+ free_AS_REP(&test_context->as_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ return true; >+} >+ >+static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context context, >+ void *data, /* struct torture_krb5_context */ >+ krb5_krbhst_info *hi, >+ time_t timeout, >+ const krb5_data *send_buf, >+ krb5_data *recv_buf) >+{ >+ krb5_error_code k5ret; >+ bool ok; >+ krb5_data modified_send_buf; >+ >+ struct torture_krb5_context *test_context >+ = talloc_get_type_abort(data, struct torture_krb5_context); >+ >+ ok = torture_krb5_pre_send_test(test_context, send_buf, &modified_send_buf); >+ if (ok == false) { >+ return EINVAL; >+ } >+ >+ k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, >+ hi, timeout, &modified_send_buf, recv_buf); >+ >+ ok = torture_krb5_post_recv_test(test_context, recv_buf); >+ if (ok == false) { >+ return EINVAL; >+ } >+ >+ test_context->packet_count++; >+ >+ return k5ret; >+} >+ >+static int test_context_destructor(struct torture_krb5_context *test_context) >+{ >+ freeaddrinfo(test_context->server); >+ return 0; >+} >+ >+ >+static bool torture_krb5_init_context_canon(struct torture_context *tctx, >+ struct test_data *test_data, >+ struct smb_krb5_context **smb_krb5_context) >+{ >+ const char *host = torture_setting_string(tctx, "host", NULL); >+ krb5_error_code k5ret; >+ bool ok; >+ >+ struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context); >+ torture_assert(tctx, test_context != NULL, "Failed to allocate"); >+ >+ test_context->test_data = test_data; >+ test_context->tctx = tctx; >+ >+ k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context); >+ torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed"); >+ >+ ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST); >+ torture_assert(tctx, ok, "Failed to parse target server"); >+ >+ talloc_set_destructor(test_context, test_context_destructor); >+ >+ set_sockaddr_port(test_context->server->ai_addr, 88); >+ >+ k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, >+ smb_krb5_send_and_recv_func_canon_override, >+ test_context); >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed"); >+ return true; >+} >+ >+ >+static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void *tcase_data) >+{ >+ krb5_error_code k5ret; >+ krb5_get_init_creds_opt *krb_options = NULL; >+ struct test_data *test_data = talloc_get_type_abort(tcase_data, struct test_data); >+ char *realm; >+ char *upper_real_realm; >+ char *username; >+ krb5_principal principal; >+ krb5_principal expected_principal; >+ char *principal_string; >+ int principal_flags; >+ char *expected_principal_string; >+ int expected_principal_flags; >+ char *got_principal_string; >+ char *assertion_message; >+ const char *password = cli_credentials_get_password(cmdline_credentials); >+ struct smb_krb5_context *smb_krb5_context; >+ bool ok; >+ krb5_creds my_creds; >+ >+ ok = torture_krb5_init_context_canon(tctx, test_data, &smb_krb5_context); >+ torture_assert(tctx, ok, "torture_krb5_init_context failed"); >+ >+ if (test_data->upper_realm) { >+ realm = strupper_talloc(test_data, test_data->realm); >+ } else { >+ realm = strlower_talloc(test_data, test_data->realm); >+ } >+ if (test_data->upper_username) { >+ username = strupper_talloc(test_data, test_data->username); >+ } else { >+ username = talloc_strdup(test_data, test_data->username); >+ } >+ >+ principal_string = talloc_asprintf(test_data, "%s@%s", username, realm); >+ >+ upper_real_realm = strupper_talloc(test_data, test_data->real_realm); >+ >+ /* >+ * If we are set to canonicalize, we get back the fixed UPPER >+ * case realm, and the real username (ie matching LDAP >+ * samAccountName) >+ * >+ * Otherwise, if we are set to enterprise, we >+ * get back the whole principal as-sent >+ * >+ * Finally, if we are not set to canonicalize, we get back the >+ * fixed UPPER case realm, but the as-sent username >+ */ >+ if (test_data->canonicalize) { >+ expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->username, upper_real_realm); >+ } else if (test_data->enterprise) { >+ expected_principal_string = principal_string; >+ } else { >+ expected_principal_string = talloc_asprintf(test_data, "%s@%s", username, upper_real_realm); >+ } >+ >+ if (test_data->enterprise) { >+ principal_flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE; >+ } else { >+ principal_flags = 0; >+ } >+ >+ if (test_data->canonicalize) { >+ expected_principal_flags = 0; >+ } else { >+ expected_principal_flags = principal_flags; >+ } >+ >+ torture_assert_int_equal(tctx, >+ krb5_parse_name_flags(smb_krb5_context->krb5_context, >+ principal_string, >+ principal_flags, >+ &principal), >+ 0, "krb5_parse_name_flags failed"); >+ torture_assert_int_equal(tctx, >+ krb5_parse_name_flags(smb_krb5_context->krb5_context, >+ expected_principal_string, >+ expected_principal_flags, >+ &expected_principal), >+ 0, "krb5_parse_name_flags failed"); >+ >+ /* >+ * Set the canonicalize flag if this test requires it >+ */ >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >+ 0, "krb5_get_init_creds_opt_alloc failed"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_set_canonicalize(smb_krb5_context->krb5_context, krb_options, test_data->canonicalize), >+ 0, "krb5_get_init_creds_opt_set_canonicalize failed"); >+ >+ k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, >+ password, NULL, NULL, 0, >+ NULL, krb_options); >+ krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ >+ /* >+ * Assert that the reply was with the correct type of >+ * principal, depending on the flags we set >+ */ >+ if (test_data->canonicalize == false && test_data->enterprise) { >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(smb_krb5_context->krb5_context, >+ my_creds.client), KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ } else { >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(smb_krb5_context->krb5_context, >+ my_creds.client), KRB5_NT_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ } >+ >+ torture_assert_int_equal(tctx, >+ krb5_unparse_name(smb_krb5_context->krb5_context, >+ my_creds.client, &got_principal_string), 0, >+ "krb5_unparse_name failed"); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password returned a different principal %s to what was expected %s", >+ got_principal_string, expected_principal_string); >+ krb5_free_unparsed_name(smb_krb5_context->krb5_context, got_principal_string); >+ >+ torture_assert(tctx, krb5_principal_compare(smb_krb5_context->krb5_context, >+ my_creds.client, expected_principal), >+ assertion_message); >+ >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(smb_krb5_context->krb5_context, >+ my_creds.server), KRB5_NT_SRV_INST, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ >+ torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >+ my_creds.server, 0), >+ "krbtgt", >+ "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]"); >+ >+ krb5_free_principal(smb_krb5_context->krb5_context, principal); >+ >+ k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds); >+ torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed"); >+ >+ return true; >+} >+ >+struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) >+{ >+ unsigned int i; >+ struct torture_suite *suite = torture_suite_create(mem_ctx, "canon"); >+ suite->description = talloc_strdup(suite, "Kerberos Canonicalisation tests"); >+ >+ for (i = 0; i < TEST_ALL; i++) { >+ char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s", >+ (i & TEST_CANONICALIZE) ? "canon" : "no-canon", >+ (i & TEST_ENTERPRISE) ? "enterprise" : "no-enterprise", >+ (i & TEST_UPPER_REALM) ? "uc-realm" : "lc-realm", >+ (i & TEST_UPPER_USERNAME) ? "uc-user" : "lc-user", >+ (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm"); >+ >+ struct test_data *test_data = talloc(suite, struct test_data); >+ if (i & TEST_NETBIOS_REALM) { >+ test_data->realm = cli_credentials_get_domain(cmdline_credentials); >+ } else { >+ test_data->realm = cli_credentials_get_realm(cmdline_credentials); >+ } >+ test_data->real_realm = cli_credentials_get_realm(cmdline_credentials); >+ test_data->username = cli_credentials_get_username(cmdline_credentials); >+ test_data->canonicalize = (i & TEST_CANONICALIZE) != 0; >+ test_data->enterprise = (i & TEST_ENTERPRISE) != 0; >+ test_data->upper_realm = (i & TEST_UPPER_REALM) != 0; >+ test_data->upper_username = (i & TEST_UPPER_USERNAME) != 0; >+ torture_suite_add_simple_tcase_const(suite, name, torture_krb5_as_req_canon, >+ test_data); >+ >+ } >+ return suite; >+} >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index 4f76001..be4b245 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -24,6 +24,7 @@ > #include "system/kerberos.h" > #include "torture/smbtorture.h" > #include "torture/winbind/proto.h" >+#include "torture/krb5/proto.h" > #include "auth/credentials/credentials.h" > #include "lib/cmdline/popt_common.h" > #include "source4/auth/kerberos/kerberos.h" >@@ -406,7 +407,6 @@ static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx) > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_CLOCK_SKEW); > } > >-NTSTATUS torture_krb5_init(void); > NTSTATUS torture_krb5_init(void) > { > struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "krb5"); >@@ -429,6 +429,7 @@ NTSTATUS torture_krb5_init(void) > torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew", > torture_krb5_as_req_clock_skew); > >+ torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite)); > torture_suite_add_suite(suite, kdc_suite); > > torture_register_suite(suite); >diff --git a/source4/torture/krb5/wscript_build b/source4/torture/krb5/wscript_build >index 963c3a3..81a5b09 100644 >--- a/source4/torture/krb5/wscript_build >+++ b/source4/torture/krb5/wscript_build >@@ -1,7 +1,7 @@ > #!/usr/bin/env python > if bld.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): > bld.SAMBA_MODULE('TORTURE_KRB5', >- source='kdc.c', >+ source='kdc.c kdc-canon.c', > autoproto='proto.h', > subsystem='smbtorture', > init_function='torture_krb5_init', >-- >2.1.4 > > >From cad986aee6acb91abcf0b7490a8f70d68f452380 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 22 Jan 2015 14:11:52 +1300 >Subject: [PATCH 20/60] kdc: Fix Samba's KDC to only change the principal in > the right cases > >If we are set to canonicalize, we get back the fixed UPPER >case realm, and the real username (ie matching LDAP >samAccountName) > >Otherwise, if we are set to enterprise, we >get back the whole principal as-sent > >Finally, if we are not set to canonicalize, we get back the >fixed UPPER case realm, but the as-sent username > >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 9fc3f1e3d6854f399e2b2322b8ab1a714353ba12) >--- > source4/kdc/db-glue.c | 32 +++++++++++++++++++++++--------- > 1 file changed, 23 insertions(+), 9 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index fae2703..ee84501 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -625,10 +625,22 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > userAccountControl |= msDS_User_Account_Control_Computed; > } > >+ /* >+ * If we are set to canonicalize, we get back the fixed UPPER >+ * case realm, and the real username (ie matching LDAP >+ * samAccountName) >+ * >+ * Otherwise, if we are set to enterprise, we >+ * get back the whole principal as-sent >+ * >+ * Finally, if we are not set to canonicalize, we get back the >+ * fixed UPPER case realm, but the as-sent username >+ */ >+ > entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); > if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { > krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >- } else if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ } else if (flags & HDB_F_CANON) { > krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); > } else { > ret = copy_Principal(principal, entry_ex->entry.principal); >@@ -637,14 +649,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > goto out; > } > >- /* While we have copied the client principal, tests >- * show that Win2k3 returns the 'corrected' realm, not >- * the client-specified realm. This code attempts to >- * replace the client principal's realm with the one >- * we determine from our records */ >- >- /* this has to be with malloc() */ >- krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ if (principal->name.name_type != KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ /* While we have copied the client principal, tests >+ * show that Win2k3 returns the 'corrected' realm, not >+ * the client-specified realm. This code attempts to >+ * replace the client principal's realm with the one >+ * we determine from our records */ >+ >+ /* this has to be with malloc() */ >+ krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ } > } > > /* First try and figure out the flags based on the userAccountControl */ >-- >2.1.4 > > >From 8f6034a0fdad95b3197003da38f8b212c8874894 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 17:39:45 +1300 >Subject: [PATCH 21/60] kdc: Add TODO to remind us where we need to hook for > RODC to get secrets > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 69fb2a7616fe3b67312904075fdb691b7fa510bb) >--- > source4/kdc/db-glue.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index ee84501..ad52284 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -374,6 +374,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, > if (allocated_keys == 0) { > if (kdc_db_ctx->rodc) { > /* We are on an RODC, but don't have keys for this account. Signal this to the caller */ >+ /* TODO: We need to call a generalised version of auth_sam_trigger_repl_secret from here */ > return HDB_ERR_NOT_FOUND_HERE; > } > >-- >2.1.4 > > >From 51107f20f870ce9b8f6a55abc400e04c85a52326 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 14:07:41 +1300 >Subject: [PATCH 22/60] torture-krb5: Add comments > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit d0751b576363a25ca67f485651b206677bf1d4b8) >--- > source4/torture/krb5/kdc-canon.c | 36 +++++++++++++++++++++++++++++++++ > source4/torture/krb5/kdc.c | 43 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 79 insertions(+) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 53a3b6a..a20f9f9 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -57,6 +57,20 @@ struct torture_krb5_context { > AS_REP as_rep; > }; > >+ >+/* >+ * Confirm that the outgoing packet meets certain expectations. This >+ * should be extended to further assert the correct and expected >+ * behaviour of the krb5 libs, so we know what we are sending to the >+ * server. >+ * >+ * Additionally, this CHANGES the request to remove the canonicalize >+ * flag automatically added by the krb5 libs when an enterprise >+ * principal is used, so we can test what the server does in this >+ * combination. >+ * >+ */ >+ > static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) > { > krb5_error_code k5ret; >@@ -93,6 +107,14 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > return true; > } > >+/* >+ * Confirm that the incoming packet from the KDC meets certain >+ * expectations. This uses a packet count to work out what test we >+ * are in, and where in the test we are, so we can assert on the >+ * expected reply packets from the KDC. >+ * >+ */ >+ > static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > KRB_ERROR error; >@@ -143,6 +165,20 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > return true; > } > >+/* >+ * This function is set in torture_krb5_init_context_canon as krb5 >+ * send_and_recv function. This allows us to override what server the >+ * test is aimed at, and to inspect the packets just before they are >+ * sent to the network, and before they are processed on the recv >+ * side. >+ * >+ * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test() >+ * functions are implement the actual tests. >+ * >+ * When this asserts, the caller will get a spurious 'cannot contact >+ * any KDC' message. >+ * >+ */ > static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context context, > void *data, /* struct torture_krb5_context */ > krb5_krbhst_info *hi, >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index be4b245..eed5d8d 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -48,6 +48,14 @@ struct torture_krb5_context { > AS_REP as_rep; > }; > >+/* >+ * Confirm that the outgoing packet meets certain expectations. This >+ * should be extended to further assert the correct and expected >+ * behaviour of the krb5 libs, so we know what we are sending to the >+ * server. >+ * >+ */ >+ > static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf) > { > size_t used; >@@ -68,6 +76,14 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > return true; > } > >+/* >+ * Confirm that the incoming packet from the KDC meets certain >+ * expectations. This uses a switch and the packet count to work out >+ * what test we are in, and where in the test we are, so we can assert >+ * on the expected reply packets from the KDC. >+ * >+ */ >+ > static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > KRB_ERROR error; >@@ -120,6 +136,10 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); > free_AS_REQ(&test_context->as_req); > break; >+ >+ /* >+ * Confirm correct error codes when we ask for the PAC. This behaviour is rather odd... >+ */ > case TORTURE_KRB5_TEST_PAC_REQUEST: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, >@@ -157,6 +177,10 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); > free_AS_REQ(&test_context->as_req); > break; >+ >+ /* >+ * Confirm correct error codes when we deliberatly send the wrong password >+ */ > case TORTURE_KRB5_TEST_BREAK_PW: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, >@@ -180,6 +204,10 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); > free_AS_REQ(&test_context->as_req); > break; >+ >+ /* >+ * Confirm correct error codes when we deliberatly skew the client clock >+ */ > case TORTURE_KRB5_TEST_CLOCK_SKEW: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, >@@ -207,6 +235,21 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > return true; > } > >+ >+/* >+ * This function is set in torture_krb5_init_context as krb5 >+ * send_and_recv function. This allows us to override what server the >+ * test is aimed at, and to inspect the packets just before they are >+ * sent to the network, and before they are processed on the recv >+ * side. >+ * >+ * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test() >+ * functions are implement the actual tests. >+ * >+ * When this asserts, the caller will get a spurious 'cannot contact >+ * any KDC' message. >+ * >+ */ > static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context, > void *data, /* struct torture_krb5_context */ > krb5_krbhst_info *hi, >-- >2.1.4 > > >From dfb6ff68ae5bb8868f061012d30d0ce3553a0b8c Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 14:09:33 +1300 >Subject: [PATCH 23/60] torture-kdc: Skip the request-pac behaviour for now > against an RODC > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 89b868f67761fbcf1319229c2f09502bdf16086e) >--- > source4/torture/krb5/kdc.c | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index eed5d8d..405b45f 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -437,6 +437,9 @@ static bool torture_krb5_as_req_win2k(struct torture_context *tctx) > > static bool torture_krb5_as_req_pac_request(struct torture_context *tctx) > { >+ if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >+ return torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users"); >+ } > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PAC_REQUEST); > } > >-- >2.1.4 > > >From 7a2beb7a2b41761d81ec5da587c3a4250e6b03a6 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 14:28:28 +1300 >Subject: [PATCH 24/60] torture-krb5: Split the expected behaviour of the RODC > up > >The expectations of the cached accounts are different to those of the RODC in general. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 62905cd6d21d457a54faa2a14e9713dcf280dbe5) >--- > source4/selftest/tests.py | 13 ++++++++++--- > source4/torture/krb5/kdc-canon.c | 2 +- > source4/torture/krb5/kdc.c | 6 +++--- > 3 files changed, 14 insertions(+), 7 deletions(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index f207b1a..b09fde2 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -547,12 +547,19 @@ for env in ["dc", "s4member", "rodc", "promoted_dc", "plugin_s4_dc", "s3member"] > plantestsuite("samba.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) > > for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'], >+ if env == "rodc": >+ extra_options = ['--option=torture:expect_rodc=true'] >+ else: >+ extra_options = [] >+ >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with specified account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'], >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") >+ >+ # These last two tests are for users cached at the RODC > if env == "rodc": >- extra_options = ['--option=torture:expect_rodc=true'] >+ extra_options = ['--option=torture:expect_rodc=true', '--option=torture:expect_cached_at_rodc=true'] > else: > extra_options = [] > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index a20f9f9..3103d94 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -149,7 +149,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, > test_context->as_rep.ticket.enc_part.kvno, > "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >- if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >+ if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Did not get a RODC number in the KVNO"); >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index 405b45f..cf8c39b 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -122,7 +122,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > torture_assert(test_context->tctx, > test_context->as_rep.ticket.enc_part.kvno, > "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >- if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >+ if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Did not get a RODC number in the KVNO"); >@@ -437,8 +437,8 @@ static bool torture_krb5_as_req_win2k(struct torture_context *tctx) > > static bool torture_krb5_as_req_pac_request(struct torture_context *tctx) > { >- if (torture_setting_bool(test_context->tctx, "expect_rodc", false)) { >- return torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users"); >+ if (torture_setting_bool(tctx, "expect_rodc", false)) { >+ torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users"); > } > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PAC_REQUEST); > } >-- >2.1.4 > > >From 1c0217a611746e6d67cd64588462c8b94812625d Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 14:38:51 +1300 >Subject: [PATCH 25/60] torture-krb5: Move test of > krb5_get_init_creds_opt_set_win2k to krb5.kdc.canon > >This allows the impact of this to be verified with the other options we are setting > >This also removes duplication in the kdc.c testsuite. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 9d7719b62ba0453b7c4e4b8a4c2062dc55ac4abd) >--- > source4/torture/krb5/kdc-canon.c | 14 +++++++++++--- > source4/torture/krb5/kdc.c | 22 ---------------------- > 2 files changed, 11 insertions(+), 25 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 3103d94..018e61d 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -35,7 +35,8 @@ > #define TEST_UPPER_REALM 0x0000004 > #define TEST_UPPER_USERNAME 0x0000008 > #define TEST_NETBIOS_REALM 0x0000010 >-#define TEST_ALL 0x000001F >+#define TEST_WIN2K 0x0000020 >+#define TEST_ALL 0x000003F > > struct test_data { > struct smb_krb5_context *smb_krb5_context; >@@ -46,6 +47,7 @@ struct test_data { > bool enterprise; > bool upper_realm; > bool upper_username; >+ bool win2k; > }; > > struct torture_krb5_context { >@@ -344,6 +346,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > krb5_get_init_creds_opt_set_canonicalize(smb_krb5_context->krb5_context, krb_options, test_data->canonicalize), > 0, "krb5_get_init_creds_opt_set_canonicalize failed"); > >+ torture_assert_int_equal(tctx, >+ krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, krb_options, test_data->win2k), >+ 0, "krb5_get_init_creds_opt_set_win2k failed"); >+ > k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, > password, NULL, NULL, 0, > NULL, krb_options); >@@ -410,12 +416,13 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > suite->description = talloc_strdup(suite, "Kerberos Canonicalisation tests"); > > for (i = 0; i < TEST_ALL; i++) { >- char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s", >+ char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s", > (i & TEST_CANONICALIZE) ? "canon" : "no-canon", > (i & TEST_ENTERPRISE) ? "enterprise" : "no-enterprise", > (i & TEST_UPPER_REALM) ? "uc-realm" : "lc-realm", > (i & TEST_UPPER_USERNAME) ? "uc-user" : "lc-user", >- (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm"); >+ (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm", >+ (i & TEST_WIN2K) ? "win2k" : "no-win2k"); > > struct test_data *test_data = talloc(suite, struct test_data); > if (i & TEST_NETBIOS_REALM) { >@@ -429,6 +436,7 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > test_data->enterprise = (i & TEST_ENTERPRISE) != 0; > test_data->upper_realm = (i & TEST_UPPER_REALM) != 0; > test_data->upper_username = (i & TEST_UPPER_USERNAME) != 0; >+ test_data->win2k = (i & TEST_WIN2K) != 0; > torture_suite_add_simple_tcase_const(suite, name, torture_krb5_as_req_canon, > test_data); > >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index cf8c39b..3eec528 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -33,7 +33,6 @@ > > enum torture_krb5_test { > TORTURE_KRB5_TEST_PLAIN, >- TORTURE_KRB5_TEST_WIN2K, > TORTURE_KRB5_TEST_PAC_REQUEST, > TORTURE_KRB5_TEST_BREAK_PW, > TORTURE_KRB5_TEST_CLOCK_SKEW, >@@ -62,7 +61,6 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > switch (test_context->test) > { > case TORTURE_KRB5_TEST_PLAIN: >- case TORTURE_KRB5_TEST_WIN2K: > case TORTURE_KRB5_TEST_PAC_REQUEST: > case TORTURE_KRB5_TEST_BREAK_PW: > case TORTURE_KRB5_TEST_CLOCK_SKEW: >@@ -91,7 +89,6 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > switch (test_context->test) > { > case TORTURE_KRB5_TEST_PLAIN: >- case TORTURE_KRB5_TEST_WIN2K: > if (test_context->packet_count == 0) { > torture_assert_int_equal(test_context->tctx, > decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >@@ -345,16 +342,6 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > case TORTURE_KRB5_TEST_PLAIN: > break; > >- case TORTURE_KRB5_TEST_WIN2K: >- torture_assert_int_equal(tctx, >- krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >- 0, "krb5_get_init_creds_opt_alloc failed"); >- >- torture_assert_int_equal(tctx, >- krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, krb_options, true), >- 0, "krb5_get_init_creds_opt_set_win2k failed"); >- break; >- > case TORTURE_KRB5_TEST_PAC_REQUEST: > torture_assert_int_equal(tctx, > krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >@@ -385,7 +372,6 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > switch (test) > { > case TORTURE_KRB5_TEST_PLAIN: >- case TORTURE_KRB5_TEST_WIN2K: > case TORTURE_KRB5_TEST_PAC_REQUEST: > torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); > break; >@@ -430,11 +416,6 @@ static bool torture_krb5_as_req_cmdline(struct torture_context *tctx) > return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PLAIN); > } > >-static bool torture_krb5_as_req_win2k(struct torture_context *tctx) >-{ >- return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_WIN2K); >-} >- > static bool torture_krb5_as_req_pac_request(struct torture_context *tctx) > { > if (torture_setting_bool(tctx, "expect_rodc", false)) { >@@ -463,9 +444,6 @@ NTSTATUS torture_krb5_init(void) > torture_suite_add_simple_test(kdc_suite, "as-req-cmdline", > torture_krb5_as_req_cmdline); > >- torture_suite_add_simple_test(kdc_suite, "as-req-win2k", >- torture_krb5_as_req_win2k); >- > torture_suite_add_simple_test(kdc_suite, "as-req-pac-request", > torture_krb5_as_req_pac_request); > >-- >2.1.4 > > >From 638936d0570f736e8c6ac91100bbe7e0b2f3f437 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 14:28:56 +1300 >Subject: [PATCH 26/60] torture-krb5: Move checking of server and client names > to krb5.kdc.canon > >This keeps this test in one place, rather than duplicated between krb5.kdc and krb5.kdc.canon > >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 157539c5ad9b819e43dceee6bb47d2027de1d982) >--- > source4/torture/krb5/kdc-canon.c | 26 +++++++++++++++++++++++++- > source4/torture/krb5/kdc.c | 19 ------------------- > 2 files changed, 25 insertions(+), 20 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 018e61d..a12ee86 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -391,16 +391,40 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > my_creds.client, expected_principal), > assertion_message); > >+ > torture_assert_int_equal(tctx, > krb5_principal_get_type(smb_krb5_context->krb5_context, > my_creds.server), KRB5_NT_SRV_INST, >- "smb_krb5_init_context gave incorrect client->name.name_type"); >+ "smb_krb5_init_context gave incorrect server->name.name_type"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_num_comp(smb_krb5_context->krb5_context, >+ my_creds.server), 2, >+ "smb_krb5_init_context gave incorrect number of components in my_creds.server->name"); > > torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, > my_creds.server, 0), > "krbtgt", > "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]"); > >+ if (test_data->canonicalize || test_data->enterprise) { >+ torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >+ my_creds.server, 1), >+ test_data->real_realm, >+ >+ "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]"); >+ } else { >+ torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >+ my_creds.server, 1), >+ realm, >+ >+ "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]"); >+ } >+ torture_assert_str_equal(tctx, krb5_principal_get_realm(smb_krb5_context->krb5_context, >+ my_creds.server), >+ test_data->real_realm, >+ "smb_krb5_init_context gave incorrect my_creds.server->realm"); >+ > krb5_free_principal(smb_krb5_context->krb5_context, principal); > > k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds); >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index 3eec528..a7b6ac8 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -386,25 +386,6 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, > > } > >- torture_assert_int_equal(tctx, >- krb5_principal_get_type(smb_krb5_context->krb5_context, >- my_creds.client), KRB5_NT_PRINCIPAL, >- "smb_krb5_init_context gave incorrect client->name.name_type"); >- >- torture_assert(tctx, krb5_principal_compare(smb_krb5_context->krb5_context, >- principal, my_creds.client), >- "krb5_get_init_creds_password returned a different principal"); >- >- torture_assert_int_equal(tctx, >- krb5_principal_get_type(smb_krb5_context->krb5_context, >- my_creds.server), KRB5_NT_SRV_INST, >- "smb_krb5_init_context gave incorrect client->name.name_type"); >- >- torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >- my_creds.server, 0), >- "krbtgt", >- "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]"); >- > k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds); > torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed"); > >-- >2.1.4 > > >From 114f9c17851d6b399050e3df23602d4b31161a89 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 16:41:50 +1300 >Subject: [PATCH 27/60] kdc: Correctly return the krbtgt/realm@REALM principal > from our KDC > >This needs to vary depending on if the client requested the canonicalize flag > >This was found by our new krb5.kdc test > >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit c1819f5fd1eb690326a1fc547422544f5c834558) >--- > source4/kdc/db-glue.c | 56 ++++++++++++++++++++++++++++----------------------- > 1 file changed, 31 insertions(+), 25 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index ad52284..042abe6 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -639,7 +639,37 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > */ > > entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); >- if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { >+ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { >+ ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); >+ if (ret) { >+ return ret; >+ } >+ >+ /* >+ * Windows seems to canonicalize the principal >+ * in a TGS REP even if the client did not specify >+ * the canonicalize flag. >+ */ >+ if (flags & (HDB_F_CANON|HDB_F_FOR_TGS_REQ)) { >+ /* When requested to do so, ensure that the >+ * both realm values in the principal are set >+ * to the upper case, canonical realm */ >+ free(entry_ex->entry.principal->name.name_string.val[1]); >+ entry_ex->entry.principal->name.name_string.val[1] = strdup(lpcfg_realm(lp_ctx)); >+ if (!entry_ex->entry.principal->name.name_string.val[1]) { >+ ret = ENOMEM; >+ krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!"); >+ return ret; >+ } >+ } >+ /* >+ * this has to be with malloc(), and appears to be >+ * required regardless of the canonicalize flag from >+ * the client >+ */ >+ krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ >+ } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { > krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); > } else if (flags & HDB_F_CANON) { > krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >@@ -1368,30 +1398,6 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context, > return HDB_ERR_NOENTRY; > } > >- /* >- * Windows seems to canonicalize the principal >- * in a TGS REP even if the client did not specify >- * the canonicalize flag. >- */ >- if (flags & (HDB_F_CANON|HDB_F_FOR_TGS_REQ)) { >- ret = krb5_copy_principal(context, principal, &alloc_principal); >- if (ret) { >- return ret; >- } >- >- /* When requested to do so, ensure that the >- * both realm values in the principal are set >- * to the upper case, canonical realm */ >- free(alloc_principal->name.name_string.val[1]); >- alloc_principal->name.name_string.val[1] = strdup(lpcfg_realm(lp_ctx)); >- if (!alloc_principal->name.name_string.val[1]) { >- ret = ENOMEM; >- krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!"); >- return ret; >- } >- principal = alloc_principal; >- } >- > ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx, > principal, SAMBA_KDC_ENT_TYPE_KRBTGT, > flags, realm_dn, msg, entry_ex); >-- >2.1.4 > > >From 76914172664a12128d9db643937bed4fc3db5a8b Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 16:43:48 +1300 >Subject: [PATCH 28/60] torture-krb5: Check for UPN hanlding in krb5.kdc.canon > test > >This allows us to confirm correct behaviour when a UPN is in use, particularly >with the canonicalize flag and with enterprise principal names > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 52526ee26555daff27cb11ca2f444c2534a4d8f2) >--- > source4/torture/krb5/kdc-canon.c | 108 ++++++++++++++++++++++++++++++++------- > 1 file changed, 90 insertions(+), 18 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index a12ee86..a0df97b 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -36,18 +36,24 @@ > #define TEST_UPPER_USERNAME 0x0000008 > #define TEST_NETBIOS_REALM 0x0000010 > #define TEST_WIN2K 0x0000020 >-#define TEST_ALL 0x000003F >+#define TEST_UPN 0x0000040 >+#define TEST_ALL 0x000007F > > struct test_data { > struct smb_krb5_context *smb_krb5_context; > const char *realm; > const char *real_realm; >+ const char *real_domain; > const char *username; >+ const char *real_username; > bool canonicalize; > bool enterprise; > bool upper_realm; > bool upper_username; >+ bool netbios_realm; > bool win2k; >+ bool upn; >+ bool other_upn_suffix; > }; > > struct torture_krb5_context { >@@ -127,8 +133,13 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > "decode_AS_REP failed"); > torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >+ if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } > free_KRB_ERROR(&error); > } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) > && (test_context->packet_count == 1)) { >@@ -273,6 +284,57 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > bool ok; > krb5_creds my_creds; > >+ const char *upn = torture_setting_string(tctx, "krb5-upn", ""); >+ >+ /* >+ * If we have not passed a UPN on the command line, >+ * then skip the UPN tests. >+ */ >+ if (test_data->upn && upn[0] == '\0') { >+ torture_skip(tctx, "This test needs a UPN specified as --option=torture:krb5-upn=user@example.com to run"); >+ } >+ >+ if (test_data->netbios_realm) { >+ test_data->realm = test_data->real_domain; >+ } else { >+ test_data->realm = test_data->real_realm; >+ } >+ >+ if (test_data->upn) { >+ char *p; >+ test_data->username = talloc_strdup(test_data, upn); >+ p = strchr(test_data->username, '@'); >+ if (p) { >+ *p = '\0'; >+ p++; >+ } >+ /* >+ * Test the UPN behaviour carefully. We can >+ * test in two different modes, depending on >+ * what UPN has been set up for us. >+ * >+ * If the UPN is in our realm, then we do all the tests with this name also. >+ * >+ * If the UPN is not in our realm, then we >+ * expect the tests that replace the realm to >+ * fail (as it won't match) >+ */ >+ if (strcasecmp(p, test_data->real_realm) != 0) { >+ test_data->other_upn_suffix = true; >+ } else { >+ test_data->other_upn_suffix = false; >+ } >+ >+ /* >+ * This lets us test the combination of the UPN prefix >+ * with a valid domain, without adding even more >+ * combinations >+ */ >+ if (test_data->netbios_realm == false) { >+ test_data->realm = p; >+ } >+ } >+ > ok = torture_krb5_init_context_canon(tctx, test_data, &smb_krb5_context); > torture_assert(tctx, ok, "torture_krb5_init_context failed"); > >@@ -303,7 +365,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * fixed UPPER case realm, but the as-sent username > */ > if (test_data->canonicalize) { >- expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->username, upper_real_realm); >+ expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->real_username, upper_real_realm); > } else if (test_data->enterprise) { > expected_principal_string = principal_string; > } else { >@@ -313,6 +375,9 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > if (test_data->enterprise) { > principal_flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE; > } else { >+ if (test_data->upn && test_data->other_upn_suffix) { >+ torture_skip(tctx, "UPN test for UPN with other UPN suffix only runs with enterprise principals"); >+ } > principal_flags = 0; > } > >@@ -355,12 +420,18 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > NULL, krb_options); > krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); > >- assertion_message = talloc_asprintf(tctx, >- "krb5_get_init_creds_password for %s failed: %s", >- principal_string, >- smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >- torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >- >+ if (test_data->netbios_realm && test_data->upn) { >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "Got wrong error_code from krb5_get_init_creds_password"); >+ /* We can't proceed with more checks */ >+ return true; >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ } >+ > /* > * Assert that the reply was with the correct type of > * principal, depending on the flags we set >@@ -440,27 +511,28 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > suite->description = talloc_strdup(suite, "Kerberos Canonicalisation tests"); > > for (i = 0; i < TEST_ALL; i++) { >- char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s", >+ char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s.%s", > (i & TEST_CANONICALIZE) ? "canon" : "no-canon", > (i & TEST_ENTERPRISE) ? "enterprise" : "no-enterprise", > (i & TEST_UPPER_REALM) ? "uc-realm" : "lc-realm", > (i & TEST_UPPER_USERNAME) ? "uc-user" : "lc-user", > (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm", >- (i & TEST_WIN2K) ? "win2k" : "no-win2k"); >+ (i & TEST_WIN2K) ? "win2k" : "no-win2k", >+ (i & TEST_UPN) ? "upn" : "no-upn"); >+ >+ struct test_data *test_data = talloc_zero(suite, struct test_data); > >- struct test_data *test_data = talloc(suite, struct test_data); >- if (i & TEST_NETBIOS_REALM) { >- test_data->realm = cli_credentials_get_domain(cmdline_credentials); >- } else { >- test_data->realm = cli_credentials_get_realm(cmdline_credentials); >- } > test_data->real_realm = cli_credentials_get_realm(cmdline_credentials); >+ test_data->real_domain = cli_credentials_get_domain(cmdline_credentials); > test_data->username = cli_credentials_get_username(cmdline_credentials); >+ test_data->real_username = cli_credentials_get_username(cmdline_credentials); > test_data->canonicalize = (i & TEST_CANONICALIZE) != 0; > test_data->enterprise = (i & TEST_ENTERPRISE) != 0; > test_data->upper_realm = (i & TEST_UPPER_REALM) != 0; > test_data->upper_username = (i & TEST_UPPER_USERNAME) != 0; >+ test_data->netbios_realm = (i & TEST_NETBIOS_REALM) != 0; > test_data->win2k = (i & TEST_WIN2K) != 0; >+ test_data->upn = (i & TEST_UPN) != 0; > torture_suite_add_simple_tcase_const(suite, name, torture_krb5_as_req_canon, > test_data); > >-- >2.1.4 > > >From 75bd67799b81e98e2d228bf91d9aac08fd918f48 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 23 Jan 2015 17:19:41 +1300 >Subject: [PATCH 29/60] selftest: Run krb5.kdc test against users with a UPN > >This tests both a UPN in our own realm, and a UPN with a non-realm suffix. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> >Autobuild-Date(master): Fri Jan 23 08:10:07 CET 2015 on sn-devel-104 > >(cherry picked from commit fba69f4a89bedaf799b3a3c78cde43f4f1d1aba3) >--- > selftest/target/Samba4.pm | 22 ++++++++++++++++++++++ > source4/selftest/tests.py | 4 ++-- > 2 files changed, 24 insertions(+), 2 deletions(-) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 721a7f5..85a328c 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -780,6 +780,18 @@ sub provision_raw_step2($$$) > return undef; > } > >+ my $ldbmodify = Samba::bindir_path($self, "ldbmodify"); >+ my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); >+ my $user_dn = "cn=testallowed,cn=users,$base_dn"; >+ open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); >+ print LDIF "dn: $user_dn >+changetype: modify >+replace: userPrincipalName >+userPrincipalName: testallowed_upn\@$ctx->{realm} >+- >+"; >+ close(LDIF); >+ > $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") > . " user add --configfile=$ctx->{smb_conf} testdenied $ctx->{password}"; > unless (system($samba_tool_cmd) == 0) { >@@ -787,6 +799,16 @@ sub provision_raw_step2($$$) > return undef; > } > >+ my $user_dn = "cn=testdenied,cn=users,$base_dn"; >+ open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); >+ print LDIF "dn: $user_dn >+changetype: modify >+replace: userPrincipalName >+userPrincipalName: testdenied_upn\@$ctx->{realm}.upn >+- >+"; >+ close(LDIF); >+ > $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") > . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' testallowed"; > unless (system($samba_tool_cmd) == 0) { >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index b09fde2..116367e 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -554,7 +554,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with specified account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestdenied%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-upn=testdenied_upn@$REALM.upn'] + extra_options, > "samba4.krb5.kdc with account DENIED permission to replicate to an RODC") > > # These last two tests are for users cached at the RODC >@@ -565,7 +565,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > > plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, > "samba4.krb5.kdc with machine account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-upn=testallowed_upn@$REALM'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > > # TODO: Verifying the databases really should be a part of the >-- >2.1.4 > > >From 46f3ac400cc051d503b537554eb8937d706faa40 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Fri, 23 Jan 2015 13:01:27 +0100 >Subject: [PATCH 30/60] s4-torture: the new krb5 kdc tests are heimdal, not dc > specific. >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Guenther > >Signed-off-by: Günther Deschner <gd@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 94cd324be9a24fcdcbf0b1c4a9dfc7a49d074b8a) >--- > source4/torture/krb5/wscript_build | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/torture/krb5/wscript_build b/source4/torture/krb5/wscript_build >index 81a5b09..3d3a840 100644 >--- a/source4/torture/krb5/wscript_build >+++ b/source4/torture/krb5/wscript_build >@@ -1,5 +1,5 @@ > #!/usr/bin/env python >-if bld.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): >+if bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'): > bld.SAMBA_MODULE('TORTURE_KRB5', > source='kdc.c kdc-canon.c', > autoproto='proto.h', >-- >2.1.4 > > >From ed05a505eee556b6a94c7991512fd4acc810c171 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Sat, 7 Feb 2015 20:58:42 +1300 >Subject: [PATCH 31/60] torture-krb5: Do not do post-recv checks if the packet > recv failed > >This may be the cause of the flapping tests in this code previously, >as the recv_buf would be 0 length. > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-By: Jelmer Vernooij <jelmer@samba.org> >Reviewed-by: Kamen Mazdrashki <kamenim@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit d7752757c29d69547b361ed094f04ae4db4c9f8a) >--- > source4/torture/krb5/kdc-canon.c | 6 +++++- > source4/torture/krb5/kdc.c | 4 +++- > 2 files changed, 8 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index a0df97b..c14be00 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -212,7 +212,11 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > } > > k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, >- hi, timeout, &modified_send_buf, recv_buf); >+ hi, timeout, &modified_send_buf, >+ recv_buf); >+ if (k5ret != 0) { >+ return k5ret; >+ } > > ok = torture_krb5_post_recv_test(test_context, recv_buf); > if (ok == false) { >diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c >index a7b6ac8..a6fcde9 100644 >--- a/source4/torture/krb5/kdc.c >+++ b/source4/torture/krb5/kdc.c >@@ -267,7 +267,9 @@ static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context > > k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, > hi, timeout, send_buf, recv_buf); >- >+ if (k5ret != 0) { >+ return k5ret; >+ } > ok = torture_krb5_post_recv_test(test_context, recv_buf); > if (ok == false) { > return EINVAL; >-- >2.1.4 > > >From f15287f45e2b9707644a0ad5135271f204edaf4a Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 2 Feb 2015 12:38:07 +1300 >Subject: [PATCH 32/60] kdc: fixup KDC to use functions portable to MIT krb5 > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 01c6991d362d26c71604649ad7a2dd4e6b695918) >--- > source4/kdc/db-glue.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index 042abe6..3cd425a 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -1264,7 +1264,7 @@ static krb5_error_code samba_kdc_lookup_client(krb5_context context, > NTSTATUS nt_status; > char *principal_string; > >- if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ if (krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { > principal_string = smb_krb5_principal_get_comp_string(mem_ctx, context, > principal, 0); > if (principal_string == NULL) { >-- >2.1.4 > > >From dd6cc85b8cc29e4d578e5158ab69cd1c85ee2b3a Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 30 Jan 2015 12:31:29 +1300 >Subject: [PATCH 33/60] kdc: make Samba KDC pass new TGS-REQ and AS-REQ (to > self) testing > >This also reverts 51b94ab3fd4d13ee38813eb7d20db11edaa667a8 as our >testing shows Windows 2012R2 does not have this behaviour. > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit f32564d643a76b2618395096d26d99654b33dd98) >--- > source4/kdc/db-glue.c | 206 ++++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 148 insertions(+), 58 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index 3cd425a..aa73641 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -640,47 +640,62 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > > entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); > if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { >- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); >- if (ret) { >- return ret; >- } >- >- /* >- * Windows seems to canonicalize the principal >- * in a TGS REP even if the client did not specify >- * the canonicalize flag. >- */ >- if (flags & (HDB_F_CANON|HDB_F_FOR_TGS_REQ)) { >- /* When requested to do so, ensure that the >+ if (flags & (HDB_F_CANON)) { >+ /* >+ * When requested to do so, ensure that the > * both realm values in the principal are set >- * to the upper case, canonical realm */ >- free(entry_ex->entry.principal->name.name_string.val[1]); >- entry_ex->entry.principal->name.name_string.val[1] = strdup(lpcfg_realm(lp_ctx)); >- if (!entry_ex->entry.principal->name.name_string.val[1]) { >- ret = ENOMEM; >- krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!"); >- return ret; >+ * to the upper case, canonical realm >+ */ >+ ret = krb5_make_principal(context, &entry_ex->entry.principal, >+ lpcfg_realm(lp_ctx), "krbtgt", >+ lpcfg_realm(lp_ctx), NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } >+ krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST); >+ } else { >+ ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } >+ /* >+ * this appears to be required regardless of >+ * the canonicalize flag from the client >+ */ >+ ret = krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; > } > } >- /* >- * this has to be with malloc(), and appears to be >- * required regardless of the canonicalize flag from >- * the client >- */ >- krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); > > } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { >- krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >- } else if (flags & HDB_F_CANON) { >- krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >+ ret = krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } >+ } else if (flags & HDB_F_CANON && flags & HDB_F_FOR_AS_REQ) { >+ /* >+ * HDB_F_CANON maps from the canonicalize flag in the >+ * packet, and has a different meaning between AS-REQ >+ * and TGS-REQ. We only change the principal in the AS-REQ case >+ */ >+ ret = krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > } else { >- ret = copy_Principal(principal, entry_ex->entry.principal); >+ ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); > if (ret) { > krb5_clear_error_message(context); > goto out; > } > >- if (principal->name.name_type != KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ if (krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) { > /* While we have copied the client principal, tests > * show that Win2k3 returns the 'corrected' realm, not > * the client-specified realm. This code attempts to >@@ -688,7 +703,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > * we determine from our records */ > > /* this has to be with malloc() */ >- krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ ret = krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > } > } > >@@ -706,7 +725,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > entry_ex->entry.flags.server = 0; > } > } >- >+ /* >+ * To give the correct type of error to the client, we must >+ * not just return the entry without .server set, we must >+ * pretend the principal does not exist. Otherwise we may >+ * return ERR_POLICY instead of >+ * KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN >+ */ >+ if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && entry_ex->entry.flags.server == 0) { >+ ret = HDB_ERR_NOENTRY; >+ krb5_set_error_message(context, ret, "samba_kdc_message2entry: no servicePrincipalName present for this server, refusing with no-such-entry"); >+ goto out; >+ } > if (flags & HDB_F_ADMIN_DATA) { > /* These (created_by, modified_by) parts of the entry are not relevant for Samba4's use > * of the Heimdal KDC. They are stored in a the traditional >@@ -716,9 +746,13 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > /* use 'whenCreated' */ > entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); > /* use 'kadmin' for now (needed by mit_samba) */ >- krb5_make_principal(context, >- &entry_ex->entry.created_by.principal, >- lpcfg_realm(lp_ctx), "kadmin", NULL); >+ ret = krb5_make_principal(context, >+ &entry_ex->entry.created_by.principal, >+ lpcfg_realm(lp_ctx), "kadmin", NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > > entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event)); > if (entry_ex->entry.modified_by == NULL) { >@@ -730,9 +764,13 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, > /* use 'whenChanged' */ > entry_ex->entry.modified_by->time = ldb_msg_find_krb5time_ldap_time(msg, "whenChanged", 0); > /* use 'kadmin' for now (needed by mit_samba) */ >- krb5_make_principal(context, >- &entry_ex->entry.modified_by->principal, >- lpcfg_realm(lp_ctx), "kadmin", NULL); >+ ret = krb5_make_principal(context, >+ &entry_ex->entry.modified_by->principal, >+ lpcfg_realm(lp_ctx), "kadmin", NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > } > > >@@ -948,9 +986,13 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > /* use 'whenCreated' */ > entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); > /* use 'kadmin' for now (needed by mit_samba) */ >- krb5_make_principal(context, >+ ret = krb5_make_principal(context, > &entry_ex->entry.created_by.principal, > realm, "kadmin", NULL); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > > entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); > if (entry_ex->entry.principal == NULL) { >@@ -973,7 +1015,11 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, > * we determine from our records > */ > >- krb5_principal_set_realm(context, entry_ex->entry.principal, realm); >+ ret = krb5_principal_set_realm(context, entry_ex->entry.principal, realm); >+ if (ret) { >+ krb5_clear_error_message(context); >+ goto out; >+ } > > entry_ex->entry.valid_start = NULL; > >@@ -1308,8 +1354,8 @@ static krb5_error_code samba_kdc_fetch_client(krb5_context context, > struct ldb_message *msg = NULL; > > ret = samba_kdc_lookup_client(context, kdc_db_ctx, >- mem_ctx, principal, user_attrs, >- &realm_dn, &msg); >+ mem_ctx, principal, user_attrs, >+ &realm_dn, &msg); > if (ret != 0) { > return ret; > } >@@ -1460,15 +1506,17 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context, > } > > static krb5_error_code samba_kdc_lookup_server(krb5_context context, >- struct samba_kdc_db_context *kdc_db_ctx, >- TALLOC_CTX *mem_ctx, >- krb5_const_principal principal, >- const char **attrs, >- struct ldb_dn **realm_dn, >- struct ldb_message **msg) >+ struct samba_kdc_db_context *kdc_db_ctx, >+ TALLOC_CTX *mem_ctx, >+ krb5_const_principal principal, >+ unsigned flags, >+ const char **attrs, >+ struct ldb_dn **realm_dn, >+ struct ldb_message **msg) > { > krb5_error_code ret; >- if (principal->name.name_string.len >= 2) { >+ if ((smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) >+ && krb5_princ_size(context, principal) >= 2) { > /* 'normal server' case */ > int ldb_ret; > NTSTATUS nt_status; >@@ -1503,14 +1551,53 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context, > if (ldb_ret != LDB_SUCCESS) { > return HDB_ERR_NOENTRY; > } >- >+ return 0; >+ } else if (!(flags & HDB_F_FOR_AS_REQ) >+ && smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ /* >+ * The behaviour of accepting an >+ * KRB5_NT_ENTERPRISE_PRINCIPAL server principal >+ * containing a UPN only applies to TGS-REQ packets, >+ * not AS-REQ packets. >+ */ >+ return samba_kdc_lookup_client(context, kdc_db_ctx, >+ mem_ctx, principal, attrs, >+ realm_dn, msg); > } else { >+ /* >+ * This case is for: >+ * - the AS-REQ, where we only accept >+ * samAccountName based lookups for the server, no >+ * matter if the name is an >+ * KRB5_NT_ENTERPRISE_PRINCIPAL or not >+ * - for the TGS-REQ when we are not given an >+ * KRB5_NT_ENTERPRISE_PRINCIPAL, which also must >+ * only lookup samAccountName based names. >+ */ > int lret; > char *short_princ; >- /* const char *realm; */ >+ krb5_principal enterprise_prinicpal = NULL; >+ >+ if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { >+ /* Need to reparse the enterprise principal to find the real target */ >+ if (principal->name.name_string.len != 1) { >+ ret = KRB5_PARSE_MALFORMED; >+ krb5_set_error_message(context, ret, "samba_kdc_lookup_server: request for an " >+ "enterprise principal with wrong (%d) number of components", >+ principal->name.name_string.len); >+ return ret; >+ } >+ ret = krb5_parse_name(context, principal->name.name_string.val[0], >+ &enterprise_prinicpal); >+ if (ret) { >+ talloc_free(mem_ctx); >+ return ret; >+ } >+ principal = enterprise_prinicpal; >+ } >+ > /* server as client principal case, but we must not lookup userPrincipalNames */ > *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); >- /* realm = krb5_principal_get_realm(context, principal); */ > > /* TODO: Check if it is our realm, otherwise give referral */ > >@@ -1540,11 +1627,13 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context, > return HDB_ERR_NOENTRY; > } > free(short_princ); >+ return 0; > } >- >- return 0; >+ return HDB_ERR_NOENTRY; > } > >+ >+ > static krb5_error_code samba_kdc_fetch_server(krb5_context context, > struct samba_kdc_db_context *kdc_db_ctx, > TALLOC_CTX *mem_ctx, >@@ -1557,7 +1646,7 @@ static krb5_error_code samba_kdc_fetch_server(krb5_context context, > struct ldb_message *msg; > > ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, principal, >- server_attrs, &realm_dn, &msg); >+ flags, server_attrs, &realm_dn, &msg); > if (ret != 0) { > return ret; > } >@@ -1787,7 +1876,8 @@ samba_kdc_check_s4u2self(krb5_context context, > } > > ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal, >- delegation_check_attrs, &realm_dn, &msg); >+ HDB_F_GET_CLIENT|HDB_F_GET_SERVER, >+ delegation_check_attrs, &realm_dn, &msg); > > krb5_free_principal(context, enterprise_prinicpal); > >@@ -1841,8 +1931,8 @@ samba_kdc_check_pkinit_ms_upn_match(krb5_context context, > } > > ret = samba_kdc_lookup_client(context, kdc_db_ctx, >- mem_ctx, certificate_principal, >- ms_upn_check_attrs, &realm_dn, &msg); >+ mem_ctx, certificate_principal, >+ ms_upn_check_attrs, &realm_dn, &msg); > > if (ret != 0) { > talloc_free(mem_ctx); >-- >2.1.4 > > >From 7e8461959213b7009a8307416f8728cc1ca9764d Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 30 Jan 2015 12:31:10 +1300 >Subject: [PATCH 34/60] torture-krb5: add TGS-REQ testing to krb5.kdc.canon > testsuite > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit bcd33c0dce793427b2c408ad592801c881770d4d) >--- > source4/selftest/tests.py | 2 +- > source4/torture/krb5/kdc-canon.c | 319 ++++++++++++++++++++++++++++++++++++--- > 2 files changed, 295 insertions(+), 26 deletions(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 116367e..bddba41 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -563,7 +563,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > else: > extra_options = [] > >- plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:expect_machine_account=true'] + extra_options, > "samba4.krb5.kdc with machine account") > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-upn=testallowed_upn@$REALM'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index c14be00..408e356 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -40,6 +40,7 @@ > #define TEST_ALL 0x000007F > > struct test_data { >+ const char *test_name; > struct smb_krb5_context *smb_krb5_context; > const char *realm; > const char *real_realm; >@@ -55,14 +56,25 @@ struct test_data { > bool upn; > bool other_upn_suffix; > }; >- >+ >+enum test_stage { >+ TEST_AS_REQ = 0, >+ TEST_SELF_TRUST_TGS_REQ, >+ TEST_TGS_REQ, >+ TEST_TGS_REQ_KRBTGT, >+ TEST_DONE >+}; >+ > struct torture_krb5_context { > struct torture_context *tctx; > struct addrinfo *server; > struct test_data *test_data; > int packet_count; >+ enum test_stage test_stage; > AS_REQ as_req; > AS_REP as_rep; >+ TGS_REQ tgs_req; >+ TGS_REP tgs_rep; > }; > > >@@ -79,14 +91,9 @@ struct torture_krb5_context { > * > */ > >-static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) > { > krb5_error_code k5ret; >- size_t used; >- torture_assert_int_equal(test_context->tctx, >- decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0, >- "decode_AS_REQ failed"); >- > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno"); > if (test_context->test_data->canonicalize || test_context->test_data->enterprise) { >@@ -115,6 +122,87 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > return true; > } > >+static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+{ >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ >+ >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.len, 2, >+ "Mismatch in name between request and expected request, expected krbtgt/realm"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], "krbtgt", >+ "Mismatch in name between request and expected request, expected krbtgt"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], test_context->test_data->realm, >+ "Mismatch in realm part of cross-realm request principal between request and expected request"); >+ >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ >+static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+{ >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->enterprise) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ >+static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+{ >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->canonicalize) { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ } else { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ } >+ >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ > /* > * Confirm that the incoming packet from the KDC meets certain > * expectations. This uses a packet count to work out what test we >@@ -123,7 +211,7 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context > * > */ > >-static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > KRB_ERROR error; > size_t used; >@@ -178,6 +266,88 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex > return true; > } > >+static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ "decode_TGS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->tgs_rep.ticket.realm, "Mismatch in realm between request and ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { >+ torture_assert_int_not_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Did not get a RODC number in the KVNO"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO"); >+ } >+ free_TGS_REP(&test_context->tgs_rep); >+ torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets"); >+ test_context->packet_count = 0; >+ test_context->test_stage = TEST_TGS_REQ; >+ free_TGS_REQ(&test_context->tgs_req); >+ return true; >+} >+ >+static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ KRB_ERROR error; >+ size_t used; >+ if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) { >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ "decode_TGS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between ticket response and expected upper case REALM"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); >+ free_TGS_REP(&test_context->tgs_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); >+ free_TGS_REQ(&test_context->tgs_req); >+ return true; >+} >+ > /* > * This function is set in torture_krb5_init_context_canon as krb5 > * send_and_recv function. This allows us to override what server the >@@ -200,17 +370,50 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > krb5_data *recv_buf) > { > krb5_error_code k5ret; >- bool ok; >+ bool ok = false; > krb5_data modified_send_buf; >+ size_t used; > > struct torture_krb5_context *test_context > = talloc_get_type_abort(data, struct torture_krb5_context); > >- ok = torture_krb5_pre_send_test(test_context, send_buf, &modified_send_buf); >+ if (test_context->test_stage == TEST_DONE) { >+ torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs"); >+ return EINVAL; >+ } >+ k5ret = decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used); >+ >+ if (k5ret == 0) { >+ test_context->test_stage = TEST_AS_REQ; >+ ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, used, &modified_send_buf); >+ } else { >+ k5ret = decode_TGS_REQ(send_buf->data, send_buf->length, &test_context->tgs_req, &used); >+ if (k5ret == 0) { >+ if (test_context->test_stage == TEST_AS_REQ) { >+ test_context->packet_count = 0; >+ if (test_context->test_data->canonicalize == false >+ || test_context->test_data->enterprise >+ || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >+ test_context->test_stage = TEST_TGS_REQ; >+ } else { >+ test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ } >+ } >+ if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { >+ ok = torture_krb5_pre_send_self_trust_tgs_req_test(test_context, send_buf, used, &modified_send_buf); >+ } else if (test_context->test_stage == TEST_TGS_REQ) { >+ ok = torture_krb5_pre_send_tgs_req_test(test_context, send_buf, used, &modified_send_buf); >+ } else if (test_context->test_stage == TEST_TGS_REQ_KRBTGT) { >+ ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf, used, &modified_send_buf); >+ } >+ } else { >+ torture_warning(test_context->tctx, "Failed to parse outgoing packet from krb5 libs"); >+ } >+ } > if (ok == false) { > return EINVAL; > } >- >+ > k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, > hi, timeout, &modified_send_buf, > recv_buf); >@@ -218,7 +421,15 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > return k5ret; > } > >- ok = torture_krb5_post_recv_test(test_context, recv_buf); >+ if (test_context->test_stage == TEST_AS_REQ) { >+ ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); >+ } else if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { >+ ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); >+ } else if (test_context->test_stage == TEST_TGS_REQ) { >+ ok = torture_krb5_post_recv_tgs_req_test(test_context, recv_buf); >+ } else if (test_context->test_stage == TEST_TGS_REQ_KRBTGT) { >+ ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); >+ } > if (ok == false) { > return EINVAL; > } >@@ -272,8 +483,6 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > krb5_error_code k5ret; > krb5_get_init_creds_opt *krb_options = NULL; > struct test_data *test_data = talloc_get_type_abort(tcase_data, struct test_data); >- char *realm; >- char *upper_real_realm; > char *username; > krb5_principal principal; > krb5_principal expected_principal; >@@ -287,6 +496,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > struct smb_krb5_context *smb_krb5_context; > bool ok; > krb5_creds my_creds; >+ krb5_ccache ccache; >+ krb5_auth_context auth_context; >+ char *cc_name; >+ krb5_data in_data, enc_ticket; > > const char *upn = torture_setting_string(tctx, "krb5-upn", ""); > >@@ -343,9 +556,9 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > torture_assert(tctx, ok, "torture_krb5_init_context failed"); > > if (test_data->upper_realm) { >- realm = strupper_talloc(test_data, test_data->realm); >+ test_data->realm = strupper_talloc(test_data, test_data->realm); > } else { >- realm = strlower_talloc(test_data, test_data->realm); >+ test_data->realm = strlower_talloc(test_data, test_data->realm); > } > if (test_data->upper_username) { > username = strupper_talloc(test_data, test_data->username); >@@ -353,10 +566,8 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > username = talloc_strdup(test_data, test_data->username); > } > >- principal_string = talloc_asprintf(test_data, "%s@%s", username, realm); >+ principal_string = talloc_asprintf(test_data, "%s@%s", username, test_data->realm); > >- upper_real_realm = strupper_talloc(test_data, test_data->real_realm); >- > /* > * If we are set to canonicalize, we get back the fixed UPPER > * case realm, and the real username (ie matching LDAP >@@ -369,11 +580,11 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * fixed UPPER case realm, but the as-sent username > */ > if (test_data->canonicalize) { >- expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->real_username, upper_real_realm); >+ expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->real_username, test_data->real_realm); > } else if (test_data->enterprise) { > expected_principal_string = principal_string; > } else { >- expected_principal_string = talloc_asprintf(test_data, "%s@%s", username, upper_real_realm); >+ expected_principal_string = talloc_asprintf(test_data, "%s@%s", username, test_data->real_realm); > } > > if (test_data->enterprise) { >@@ -491,7 +702,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > } else { > torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, > my_creds.server, 1), >- realm, >+ test_data->realm, > > "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]"); > } >@@ -500,10 +711,67 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > test_data->real_realm, > "smb_krb5_init_context gave incorrect my_creds.server->realm"); > >+ /* Store the result of the 'kinit' above into a memory ccache */ >+ cc_name = talloc_asprintf(tctx, "MEMORY:%s", test_data->test_name); >+ torture_assert_int_equal(tctx, krb5_cc_resolve(smb_krb5_context->krb5_context, cc_name, >+ &ccache), >+ 0, "krb5_cc_resolve failed"); >+ >+ torture_assert_int_equal(tctx, krb5_cc_initialize(smb_krb5_context->krb5_context, >+ ccache, my_creds.client), >+ 0, "krb5_cc_initialize failed"); >+ >+ torture_assert_int_equal(tctx, krb5_cc_store_cred(smb_krb5_context->krb5_context, >+ ccache, &my_creds), >+ 0, "krb5_cc_store_cred failed"); >+ >+ /* Prepare a TGS-REQ */ >+ torture_assert_int_equal(tctx, krb5_auth_con_init(smb_krb5_context->krb5_context, &auth_context), >+ 0, "krb5_auth_con_init failed"); >+ >+ /* Confirm we can not ask for our own name as a server */ >+ in_data.length = 0; >+ k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, >+ &auth_context, >+ 0, >+ principal, >+ &in_data, ccache, >+ &enc_ticket); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_mk_req_exact for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ if (torture_setting_bool(tctx, "expect_machine_account", false)) { >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ } else { >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, assertion_message); >+ } >+ >+ /* >+ * Ask for a ticket to the KDC krbtgt account itself. The >+ * value in my_creds.server varies (in the non-canonicalize >+ * case) per the AS-REQ tests above, so we cover the same >+ * variations >+ */ >+ in_data.length = 0; >+ k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, >+ &auth_context, >+ 0, >+ my_creds.server, >+ &in_data, ccache, >+ &enc_ticket); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_mk_req_exact for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ > krb5_free_principal(smb_krb5_context->krb5_context, principal); > >- k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds); >- torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed"); >+ torture_assert_int_equal(tctx, krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds), >+ 0, "krb5_free_cred_contents failed"); > > return true; > } >@@ -526,7 +794,8 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > > struct test_data *test_data = talloc_zero(suite, struct test_data); > >- test_data->real_realm = cli_credentials_get_realm(cmdline_credentials); >+ test_data->test_name = name; >+ test_data->real_realm = strupper_talloc(test_data, cli_credentials_get_realm(cmdline_credentials)); > test_data->real_domain = cli_credentials_get_domain(cmdline_credentials); > test_data->username = cli_credentials_get_username(cmdline_credentials); > test_data->real_username = cli_credentials_get_username(cmdline_credentials); >-- >2.1.4 > > >From 21861306e0dfd4bbb627efb095dc4ca8a9547741 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 30 Jan 2015 18:17:16 +1300 >Subject: [PATCH 35/60] torture-krb5: Add tests for the canonicalise TGS-REQ > case > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 0a4374a93aced30245c0719e6a279f1dd7ea78f1) >--- > source4/torture/krb5/kdc-canon.c | 199 ++++++++++++++++++++++++++++++++++----- > 1 file changed, 173 insertions(+), 26 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 408e356..3c33884 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -59,6 +59,7 @@ struct test_data { > > enum test_stage { > TEST_AS_REQ = 0, >+ TEST_TGS_REQ_CANON, > TEST_SELF_TRUST_TGS_REQ, > TEST_TGS_REQ, > TEST_TGS_REQ_KRBTGT, >@@ -122,18 +123,60 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ > return true; > } > >-static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) > { > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, true, "krb5 libs unexpectedly did not set canonicalize!"); > >+ if (test_context->test_data->enterprise) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); > >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->real_realm, >+ } else if (test_context->test_data->canonicalize) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, > "Mismatch in realm between request and expected request"); > >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } >+ >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ >+static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+{ >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->canonicalize) { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ } else { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ } > torture_assert_int_equal(test_context->tctx, > test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, > "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >@@ -146,7 +189,6 @@ static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_co > torture_assert_str_equal(test_context->tctx, > test_context->tgs_req.req_body.sname->name_string.val[1], test_context->test_data->realm, > "Mismatch in realm part of cross-realm request principal between request and expected request"); >- > *modified_send_buf = *send_buf; > > return true; >@@ -156,7 +198,7 @@ static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context *test > { > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); > > if (test_context->test_data->enterprise) { > torture_assert_int_equal(test_context->tctx, >@@ -175,6 +217,7 @@ static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context *test > "Mismatch in realm between request and expected request"); > > } >+ > *modified_send_buf = *send_buf; > > return true; >@@ -184,7 +227,7 @@ static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_contex > { > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); > > if (test_context->test_data->canonicalize) { > torture_assert_str_equal(test_context->tctx, >@@ -266,6 +309,60 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > return true; > } > >+static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ KRB_ERROR error; >+ size_t used; >+ if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) { >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ "decode_TGS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between ticket response and expected upper case REALM"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); >+ free_TGS_REP(&test_context->tgs_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets"); >+ free_TGS_REQ(&test_context->tgs_req); >+ >+ /* >+ * This tries to guess when the krb5 >+ * libs will ask for a cross-realm >+ * ticket, and when they will just ask >+ * the KDC directly. We always ask directly if 'canonicalize == true' becuase we use different client calls in that case. >+ */ >+ if (test_context->test_data->canonicalize == false >+ || test_context->test_data->enterprise >+ || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >+ test_context->test_stage = TEST_TGS_REQ; >+ } else { >+ test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ } >+ return true; >+} >+ > static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > size_t used; >@@ -301,7 +398,7 @@ static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_c > 0, "Unexpecedly got a RODC number in the KVNO"); > } > free_TGS_REP(&test_context->tgs_rep); >- torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets"); >+ torture_assert(test_context->tctx, test_context->packet_count == 1, "too many packets"); > test_context->packet_count = 0; > test_context->test_stage = TEST_TGS_REQ; > free_TGS_REQ(&test_context->tgs_req); >@@ -343,7 +440,7 @@ static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context *tes > 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); > free_TGS_REP(&test_context->tgs_rep); > } >- torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); >+ torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); > free_TGS_REQ(&test_context->tgs_req); > return true; > } >@@ -381,25 +478,31 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs"); > return EINVAL; > } >- k5ret = decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used); > >- if (k5ret == 0) { >- test_context->test_stage = TEST_AS_REQ; >+ if (decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used) == 0) { > ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, used, &modified_send_buf); > } else { > k5ret = decode_TGS_REQ(send_buf->data, send_buf->length, &test_context->tgs_req, &used); > if (k5ret == 0) { > if (test_context->test_stage == TEST_AS_REQ) { > test_context->packet_count = 0; >- if (test_context->test_data->canonicalize == false >- || test_context->test_data->enterprise >- || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >- test_context->test_stage = TEST_TGS_REQ; >+ if (test_context->test_data->canonicalize == false && test_context->test_data->enterprise == false >+ && (test_context->test_data->upper_realm == false || test_context->test_data->netbios_realm == true)) { >+ if (test_context->test_data->canonicalize == false >+ || test_context->test_data->enterprise >+ || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >+ test_context->test_stage = TEST_TGS_REQ; >+ } else { >+ test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ } > } else { >- test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ test_context->test_stage = TEST_TGS_REQ_CANON; > } > } >- if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { >+ >+ if (test_context->test_stage == TEST_TGS_REQ_CANON) { >+ ok = torture_krb5_pre_send_tgs_req_canon_test(test_context, send_buf, used, &modified_send_buf); >+ } else if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { > ok = torture_krb5_pre_send_self_trust_tgs_req_test(test_context, send_buf, used, &modified_send_buf); > } else if (test_context->test_stage == TEST_TGS_REQ) { > ok = torture_krb5_pre_send_tgs_req_test(test_context, send_buf, used, &modified_send_buf); >@@ -423,6 +526,8 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > > if (test_context->test_stage == TEST_AS_REQ) { > ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); >+ } else if (test_context->test_stage == TEST_TGS_REQ_CANON) { >+ ok = torture_krb5_post_recv_tgs_req_canon_test(test_context, recv_buf); > } else if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); > } else if (test_context->test_stage == TEST_TGS_REQ) { >@@ -496,10 +601,12 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > struct smb_krb5_context *smb_krb5_context; > bool ok; > krb5_creds my_creds; >+ krb5_creds *server_creds; > krb5_ccache ccache; > krb5_auth_context auth_context; > char *cc_name; > krb5_data in_data, enc_ticket; >+ krb5_get_creds_opt opt; > > const char *upn = torture_setting_string(tctx, "krb5-upn", ""); > >@@ -726,10 +833,56 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > 0, "krb5_cc_store_cred failed"); > > /* Prepare a TGS-REQ */ >+ torture_assert_int_equal(tctx, >+ krb5_get_creds_opt_alloc(smb_krb5_context->krb5_context, &opt), >+ 0, "krb5_get_creds_opt_alloc"); >+ >+ krb5_get_creds_opt_add_options(smb_krb5_context->krb5_context, >+ opt, >+ KRB5_GC_CANONICALIZE); >+ >+ /* Confirm if we can get a ticket to our own name */ >+ k5ret = krb5_get_creds(smb_krb5_context->krb5_context, opt, ccache, principal, &server_creds); >+ >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_creds for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ >+ /* We should only be able to get a ticket to our own name if we are a machine account */ >+ if (torture_setting_bool(tctx, "expect_machine_account", false)) { >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ torture_assert_int_equal(tctx, krb5_cc_store_cred(smb_krb5_context->krb5_context, >+ ccache, server_creds), >+ 0, "krb5_cc_store_cred failed"); >+ >+ torture_assert_int_equal(tctx, >+ krb5_free_creds(smb_krb5_context->krb5_context, >+ server_creds), >+ 0, "krb5_free_cred_contents failed"); >+ >+ } else { >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, assertion_message); >+ } >+ } >+ /* >+ * Confirm gettting a ticket to pass to the server. >+ * >+ * This triggers the client to attempt to get a >+ * cross-realm ticket between the alternate names of >+ * the server, and we need to confirm that behaviour. >+ * >+ * The cache isn't used because we asked the above not to >+ * pollute the cache >+ */ >+ > torture_assert_int_equal(tctx, krb5_auth_con_init(smb_krb5_context->krb5_context, &auth_context), > 0, "krb5_auth_con_init failed"); > >- /* Confirm we can not ask for our own name as a server */ > in_data.length = 0; > k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, > &auth_context, >@@ -748,12 +901,6 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, assertion_message); > } > >- /* >- * Ask for a ticket to the KDC krbtgt account itself. The >- * value in my_creds.server varies (in the non-canonicalize >- * case) per the AS-REQ tests above, so we cover the same >- * variations >- */ > in_data.length = 0; > k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, > &auth_context, >-- >2.1.4 > > >From fff1c45523ffc522cf3b901bcb035a77beeff723 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 2 Feb 2015 12:18:23 +1300 >Subject: [PATCH 36/60] torture-krb5: Reformat and re-work test to be easier to > follow > >The behaviour is the same as in the previous commit, but it is much easier to follow >as the main test code now indicates to the send_and_recv callbacks what stage of the >test we are at, and resets the packet counter between stages. > >This also re-orders the code so that the send and recv callbacks for each stage >are next to each other, and uses a case statement in the main send_and_recv driver >for clarity. > >Andrew Bartlett > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 11871c853a911b85ebb3f9ff5671ce1f9024188f) >--- > source4/torture/krb5/kdc-canon.c | 855 ++++++++++++++++++++++++++------------- > 1 file changed, 573 insertions(+), 282 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 3c33884..8c9543c 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -41,7 +41,6 @@ > > struct test_data { > const char *test_name; >- struct smb_krb5_context *smb_krb5_context; > const char *realm; > const char *real_realm; > const char *real_domain; >@@ -67,6 +66,7 @@ enum test_stage { > }; > > struct torture_krb5_context { >+ struct smb_krb5_context *smb_krb5_context; > struct torture_context *tctx; > struct addrinfo *server; > struct test_data *test_data; >@@ -80,6 +80,8 @@ struct torture_krb5_context { > > > /* >+ * TEST_AS_REQ - SEND >+ * > * Confirm that the outgoing packet meets certain expectations. This > * should be extended to further assert the correct and expected > * behaviour of the krb5 libs, so we know what we are sending to the >@@ -92,21 +94,39 @@ struct torture_krb5_context { > * > */ > >-static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >+static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_context, >+ const krb5_data *send_buf, >+ krb5_data *modified_send_buf) > { > krb5_error_code k5ret; >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, decode_AS_REQ(send_buf->data, send_buf->length, >+ &test_context->as_req, &used), >+ 0, "decode_AS_REQ for TEST_AS_REQ failed"); > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, >+ 5, "Got wrong as_req->pvno"); > if (test_context->test_data->canonicalize || test_context->test_data->enterprise) { >- torture_assert(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, "krb5 libs did not set canonicalize!"); >+ torture_assert(test_context->tctx, >+ test_context->as_req.req_body.kdc_options.canonicalize, >+ "krb5 libs did not set canonicalize!"); > } else { >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_req.req_body.kdc_options.canonicalize, >+ false, >+ "krb5 libs unexpectedly set canonicalize!"); > } > > if (test_context->test_data->enterprise) { >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.cname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, "krb5 libs did not pass principal as enterprise!"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_req.req_body.cname->name_type, >+ KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "krb5 libs did not pass principal as enterprise!"); > } else { >- torture_assert_int_equal(test_context->tctx, test_context->as_req.req_body.cname->name_type, KRB5_NT_PRINCIPAL, "krb5 libs unexpectedly set principal as enterprise!"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_req.req_body.cname->name_type, >+ KRB5_NT_PRINCIPAL, >+ "krb5 libs unexpectedly set principal as enterprise!"); > } > > /* Force off canonicalize that was forced on by the krb5 libs */ >@@ -119,171 +139,86 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ > torture_assert_int_equal(test_context->tctx, > k5ret, 0, > "encode_AS_REQ failed"); >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, "re-encode length mismatch"); >- return true; >-} >- >-static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >-{ >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, true, "krb5 libs unexpectedly did not set canonicalize!"); >- >- if (test_context->test_data->enterprise) { >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- >- } else if (test_context->test_data->canonicalize) { >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- >- } else { >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, test_context->test_data->realm, >- "Mismatch in realm between request and expected request"); >- >- } >- >- *modified_send_buf = *send_buf; >- >- return true; >-} >- >-static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >-{ >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >- >- if (test_context->test_data->canonicalize) { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- } else { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->realm, >- "Mismatch in realm between request and expected request"); >- } >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_string.len, 2, >- "Mismatch in name between request and expected request, expected krbtgt/realm"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_string.val[0], "krbtgt", >- "Mismatch in name between request and expected request, expected krbtgt"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_string.val[1], test_context->test_data->realm, >- "Mismatch in realm part of cross-realm request principal between request and expected request"); >- *modified_send_buf = *send_buf; >- >- return true; >-} >- >-static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >-{ >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >- >- if (test_context->test_data->enterprise) { >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- >- } else { >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, test_context->test_data->realm, >- "Mismatch in realm between request and expected request"); >- >- } >- >- *modified_send_buf = *send_buf; >- >- return true; >-} >- >-static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, size_t used, krb5_data *modified_send_buf) >-{ >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >- torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >- >- if (test_context->test_data->canonicalize) { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- } else { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->realm, >- "Mismatch in realm between request and expected request"); >- } >- >- *modified_send_buf = *send_buf; >- >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, >+ "re-encode length mismatch"); > return true; > } > > /* >- * Confirm that the incoming packet from the KDC meets certain >- * expectations. This uses a packet count to work out what test we >- * are in, and where in the test we are, so we can assert on the >- * expected reply packets from the KDC. >+ * TEST_AS_REQ - RECV >+ * >+ * Confirm that the reply packet from the KDC meets certain >+ * expectations as part of TEST_AS_REQ. This uses a packet count to >+ * work out what packet we are up to in the multiple exchanged >+ * triggerd by krb5_get_init_creds_password(). > * > */ > >-static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test_context, >+ const krb5_data *recv_buf) > { > KRB_ERROR error; > size_t used; > if (test_context->packet_count == 0) { >+ /* >+ * The client libs obtain the salt by attempting to >+ * authenticate without pre-authentication and getting >+ * the correct salt with the >+ * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in >+ * the test (netbios_realm && upn) that deliberatly >+ * has an incorrect principal, we check we get the >+ * correct error. >+ */ > torture_assert_int_equal(test_context->tctx, >- decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, >+ decode_KRB_ERROR(recv_buf->data, recv_buf->length, >+ &error, &used), 0, > "decode_AS_REP failed"); >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, >+ "Got wrong error.pvno"); > if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, > "Got wrong error.error_code"); > } else { >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, > "Got wrong error.error_code"); > } > free_KRB_ERROR(&error); > } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) > && (test_context->packet_count == 1)) { >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ /* >+ * The Windows 2012R2 KDC will always respond with >+ * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket >+ * won't fit, because of the PAC. (It appears to do >+ * this always, even if it will). This triggers the >+ * client to try again over TCP. >+ */ >+ torture_assert_int_equal(test_context->tctx, >+ used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ error.pvno, 5, >+ "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, > "Got wrong error.error_code"); > free_KRB_ERROR(&error); > } else { >+ /* >+ * Finally the successful packet. >+ */ > torture_assert_int_equal(test_context->tctx, >- decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, >+ decode_AS_REP(recv_buf->data, recv_buf->length, >+ &test_context->as_rep, &used), 0, > "decode_AS_REP failed"); >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); > torture_assert_int_equal(test_context->tctx, > test_context->as_rep.pvno, 5, > "Got wrong as_rep->pvno"); >@@ -293,6 +228,17 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > torture_assert(test_context->tctx, > test_context->as_rep.ticket.enc_part.kvno, > "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ >+ /* >+ * We can confirm that the correct proxy behaviour is >+ * in use on the KDC by checking the KVNO of the >+ * krbtgt account returned in the reply. >+ * >+ * A packet passed to the full RW DC will not have a >+ * KVNO in the upper bits, while a packet processed >+ * locally on the RODC will have these bits filled in >+ * the msDS-SecondaryKrbTgtNumber >+ */ > if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >@@ -309,20 +255,100 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > return true; > } > >+/* >+ * TEST_TGS_REQ_CANON >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_get_creds >+ * certain expectations, like that the canonicalize bit is set (this >+ * test is to force that handling) and that if an enterprise name was >+ * requested, that it was sent. >+ * >+ */ >+ >+static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context *test_context, >+ const krb5_data *send_buf, >+ krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_TGS_REQ_CANON test failed"); >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ true, "krb5 libs unexpectedly did not set canonicalize!"); >+ >+ if (test_context->test_data->enterprise) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } else if (test_context->test_data->canonicalize) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } >+ >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ >+/* >+ * TEST_TGS_REQ_CANON - RECV >+ * >+ * Confirm that the reply TGS-REP or error packet from the KDC meets >+ * certain expectations as part of TEST_TGS_REQ_CANON. >+ * >+ * This is triggered by krb5_get_creds() >+ * >+ */ >+ > static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > KRB_ERROR error; > size_t used; >+ >+ /* >+ * If this account did not have a servicePrincipalName, then >+ * we expect a errro packet, not a TGS-REQ >+ */ > if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) { > torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ torture_assert_int_equal(test_context->tctx, >+ error.pvno, 5, >+ "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, > "Got wrong error.error_code"); > } else { > torture_assert_int_equal(test_context->tctx, >- decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, >+ &test_context->tgs_rep, >+ &used), >+ 0, > "decode_TGS_REP failed"); >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ used, recv_buf->length, >+ "length mismatch"); > torture_assert_int_equal(test_context->tctx, > test_context->tgs_rep.pvno, 5, > "Got wrong as_rep->pvno"); >@@ -337,8 +363,9 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex > test_context->test_data->real_realm, > "Mismatch in realm between ticket response and expected upper case REALM"); > torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_type, > test_context->tgs_req.req_body.sname->name_type, >- test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ "Mismatch in name_type between request and ticket response"); > torture_assert_int_equal(test_context->tctx, > *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); >@@ -347,27 +374,80 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex > torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets"); > free_TGS_REQ(&test_context->tgs_req); > >- /* >- * This tries to guess when the krb5 >- * libs will ask for a cross-realm >- * ticket, and when they will just ask >- * the KDC directly. We always ask directly if 'canonicalize == true' becuase we use different client calls in that case. >- */ >- if (test_context->test_data->canonicalize == false >- || test_context->test_data->enterprise >- || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >- test_context->test_stage = TEST_TGS_REQ; >+ return true; >+} >+ >+/* >+ * TEST_SELF_TRUST_TGS_REQ >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact() >+ * certain expectations, like that the canonicalize bit is set (this >+ * test is to force that handling). >+ * >+ * This test is for the case where the name we ask for, while a valid >+ * alternate name for our own realm is used. The client acts as if >+ * this is cross-realm trust. >+ * >+ */ >+ >+static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context, >+ const krb5_data *send_buf, >+ krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_SELF_TRUST_TGS_REQ test failed"); >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.req_body.kdc_options.canonicalize, false, "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->canonicalize) { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); > } else { >- test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); > } >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.len, 2, >+ "Mismatch in name between request and expected request, expected krbtgt/realm"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], "krbtgt", >+ "Mismatch in name between request and expected request, expected krbtgt"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], test_context->test_data->realm, >+ "Mismatch in realm part of cross-realm request principal between request and expected request"); >+ *modified_send_buf = *send_buf; >+ > return true; > } > >+/* >+ * TEST_SELF_TRUST_TGS_REQ and TEST_TGS_REQ_KRBTGT - RECV >+ * >+ * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(), >+ * where the client is behaving as if this is a cross-realm trust due >+ * to case or netbios vs dns name differences meets certain >+ * expectations. >+ * >+ */ >+ > static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > size_t used; > torture_assert_int_equal(test_context->tctx, >- decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, >+ &test_context->tgs_rep, &used), >+ 0, > "decode_TGS_REP failed"); > torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, >@@ -381,13 +461,23 @@ static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_c > "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); > torture_assert_str_equal(test_context->tctx, > test_context->tgs_req.req_body.realm, >- test_context->tgs_rep.ticket.realm, "Mismatch in realm between request and ticket response"); >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, >- test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ test_context->tgs_rep.ticket.realm, >+ "Mismatch in realm between request and ticket response"); > torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_type, > test_context->tgs_req.req_body.sname->name_type, >- test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ "Mismatch in name_type between request and ticket response"); >+ >+ /* >+ * We can confirm that the correct proxy behaviour is >+ * in use on the KDC by checking the KVNO of the >+ * krbtgt account returned in the reply. >+ * >+ * A packet passed to the full RW DC will not have a >+ * KVNO in the upper bits, while a packet processed >+ * locally on the RODC will have these bits filled in >+ * the msDS-SecondaryKrbTgtNumber >+ */ > if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >@@ -398,27 +488,102 @@ static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_c > 0, "Unexpecedly got a RODC number in the KVNO"); > } > free_TGS_REP(&test_context->tgs_rep); >- torture_assert(test_context->tctx, test_context->packet_count == 1, "too many packets"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->packet_count, 0, >+ "too many packets"); > test_context->packet_count = 0; > test_context->test_stage = TEST_TGS_REQ; > free_TGS_REQ(&test_context->tgs_req); > return true; > } > >+/* >+ * TEST_TGS_REQ >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact() >+ * certain expectations, like that the canonicalize bit is set (this >+ * test is to force that handling) and that if an enterprise name was >+ * requested, that it was sent. >+ * >+ */ >+ >+static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_TGS_REQ test failed"); >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, >+ "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ false, >+ "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->enterprise) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ >+ } >+ >+ *modified_send_buf = *send_buf; >+ >+ return true; >+} >+ >+/* >+ * TEST_TGS_REQ - RECV >+ * >+ * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(), for >+ * the actual target service. >+ * >+ */ >+ > static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) > { > KRB_ERROR error; > size_t used; >+ /* >+ * If this account did not have a servicePrincipalName, then >+ * we expect a errro packet, not a TGS-REQ >+ */ > if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) { >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >- torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); >- torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ torture_assert_int_equal(test_context->tctx, >+ used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ error.pvno, 5, >+ "Got wrong error.pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, > "Got wrong error.error_code"); > } else { > torture_assert_int_equal(test_context->tctx, >- decode_TGS_REP(recv_buf->data, recv_buf->length, &test_context->tgs_rep, &used), 0, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, >+ &test_context->tgs_rep, &used), >+ 0, > "decode_TGS_REP failed"); >- torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); > torture_assert_int_equal(test_context->tctx, > test_context->tgs_rep.pvno, 5, > "Got wrong as_rep->pvno"); >@@ -442,6 +607,52 @@ static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context *tes > } > torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); > free_TGS_REQ(&test_context->tgs_req); >+ test_context->test_stage = TEST_DONE; >+ return true; >+} >+ >+/* >+ * TEST_TGS_REQ_KRBTGT >+ * >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact() >+ * for the krbtgt/realm principal meets certain expectations, like >+ * that the canonicalize bit is not set >+ * >+ */ >+ >+static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_TGS_REQ test failed"); >+ torture_assert_int_equal(test_context->tctx, >+ used, send_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.pvno, 5, >+ "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ false, >+ "krb5 libs unexpectedly set canonicalize!"); >+ >+ if (test_context->test_data->canonicalize) { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ } else { >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); >+ } >+ >+ *modified_send_buf = *send_buf; >+ test_context->test_stage = TEST_DONE; > return true; > } > >@@ -469,49 +680,34 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > krb5_error_code k5ret; > bool ok = false; > krb5_data modified_send_buf; >- size_t used; >- >+ > struct torture_krb5_context *test_context > = talloc_get_type_abort(data, struct torture_krb5_context); > >- if (test_context->test_stage == TEST_DONE) { >+ switch (test_context->test_stage) { >+ case TEST_DONE: > torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs"); > return EINVAL; >- } >- >- if (decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used) == 0) { >- ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, used, &modified_send_buf); >- } else { >- k5ret = decode_TGS_REQ(send_buf->data, send_buf->length, &test_context->tgs_req, &used); >- if (k5ret == 0) { >- if (test_context->test_stage == TEST_AS_REQ) { >- test_context->packet_count = 0; >- if (test_context->test_data->canonicalize == false && test_context->test_data->enterprise == false >- && (test_context->test_data->upper_realm == false || test_context->test_data->netbios_realm == true)) { >- if (test_context->test_data->canonicalize == false >- || test_context->test_data->enterprise >- || (test_context->test_data->upper_realm && test_context->test_data->netbios_realm == false)) { >- test_context->test_stage = TEST_TGS_REQ; >- } else { >- test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >- } >- } else { >- test_context->test_stage = TEST_TGS_REQ_CANON; >- } >- } >- >- if (test_context->test_stage == TEST_TGS_REQ_CANON) { >- ok = torture_krb5_pre_send_tgs_req_canon_test(test_context, send_buf, used, &modified_send_buf); >- } else if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { >- ok = torture_krb5_pre_send_self_trust_tgs_req_test(test_context, send_buf, used, &modified_send_buf); >- } else if (test_context->test_stage == TEST_TGS_REQ) { >- ok = torture_krb5_pre_send_tgs_req_test(test_context, send_buf, used, &modified_send_buf); >- } else if (test_context->test_stage == TEST_TGS_REQ_KRBTGT) { >- ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf, used, &modified_send_buf); >- } >- } else { >- torture_warning(test_context->tctx, "Failed to parse outgoing packet from krb5 libs"); >- } >+ case TEST_AS_REQ: >+ ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, >+ &modified_send_buf); >+ break; >+ case TEST_TGS_REQ_CANON: >+ ok = torture_krb5_pre_send_tgs_req_canon_test(test_context, send_buf, >+ &modified_send_buf); >+ break; >+ case TEST_SELF_TRUST_TGS_REQ: >+ ok = torture_krb5_pre_send_self_trust_tgs_req_test(test_context, send_buf, >+ &modified_send_buf); >+ break; >+ case TEST_TGS_REQ: >+ ok = torture_krb5_pre_send_tgs_req_test(test_context, send_buf, >+ &modified_send_buf); >+ break; >+ case TEST_TGS_REQ_KRBTGT: >+ ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf, >+ &modified_send_buf); >+ break; > } > if (ok == false) { > return EINVAL; >@@ -524,16 +720,25 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > return k5ret; > } > >- if (test_context->test_stage == TEST_AS_REQ) { >+ switch (test_context->test_stage) { >+ case TEST_DONE: >+ torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs"); >+ return EINVAL; >+ case TEST_AS_REQ: > ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); >- } else if (test_context->test_stage == TEST_TGS_REQ_CANON) { >+ break; >+ case TEST_TGS_REQ_CANON: > ok = torture_krb5_post_recv_tgs_req_canon_test(test_context, recv_buf); >- } else if (test_context->test_stage == TEST_SELF_TRUST_TGS_REQ) { >+ break; >+ case TEST_SELF_TRUST_TGS_REQ: > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); >- } else if (test_context->test_stage == TEST_TGS_REQ) { >+ break; >+ case TEST_TGS_REQ: > ok = torture_krb5_post_recv_tgs_req_test(test_context, recv_buf); >- } else if (test_context->test_stage == TEST_TGS_REQ_KRBTGT) { >+ break; >+ case TEST_TGS_REQ_KRBTGT: > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); >+ break; > } > if (ok == false) { > return EINVAL; >@@ -553,7 +758,7 @@ static int test_context_destructor(struct torture_krb5_context *test_context) > > static bool torture_krb5_init_context_canon(struct torture_context *tctx, > struct test_data *test_data, >- struct smb_krb5_context **smb_krb5_context) >+ struct torture_krb5_context **torture_krb5_context) > { > const char *host = torture_setting_string(tctx, "host", NULL); > krb5_error_code k5ret; >@@ -565,7 +770,7 @@ static bool torture_krb5_init_context_canon(struct torture_context *tctx, > test_context->test_data = test_data; > test_context->tctx = tctx; > >- k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context); >+ k5ret = smb_krb5_init_context(test_context, tctx->lp_ctx, &test_context->smb_krb5_context); > torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed"); > > ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST); >@@ -575,10 +780,11 @@ static bool torture_krb5_init_context_canon(struct torture_context *tctx, > > set_sockaddr_port(test_context->server->ai_addr, 88); > >- k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, >+ k5ret = krb5_set_send_to_kdc_func(test_context->smb_krb5_context->krb5_context, > smb_krb5_send_and_recv_func_canon_override, > test_context); > torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed"); >+ *torture_krb5_context = test_context; > return true; > } > >@@ -598,7 +804,8 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > char *got_principal_string; > char *assertion_message; > const char *password = cli_credentials_get_password(cmdline_credentials); >- struct smb_krb5_context *smb_krb5_context; >+ krb5_context k5_context; >+ struct torture_krb5_context *test_context; > bool ok; > krb5_creds my_creds; > krb5_creds *server_creds; >@@ -659,8 +866,9 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > } > } > >- ok = torture_krb5_init_context_canon(tctx, test_data, &smb_krb5_context); >+ ok = torture_krb5_init_context_canon(tctx, test_data, &test_context); > torture_assert(tctx, ok, "torture_krb5_init_context failed"); >+ k5_context = test_context->smb_krb5_context->krb5_context; > > if (test_data->upper_realm) { > test_data->realm = strupper_talloc(test_data, test_data->realm); >@@ -687,11 +895,17 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * fixed UPPER case realm, but the as-sent username > */ > if (test_data->canonicalize) { >- expected_principal_string = talloc_asprintf(test_data, "%s@%s", test_data->real_username, test_data->real_realm); >+ expected_principal_string = talloc_asprintf(test_data, >+ "%s@%s", >+ test_data->real_username, >+ test_data->real_realm); > } else if (test_data->enterprise) { > expected_principal_string = principal_string; > } else { >- expected_principal_string = talloc_asprintf(test_data, "%s@%s", username, test_data->real_realm); >+ expected_principal_string = talloc_asprintf(test_data, >+ "%s@%s", >+ username, >+ test_data->real_realm); > } > > if (test_data->enterprise) { >@@ -710,47 +924,61 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > } > > torture_assert_int_equal(tctx, >- krb5_parse_name_flags(smb_krb5_context->krb5_context, >+ krb5_parse_name_flags(k5_context, > principal_string, > principal_flags, > &principal), > 0, "krb5_parse_name_flags failed"); > torture_assert_int_equal(tctx, >- krb5_parse_name_flags(smb_krb5_context->krb5_context, >+ krb5_parse_name_flags(k5_context, > expected_principal_string, > expected_principal_flags, > &expected_principal), > 0, "krb5_parse_name_flags failed"); > >+ /* >+ * Prepare a AS-REQ and run the TEST_AS_REQ tests >+ * >+ */ >+ >+ test_context->test_stage = TEST_AS_REQ; >+ test_context->packet_count = 0; >+ > /* > * Set the canonicalize flag if this test requires it > */ > torture_assert_int_equal(tctx, >- krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options), >+ krb5_get_init_creds_opt_alloc(k5_context, &krb_options), > 0, "krb5_get_init_creds_opt_alloc failed"); > > torture_assert_int_equal(tctx, >- krb5_get_init_creds_opt_set_canonicalize(smb_krb5_context->krb5_context, krb_options, test_data->canonicalize), >+ krb5_get_init_creds_opt_set_canonicalize(k5_context, >+ krb_options, >+ test_data->canonicalize), > 0, "krb5_get_init_creds_opt_set_canonicalize failed"); > > torture_assert_int_equal(tctx, >- krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, krb_options, test_data->win2k), >+ krb5_get_init_creds_opt_set_win2k(k5_context, >+ krb_options, >+ test_data->win2k), > 0, "krb5_get_init_creds_opt_set_win2k failed"); > >- k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, >+ k5ret = krb5_get_init_creds_password(k5_context, &my_creds, principal, > password, NULL, NULL, 0, > NULL, krb_options); >- krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); >+ krb5_get_init_creds_opt_free(k5_context, krb_options); > > if (test_data->netbios_realm && test_data->upn) { >- torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "Got wrong error_code from krb5_get_init_creds_password"); >+ torture_assert_int_equal(tctx, k5ret, >+ KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, >+ "Got wrong error_code from krb5_get_init_creds_password"); > /* We can't proceed with more checks */ > return true; > } else { > assertion_message = talloc_asprintf(tctx, > "krb5_get_init_creds_password for %s failed: %s", > principal_string, >- smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > } > >@@ -760,131 +988,173 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > */ > if (test_data->canonicalize == false && test_data->enterprise) { > torture_assert_int_equal(tctx, >- krb5_principal_get_type(smb_krb5_context->krb5_context, >- my_creds.client), KRB5_NT_ENTERPRISE_PRINCIPAL, >+ krb5_principal_get_type(k5_context, >+ my_creds.client), >+ KRB5_NT_ENTERPRISE_PRINCIPAL, > "smb_krb5_init_context gave incorrect client->name.name_type"); > } else { > torture_assert_int_equal(tctx, >- krb5_principal_get_type(smb_krb5_context->krb5_context, >- my_creds.client), KRB5_NT_PRINCIPAL, >+ krb5_principal_get_type(k5_context, >+ my_creds.client), >+ KRB5_NT_PRINCIPAL, > "smb_krb5_init_context gave incorrect client->name.name_type"); > } >- >+ > torture_assert_int_equal(tctx, >- krb5_unparse_name(smb_krb5_context->krb5_context, >+ krb5_unparse_name(k5_context, > my_creds.client, &got_principal_string), 0, > "krb5_unparse_name failed"); > > assertion_message = talloc_asprintf(tctx, > "krb5_get_init_creds_password returned a different principal %s to what was expected %s", > got_principal_string, expected_principal_string); >- krb5_free_unparsed_name(smb_krb5_context->krb5_context, got_principal_string); >- >- torture_assert(tctx, krb5_principal_compare(smb_krb5_context->krb5_context, >+ krb5_free_unparsed_name(k5_context, got_principal_string); >+ >+ torture_assert(tctx, krb5_principal_compare(k5_context, > my_creds.client, expected_principal), > assertion_message); >- >+ > > torture_assert_int_equal(tctx, >- krb5_principal_get_type(smb_krb5_context->krb5_context, >+ krb5_principal_get_type(k5_context, > my_creds.server), KRB5_NT_SRV_INST, > "smb_krb5_init_context gave incorrect server->name.name_type"); >- >+ > torture_assert_int_equal(tctx, >- krb5_principal_get_num_comp(smb_krb5_context->krb5_context, >+ krb5_principal_get_num_comp(k5_context, > my_creds.server), 2, > "smb_krb5_init_context gave incorrect number of components in my_creds.server->name"); > >- torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >- my_creds.server, 0), >+ torture_assert_str_equal(tctx, >+ krb5_principal_get_comp_string(k5_context, >+ my_creds.server, 0), > "krbtgt", > "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]"); > > if (test_data->canonicalize || test_data->enterprise) { >- torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >- my_creds.server, 1), >+ torture_assert_str_equal(tctx, >+ krb5_principal_get_comp_string(k5_context, >+ my_creds.server, 1), > test_data->real_realm, >- >+ > "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]"); > } else { >- torture_assert_str_equal(tctx, krb5_principal_get_comp_string(smb_krb5_context->krb5_context, >- my_creds.server, 1), >+ torture_assert_str_equal(tctx, >+ krb5_principal_get_comp_string(k5_context, >+ my_creds.server, 1), > test_data->realm, >- >+ > "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]"); > } >- torture_assert_str_equal(tctx, krb5_principal_get_realm(smb_krb5_context->krb5_context, >- my_creds.server), >+ torture_assert_str_equal(tctx, >+ krb5_principal_get_realm(k5_context, >+ my_creds.server), > test_data->real_realm, > "smb_krb5_init_context gave incorrect my_creds.server->realm"); > > /* Store the result of the 'kinit' above into a memory ccache */ > cc_name = talloc_asprintf(tctx, "MEMORY:%s", test_data->test_name); >- torture_assert_int_equal(tctx, krb5_cc_resolve(smb_krb5_context->krb5_context, cc_name, >+ torture_assert_int_equal(tctx, krb5_cc_resolve(k5_context, cc_name, > &ccache), > 0, "krb5_cc_resolve failed"); > >- torture_assert_int_equal(tctx, krb5_cc_initialize(smb_krb5_context->krb5_context, >+ torture_assert_int_equal(tctx, krb5_cc_initialize(k5_context, > ccache, my_creds.client), > 0, "krb5_cc_initialize failed"); > >- torture_assert_int_equal(tctx, krb5_cc_store_cred(smb_krb5_context->krb5_context, >+ torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context, > ccache, &my_creds), > 0, "krb5_cc_store_cred failed"); > >- /* Prepare a TGS-REQ */ >+ /* >+ * Prepare a TGS-REQ and run the TEST_TGS_REQ_CANON tests >+ * >+ * This tests krb5_get_creds behaviour, which allows us to set >+ * the KRB5_GC_CANONICALIZE option >+ */ >+ >+ test_context->test_stage = TEST_TGS_REQ_CANON; >+ test_context->packet_count = 0; >+ > torture_assert_int_equal(tctx, >- krb5_get_creds_opt_alloc(smb_krb5_context->krb5_context, &opt), >+ krb5_get_creds_opt_alloc(k5_context, &opt), > 0, "krb5_get_creds_opt_alloc"); > >- krb5_get_creds_opt_add_options(smb_krb5_context->krb5_context, >+ krb5_get_creds_opt_add_options(k5_context, > opt, > KRB5_GC_CANONICALIZE); > > /* Confirm if we can get a ticket to our own name */ >- k5ret = krb5_get_creds(smb_krb5_context->krb5_context, opt, ccache, principal, &server_creds); >+ k5ret = krb5_get_creds(k5_context, opt, ccache, principal, &server_creds); > >+ /* >+ * In these situations, the code above does not store a >+ * principal in the credentials cache matching what >+ * krb5_get_creds() needs, so the test fails. >+ * >+ */ > if (test_data->canonicalize == false && test_data->enterprise == false > && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >- torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, >+ "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); > } else { > assertion_message = talloc_asprintf(tctx, > "krb5_get_creds for %s failed: %s", > principal_string, >- smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ smb_get_krb5_error_message(k5_context, k5ret, >+ tctx)); > >- /* We should only be able to get a ticket to our own name if we are a machine account */ >+ /* >+ * Only machine accounts (strictly, accounts with a >+ * servicePrincipalName) can expect this test to succeed >+ */ > if (torture_setting_bool(tctx, "expect_machine_account", false)) { > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >- torture_assert_int_equal(tctx, krb5_cc_store_cred(smb_krb5_context->krb5_context, >+ torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context, > ccache, server_creds), > 0, "krb5_cc_store_cred failed"); > > torture_assert_int_equal(tctx, >- krb5_free_creds(smb_krb5_context->krb5_context, >+ krb5_free_creds(k5_context, > server_creds), > 0, "krb5_free_cred_contents failed"); > > } else { >- torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, assertion_message); >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, >+ assertion_message); > } > } >+ > /* >- * Confirm gettting a ticket to pass to the server. >+ * Confirm gettting a ticket to pass to the server, running >+ * either the TEST_TGS_REQ or TEST_SELF_TRUST_TGS_REQ stage. > * > * This triggers the client to attempt to get a > * cross-realm ticket between the alternate names of > * the server, and we need to confirm that behaviour. > * >- * The cache isn't used because we asked the above not to >- * pollute the cache > */ > >- torture_assert_int_equal(tctx, krb5_auth_con_init(smb_krb5_context->krb5_context, &auth_context), >+ /* >+ * This tries to guess when the krb5 libs will ask for a >+ * cross-realm ticket, and when they will just ask the KDC >+ * directly. >+ */ >+ if (test_context->test_data->canonicalize == false >+ || test_context->test_data->enterprise >+ || (test_context->test_data->upper_realm >+ && test_context->test_data->netbios_realm == false)) { >+ test_context->test_stage = TEST_TGS_REQ; >+ } else { >+ test_context->test_stage = TEST_SELF_TRUST_TGS_REQ; >+ } >+ >+ test_context->packet_count = 0; >+ torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context), > 0, "krb5_auth_con_init failed"); > > in_data.length = 0; >- k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, >+ k5ret = krb5_mk_req_exact(k5_context, > &auth_context, > 0, > principal, >@@ -894,15 +1164,35 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > assertion_message = talloc_asprintf(tctx, > "krb5_mk_req_exact for %s failed: %s", > principal_string, >- smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); >+ >+ /* >+ * Only machine accounts (strictly, accounts with a >+ * servicePrincipalName) can expect this test to succeed >+ */ > if (torture_setting_bool(tctx, "expect_machine_account", false)) { > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > } else { >- torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, assertion_message); >+ torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, >+ assertion_message); > } > >+ /* >+ * Confirm gettting a ticket for the same krbtgt/realm that we >+ * got back with the initial ticket, running the >+ * TEST_TGS_REQ_KRBTGT stage. >+ * >+ * This triggers the client to attempt to get a >+ * cross-realm ticket between the alternate names of >+ * the server, and we need to confirm that behaviour. >+ * >+ */ >+ >+ test_context->test_stage = TEST_TGS_REQ_KRBTGT; >+ test_context->packet_count = 0; >+ > in_data.length = 0; >- k5ret = krb5_mk_req_exact(smb_krb5_context->krb5_context, >+ k5ret = krb5_mk_req_exact(k5_context, > &auth_context, > 0, > my_creds.server, >@@ -912,12 +1202,12 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > assertion_message = talloc_asprintf(tctx, > "krb5_mk_req_exact for %s failed: %s", > principal_string, >- smb_get_krb5_error_message(smb_krb5_context->krb5_context, k5ret, tctx)); >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > >- krb5_free_principal(smb_krb5_context->krb5_context, principal); >- >- torture_assert_int_equal(tctx, krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds), >+ krb5_free_principal(k5_context, principal); >+ >+ torture_assert_int_equal(tctx, krb5_free_cred_contents(k5_context, &my_creds), > 0, "krb5_free_cred_contents failed"); > > return true; >@@ -942,7 +1232,8 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > struct test_data *test_data = talloc_zero(suite, struct test_data); > > test_data->test_name = name; >- test_data->real_realm = strupper_talloc(test_data, cli_credentials_get_realm(cmdline_credentials)); >+ test_data->real_realm >+ = strupper_talloc(test_data, cli_credentials_get_realm(cmdline_credentials)); > test_data->real_domain = cli_credentials_get_domain(cmdline_credentials); > test_data->username = cli_credentials_get_username(cmdline_credentials); > test_data->real_username = cli_credentials_get_username(cmdline_credentials); >-- >2.1.4 > > >From 67e8b462de1ce777688b9168bca02ff1ef18fe95 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 2 Feb 2015 13:55:25 +1300 >Subject: [PATCH 37/60] torture-krb5: Improve the assertions in our KDC tests > to be more explicit > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 4bafb45b096e7246d8186f379a4663b755fb0d37) >--- > source4/torture/krb5/kdc-canon.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 8c9543c..ef00e70 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -367,6 +367,17 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex > test_context->tgs_req.req_body.sname->name_type, > "Mismatch in name_type between request and ticket response"); > torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.len, >+ test_context->tgs_req.req_body.sname->name_string.len, >+ "Mismatch in name_string.len between request and ticket response"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.len >= 1, >+ "name_string.len should be >=1 in ticket response"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[0], >+ test_context->tgs_req.req_body.sname->name_string.val[0], >+ "Mismatch in name between request and expected request"); >+ torture_assert_int_equal(test_context->tctx, > *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); > free_TGS_REP(&test_context->tgs_rep); >-- >2.1.4 > > >From 23900a2decf18e0b92457684c8c0fbb518d07aed Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 2 Feb 2015 15:01:40 +1300 >Subject: [PATCH 38/60] torture-krb5: Add tests for AS-REQ to our own name > >This allows us to probe the behaviour of AS-REQ requests against a principal other than krbtgt/ > >This alos allows verification of behaviour of principals of type KRB5_NT_ENTERPRISE_PRINCIPAL > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 5fe76cc02a1f09213b4b4a65dc53ad4d2ce97c86) >--- > source4/torture/krb5/kdc-canon.c | 195 +++++++++++++++++++++++++++++++++------ > 1 file changed, 166 insertions(+), 29 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index ef00e70..44f8d91 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -62,6 +62,7 @@ enum test_stage { > TEST_SELF_TRUST_TGS_REQ, > TEST_TGS_REQ, > TEST_TGS_REQ_KRBTGT, >+ TEST_AS_REQ_SELF, > TEST_DONE > }; > >@@ -80,7 +81,7 @@ struct torture_krb5_context { > > > /* >- * TEST_AS_REQ - SEND >+ * TEST_AS_REQ and TEST_AS_REQ_SELF - SEND > * > * Confirm that the outgoing packet meets certain expectations. This > * should be extended to further assert the correct and expected >@@ -98,11 +99,13 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ > const krb5_data *send_buf, > krb5_data *modified_send_buf) > { >+ AS_REQ mod_as_req; > krb5_error_code k5ret; > size_t used; > torture_assert_int_equal(test_context->tctx, decode_AS_REQ(send_buf->data, send_buf->length, > &test_context->as_req, &used), > 0, "decode_AS_REQ for TEST_AS_REQ failed"); >+ mod_as_req = test_context->as_req; > torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch"); > torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, > 5, "Got wrong as_req->pvno"); >@@ -131,21 +134,33 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ > > /* Force off canonicalize that was forced on by the krb5 libs */ > if (test_context->test_data->canonicalize == false && test_context->test_data->enterprise) { >- test_context->as_req.req_body.kdc_options.canonicalize = false; >+ mod_as_req.req_body.kdc_options.canonicalize = false; >+ } >+ >+ if (test_context->test_stage == TEST_AS_REQ_SELF) { >+ /* >+ * Force the server name to match the client name, >+ * including the name type. This isn't possible with >+ * the krb5 client libs alone >+ */ >+ mod_as_req.req_body.sname = test_context->as_req.req_body.cname; > } > > ASN1_MALLOC_ENCODE(AS_REQ, modified_send_buf->data, modified_send_buf->length, >- &test_context->as_req, &used, k5ret); >+ &mod_as_req, &used, k5ret); > torture_assert_int_equal(test_context->tctx, > k5ret, 0, > "encode_AS_REQ failed"); >- torture_assert_int_equal(test_context->tctx, used, send_buf->length, >- "re-encode length mismatch"); >+ >+ if (test_context->test_stage != TEST_AS_REQ_SELF) { >+ torture_assert_int_equal(test_context->tctx, used, send_buf->length, >+ "re-encode length mismatch"); >+ } > return true; > } > > /* >- * TEST_AS_REQ - RECV >+ * TEST_AS_REQ and TEST_AS_REQ_SELF- RECV > * > * Confirm that the reply packet from the KDC meets certain > * expectations as part of TEST_AS_REQ. This uses a packet count to >@@ -177,17 +192,37 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > "length mismatch"); > torture_assert_int_equal(test_context->tctx, error.pvno, 5, > "Got wrong error.pvno"); >- if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } else { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >+ if (test_context->test_stage == TEST_AS_REQ) { >+ if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } >+ } else if (test_context->test_stage == TEST_AS_REQ_SELF) { >+ if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false >+ || (test_context->test_data->upn == true)) >+ && error.error_code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE) { >+ /* >+ * IGNORE >+ * >+ * This case is because Samba's Heimdal KDC >+ * checks server and client accounts before >+ * checking for pre-authentication. >+ */ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } > } >+ > free_KRB_ERROR(&error); > } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) > && (test_context->packet_count == 1)) { >@@ -204,10 +239,19 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > torture_assert_int_equal(test_context->tctx, > error.pvno, 5, > "Got wrong error.pvno"); >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >+ if (test_context->test_stage != TEST_AS_REQ_SELF >+ || ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) >+ && (test_context->test_data->upn == false)))) { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } > free_KRB_ERROR(&error); > } else { > /* >@@ -239,7 +283,8 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > * locally on the RODC will have these bits filled in > * the msDS-SecondaryKrbTgtNumber > */ >- if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { >+ if (test_context->test_stage == TEST_AS_REQ >+ && torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Did not get a RODC number in the KVNO"); >@@ -719,6 +764,10 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf, > &modified_send_buf); > break; >+ case TEST_AS_REQ_SELF: >+ ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, >+ &modified_send_buf); >+ break; > } > if (ok == false) { > return EINVAL; >@@ -750,6 +799,9 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > case TEST_TGS_REQ_KRBTGT: > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); > break; >+ case TEST_AS_REQ_SELF: >+ ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); >+ break; > } > if (ok == false) { > return EINVAL; >@@ -805,7 +857,6 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > krb5_error_code k5ret; > krb5_get_init_creds_opt *krb_options = NULL; > struct test_data *test_data = talloc_get_type_abort(tcase_data, struct test_data); >- char *username; > krb5_principal principal; > krb5_principal expected_principal; > char *principal_string; >@@ -887,12 +938,12 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > test_data->realm = strlower_talloc(test_data, test_data->realm); > } > if (test_data->upper_username) { >- username = strupper_talloc(test_data, test_data->username); >+ test_data->username = strupper_talloc(test_data, test_data->username); > } else { >- username = talloc_strdup(test_data, test_data->username); >+ test_data->username = talloc_strdup(test_data, test_data->username); > } > >- principal_string = talloc_asprintf(test_data, "%s@%s", username, test_data->realm); >+ principal_string = talloc_asprintf(test_data, "%s@%s", test_data->username, test_data->realm); > > /* > * If we are set to canonicalize, we get back the fixed UPPER >@@ -915,7 +966,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > } else { > expected_principal_string = talloc_asprintf(test_data, > "%s@%s", >- username, >+ test_data->username, > test_data->real_realm); > } > >@@ -977,7 +1028,6 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > k5ret = krb5_get_init_creds_password(k5_context, &my_creds, principal, > password, NULL, NULL, 0, > NULL, krb_options); >- krb5_get_init_creds_opt_free(k5_context, krb_options); > > if (test_data->netbios_realm && test_data->upn) { > torture_assert_int_equal(tctx, k5ret, >@@ -1119,7 +1169,8 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * Only machine accounts (strictly, accounts with a > * servicePrincipalName) can expect this test to succeed > */ >- if (torture_setting_bool(tctx, "expect_machine_account", false)) { >+ if (torture_setting_bool(tctx, "expect_machine_account", false) >+ && (test_data->enterprise || test_data->upn == false)) { > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context, > ccache, server_creds), >@@ -1181,7 +1232,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * Only machine accounts (strictly, accounts with a > * servicePrincipalName) can expect this test to succeed > */ >- if (torture_setting_bool(tctx, "expect_machine_account", false)) { >+ if (torture_setting_bool(tctx, "expect_machine_account", false) && (test_data->enterprise || test_data->upn == false)) { > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > } else { > torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, >@@ -1216,7 +1267,93 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > smb_get_krb5_error_message(k5_context, k5ret, tctx)); > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > >+ /* >+ * Confirm gettting a ticket for our own principal that we >+ * got back with the initial ticket, running the >+ * TEST_AS_REQ_SELF stage. >+ * >+ */ >+ test_context->test_stage = TEST_AS_REQ_SELF; >+ test_context->packet_count = 0; >+ >+ k5ret = krb5_get_init_creds_password(k5_context, &my_creds, principal, >+ password, NULL, NULL, 0, >+ principal_string, krb_options); >+ >+ if (torture_setting_bool(test_context->tctx, "expect_machine_account", false) && (test_data->upn == false)) { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "Got wrong error_code from krb5_get_init_creds_password, expected KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN trying to get a ticket to %s for %s", principal_string, principal_string); >+ torture_assert_int_equal(tctx, k5ret, >+ KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, >+ assertion_message); >+ /* We can't proceed with more checks */ >+ return true; >+ } >+ >+ /* >+ * Assert that the reply was with the correct type of >+ * principal, depending on the flags we set >+ */ >+ if (test_data->canonicalize == false && test_data->enterprise) { >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(k5_context, >+ my_creds.client), >+ KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(k5_context, >+ my_creds.server), >+ KRB5_NT_ENTERPRISE_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect server->name.name_type"); >+ } else { >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(k5_context, >+ my_creds.client), >+ KRB5_NT_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect client->name.name_type"); >+ torture_assert_int_equal(tctx, >+ krb5_principal_get_type(k5_context, >+ my_creds.server), >+ KRB5_NT_PRINCIPAL, >+ "smb_krb5_init_context gave incorrect server->name.name_type"); >+ } >+ >+ torture_assert_int_equal(tctx, >+ krb5_unparse_name(k5_context, >+ my_creds.client, &got_principal_string), 0, >+ "krb5_unparse_name failed"); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password returned a different principal %s to what was expected %s", >+ got_principal_string, expected_principal_string); >+ krb5_free_unparsed_name(k5_context, got_principal_string); >+ >+ torture_assert(tctx, krb5_principal_compare(k5_context, >+ my_creds.client, expected_principal), >+ assertion_message); >+ >+ torture_assert_int_equal(tctx, >+ krb5_unparse_name(k5_context, >+ my_creds.client, &got_principal_string), 0, >+ "krb5_unparse_name failed"); >+ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_init_creds_password returned a different server principal %s to what was expected %s", >+ got_principal_string, expected_principal_string); >+ krb5_free_unparsed_name(k5_context, got_principal_string); >+ >+ torture_assert(tctx, krb5_principal_compare(k5_context, >+ my_creds.client, expected_principal), >+ assertion_message); >+ > krb5_free_principal(k5_context, principal); >+ krb5_get_init_creds_opt_free(k5_context, krb_options); > > torture_assert_int_equal(tctx, krb5_free_cred_contents(k5_context, &my_creds), > 0, "krb5_free_cred_contents failed"); >-- >2.1.4 > > >From 5f51cf17b8ed8a5e623446a1a4336b882da98811 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 3 Feb 2015 11:36:49 +1300 >Subject: [PATCH 39/60] selftest: Run krb5.kdc with an account that has a UPN > and an SPN > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 32e2b75a96b45d64d6059240ef2e8da924c6c84e) >--- > selftest/target/Samba4.pm | 2 ++ > source4/selftest/tests.py | 2 +- > 2 files changed, 3 insertions(+), 1 deletion(-) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 85a328c..3cd3c39 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -788,6 +788,8 @@ sub provision_raw_step2($$$) > changetype: modify > replace: userPrincipalName > userPrincipalName: testallowed_upn\@$ctx->{realm} >+replace: servicePrincipalName >+servicePrincipalName: host/testallowed > - > "; > close(LDIF); >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index bddba41..5f2d9f1 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -565,7 +565,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > > plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:expect_machine_account=true'] + extra_options, > "samba4.krb5.kdc with machine account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-upn=testallowed_upn@$REALM'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:expect_machine_account=true', '--option=torture:krb5-upn=testallowed_upn@$REALM'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > > # TODO: Verifying the databases really should be a part of the >-- >2.1.4 > > >From f648bbfc4c69e274d9bc37b748ad00388e5ef18e Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 3 Feb 2015 15:22:52 +1300 >Subject: [PATCH 40/60] torture-krb5: Further test improvements to cover > KRB5_GC_CANONICALIZE on krbtgt/ > >This covers more of the protocol, and confirms which tests actually send network >packets (and so actually run the assertions in the send_and_recv handlers. >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> > >(cherry picked from commit e05ad3500fb501f87c1eb77a1c13c5c237f02b3d) >--- > source4/torture/krb5/kdc-canon.c | 259 ++++++++++++++++++++++++++++++++++++--- > 1 file changed, 243 insertions(+), 16 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 44f8d91..8dbfd93 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -58,6 +58,7 @@ struct test_data { > > enum test_stage { > TEST_AS_REQ = 0, >+ TEST_TGS_REQ_KRBTGT_CANON, > TEST_TGS_REQ_CANON, > TEST_SELF_TRUST_TGS_REQ, > TEST_TGS_REQ, >@@ -301,6 +302,128 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > } > > /* >+ * TEST_TGS_REQ_KRBTGT_CANON >+ * >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_get_creds() >+ * for the krbtgt/realm principal meets certain expectations, like >+ * that the canonicalize bit is not set >+ * >+ */ >+ >+static bool torture_krb5_pre_send_tgs_req_krbtgt_canon_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_TGS_REQ test failed"); >+ torture_assert_int_equal(test_context->tctx, >+ used, send_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.pvno, 5, >+ "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ true, >+ "krb5 libs unexpectedly did not set canonicalize!"); >+ >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ KRB5_NT_PRINCIPAL, >+ "Mismatch in name_type between request and expected request"); >+ >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ *modified_send_buf = *send_buf; >+ return true; >+} >+ >+/* >+ * TEST_TGS_REQ_KRBTGT_CANON >+ * >+ * Confirm that the reply TGS-REP packet for krb5_get_creds() >+ * where the client is behaving as if this is a cross-realm trust due >+ * to case or netbios vs dns name differences meets certain >+ * expectations, while canonicalize is set >+ * >+ */ >+ >+static bool torture_krb5_post_recv_tgs_req_krbtgt_canon_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, >+ &test_context->tgs_rep, &used), >+ 0, >+ "decode_TGS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->tgs_rep.ticket.realm, >+ "Mismatch in realm between request and ticket response"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between ticket response and expected ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_type, >+ KRB5_NT_SRV_INST, >+ "Mismatch in name_type between ticket response and expected value of KRB5_NT_SRV_INST"); >+ >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.len, >+ 2, >+ "Mismatch in name_type between ticket response and expected value, expected krbtgt/REALM@REALM"); >+ >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[0], "krbtgt", >+ "Mismatch in name between reponse and expected response, expected krbtgt"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[1], test_context->test_data->real_realm, >+ "Mismatch in realm part of krbtgt/ in expected response, expected krbtgt/REALM@REALM"); >+ >+ /* >+ * We can confirm that the correct proxy behaviour is >+ * in use on the KDC by checking the KVNO of the >+ * krbtgt account returned in the reply. >+ * >+ * A packet passed to the full RW DC will not have a >+ * KVNO in the upper bits, while a packet processed >+ * locally on the RODC will have these bits filled in >+ * the msDS-SecondaryKrbTgtNumber >+ */ >+ if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { >+ torture_assert_int_not_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Did not get a RODC number in the KVNO"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO"); >+ } >+ free_TGS_REP(&test_context->tgs_rep); >+ torture_assert(test_context->tctx, >+ test_context->packet_count < 2, >+ "too many packets"); >+ free_TGS_REQ(&test_context->tgs_req); >+ return true; >+} >+ >+/* > * TEST_TGS_REQ_CANON > * > * Confirm that the outgoing TGS-REQ packet from krb5_get_creds >@@ -695,17 +818,10 @@ static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_contex > false, > "krb5 libs unexpectedly set canonicalize!"); > >- if (test_context->test_data->canonicalize) { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->real_realm, >- "Mismatch in realm between request and expected request"); >- } else { >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.realm, >- test_context->test_data->realm, >- "Mismatch in realm between request and expected request"); >- } >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->realm, >+ "Mismatch in realm between request and expected request"); > > *modified_send_buf = *send_buf; > test_context->test_stage = TEST_DONE; >@@ -748,6 +864,10 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, > &modified_send_buf); > break; >+ case TEST_TGS_REQ_KRBTGT_CANON: >+ ok = torture_krb5_pre_send_tgs_req_krbtgt_canon_test(test_context, send_buf, >+ &modified_send_buf); >+ break; > case TEST_TGS_REQ_CANON: > ok = torture_krb5_pre_send_tgs_req_canon_test(test_context, send_buf, > &modified_send_buf); >@@ -787,6 +907,9 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > case TEST_AS_REQ: > ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); > break; >+ case TEST_TGS_REQ_KRBTGT_CANON: >+ ok = torture_krb5_post_recv_tgs_req_krbtgt_canon_test(test_context, recv_buf); >+ break; > case TEST_TGS_REQ_CANON: > ok = torture_krb5_post_recv_tgs_req_canon_test(test_context, recv_buf); > break; >@@ -858,8 +981,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > krb5_get_init_creds_opt *krb_options = NULL; > struct test_data *test_data = talloc_get_type_abort(tcase_data, struct test_data); > krb5_principal principal; >+ krb5_principal krbtgt_other; > krb5_principal expected_principal; > char *principal_string; >+ char *krbtgt_other_string; > int principal_flags; > char *expected_principal_string; > int expected_principal_flags; >@@ -1043,6 +1168,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); > } > >+ torture_assert(tctx, >+ test_context->packet_count > 1, >+ "Expected krb5_get_init_creds_password to send more packets"); >+ > /* > * Assert that the reply was with the correct type of > * principal, depending on the flags we set >@@ -1128,6 +1257,82 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > 0, "krb5_cc_store_cred failed"); > > /* >+ * Prepare a TGS-REQ and run the TEST_TGS_REQ_KRBTGT_CANON tests >+ * >+ * This tests krb5_get_creds behaviour, which allows us to set >+ * the KRB5_GC_CANONICALIZE option against the krbtgt/ principal >+ */ >+ >+ krbtgt_other_string = talloc_asprintf(test_data, "krbtgt/%s@%s", test_data->real_domain, test_data->real_realm); >+ torture_assert_int_equal(tctx, >+ krb5_make_principal(k5_context, &krbtgt_other, >+ test_data->real_realm, "krbtgt", >+ test_data->real_domain, NULL), >+ 0, "krb5_make_principal failed"); >+ >+ test_context->test_stage = TEST_TGS_REQ_KRBTGT_CANON; >+ test_context->packet_count = 0; >+ >+ torture_assert_int_equal(tctx, >+ krb5_get_creds_opt_alloc(k5_context, &opt), >+ 0, "krb5_get_creds_opt_alloc"); >+ >+ krb5_get_creds_opt_add_options(k5_context, >+ opt, >+ KRB5_GC_CANONICALIZE); >+ >+ krb5_get_creds_opt_add_options(k5_context, >+ opt, >+ KRB5_GC_NO_STORE); >+ >+ /* Confirm if we can get a ticket krbtgt/realm that we got back with the initial kinit */ >+ k5ret = krb5_get_creds(k5_context, opt, ccache, krbtgt_other, &server_creds); >+ >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && test_data->netbios_realm && test_data->upper_realm) { >+ /* >+ * In these situations, the code above does store a >+ * principal in the credentials cache matching what >+ * krb5_get_creds() needs, so the test succeds, with no packets. >+ * >+ */ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_creds for %s failed with: %s", >+ krbtgt_other_string, >+ smb_get_krb5_error_message(k5_context, k5ret, >+ tctx)); >+ >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ torture_assert_int_equal(tctx, >+ test_context->packet_count, >+ 0, "Expected krb5_get_creds not to send packets"); >+ } else if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, >+ "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ } else { >+ >+ /* >+ * In these situations, the code above does not store a >+ * principal in the credentials cache matching what >+ * krb5_get_creds() needs without talking to the KDC, so the >+ * test fails with looping detected because when we set >+ * canonicalize we confuse the client libs. >+ * >+ */ >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_get_creds for %s should have failed with looping detected: %s", >+ krbtgt_other_string, >+ smb_get_krb5_error_message(k5_context, k5ret, >+ tctx)); >+ >+ torture_assert_int_equal(tctx, k5ret, KRB5_GET_IN_TKT_LOOP, assertion_message); >+ torture_assert_int_equal(tctx, >+ test_context->packet_count, >+ 2, "Expected krb5_get_creds to send packets"); >+ } >+ >+ /* > * Prepare a TGS-REQ and run the TEST_TGS_REQ_CANON tests > * > * This tests krb5_get_creds behaviour, which allows us to set >@@ -1145,6 +1350,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > opt, > KRB5_GC_CANONICALIZE); > >+ krb5_get_creds_opt_add_options(k5_context, >+ opt, >+ KRB5_GC_NO_STORE); >+ > /* Confirm if we can get a ticket to our own name */ > k5ret = krb5_get_creds(k5_context, opt, ccache, principal, &server_creds); > >@@ -1185,6 +1394,10 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, > assertion_message); > } >+ >+ torture_assert_int_equal(tctx, >+ test_context->packet_count, >+ 1, "Expected krb5_get_creds to send packets"); > } > > /* >@@ -1222,7 +1435,6 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > principal, > &in_data, ccache, > &enc_ticket); >- > assertion_message = talloc_asprintf(tctx, > "krb5_mk_req_exact for %s failed: %s", > principal_string, >@@ -1240,14 +1452,21 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > } > > /* >+ * Only in these cases would the above code have needed to >+ * send packets to the network >+ */ >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert(tctx, >+ test_context->packet_count > 0, >+ "Expected krb5_get_creds to send packets"); >+ } >+ >+ /* > * Confirm gettting a ticket for the same krbtgt/realm that we > * got back with the initial ticket, running the > * TEST_TGS_REQ_KRBTGT stage. > * >- * This triggers the client to attempt to get a >- * cross-realm ticket between the alternate names of >- * the server, and we need to confirm that behaviour. >- * > */ > > test_context->test_stage = TEST_TGS_REQ_KRBTGT; >@@ -1286,12 +1505,20 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > principal_string, > smb_get_krb5_error_message(k5_context, k5ret, tctx)); > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ torture_assert(tctx, >+ test_context->packet_count >= 2, >+ "Expected krb5_get_init_creds_password to send more packets"); >+ > } else { > assertion_message = talloc_asprintf(tctx, > "Got wrong error_code from krb5_get_init_creds_password, expected KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN trying to get a ticket to %s for %s", principal_string, principal_string); > torture_assert_int_equal(tctx, k5ret, > KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, > assertion_message); >+ torture_assert(tctx, >+ test_context->packet_count >= 1, >+ "Expected krb5_get_init_creds_password to send more packets"); >+ > /* We can't proceed with more checks */ > return true; > } >-- >2.1.4 > > >From 1d985528a0728f051d41fb3a7c7347bcc456b0fe Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 3 Feb 2015 15:51:41 +1300 >Subject: [PATCH 41/60] torture-krb5: Add additional assertions for non-canon > TGS-REP > >This confirms that the KDC does not modify the returned principal in a TGS-REP unconditionally. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit 60c791339122b8b3f9be5bc085badd14e2ca6058) >--- > source4/torture/krb5/kdc-canon.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 8dbfd93..d18905e 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -647,6 +647,15 @@ static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_c > test_context->tgs_req.req_body.sname->name_type, > "Mismatch in name_type between request and ticket response"); > >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.len, 2, >+ "Mismatch in name between request and expected request, expected krbtgt/realm"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[0], "krbtgt", >+ "Mismatch in name between request and expected request, expected krbtgt"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[1], test_context->test_data->realm, >+ "Mismatch in realm part of cross-realm request principal between response and expected request"); > /* > * We can confirm that the correct proxy behaviour is > * in use on the KDC by checking the KVNO of the >-- >2.1.4 > > >From 8c1f7094eebba9c8c6d4cadcc6047a5aaabdd57c Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 5 Feb 2015 10:11:42 +1300 >Subject: [PATCH 42/60] torture-krb5: Split out TEST_AS_REQ_SELF recv testing > routine > >This duplicates more code, but re-using the callbacks makes it much, much harder to debug > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 0a4da2fc97de2ce81c168820f2f5a792388d5bc5) >--- > source4/torture/krb5/kdc-canon.c | 236 ++++++++++++++++++++++++++++++--------- > 1 file changed, 186 insertions(+), 50 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index d18905e..c904a36 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -161,7 +161,7 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ > } > > /* >- * TEST_AS_REQ and TEST_AS_REQ_SELF- RECV >+ * TEST_AS_REQ - RECV > * > * Confirm that the reply packet from the KDC meets certain > * expectations as part of TEST_AS_REQ. This uses a packet count to >@@ -176,6 +176,7 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > KRB_ERROR error; > size_t used; > if (test_context->packet_count == 0) { >+ krb5_error_code k5ret; > /* > * The client libs obtain the salt by attempting to > * authenticate without pre-authentication and getting >@@ -185,43 +186,48 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > * has an incorrect principal, we check we get the > * correct error. > */ >- torture_assert_int_equal(test_context->tctx, >- decode_KRB_ERROR(recv_buf->data, recv_buf->length, >- &error, &used), 0, >- "decode_AS_REP failed"); >+ k5ret = decode_KRB_ERROR(recv_buf->data, recv_buf->length, >+ &error, &used); >+ if (k5ret != 0) { >+ AS_REP as_rep; >+ k5ret = decode_AS_REP(recv_buf->data, recv_buf->length, >+ &as_rep, &used); >+ if (k5ret == 0) { >+ if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >+ torture_assert(test_context->tctx, false, >+ "expected to get a KRB_ERROR packet with " >+ "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, got valid AS-REP"); >+ } else { >+ torture_assert(test_context->tctx, false, >+ "expected to get a KRB_ERROR packet with " >+ "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP"); >+ } >+ } else { >+ if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >+ torture_assert(test_context->tctx, false, >+ "unable to decode as KRB-ERROR or AS-REP, " >+ "expected to get a KRB_ERROR packet with KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN"); >+ } else { >+ torture_assert(test_context->tctx, false, >+ "unable to decode as KRB-ERROR or AS-REP, " >+ "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED"); >+ } >+ } >+ } > torture_assert_int_equal(test_context->tctx, used, recv_buf->length, > "length mismatch"); > torture_assert_int_equal(test_context->tctx, error.pvno, 5, > "Got wrong error.pvno"); >- if (test_context->test_stage == TEST_AS_REQ) { >- if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } else { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } >- } else if (test_context->test_stage == TEST_AS_REQ_SELF) { >- if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false >- || (test_context->test_data->upn == true)) >- && error.error_code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE) { >- /* >- * IGNORE >- * >- * This case is because Samba's Heimdal KDC >- * checks server and client accounts before >- * checking for pre-authentication. >- */ >- } else { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } >+ if (test_context->test_data->netbios_realm && test_context->test_data->upn) { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); > } > > free_KRB_ERROR(&error); >@@ -240,19 +246,10 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > torture_assert_int_equal(test_context->tctx, > error.pvno, 5, > "Got wrong error.pvno"); >- if (test_context->test_stage != TEST_AS_REQ_SELF >- || ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) >- && (test_context->test_data->upn == false)))) { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } else { >- torture_assert_int_equal(test_context->tctx, >- error.error_code, >- KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >- "Got wrong error.error_code"); >- } >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); > free_KRB_ERROR(&error); > } else { > /* >@@ -284,8 +281,7 @@ static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test > * locally on the RODC will have these bits filled in > * the msDS-SecondaryKrbTgtNumber > */ >- if (test_context->test_stage == TEST_AS_REQ >- && torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { >+ if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) { > torture_assert_int_not_equal(test_context->tctx, > *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, > 0, "Did not get a RODC number in the KVNO"); >@@ -837,6 +833,146 @@ static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_contex > return true; > } > >+/* >+ * TEST_AS_REQ_SELF - RECV >+ * >+ * Confirm that the reply packet from the KDC meets certain >+ * expectations as part of TEST_AS_REQ. This uses a packet count to >+ * work out what packet we are up to in the multiple exchanged >+ * triggerd by krb5_get_init_creds_password(). >+ * >+ */ >+ >+static bool torture_krb5_post_recv_as_req_self_test(struct torture_krb5_context *test_context, >+ const krb5_data *recv_buf) >+{ >+ KRB_ERROR error; >+ size_t used; >+ if (test_context->packet_count == 0) { >+ krb5_error_code k5ret; >+ /* >+ * The client libs obtain the salt by attempting to >+ * authenticate without pre-authentication and getting >+ * the correct salt with the >+ * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in >+ * the test (netbios_realm && upn) that deliberatly >+ * has an incorrect principal, we check we get the >+ * correct error. >+ */ >+ k5ret = decode_KRB_ERROR(recv_buf->data, recv_buf->length, >+ &error, &used); >+ if (k5ret != 0) { >+ AS_REP as_rep; >+ k5ret = decode_AS_REP(recv_buf->data, recv_buf->length, >+ &as_rep, &used); >+ if (k5ret == 0) { >+ if (torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false >+ || (test_context->test_data->upn == true)) { >+ torture_assert(test_context->tctx, false, >+ "expected to get a KRB_ERROR packet with " >+ "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP"); >+ } else { >+ torture_assert(test_context->tctx, false, >+ "expected to get a KRB_ERROR packet with " >+ "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP"); >+ } >+ } else { >+ if (torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false >+ || (test_context->test_data->upn == true)) { >+ torture_assert(test_context->tctx, false, >+ "unable to decode as KRB-ERROR or AS-REP, " >+ "expected to get a KRB_ERROR packet with KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED"); >+ } else { >+ torture_assert(test_context->tctx, false, >+ "unable to decode as KRB-ERROR or AS-REP, " >+ "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED"); >+ } >+ } >+ } >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, error.pvno, 5, >+ "Got wrong error.pvno"); >+ if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false >+ || (test_context->test_data->upn == true)) >+ && error.error_code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE) { >+ /* >+ * IGNORE >+ * >+ * This case is because Samba's Heimdal KDC >+ * checks server and client accounts before >+ * checking for pre-authentication. >+ */ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } >+ >+ free_KRB_ERROR(&error); >+ } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) >+ && (test_context->packet_count == 1)) { >+ /* >+ * The Windows 2012R2 KDC will always respond with >+ * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket >+ * won't fit, because of the PAC. (It appears to do >+ * this always, even if it will). This triggers the >+ * client to try again over TCP. >+ */ >+ torture_assert_int_equal(test_context->tctx, >+ used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ error.pvno, 5, >+ "Got wrong error.pvno"); >+ if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) >+ && (test_context->test_data->upn == false))) { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ error.error_code, >+ KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, >+ "Got wrong error.error_code"); >+ } >+ free_KRB_ERROR(&error); >+ } else { >+ /* >+ * Finally the successful packet. >+ */ >+ torture_assert_int_equal(test_context->tctx, >+ decode_AS_REP(recv_buf->data, recv_buf->length, >+ &test_context->as_rep, &used), 0, >+ "decode_AS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->as_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->as_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ >+ /* >+ * We do not expect an RODC number here in the KVNO, >+ * as this is a ticket to the user's own account. >+ */ >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO"); >+ free_AS_REP(&test_context->as_rep); >+ } >+ torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); >+ free_AS_REQ(&test_context->as_req); >+ return true; >+} >+ > /* > * This function is set in torture_krb5_init_context_canon as krb5 > * send_and_recv function. This allows us to override what server the >@@ -932,7 +1068,7 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); > break; > case TEST_AS_REQ_SELF: >- ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf); >+ ok = torture_krb5_post_recv_as_req_self_test(test_context, recv_buf); > break; > } > if (ok == false) { >-- >2.1.4 > > >From 5e398255547382c7111145009cc06057abecd246 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 5 Feb 2015 15:49:40 +1300 >Subject: [PATCH 43/60] torture-krb5: Add test in for normal TGS-REQ > >For example, host/server > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 52b74a4eaf82b892bddabcd70a3bc38c4fdc8410) >--- > source4/torture/krb5/kdc-canon.c | 173 ++++++++++++++++++++++++++++++++++++++- > 1 file changed, 172 insertions(+), 1 deletion(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index c904a36..f6b7815 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -54,6 +54,8 @@ struct test_data { > bool win2k; > bool upn; > bool other_upn_suffix; >+ const char *krb5_service; >+ const char *krb5_hostname; > }; > > enum test_stage { >@@ -63,6 +65,7 @@ enum test_stage { > TEST_SELF_TRUST_TGS_REQ, > TEST_TGS_REQ, > TEST_TGS_REQ_KRBTGT, >+ TEST_TGS_REQ_HOST, > TEST_AS_REQ_SELF, > TEST_DONE > }; >@@ -834,6 +837,113 @@ static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_contex > } > > /* >+ * TEST_TGS_REQ_HOST >+ * >+ * >+ * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact() >+ * for the krbtgt/realm principal meets certain expectations, like >+ * that the canonicalize bit is not set >+ * >+ */ >+ >+static bool torture_krb5_pre_send_tgs_req_host_test(struct torture_krb5_context *test_context, const krb5_data *send_buf, krb5_data *modified_send_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REQ(send_buf->data, send_buf->length, >+ &test_context->tgs_req, &used), >+ 0, "decode_TGS_REQ for TEST_TGS_REQ test failed"); >+ torture_assert_int_equal(test_context->tctx, >+ used, send_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.pvno, 5, >+ "Got wrong as_req->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ true, >+ "krb5 libs unexpectedly did not set canonicalize!"); >+ >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.len, 2, >+ "Mismatch in name between request and expected request, expected krbtgt/realm"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], >+ test_context->test_data->krb5_service, >+ "Mismatch in name between request and expected request, expected krbtgt"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], >+ test_context->test_data->krb5_hostname, >+ "Mismatch in realm part of cross-realm request principal between request and expected request"); >+ >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between request and expected request"); >+ >+ *modified_send_buf = *send_buf; >+ return true; >+} >+ >+/* >+ * TEST_TGS_REQ_HOST - RECV >+ * >+ * Confirm that the reply TGS-REP packet for krb5_mk_req(), for >+ * the actual target service, as a SPN, not a any other name type. >+ * >+ */ >+ >+static bool torture_krb5_post_recv_tgs_req_host_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) >+{ >+ size_t used; >+ torture_assert_int_equal(test_context->tctx, >+ decode_TGS_REP(recv_buf->data, recv_buf->length, >+ &test_context->tgs_rep, &used), >+ 0, >+ "decode_TGS_REP failed"); >+ torture_assert_int_equal(test_context->tctx, used, recv_buf->length, >+ "length mismatch"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.pvno, 5, >+ "Got wrong as_rep->pvno"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.tkt_vno, 5, >+ "Got wrong as_rep->ticket.tkt_vno"); >+ torture_assert(test_context->tctx, >+ test_context->tgs_rep.ticket.enc_part.kvno, >+ "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.realm, >+ test_context->test_data->real_realm, >+ "Mismatch in realm between ticket response and expected upper case REALM"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, >+ test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.len, 2, >+ "Mismatch in name between request and expected request, expected service/hostname"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[0], >+ test_context->test_data->krb5_service, >+ "Mismatch in name between request and expected request, expected service/hostname"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_rep.ticket.sname.name_string.val[1], >+ test_context->test_data->krb5_hostname, >+ "Mismatch in name between request and expected request, expected service/hostname"); >+ >+ torture_assert_int_equal(test_context->tctx, >+ *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, >+ 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); >+ free_TGS_REP(&test_context->tgs_rep); >+ >+ torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); >+ return true; >+} >+ >+/* > * TEST_AS_REQ_SELF - RECV > * > * Confirm that the reply packet from the KDC meets certain >@@ -1029,6 +1139,10 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf, > &modified_send_buf); > break; >+ case TEST_TGS_REQ_HOST: >+ ok = torture_krb5_pre_send_tgs_req_host_test(test_context, send_buf, >+ &modified_send_buf); >+ break; > case TEST_AS_REQ_SELF: > ok = torture_krb5_pre_send_as_req_test(test_context, send_buf, > &modified_send_buf); >@@ -1067,6 +1181,9 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > case TEST_TGS_REQ_KRBTGT: > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); > break; >+ case TEST_TGS_REQ_HOST: >+ ok = torture_krb5_post_recv_tgs_req_host_test(test_context, recv_buf); >+ break; > case TEST_AS_REQ_SELF: > ok = torture_krb5_post_recv_as_req_self_test(test_context, recv_buf); > break; >@@ -1148,6 +1265,8 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > krb5_get_creds_opt opt; > > const char *upn = torture_setting_string(tctx, "krb5-upn", ""); >+ test_data->krb5_service = torture_setting_string(tctx, "krb5-service", "host"); >+ test_data->krb5_hostname = torture_setting_string(tctx, "krb5-hostname", ""); > > /* > * If we have not passed a UPN on the command line, >@@ -1604,7 +1723,59 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > && (test_data->upper_realm == false || test_data->netbios_realm == true)) { > torture_assert(tctx, > test_context->packet_count > 0, >- "Expected krb5_get_creds to send packets"); >+ "Expected krb5_mk_req_exact to send packets"); >+ } >+ >+ /* >+ * Confirm gettting a ticket to pass to the server, running >+ * the TEST_TGS_REQ_HOST stage >+ * >+ * This triggers the client to attempt to get a >+ * cross-realm ticket between the alternate names of >+ * the server, and we need to confirm that behaviour. >+ * >+ */ >+ >+ if (*test_data->krb5_service && *test_data->krb5_hostname) { >+ /* >+ * This tries to guess when the krb5 libs will ask for a >+ * cross-realm ticket, and when they will just ask the KDC >+ * directly. >+ */ >+ test_context->test_stage = TEST_TGS_REQ_HOST; >+ >+ test_context->packet_count = 0; >+ torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context), >+ 0, "krb5_auth_con_init failed"); >+ >+ in_data.length = 0; >+ k5ret = krb5_mk_req(k5_context, >+ &auth_context, >+ 0, >+ test_data->krb5_service, >+ test_data->krb5_hostname, >+ &in_data, ccache, >+ &enc_ticket); >+ >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, >+ "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_mk_req for %s failed: %s", >+ principal_string, >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); >+ >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ /* >+ * Only in these cases would the above code have needed to >+ * send packets to the network >+ */ >+ torture_assert(tctx, >+ test_context->packet_count > 0, >+ "Expected krb5_get_creds to send packets"); >+ } > } > > /* >-- >2.1.4 > > >From dded3181248a888d72fde304b98e050e99c4eda1 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 5 Feb 2015 16:44:23 +1300 >Subject: [PATCH 44/60] torture-krb5: Add test for TGS-REQ with type > KRB5_NT_PRINCIPAL, KRB5_NT_SRV_INST, KRB5_NT_SRV_HST > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 3c89b25e4fbc86981ec2cfaebbd5e119a5fc965d) >--- > source4/selftest/tests.py | 8 +- > source4/torture/krb5/kdc-canon.c | 176 +++++++++++++++++++++++++++++++++------ > 2 files changed, 158 insertions(+), 26 deletions(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 5f2d9f1..9dccb92 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -563,9 +563,13 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > else: > extra_options = [] > >- plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:expect_machine_account=true'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-hostname=$SERVER', '--option=torture:expect_machine_account=true'] + extra_options, > "samba4.krb5.kdc with machine account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:expect_machine_account=true', '--option=torture:krb5-upn=testallowed_upn@$REALM'] + extra_options, >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', >+ '--workgroup=$DOMAIN', '--realm=$REALM', >+ '--option=torture:expect_machine_account=true', >+ '--option=torture:krb5-upn=testallowed_upn@$REALM', >+ '--option=torture:krb5-hostname=testallowed'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > > # TODO: Verifying the databases really should be a part of the >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index f6b7815..e745fe5 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -66,6 +66,8 @@ enum test_stage { > TEST_TGS_REQ, > TEST_TGS_REQ_KRBTGT, > TEST_TGS_REQ_HOST, >+ TEST_TGS_REQ_HOST_SRV_INST, >+ TEST_TGS_REQ_HOST_SRV_HST, > TEST_AS_REQ_SELF, > TEST_DONE > }; >@@ -837,7 +839,7 @@ static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_contex > } > > /* >- * TEST_TGS_REQ_HOST >+ * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST and TEST_TGS_REQ_HOST_SRV_HST > * > * > * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact() >@@ -860,25 +862,54 @@ static bool torture_krb5_pre_send_tgs_req_host_test(struct torture_krb5_context > test_context->tgs_req.pvno, 5, > "Got wrong as_req->pvno"); > torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.kdc_options.canonicalize, >- true, >- "krb5 libs unexpectedly did not set canonicalize!"); >- >- torture_assert_int_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >- "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >- torture_assert_int_equal(test_context->tctx, > test_context->tgs_req.req_body.sname->name_string.len, 2, > "Mismatch in name between request and expected request, expected krbtgt/realm"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_string.val[0], >- test_context->test_data->krb5_service, >- "Mismatch in name between request and expected request, expected krbtgt"); >- torture_assert_str_equal(test_context->tctx, >- test_context->tgs_req.req_body.sname->name_string.val[1], >- test_context->test_data->krb5_hostname, >- "Mismatch in realm part of cross-realm request principal between request and expected request"); >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.kdc_options.canonicalize, >+ true, >+ "krb5 libs unexpectedly did not set canonicalize!"); >+ >+ if (test_context->test_stage == TEST_TGS_REQ_HOST_SRV_INST) { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_SRV_INST, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_INST"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], >+ strupper_talloc(test_context, test_context->test_data->krb5_service), >+ "Mismatch in name between request and expected request, expected service"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], >+ test_context->test_data->krb5_hostname, >+ "Mismatch in hostname part between request and expected request"); >+ >+ } else if (test_context->test_stage == TEST_TGS_REQ_HOST_SRV_HST) { > >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_SRV_HST, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_HST"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], >+ test_context->test_data->krb5_service, >+ "Mismatch in name between request and expected request, expected service"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], >+ strupper_talloc(test_context, test_context->test_data->krb5_hostname), >+ "Mismatch in hostname part between request and expected request"); >+ >+ } else { >+ torture_assert_int_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL, >+ "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[0], >+ test_context->test_data->krb5_service, >+ "Mismatch in name between request and expected request, expected service"); >+ torture_assert_str_equal(test_context->tctx, >+ test_context->tgs_req.req_body.sname->name_string.val[1], >+ test_context->test_data->krb5_hostname, >+ "Mismatch in hostname part between request and expected request"); >+ >+ } > torture_assert_str_equal(test_context->tctx, > test_context->tgs_req.req_body.realm, > test_context->test_data->real_realm, >@@ -889,7 +920,7 @@ static bool torture_krb5_pre_send_tgs_req_host_test(struct torture_krb5_context > } > > /* >- * TEST_TGS_REQ_HOST - RECV >+ * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST - RECV > * > * Confirm that the reply TGS-REP packet for krb5_mk_req(), for > * the actual target service, as a SPN, not a any other name type. >@@ -927,11 +958,11 @@ static bool torture_krb5_post_recv_tgs_req_host_test(struct torture_krb5_context > "Mismatch in name between request and expected request, expected service/hostname"); > torture_assert_str_equal(test_context->tctx, > test_context->tgs_rep.ticket.sname.name_string.val[0], >- test_context->test_data->krb5_service, >+ test_context->tgs_req.req_body.sname->name_string.val[0], > "Mismatch in name between request and expected request, expected service/hostname"); > torture_assert_str_equal(test_context->tctx, > test_context->tgs_rep.ticket.sname.name_string.val[1], >- test_context->test_data->krb5_hostname, >+ test_context->tgs_req.req_body.sname->name_string.val[1], > "Mismatch in name between request and expected request, expected service/hostname"); > > torture_assert_int_equal(test_context->tctx, >@@ -1140,6 +1171,8 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > &modified_send_buf); > break; > case TEST_TGS_REQ_HOST: >+ case TEST_TGS_REQ_HOST_SRV_INST: >+ case TEST_TGS_REQ_HOST_SRV_HST: > ok = torture_krb5_pre_send_tgs_req_host_test(test_context, send_buf, > &modified_send_buf); > break; >@@ -1182,6 +1215,8 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf); > break; > case TEST_TGS_REQ_HOST: >+ case TEST_TGS_REQ_HOST_SRV_INST: >+ case TEST_TGS_REQ_HOST_SRV_HST: > ok = torture_krb5_post_recv_tgs_req_host_test(test_context, recv_buf); > break; > case TEST_AS_REQ_SELF: >@@ -1728,7 +1763,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > > /* > * Confirm gettting a ticket to pass to the server, running >- * the TEST_TGS_REQ_HOST stage >+ * the TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST stage > * > * This triggers the client to attempt to get a > * cross-realm ticket between the alternate names of >@@ -1737,13 +1772,13 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > */ > > if (*test_data->krb5_service && *test_data->krb5_hostname) { >+ krb5_principal host_principal_srv_inst; > /* > * This tries to guess when the krb5 libs will ask for a > * cross-realm ticket, and when they will just ask the KDC > * directly. > */ > test_context->test_stage = TEST_TGS_REQ_HOST; >- > test_context->packet_count = 0; > torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context), > 0, "krb5_auth_con_init failed"); >@@ -1763,8 +1798,101 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); > } else { > assertion_message = talloc_asprintf(tctx, >- "krb5_mk_req for %s failed: %s", >- principal_string, >+ "krb5_mk_req for %s/%s failed: %s", >+ test_data->krb5_hostname, >+ test_data->krb5_service, >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); >+ >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ /* >+ * Only in these cases would the above code have needed to >+ * send packets to the network >+ */ >+ torture_assert(tctx, >+ test_context->packet_count > 0, >+ "Expected krb5_get_creds to send packets"); >+ } >+ >+ >+ test_context->test_stage = TEST_TGS_REQ_HOST_SRV_INST; >+ test_context->packet_count = 0; >+ >+ torture_assert_int_equal(tctx, >+ krb5_make_principal(k5_context, &host_principal_srv_inst, >+ test_data->real_realm, >+ strupper_talloc(tctx, test_data->krb5_service), >+ test_data->krb5_hostname, >+ NULL), >+ 0, "krb5_make_principal failed"); >+ >+ krb5_principal_set_type(k5_context, host_principal_srv_inst, KRB5_NT_SRV_INST); >+ >+ torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context), >+ 0, "krb5_auth_con_init failed"); >+ >+ in_data.length = 0; >+ k5ret = krb5_mk_req_exact(k5_context, >+ &auth_context, >+ 0, >+ host_principal_srv_inst, >+ &in_data, ccache, >+ &enc_ticket); >+ krb5_free_principal(k5_context, host_principal_srv_inst); >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, >+ "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s", >+ test_data->krb5_service, >+ test_data->krb5_hostname, >+ smb_get_krb5_error_message(k5_context, k5ret, tctx)); >+ >+ torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ /* >+ * Only in these cases would the above code have needed to >+ * send packets to the network >+ */ >+ torture_assert(tctx, >+ test_context->packet_count > 0, >+ "Expected krb5_get_creds to send packets"); >+ } >+ >+ >+ test_context->test_stage = TEST_TGS_REQ_HOST_SRV_HST; >+ test_context->packet_count = 0; >+ >+ torture_assert_int_equal(tctx, >+ krb5_make_principal(k5_context, &host_principal_srv_inst, >+ test_data->real_realm, >+ test_data->krb5_service, >+ strupper_talloc(tctx, test_data->krb5_hostname), >+ NULL), >+ 0, "krb5_make_principal failed"); >+ >+ krb5_principal_set_type(k5_context, host_principal_srv_inst, KRB5_NT_SRV_HST); >+ >+ torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context), >+ 0, "krb5_auth_con_init failed"); >+ >+ in_data.length = 0; >+ k5ret = krb5_mk_req_exact(k5_context, >+ &auth_context, >+ 0, >+ host_principal_srv_inst, >+ &in_data, ccache, >+ &enc_ticket); >+ krb5_free_principal(k5_context, host_principal_srv_inst); >+ if (test_data->canonicalize == false && test_data->enterprise == false >+ && (test_data->upper_realm == false || test_data->netbios_realm == true)) { >+ torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND, >+ "krb5_get_creds should have failed with KRB5_CC_NOTFOUND"); >+ } else { >+ assertion_message = talloc_asprintf(tctx, >+ "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s", >+ test_data->krb5_service, >+ test_data->krb5_hostname, > smb_get_krb5_error_message(k5_context, k5ret, tctx)); > > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >-- >2.1.4 > > >From c0a343d6cc6a53cd9e02d0e2a601a3dd23f0d8b9 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 6 Feb 2015 08:53:21 +1300 >Subject: [PATCH 45/60] auth/kerberos: Use talloc_stackframe to avoid memory > and FD leak of event context > >The smb_krb5_send_and_recv_func_forced and smb_krb5_send_and_recv_func >functions could leak an event context including an epoll FD and some >memory. This may explain a flapping test in krb5.kdc > >Andrew Bartlett > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-By: Jelmer Vernooij <jelmer@samba.org> >Reviewed-by: Kamen Mazdrashki <kamenim@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >(cherry picked from commit bdde51b26f4f5bcd6b0dcb5557fee40d7bc40207) >--- > source4/auth/kerberos/krb5_init_context.c | 60 +++++++++++++++++-------------- > 1 file changed, 33 insertions(+), 27 deletions(-) > >diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c >index e8a1a6c..7fcc8a6 100644 >--- a/source4/auth/kerberos/krb5_init_context.c >+++ b/source4/auth/kerberos/krb5_init_context.c >@@ -228,8 +228,8 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > > DATA_BLOB send_blob; > >- TALLOC_CTX *tmp_ctx = talloc_new(NULL); >- if (!tmp_ctx) { >+ TALLOC_CTX *frame = talloc_stackframe(); >+ if (frame == NULL) { > return ENOMEM; > } > >@@ -237,9 +237,9 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > > for (a = ai; a; a = a->ai_next) { > struct socket_address *remote_addr; >- smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket); >+ smb_krb5 = talloc(frame, struct smb_krb5_socket); > if (!smb_krb5) { >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return ENOMEM; > } > smb_krb5->hi = hi; >@@ -254,7 +254,7 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > break; > #endif > default: >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return EINVAL; > } > >@@ -267,7 +267,7 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0); > break; > case KRB5_KRBHST_HTTP: >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return EINVAL; > } > if (!NT_STATUS_IS_OK(status)) { >@@ -335,12 +335,12 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > packet_send(smb_krb5->packet, smb_krb5->request); > break; > case KRB5_KRBHST_HTTP: >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return EINVAL; > } > while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { > if (tevent_loop_once(ev) != 0) { >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return EINVAL; > } > >@@ -355,7 +355,7 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > func, > data); > if (ret != 0) { >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return ret; > } > } >@@ -381,14 +381,14 @@ static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, > > ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length); > if (ret) { >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return ret; > } > talloc_free(smb_krb5); > > break; > } >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > if (a) { > return 0; > } >@@ -406,16 +406,16 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, > struct addrinfo *ai; > > struct tevent_context *ev; >- TALLOC_CTX *tmp_ctx = talloc_new(NULL); >- if (!tmp_ctx) { >+ TALLOC_CTX *frame = talloc_stackframe(); >+ if (frame == NULL) { > return ENOMEM; > } > >- if (!data) { >+ if (data == NULL) { > /* If no event context was available, then create one for this loop */ >- ev = samba_tevent_context_init(tmp_ctx); >- if (!ev) { >- talloc_free(tmp_ctx); >+ ev = samba_tevent_context_init(frame); >+ if (ev == NULL) { >+ TALLOC_FREE(frame); > return ENOMEM; > } > } else { >@@ -424,10 +424,13 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, > > ret = krb5_krbhst_get_addrinfo(context, hi, &ai); > if (ret) { >- talloc_free(tmp_ctx); >+ TALLOC_FREE(frame); > return ret; > } >- return smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf); >+ >+ ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf); >+ TALLOC_FREE(frame); >+ return ret; > } > > krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, >@@ -437,24 +440,27 @@ krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, > const krb5_data *send_buf, > krb5_data *recv_buf) > { >+ krb5_error_code k5ret; > struct addrinfo *ai = data; > > struct tevent_context *ev; >- TALLOC_CTX *tmp_ctx = talloc_new(NULL); >- if (!tmp_ctx) { >+ TALLOC_CTX *frame = talloc_stackframe(); >+ if (frame == NULL) { > return ENOMEM; > } > >- /* If no event context was available, then create one for this loop */ >- ev = samba_tevent_context_init(tmp_ctx); >- if (!ev) { >- talloc_free(tmp_ctx); >+ /* no event context is passed in, create one for this loop */ >+ ev = samba_tevent_context_init(frame); >+ if (ev == NULL) { >+ TALLOC_FREE(frame); > return ENOMEM; > } > > /* No need to pass in send_and_recv functions, we won't nest on this private event loop */ >- return smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL, >- timeout, send_buf, recv_buf); >+ k5ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL, >+ timeout, send_buf, recv_buf); >+ TALLOC_FREE(frame); >+ return k5ret; > } > #endif > >-- >2.1.4 > > >From 094405b30b7e0821e09fd0e1ca96fbbec6e25402 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Sat, 7 Feb 2015 19:45:24 +1300 >Subject: [PATCH 46/60] torture-krb5: Provide a generic handler to catch and > print unexpected KRB_ERROR packets > >This may aid debugging in the future. > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-By: Jelmer Vernooij <jelmer@samba.org> >Reviewed-by: Kamen Mazdrashki <kamenim@samba.org> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> >Autobuild-Date(master): Sun Feb 8 10:37:23 CET 2015 on sn-devel-104 > >(cherry picked from commit bfccf0abf8a11788b59edab1983d14114906c7f4) >--- > source4/torture/krb5/kdc-canon.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index e745fe5..312c7b5 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -60,16 +60,16 @@ struct test_data { > > enum test_stage { > TEST_AS_REQ = 0, >- TEST_TGS_REQ_KRBTGT_CANON, >- TEST_TGS_REQ_CANON, >- TEST_SELF_TRUST_TGS_REQ, >- TEST_TGS_REQ, >- TEST_TGS_REQ_KRBTGT, >- TEST_TGS_REQ_HOST, >- TEST_TGS_REQ_HOST_SRV_INST, >- TEST_TGS_REQ_HOST_SRV_HST, >- TEST_AS_REQ_SELF, >- TEST_DONE >+ TEST_TGS_REQ_KRBTGT_CANON = 1, >+ TEST_TGS_REQ_CANON = 2, >+ TEST_SELF_TRUST_TGS_REQ = 3, >+ TEST_TGS_REQ = 4, >+ TEST_TGS_REQ_KRBTGT = 5, >+ TEST_TGS_REQ_HOST = 6, >+ TEST_TGS_REQ_HOST_SRV_INST = 7, >+ TEST_TGS_REQ_HOST_SRV_HST = 8, >+ TEST_AS_REQ_SELF = 9, >+ TEST_DONE = 10 > }; > > struct torture_krb5_context { >@@ -1224,6 +1224,18 @@ static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context c > break; > } > if (ok == false) { >+ KRB_ERROR error; >+ size_t used; >+ torture_warning(test_context->tctx, "Packet of length %llu failed post-recv checks in test stage %d", (unsigned long long)recv_buf->length, test_context->test_stage); >+ if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) { >+ torture_warning(test_context->tctx, >+ "STAGE: %d Unexpectedly got a KRB-ERROR packet " >+ "with error code %d (%s)", >+ test_context->test_stage, >+ error.error_code, >+ error_message(error.error_code + KRB5KDC_ERR_NONE)); >+ free_KRB_ERROR(&error); >+ } > return EINVAL; > } > >-- >2.1.4 > > >From 175f4b7bcca393a7f7de89078fbdb2e8995b6ba8 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 9 Mar 2015 16:00:56 +1300 >Subject: [PATCH 47/60] kdc: Fix S4U2Self handling with > KRB5_NT_ENTERPRISE_PRINCIPAL containing a UPN > >This is now handled properly by samba_kdc_lookup_server() and this wrapper actually >breaks things. > >Andrew Bartlett > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit a1ddee8d2f9e58e04f3203db9afa576354dd2079) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/kdc/db-glue.c | 21 --------------------- > 1 file changed, 21 deletions(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index aa73641..0bc907e 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -1839,7 +1839,6 @@ samba_kdc_check_s4u2self(krb5_context context, > krb5_const_principal target_principal) > { > krb5_error_code ret; >- krb5_principal enterprise_prinicpal = NULL; > struct ldb_dn *realm_dn; > struct ldb_message *msg; > struct dom_sid *orig_sid; >@@ -1857,30 +1856,10 @@ samba_kdc_check_s4u2self(krb5_context context, > return ret; > } > >- if (target_principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { >- /* Need to reparse the enterprise principal to find the real target */ >- if (target_principal->name.name_string.len != 1) { >- ret = KRB5_PARSE_MALFORMED; >- krb5_set_error_message(context, ret, "samba_kdc_check_s4u2self: request for delegation to enterprise principal with wrong (%d) number of components", >- target_principal->name.name_string.len); >- talloc_free(mem_ctx); >- return ret; >- } >- ret = krb5_parse_name(context, target_principal->name.name_string.val[0], >- &enterprise_prinicpal); >- if (ret) { >- talloc_free(mem_ctx); >- return ret; >- } >- target_principal = enterprise_prinicpal; >- } >- > ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal, > HDB_F_GET_CLIENT|HDB_F_GET_SERVER, > delegation_check_attrs, &realm_dn, &msg); > >- krb5_free_principal(context, enterprise_prinicpal); >- > if (ret != 0) { > talloc_free(mem_ctx); > return ret; >-- >2.1.4 > > >From 07ae5beddd22c9449bc1ad5c535a5d9d952d5e35 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Mon, 9 Mar 2015 11:12:01 +1300 >Subject: [PATCH 48/60] torture-krb5: Add an initial test for s4u2self > behaviour > >This test only checks for S4U2Self of the same user, but shows >that a user account is not a valid service for this purpose. > >Andrew Bartlett > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Mon Mar 9 12:10:09 CET 2015 on sn-devel-104 > >(cherry picked from commit 02f6cfd14c8ac15b5d8a55783bb98a87557394d5) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/torture/krb5/kdc-canon.c | 18 +++++++++++++++--- > 1 file changed, 15 insertions(+), 3 deletions(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 312c7b5..49c6c26 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -37,7 +37,8 @@ > #define TEST_NETBIOS_REALM 0x0000010 > #define TEST_WIN2K 0x0000020 > #define TEST_UPN 0x0000040 >-#define TEST_ALL 0x000007F >+#define TEST_S4U2SELF 0x0000080 >+#define TEST_ALL 0x00000FF > > struct test_data { > const char *test_name; >@@ -54,6 +55,7 @@ struct test_data { > bool win2k; > bool upn; > bool other_upn_suffix; >+ bool s4u2self; > const char *krb5_service; > const char *krb5_hostname; > }; >@@ -1665,6 +1667,14 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > opt, > KRB5_GC_NO_STORE); > >+ if (test_data->s4u2self) { >+ torture_assert_int_equal(tctx, >+ krb5_get_creds_opt_set_impersonate(k5_context, >+ opt, >+ principal), >+ 0, "krb5_get_creds_opt_set_impersonate failed"); >+ } >+ > /* Confirm if we can get a ticket to our own name */ > k5ret = krb5_get_creds(k5_context, opt, ccache, principal, &server_creds); > >@@ -2051,14 +2061,15 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > suite->description = talloc_strdup(suite, "Kerberos Canonicalisation tests"); > > for (i = 0; i < TEST_ALL; i++) { >- char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s.%s", >+ char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s.%s.%s", > (i & TEST_CANONICALIZE) ? "canon" : "no-canon", > (i & TEST_ENTERPRISE) ? "enterprise" : "no-enterprise", > (i & TEST_UPPER_REALM) ? "uc-realm" : "lc-realm", > (i & TEST_UPPER_USERNAME) ? "uc-user" : "lc-user", > (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm", > (i & TEST_WIN2K) ? "win2k" : "no-win2k", >- (i & TEST_UPN) ? "upn" : "no-upn"); >+ (i & TEST_UPN) ? "upn" : "no-upn", >+ (i & TEST_S4U2SELF) ? "s4u2self" : "normal"); > > struct test_data *test_data = talloc_zero(suite, struct test_data); > >@@ -2075,6 +2086,7 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) > test_data->netbios_realm = (i & TEST_NETBIOS_REALM) != 0; > test_data->win2k = (i & TEST_WIN2K) != 0; > test_data->upn = (i & TEST_UPN) != 0; >+ test_data->s4u2self = (i & TEST_S4U2SELF) != 0; > torture_suite_add_simple_tcase_const(suite, name, torture_krb5_as_req_canon, > test_data); > >-- >2.1.4 > > >From 240955131cc487faa6bac0b9910eb2cd7c8a3690 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 11 Mar 2015 15:57:06 +1300 >Subject: [PATCH 49/60] auth/kerberos: Do a string comparison in > kerberos_decode_pac() not a principal comparison > >This ensures that if an enterprise principal is used, we do the >comparison properly > >This matters as in the enterprise case, which can be triggered by MIT >kinit -E, does not use canonicalization, and so the enterprise name, >with the @ in it, is in the logon name. > >Otherwise, we get errors like: > Name in PAC [TESTALLOWED@WIN2012R2] does not match principal name in ticket > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit e48d136e3a5c89c9bab8ea898775fad1449d2f96) >--- > auth/kerberos/kerberos_pac.c | 23 ++++++++++++----------- > 1 file changed, 12 insertions(+), 11 deletions(-) > >diff --git a/auth/kerberos/kerberos_pac.c b/auth/kerberos/kerberos_pac.c >index 8f55c8f..32d9d7f 100644 >--- a/auth/kerberos/kerberos_pac.c >+++ b/auth/kerberos/kerberos_pac.c >@@ -106,7 +106,6 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, > DATA_BLOB modified_pac_blob; > > NTTIME tgs_authtime_nttime; >- krb5_principal client_principal_pac = NULL; > int i; > > struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; >@@ -357,28 +356,30 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, > } > > if (client_principal) { >- ret = smb_krb5_parse_name_norealm(context, >- logon_name->account_name, >- &client_principal_pac); >+ char *client_principal_string; >+ ret = krb5_unparse_name_flags(context, client_principal, >+ KRB5_PRINCIPAL_UNPARSE_NO_REALM|KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &client_principal_string); > if (ret) { >- DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n", >+ DEBUG(2, ("Could not unparse name from ticket to match with name from PAC: [%s]:%s\n", > logon_name->account_name, error_message(ret))); > talloc_free(tmp_ctx); > return NT_STATUS_INVALID_PARAMETER; > } > >- bool_ret = smb_krb5_principal_compare_any_realm(context, >- client_principal, >- client_principal_pac); >- >- krb5_free_principal(context, client_principal_pac); >+ bool_ret = strcmp(client_principal_string, logon_name->account_name) == 0; > > if (!bool_ret) { > DEBUG(2, ("Name in PAC [%s] does not match principal name " >- "in ticket\n", logon_name->account_name)); >+ "in ticket [%s]\n", >+ logon_name->account_name, >+ client_principal_string)); >+ SAFE_FREE(client_principal_string); > talloc_free(tmp_ctx); > return NT_STATUS_ACCESS_DENIED; > } >+ SAFE_FREE(client_principal_string); >+ > } > > DEBUG(3,("Found account name from PAC: %s [%s]\n", >-- >2.1.4 > > >From 82e7e3c19c398fffd551578216a796549e6ada62 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 11:27:57 +1300 >Subject: [PATCH 50/60] auth/kerberos: Use KRB5_PRINCIPAL_UNPARSE_DISPLAY in > kerberos_create_pac() > >This ensures that in the all-Samba PAC creation code, we do not escape a space character if present >in the logon name. This matches what we do in the Heimdal code in the KDC. > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit bc8b580659d429690f6b54f17368526fc8c845e3) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/auth/kerberos/kerberos_pac.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > >diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c >index 5d65461..20cfe88 100644 >--- a/source4/auth/kerberos/kerberos_pac.c >+++ b/source4/auth/kerberos/kerberos_pac.c >@@ -251,7 +251,9 @@ > LOGON_INFO->info3 = *sam3; > > ret = krb5_unparse_name_flags(context, client_principal, >- KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); >+ KRB5_PRINCIPAL_UNPARSE_NO_REALM | >+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &name); > if (ret) { > return ret; > } >-- >2.1.4 > > >From c335302e6c044b317df70982605144a30657217e Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 18 Dec 2014 11:03:44 +1300 >Subject: [PATCH 51/60] gensec_krb5: Match behaviour of gensec_gssapi for > password-based keytabs > >This allows the winbind.pac.krb5 test to pass against the s3member environment, which uses the password from secrets.tdb. > >Andrew Bartlett > >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 121bbc01842db03570623eadcbb97edab30ca651) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/auth/gensec/gensec_krb5.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > >diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c >index c34c434..a81dfc3 100644 >--- a/source4/auth/gensec/gensec_krb5.c >+++ b/source4/auth/gensec/gensec_krb5.c >@@ -591,6 +591,16 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, > return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; > } > >+ if (keytab->password_based || obtained < CRED_SPECIFIED) { >+ /* >+ * Use match-by-key in this case (matches >+ * cli_credentials_get_server_gss_creds() >+ * behaviour). No need to free the memory, >+ * this is handled with a talloc destructor. >+ */ >+ server_in_keytab = NULL; >+ } >+ > /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */ > if (gensec_krb5_state->gssapi > && gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) { >-- >2.1.4 > > >From cb4344b6a49eb439ac9cb0cfd40c3cd54ab57186 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 11 Mar 2015 15:58:36 +1300 >Subject: [PATCH 52/60] torture-krb5: Test accepting the ticket to ensure PAC > is well-formed > >A future test will ask for impersonation to a different user, and >validate returned principal and the PAC matches that user. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit a1b4a5d977862bda48819d3f0b33eccbd10ca4fd) >--- > source4/torture/krb5/kdc-canon.c | 135 ++++++++++++++++++++++++++++++++++++++- > 1 file changed, 134 insertions(+), 1 deletion(-) > >diff --git a/source4/torture/krb5/kdc-canon.c b/source4/torture/krb5/kdc-canon.c >index 49c6c26..20f0cf1 100644 >--- a/source4/torture/krb5/kdc-canon.c >+++ b/source4/torture/krb5/kdc-canon.c >@@ -29,6 +29,10 @@ > #include "source4/auth/kerberos/kerberos.h" > #include "source4/auth/kerberos/kerberos_util.h" > #include "lib/util/util_net.h" >+#include "auth/auth.h" >+#include "auth/auth_sam_reply.h" >+#include "auth/gensec/gensec.h" >+#include "param/param.h" > > #define TEST_CANONICALIZE 0x0000001 > #define TEST_ENTERPRISE 0x0000002 >@@ -87,6 +91,121 @@ struct torture_krb5_context { > TGS_REP tgs_rep; > }; > >+struct pac_data { >+ const char *principal_name; >+}; >+ >+/* >+ * A helper function which avoids touching the local databases to >+ * generate the session info, as we just want to verify the principal >+ * name that we found in the ticket not the full local token >+ */ >+static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx, >+ TALLOC_CTX *mem_ctx, >+ struct smb_krb5_context *smb_krb5_context, >+ DATA_BLOB *pac_blob, >+ const char *principal_name, >+ const struct tsocket_address *remote_address, >+ uint32_t session_info_flags, >+ struct auth_session_info **session_info) >+{ >+ NTSTATUS nt_status; >+ struct auth_user_info_dc *user_info_dc; >+ TALLOC_CTX *tmp_ctx; >+ struct pac_data *pac_data; >+ >+ tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context"); >+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); >+ >+ auth_ctx->private_data = pac_data = talloc_zero(auth_ctx, struct pac_data); >+ >+ pac_data->principal_name = talloc_strdup(pac_data, principal_name); >+ if (!pac_data->principal_name) { >+ talloc_free(tmp_ctx); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ nt_status = kerberos_pac_blob_to_user_info_dc(tmp_ctx, >+ *pac_blob, >+ smb_krb5_context->krb5_context, >+ &user_info_dc, NULL, NULL); >+ if (!NT_STATUS_IS_OK(nt_status)) { >+ talloc_free(tmp_ctx); >+ return nt_status; >+ } >+ >+ if (user_info_dc->info->authenticated) { >+ session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED; >+ } >+ >+ session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES; >+ nt_status = auth_generate_session_info(mem_ctx, >+ NULL, >+ NULL, >+ user_info_dc, session_info_flags, >+ session_info); >+ if (!NT_STATUS_IS_OK(nt_status)) { >+ talloc_free(tmp_ctx); >+ return nt_status; >+ } >+ >+ talloc_free(tmp_ctx); >+ return NT_STATUS_OK; >+} >+ >+/* Check to see if we can pass the PAC across to the NETLOGON server for validation */ >+ >+/* Also happens to be a really good one-step verfication of our Kerberos stack */ >+ >+static bool test_accept_ticket(struct torture_context *tctx, >+ struct cli_credentials *credentials, >+ const char *principal, >+ DATA_BLOB client_to_server) >+{ >+ NTSTATUS status; >+ struct gensec_security *gensec_server_context; >+ DATA_BLOB server_to_client; >+ struct auth4_context *auth_context; >+ struct auth_session_info *session_info; >+ struct pac_data *pac_data; >+ TALLOC_CTX *tmp_ctx = talloc_new(tctx); >+ >+ torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed"); >+ >+ auth_context = talloc_zero(tmp_ctx, struct auth4_context); >+ torture_assert(tctx, auth_context != NULL, "talloc_new() failed"); >+ >+ auth_context->generate_session_info_pac = test_generate_session_info_pac; >+ >+ status = gensec_server_start(tctx, >+ lpcfg_gensec_settings(tctx, tctx->lp_ctx), >+ auth_context, &gensec_server_context); >+ torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed"); >+ >+ status = gensec_set_credentials(gensec_server_context, credentials); >+ torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed"); >+ >+ status = gensec_start_mech_by_name(gensec_server_context, "krb5"); >+ torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_name (server) failed"); >+ >+ server_to_client = data_blob(NULL, 0); >+ >+ /* Do a client-server update dance */ >+ status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client); >+ torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed"); >+ >+ /* Extract the PAC using Samba's code */ >+ >+ status = gensec_session_info(gensec_server_context, gensec_server_context, &session_info); >+ torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed"); >+ >+ pac_data = talloc_get_type(auth_context->private_data, struct pac_data); >+ >+ torture_assert(tctx, pac_data != NULL, "gensec_update failed to fill in pac_data in auth_context"); >+ torture_assert(tctx, pac_data->principal_name != NULL, "principal_name not present"); >+ torture_assert_str_equal(tctx, pac_data->principal_name, principal, "wrong principal name"); >+ return true; >+} > > /* > * TEST_AS_REQ and TEST_AS_REQ_SELF - SEND >@@ -1298,6 +1417,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > char *krbtgt_other_string; > int principal_flags; > char *expected_principal_string; >+ char *expected_unparse_principal_string; > int expected_principal_flags; > char *got_principal_string; > char *assertion_message; >@@ -1436,6 +1556,11 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > &expected_principal), > 0, "krb5_parse_name_flags failed"); > >+ torture_assert_int_equal(tctx, >+ krb5_unparse_name(k5_context, >+ expected_principal, >+ &expected_unparse_principal_string), >+ 0, "krb5_unparse_name failed"); > /* > * Prepare a AS-REQ and run the TEST_AS_REQ tests > * >@@ -1752,7 +1877,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > in_data.length = 0; > k5ret = krb5_mk_req_exact(k5_context, > &auth_context, >- 0, >+ AP_OPTS_USE_SUBKEY, > principal, > &in_data, ccache, > &enc_ticket); >@@ -1766,7 +1891,15 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * > * servicePrincipalName) can expect this test to succeed > */ > if (torture_setting_bool(tctx, "expect_machine_account", false) && (test_data->enterprise || test_data->upn == false)) { >+ DATA_BLOB client_to_server; > torture_assert_int_equal(tctx, k5ret, 0, assertion_message); >+ client_to_server = data_blob_const(enc_ticket.data, enc_ticket.length); >+ torture_assert(tctx, >+ test_accept_ticket(tctx, cmdline_credentials, >+ expected_unparse_principal_string, >+ client_to_server), >+ "test_accept_ticket failed - failed to accept the ticket we just created"); >+ krb5_data_free(&enc_ticket); > } else { > torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, > assertion_message); >-- >2.1.4 > > >From ccff536a590e96f5585996a52b971e9a19f95483 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 10 Mar 2015 15:36:01 +0100 >Subject: [PATCH 53/60] heimdal:lib/krb5: allow enterprise principals in > verify_logonname() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit b7cc8c1187ff967e44587cd0d09185330378f366) >--- > source4/heimdal/lib/krb5/pac.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > >diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c >index 91f68d5..a28dc82 100644 >--- a/source4/heimdal/lib/krb5/pac.c >+++ b/source4/heimdal/lib/krb5/pac.c >@@ -677,7 +677,9 @@ verify_logonname(krb5_context context, > return ret; > } > } >- ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); >+ ret = krb5_parse_name_flags(context, s, >+ KRB5_PRINCIPAL_PARSE_NO_REALM | >+ KRB5_PRINCIPAL_PARSE_ENTERPRISE, &p2); > free(s); > if (ret) > return ret; >-- >2.1.4 > > >From 9d35654544e58e18566008a9f0db288d6e685307 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 10 Mar 2015 15:33:14 +0100 >Subject: [PATCH 54/60] heimdal:lib/krb5: let build_logon_name() use > KRB5_PRINCIPAL_UNPARSE_DISPLAY > >An ENTERPRISE principal should result in 'administrator@S4XDOM.BASE' >instead of 'administrator\@S4XDOM.BASE'. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit da99f8a5b9e492406b5d64bb53f090de3fd93957) >--- > source4/heimdal/lib/krb5/pac.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > >diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c >index a28dc82..9328647 100644 >--- a/source4/heimdal/lib/krb5/pac.c >+++ b/source4/heimdal/lib/krb5/pac.c >@@ -724,7 +724,9 @@ build_logon_name(krb5_context context, > CHECK(ret, krb5_store_uint32(sp, t >> 32), out); > > ret = krb5_unparse_name_flags(context, principal, >- KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s); >+ KRB5_PRINCIPAL_UNPARSE_NO_REALM | >+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &s); > if (ret) > goto out; > >-- >2.1.4 > > >From 5ecadbf3ce9c0cb4fb00c6cee8311aef65be2f49 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 12:50:23 +1300 >Subject: [PATCH 55/60] dsdb: Allow spaces in userPrincipalName values > >This is needed to enable a kinit with a UPN that has a space in it > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 3cd871321667045635d8236d91386070e84770a4) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/dsdb/samdb/cracknames.c | 14 ++++++++++++-- > 1 file changed, 12 insertions(+), 2 deletions(-) > >diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c >index 0d1a800..a03b03d 100644 >--- a/source4/dsdb/samdb/cracknames.c >+++ b/source4/dsdb/samdb/cracknames.c >@@ -680,8 +680,18 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, > > domain_filter = NULL; > >- /* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */ >- ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name); >+ /* >+ * By getting the unparsed name here, we ensure the >+ * escaping is removed correctly (and trust the client >+ * less). The important thing here is that a >+ * userPrincipalName may have a space in it, and this >+ * must not be kerberos escaped to match this filter, >+ * so we specify KRB5_PRINCIPAL_UNPARSE_DISPLAY >+ */ >+ ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, >+ principal, >+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &unparsed_name); > if (ret) { > krb5_free_principal(smb_krb5_context->krb5_context, principal); > return WERR_NOMEM; >-- >2.1.4 > > >From 35660801483650f8be714bb81997a39c36f8b6f3 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 12 Mar 2015 10:43:57 +0100 >Subject: [PATCH 56/60] selftest: fix the basedn for local accounts in non-DC > environments e.g. s4member > >open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); >doesn't generate an error if the command fails... > >'testallowed' is a local account here, with a dn of >CN=testallowed,CN=Users,DC=S4MEMBER instead of domain user >CN=testallowed,CN=Users,DC=samba,DC=example,DC=com > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 979385cd0fd20957d552e64edc07ea2fa0edc0fc) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > selftest/target/Samba4.pm | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 3cd3c39..5cb98cc 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -782,6 +782,11 @@ sub provision_raw_step2($$$) > > my $ldbmodify = Samba::bindir_path($self, "ldbmodify"); > my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); >+ >+ if ($ctx->{server_role} ne "domain controller") { >+ $base_dn = "DC=$ctx->{netbiosname}"; >+ } >+ > my $user_dn = "cn=testallowed,cn=users,$base_dn"; > open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); > print LDIF "dn: $user_dn >-- >2.1.4 > > >From c15bde69d9a3ef34c4373be3a7f27dd11cec504c Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 12:56:56 +1300 >Subject: [PATCH 57/60] selftest: Change testsuite to use a UPN with a space in > it > >This shows that the previous patch is correct > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit d3e0d7e2b0ee9fb72a8c602c86aee1d2f2755236) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > selftest/target/Samba4.pm | 2 +- > source4/selftest/tests.py | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index 5cb98cc..eb06d67 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -792,7 +792,7 @@ sub provision_raw_step2($$$) > print LDIF "dn: $user_dn > changetype: modify > replace: userPrincipalName >-userPrincipalName: testallowed_upn\@$ctx->{realm} >+userPrincipalName: testallowed upn\@$ctx->{realm} > replace: servicePrincipalName > servicePrincipalName: host/testallowed > - >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 9dccb92..b6d1e8a 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -568,7 +568,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', > '--workgroup=$DOMAIN', '--realm=$REALM', > '--option=torture:expect_machine_account=true', >- '--option=torture:krb5-upn=testallowed_upn@$REALM', >+ '--option=torture:krb5-upn=testallowed\ upn@$REALM', > '--option=torture:krb5-hostname=testallowed'] + extra_options, > "samba4.krb5.kdc with account ALLOWED permission to replicate to an RODC") > >-- >2.1.4 > > >From f2c053e603553b0600214b8836c2c051df74de48 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 13:29:56 +1300 >Subject: [PATCH 58/60] dsdb: Ensure we cope with a samAccountName with a space > in it in DsCrackName() > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 7ed24924d2917556a03c51eadcb65b3e3c1e8af6) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/dsdb/samdb/cracknames.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > >diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c >index a03b03d..ae334b4 100644 >--- a/source4/dsdb/samdb/cracknames.c >+++ b/source4/dsdb/samdb/cracknames.c >@@ -323,8 +323,16 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, > return WERR_OK; > } > >+ /* >+ * The important thing here is that a samAccountName may have >+ * a space in it, and this must not be kerberos escaped to >+ * match this filter, so we specify >+ * KRB5_PRINCIPAL_UNPARSE_DISPLAY >+ */ > ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal, >- KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short); >+ KRB5_PRINCIPAL_UNPARSE_NO_REALM | >+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &unparsed_name_short); > krb5_free_principal(smb_krb5_context->krb5_context, principal); > > if (ret) { >-- >2.1.4 > > >From 17432d41862fd2760e48c296074f8784ae72cb71 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 13:29:56 +1300 >Subject: [PATCH 59/60] kdc: Ensure we cope with a samAccountName with a space > in it > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 7f5740f34226301e2172c7e2024fd8c6c4ededf5) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > source4/kdc/db-glue.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > >diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c >index 0bc907e..8f2b361 100644 >--- a/source4/kdc/db-glue.c >+++ b/source4/kdc/db-glue.c >@@ -1601,7 +1601,10 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context, > > /* TODO: Check if it is our realm, otherwise give referral */ > >- ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ); >+ ret = krb5_unparse_name_flags(context, principal, >+ KRB5_PRINCIPAL_UNPARSE_NO_REALM | >+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, >+ &short_princ); > > if (ret != 0) { > krb5_set_error_message(context, ret, "samba_kdc_lookup_principal: could not parse principal"); >-- >2.1.4 > > >From 24faf8a6d5e2d40b04280597e0072c46a048fb28 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 12 Mar 2015 13:43:49 +1300 >Subject: [PATCH 60/60] selftest: Change testsuite to use a samAccountName with > a space in it > >This shows that the previous patch is correct > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 4bebab21463825c22cced6e8c59b99c525172911) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11142 >--- > selftest/target/Samba4.pm | 17 +++++++++++++---- > source4/selftest/tests.py | 2 +- > 2 files changed, 14 insertions(+), 5 deletions(-) > >diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm >index eb06d67..11c2148 100755 >--- a/selftest/target/Samba4.pm >+++ b/selftest/target/Samba4.pm >@@ -791,6 +791,15 @@ sub provision_raw_step2($$$) > open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); > print LDIF "dn: $user_dn > changetype: modify >+replace: samAccountName >+samAccountName: test allowed >+- >+"; >+ close(LDIF); >+ >+ open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); >+ print LDIF "dn: $user_dn >+changetype: modify > replace: userPrincipalName > userPrincipalName: testallowed upn\@$ctx->{realm} > replace: servicePrincipalName >@@ -817,9 +826,9 @@ userPrincipalName: testdenied_upn\@$ctx->{realm}.upn > close(LDIF); > > $samba_tool_cmd = Samba::bindir_path($self, "samba-tool") >- . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' testallowed"; >+ . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' 'test allowed'"; > unless (system($samba_tool_cmd) == 0) { >- warn("Unable to add testallowed user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n"); >+ warn("Unable to add 'test allowed' user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n"); > return undef; > } > >@@ -1544,10 +1553,10 @@ sub provision_rodc($$$) > return undef; > } > >- # This ensures deterministic behaviour for tests that want to have the testallowed >+ # This ensures deterministic behaviour for tests that want to have the 'test allowed' > # user password verified on the RODC > $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; >- $cmd .= "$samba_tool rodc preload testallowed $ret->{CONFIGURATION}"; >+ $cmd .= "$samba_tool rodc preload 'test allowed' $ret->{CONFIGURATION}"; > $cmd .= " --server=$dcvars->{DC_SERVER}"; > > unless (system($cmd) == 0) { >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index b6d1e8a..ea0afd6 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -565,7 +565,7 @@ for env in ["dc", "rodc", "promoted_dc", "plugin_s4_dc", "fl2000dc", "fl2003dc", > > plansmbtorture4testsuite('krb5.kdc', "%s:local" % env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-P', '--workgroup=$DOMAIN', '--realm=$REALM', '--option=torture:krb5-hostname=$SERVER', '--option=torture:expect_machine_account=true'] + extra_options, > "samba4.krb5.kdc with machine account") >- plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utestallowed%$PASSWORD', >+ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", '-Utest\ allowed%$PASSWORD', > '--workgroup=$DOMAIN', '--realm=$REALM', > '--option=torture:expect_machine_account=true', > '--option=torture:krb5-upn=testallowed\ upn@$REALM', >-- >2.1.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
abartlet
:
review?
(
metze
)
Actions:
View
Attachments on
bug 11142
:
10829
|
10836
|
10851
|
10870
| 10874