The branch, master has been updated via d88f1c82b2f credentials: Workaround krb5_cc_remove_cred not implemented in MIT kerberos via 937ad9d2a00 credentials: Initialize krb5 client to retrieve creds from ccache via c12914c6697 selftests: Place credential cache file inside environment directory from cbee3037a29 waf: only set mandatory to False if not already set by the caller
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit d88f1c82b2fa682ca3ed0256b4728f7e1b6999fc Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 27 17:12:09 2019 +0100 credentials: Workaround krb5_cc_remove_cred not implemented in MIT kerberos Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Mon Apr 29 19:15:48 UTC 2019 on sn-devel-184 commit 937ad9d2a00d1b993d37ff5801fd301eccd87556 Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 27 17:07:05 2019 +0100 credentials: Initialize krb5 client to retrieve creds from ccache MIT kerberos require krb5_creds.client to be initialized to match krb5_creds.server with the cached credentials. Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit c12914c6697c70d5c15776537f7f331d306933bb Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 27 17:05:20 2019 +0100 selftests: Place credential cache file inside environment directory Pair-Programmed-With: Andreas Schneider <a...@samba.org> Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/credentials/credentials_krb5.c | 164 ++++++++++++++++++++++++++++++++++++ source4/selftest/tests.py | 2 +- 2 files changed, 165 insertions(+), 1 deletion(-) Changeset truncated at 500 lines: diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index d8ca6d97115..20e677e521a 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -365,6 +365,144 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, return 0; } +#ifndef SAMBA4_USES_HEIMDAL +/* + * This function is a workaround for old MIT Kerberos versions which did not + * implement the krb5_cc_remove_cred function. It creates a temporary + * credentials cache to copy the credentials in the current cache + * except the one we want to remove and then overwrites the contents of the + * current cache with the temporary copy. + */ +static krb5_error_code krb5_cc_remove_cred_wrap(struct ccache_container *ccc, + krb5_creds *creds) +{ + krb5_ccache dummy_ccache = NULL; + krb5_creds cached_creds = {0}; + krb5_cc_cursor cursor = NULL; + krb5_error_code code; + char *dummy_name; + + dummy_name = talloc_asprintf(ccc, + "MEMORY:copy_ccache-%p", + &ccc->ccache); + if (dummy_name == NULL) { + return KRB5_CC_NOMEM; + } + + code = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, + dummy_name, + &dummy_ccache); + if (code != 0) { + DBG_ERR("krb5_cc_resolve failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + TALLOC_FREE(dummy_name); + return code; + } + + TALLOC_FREE(dummy_name); + + code = krb5_cc_start_seq_get(ccc->smb_krb5_context->krb5_context, + ccc->ccache, + &cursor); + if (code != 0) { + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + + DBG_ERR("krb5_cc_start_seq_get failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + + while ((code = krb5_cc_next_cred(ccc->smb_krb5_context->krb5_context, + ccc->ccache, + &cursor, + &cached_creds)) == 0) { + /* If the principal matches skip it and do not copy to the + * temporary cache as this is the one we want to remove */ + if (krb5_principal_compare_flags( + ccc->smb_krb5_context->krb5_context, + creds->server, + cached_creds.server, + 0)) { + continue; + } + + code = krb5_cc_store_cred( + ccc->smb_krb5_context->krb5_context, + dummy_ccache, + &cached_creds); + if (code != 0) { + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + DBG_ERR("krb5_cc_store_cred failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + } + + if (code == KRB5_CC_END) { + krb5_cc_end_seq_get(ccc->smb_krb5_context->krb5_context, + dummy_ccache, + &cursor); + code = 0; + } + + if (code != 0) { + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + DBG_ERR("krb5_cc_next_cred failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + + code = krb5_cc_initialize(ccc->smb_krb5_context->krb5_context, + ccc->ccache, + creds->client); + if (code != 0) { + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + DBG_ERR("krb5_cc_initialize failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + + code = krb5_cc_copy_creds(ccc->smb_krb5_context->krb5_context, + dummy_ccache, + ccc->ccache); + if (code != 0) { + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + DBG_ERR("krb5_cc_copy_creds failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + + code = krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, + dummy_ccache); + if (code != 0) { + DBG_ERR("krb5_cc_destroy failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + code, ccc)); + return code; + } + + return code; +} +#endif + /* * Indicate the we failed to log in to this service/host with these * credentials. The caller passes an unsigned int which they @@ -406,6 +544,21 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred return false; } + /* MIT kerberos requires creds.client to match against cached + * credentials */ + ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, + ccc->ccache, + &creds.client); + if (ret != 0) { + krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, + &creds); + DBG_ERR("krb5_cc_get_principal failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + ret, ccc)); + return false; + } + ret = krb5_cc_retrieve_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds, &creds2); if (ret != 0) { /* don't retry - we didn't find these credentials to remove */ @@ -414,6 +567,13 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred } ret = krb5_cc_remove_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds); +#ifndef SAMBA4_USES_HEIMDAL + if (ret == KRB5_CC_NOSUPP) { + /* Old MIT kerberos versions did not implement + * krb5_cc_remove_cred */ + ret = krb5_cc_remove_cred_wrap(ccc, &creds); + } +#endif krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds); krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds2); if (ret != 0) { @@ -423,6 +583,10 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred * creds don't exist, which is why we do a separate * krb5_cc_retrieve_cred() above. */ + DBG_ERR("krb5_cc_remove_cred failed: %s\n", + smb_get_krb5_error_message( + ccc->smb_krb5_context->krb5_context, + ret, ccc)); return false; } return true; diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 12e8538315e..234862c9a62 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -479,7 +479,7 @@ plantestsuite("samba4.blackbox.locktest(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.j plantestsuite("samba4.blackbox.masktest", "ad_dc_ntvfs", [os.path.join(samba4srcdir, "torture/tests/test_masktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX']) plantestsuite("samba4.blackbox.gentest(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(samba4srcdir, "torture/tests/test_gentest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', "$PREFIX"]) plantestsuite("samba4.blackbox.rfc2307_mapping(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) -plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) +plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX/chgdcpass', "aes256-cts-hmac-sha1-96", '$PREFIX/chgdcpass', smbclient4]) plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) plantestsuite("samba4.blackbox.net_ads(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_net_ads.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS']) plantestsuite("samba4.blackbox.client_etypes_all(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_client_etypes.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS', 'all', '17_18_23']) -- Samba Shared Repository