The branch, master has been updated via 87e31f88f28 s3:libsmb: let cli_session_creds_init() keep the value from 'client use kerberos' via e6c693b7056 s3:winbindd: pass a NULL ccache to kerberos_return_pac() for a MEMORY ccache via 147565232dc s3:libads: use smb_krb5_cc_new_unique_memory() in kerberos_return_pac() via 16a5279e291 auth/credentials: use smb_krb5_cc_new_unique_memory() in cli_credentials_new_ccache() via 176c55efb20 auth/credentials: use smb_krb5_cc_new_unique_memory() in cli_credentials_shallow_ccache() via 5d385ab691f auth/credentials: use smb_krb5_cc_new_unique_memory() in smb_gss_krb5_copy_ccache() via 92bebeb58ef auth/credentials: use smb_krb5_cc_new_unique_memory() in krb5_cc_remove_cred_wrap() via 21b96f010a4 lib/krb5_wrap: make use of smb_krb5_cc_new_unique_memory() in smb_krb5_kinit_s4u2_ccache() via 48bcc218c98 lib/krb5_wrap: add smb_krb5_cc_new_unique_memory() via e3f97f35b18 s3:gse: don't call krb5_cc_resolve() as server via 6ced3c6af22 s3:gse: avoid prompting for a password that we don't use in the end via ce05fe3b718 s3:gse: make use of gensec_kerberos_possible() via 4dd2468d5bc s4:gensec_gssapi: make use of gensec_kerberos_possible() via a3c87bf4404 auth/gensec: add gensec_get_unparsed_target_principal() helper via 996fd13949b auth/gensec: add gensec_kerberos_possible() helper via 1275e77933f s3:client: avoid cli_credentials_get_password() to check for a specified password via b9cf6c8dd4d auth:creds: Add test for cli_credentials_get_username_obtained() via f9afd24c907 auth/credentials: add cli_credentials_get_username_obtained() via 7f0aff46825 auth:creds: Add test for cli_credentials_get_password_obtained() via c14366cce45 auth/credentials: add cli_credentials_get_password_obtained() via a85f1b6facd lib/cmdline: skip the password prompt if we have a valid krb5 ccache via c7d3946659f auth/credentials: add cli_credentials_get_ccache_name_obtained() via 4723d695608 auth:creds: Add test for cli_credentials_get_principal_obtained() via 1e5546748cd auth/credentials: add cli_credentials_get_principal_obtained() from 5edd1e7c3ee smbd: Implement FSCTL_DELETE_REPARSE_POINT
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 87e31f88f28210dc6b7033182435f55204098368 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 7 15:31:39 2024 +0100 s3:libsmb: let cli_session_creds_init() keep the value from 'client use kerberos' Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Tue May 7 12:33:29 UTC 2024 on atb-devel-224 commit e6c693b705686a590d2fa8f434ff015d8926a349 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Feb 28 17:28:43 2024 +0100 s3:winbindd: pass a NULL ccache to kerberos_return_pac() for a MEMORY ccache It means kerberos_return_pac() will use smb_krb5_cc_new_unique_memory(). Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 147565232dc7cc3127e09268000723c5a3eea62b Author: Stefan Metzmacher <me...@samba.org> Date: Wed Feb 28 17:27:39 2024 +0100 s3:libads: use smb_krb5_cc_new_unique_memory() in kerberos_return_pac() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 16a5279e2918e7348f1695629bf3fa61c9007424 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 16:38:42 2024 +0100 auth/credentials: use smb_krb5_cc_new_unique_memory() in cli_credentials_new_ccache() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 176c55efb202f1f218c6c4ddf69d2d357488e25f Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 16:21:02 2024 +0100 auth/credentials: use smb_krb5_cc_new_unique_memory() in cli_credentials_shallow_ccache() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 5d385ab691f21bdd4524c41560c7f53653cf179d Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 16:19:58 2024 +0100 auth/credentials: use smb_krb5_cc_new_unique_memory() in smb_gss_krb5_copy_ccache() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 92bebeb58ef5ab91937d29640bf7a3c7929518ca Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 15:49:09 2024 +0100 auth/credentials: use smb_krb5_cc_new_unique_memory() in krb5_cc_remove_cred_wrap() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 21b96f010a4f9472a03aca5f4c1ed5a658530f52 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 15:47:15 2024 +0100 lib/krb5_wrap: make use of smb_krb5_cc_new_unique_memory() in smb_krb5_kinit_s4u2_ccache() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 48bcc218c980e9478e2a3479e889766e6ca7f1dd Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 27 15:42:37 2024 +0100 lib/krb5_wrap: add smb_krb5_cc_new_unique_memory() This generates a memory credential cache that is not visible to a (the default) credential cache collection. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit e3f97f35b18f9c11d718223b64de87ce1c08f64c Author: Stefan Metzmacher <me...@samba.org> Date: Thu Feb 29 16:15:37 2024 +0100 s3:gse: don't call krb5_cc_resolve() as server Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 6ced3c6af22a5e8f7d84e52c769029ea8a265724 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Apr 14 14:23:23 2022 +0200 s3:gse: avoid prompting for a password that we don't use in the end Currently we rely on a valid default credential cache being available and don't make use of the password. In future we'll do a kinit on demand, but that's for another day. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit ce05fe3b718a5d242f31f1acb25f5d7c5a6e4e0a Author: Stefan Metzmacher <me...@samba.org> Date: Tue Mar 5 15:33:51 2024 +0100 s3:gse: make use of gensec_kerberos_possible() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 4dd2468d5bcd704d8a745f9f3e487e539ae66bbb Author: Stefan Metzmacher <me...@samba.org> Date: Tue Mar 5 15:33:51 2024 +0100 s4:gensec_gssapi: make use of gensec_kerberos_possible() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit a3c87bf440457c59cdad8883fca142b5f06da587 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Mar 5 15:32:59 2024 +0100 auth/gensec: add gensec_get_unparsed_target_principal() helper This will be useful for debugging. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 996fd13949b9c4aa842971520a6a6d3059559caa Author: Stefan Metzmacher <me...@samba.org> Date: Tue Mar 5 14:41:39 2024 +0100 auth/gensec: add gensec_kerberos_possible() helper Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 1275e77933f74b5b8551aa9c5e5f84fbd561de04 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Apr 14 13:49:39 2022 +0200 s3:client: avoid cli_credentials_get_password() to check for a specified password Using cli_credentials_get_password_obtained() is more lightweight as it avoids a possible password prompt. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit b9cf6c8dd4d256300df170b1b21a86fe02416018 Author: Andreas Schneider <a...@samba.org> Date: Tue May 7 07:45:50 2024 +0200 auth:creds: Add test for cli_credentials_get_username_obtained() Signed-off-by: Andreas Schneider <a...@samba.org> commit f9afd24c907eaecd65a3b7a1387139472876047d Author: Stefan Metzmacher <me...@samba.org> Date: Wed Mar 13 17:50:34 2024 +0100 auth/credentials: add cli_credentials_get_username_obtained() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 7f0aff468256415c76bbcd5c7249f909de9f3b91 Author: Andreas Schneider <a...@samba.org> Date: Tue May 7 07:44:22 2024 +0200 auth:creds: Add test for cli_credentials_get_password_obtained() Signed-off-by: Andreas Schneider <a...@samba.org> commit c14366cce45a437584d9050067a34fffb847e134 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Apr 14 13:46:18 2022 +0200 auth/credentials: add cli_credentials_get_password_obtained() It's often useful to know if a password was already explicitly specified without triggering the password callback function. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit a85f1b6facd2b641f98dcea9b997a02d8f276882 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Apr 14 13:34:37 2022 +0200 lib/cmdline: skip the password prompt if we have a valid krb5 ccache BUG: https://bugzilla.samba.org/show_bug.cgi?id=15018 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit c7d3946659ff9ce167f68f3f052fae02a8907869 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Apr 14 13:29:47 2022 +0200 auth/credentials: add cli_credentials_get_ccache_name_obtained() It's often good to know if a credential structure already has a valid kerberos credential cache attached, without the side effect of doing a kinit and prompt for a password. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15018 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 4723d695608e7737176e4f6eb407885a38989fc8 Author: Andreas Schneider <a...@samba.org> Date: Tue May 7 07:54:46 2024 +0200 auth:creds: Add test for cli_credentials_get_principal_obtained() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15018 Signed-off-by: Andreas Schneider <a...@samba.org> commit 1e5546748cd22c9e654ed066ab1d27aadec0d3d3 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Mar 13 17:50:56 2024 +0100 auth/credentials: add cli_credentials_get_principal_obtained() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15018 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/credentials/credentials.c | 83 +++++++++++++++++++ auth/credentials/credentials.h | 8 ++ auth/credentials/credentials_krb5.c | 160 +++++++++++++++++++++++++----------- auth/credentials/tests/test_creds.c | 13 ++- auth/gensec/gensec_internal.h | 4 + auth/gensec/gensec_util.c | 81 ++++++++++++++++++ lib/cmdline/cmdline.c | 19 +++++ lib/krb5_wrap/krb5_samba.c | 78 +++++++++++++++++- lib/krb5_wrap/krb5_samba.h | 5 ++ source3/client/client.c | 4 +- source3/libads/authdata.c | 33 +++++++- source3/librpc/crypto/gse.c | 76 ++++++++--------- source3/libsmb/cliconnect.c | 8 +- source3/winbindd/winbindd_pam.c | 47 ++++++----- source4/auth/gensec/gensec_gssapi.c | 42 +++------- 15 files changed, 511 insertions(+), 150 deletions(-) Changeset truncated at 500 lines: diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index 6a590483e99..441db6f0e5b 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -176,6 +176,18 @@ _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *cr return creds->gensec_features; } +/** + * @brief Find out how the username was obtained. + * + * @param cred A credentials context. + * + * @return The obtained information for the username. + */ +_PUBLIC_ enum credentials_obtained +cli_credentials_get_username_obtained(struct cli_credentials *cred) +{ + return cred->username_obtained; +} /** * Obtain the username for this credentials context. @@ -268,6 +280,64 @@ _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred) } +/** + * @brief Find out how the principal was obtained. + * + * @param cred A credentials context. + * + * @return The obtained information for the principal. + */ +_PUBLIC_ enum credentials_obtained +cli_credentials_get_principal_obtained(struct cli_credentials *cred) +{ + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred, + cred->machine_account_pending_lp_ctx); + } + + if (cred->principal_obtained < cred->username_obtained + || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) { + const char *effective_username = NULL; + const char *effective_realm = NULL; + enum credentials_obtained effective_obtained; + + /* + * We don't want to trigger a callbacks in + * cli_credentials_get_username() + * cli_credentials_get_domain() + * nor + * cli_credentials_get_realm() + */ + + effective_username = cred->username; + if (effective_username == NULL || strlen(effective_username) == 0) { + return cred->username_obtained; + } + + if (cred->domain_obtained > cred->realm_obtained) { + effective_realm = cred->domain; + effective_obtained = MIN(cred->domain_obtained, + cred->username_obtained); + } else { + effective_realm = cred->realm; + effective_obtained = MIN(cred->realm_obtained, + cred->username_obtained); + } + + if (effective_realm == NULL || strlen(effective_realm) == 0) { + effective_realm = cred->domain; + effective_obtained = MIN(cred->domain_obtained, + cred->username_obtained); + } + + if (effective_realm != NULL && strlen(effective_realm) != 0) { + return effective_obtained; + } + } + + return cred->principal_obtained; +} + /** * Obtain the client principal for this credentials context. * @param cred credentials context @@ -453,6 +523,19 @@ _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred) return cred->password; } +/** + * @brief Find out how the password was obtained. + * + * @param cred A credentials context. + * + * @return The obtained information for the password. + */ +_PUBLIC_ enum credentials_obtained +cli_credentials_get_password_obtained(struct cli_credentials *cred) +{ + return cred->password_obtained; +} + /** * @brief Obtain the password for this credentials context. * diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index 9a9bd513201..386647c7aae 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -91,6 +91,7 @@ struct cli_credentials *cli_credentials_init_server(TALLOC_CTX *mem_ctx, void cli_credentials_set_anonymous(struct cli_credentials *cred); bool cli_credentials_wrong_password(struct cli_credentials *cred); const char *cli_credentials_get_password(struct cli_credentials *cred); +enum credentials_obtained cli_credentials_get_password_obtained(struct cli_credentials *cred); const char *cli_credentials_get_password_and_obtained(struct cli_credentials *cred, enum credentials_obtained *obtained); void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, @@ -105,6 +106,7 @@ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_ DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key); const char *cli_credentials_get_realm(struct cli_credentials *cred); const char *cli_credentials_get_username(struct cli_credentials *cred); +enum credentials_obtained cli_credentials_get_username_obtained(struct cli_credentials *cred); const char *cli_credentials_get_username_and_obtained(struct cli_credentials *cred, enum credentials_obtained *obtained); int cli_credentials_get_krb5_context(struct cli_credentials *cred, @@ -120,6 +122,10 @@ int cli_credentials_get_named_ccache(struct cli_credentials *cred, struct loadparm_context *lp_ctx, char *ccache_name, struct ccache_container **ccc, const char **error_string); +bool cli_credentials_get_ccache_name_obtained(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx, + char **ccache_name, + enum credentials_obtained *obtained); bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred, const char *principal, unsigned int *count); @@ -280,6 +286,8 @@ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, bool cli_credentials_set_username_callback(struct cli_credentials *cred, const char *(*username_cb) (struct cli_credentials *)); +enum credentials_obtained cli_credentials_get_principal_obtained(struct cli_credentials *cred); + /** * Obtain the client principal for this credentials context. * @param cred credentials context diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index dcfa2e4daee..49077db23b3 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -79,25 +79,15 @@ static uint32_t smb_gss_krb5_copy_ccache(uint32_t *min_stat, krb5_cc_cursor cursor = NULL; krb5_principal princ = NULL; krb5_error_code code; - char *dummy_name; uint32_t maj_stat = GSS_S_FAILURE; - dummy_name = talloc_asprintf(ccc, - "MEMORY:gss_krb5_copy_ccache-%p", - &ccc->ccache); - if (dummy_name == NULL) { - *min_stat = ENOMEM; - return GSS_S_FAILURE; - } - /* * Create a dummy ccache, so we can iterate over the credentials * and find the default principal for the ccache we want to * copy. The new ccache needs to be initialized with this * principal. */ - code = krb5_cc_resolve(context, dummy_name, &dummy_ccache); - TALLOC_FREE(dummy_name); + code = smb_krb5_cc_new_unique_memory(context, NULL, NULL, &dummy_ccache); if (code != 0) { *min_stat = code; return GSS_S_FAILURE; @@ -382,29 +372,18 @@ static krb5_error_code krb5_cc_remove_cred_wrap(struct ccache_container *ccc, 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); + code = smb_krb5_cc_new_unique_memory(ccc->smb_krb5_context->krb5_context, + NULL, NULL, + &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); @@ -597,10 +576,11 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred static int cli_credentials_new_ccache(struct cli_credentials *cred, struct loadparm_context *lp_ctx, - char *ccache_name, + char *given_ccache_name, struct ccache_container **_ccc, const char **error_string) { + char *ccache_name = given_ccache_name; bool must_free_cc_name = false; krb5_error_code ret; struct ccache_container *ccc = talloc(cred, struct ccache_container); @@ -623,25 +603,27 @@ static int cli_credentials_new_ccache(struct cli_credentials *cred, } if (!ccache_name) { - must_free_cc_name = true; - if (lpcfg_parm_bool(lp_ctx, NULL, "credentials", "krb5_cc_file", false)) { ccache_name = talloc_asprintf(ccc, "FILE:/tmp/krb5_cc_samba_%u_%p", (unsigned int)getpid(), ccc); - } else { - ccache_name = talloc_asprintf(ccc, "MEMORY:%p", - ccc); - } - - if (!ccache_name) { - talloc_free(ccc); - (*error_string) = strerror(ENOMEM); - return ENOMEM; + if (ccache_name == NULL) { + talloc_free(ccc); + (*error_string) = strerror(ENOMEM); + return ENOMEM; + } + must_free_cc_name = true; } } - ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, - &ccc->ccache); + if (ccache_name != NULL) { + ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, + &ccc->ccache); + } else { + ret = smb_krb5_cc_new_unique_memory(ccc->smb_krb5_context->krb5_context, + ccc, &ccache_name, + &ccc->ccache); + must_free_cc_name = true; + } if (ret) { (*error_string) = talloc_asprintf(cred, "failed to resolve a krb5 ccache (%s): %s\n", ccache_name, @@ -758,6 +740,95 @@ _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred, return cli_credentials_get_named_ccache(cred, event_ctx, lp_ctx, NULL, ccc, error_string); } +/** + * @brief Check if a valid Kerberos credential cache is attached. + * + * This will not ask for a password nor do a kinit. + * + * @param cred The credentials context. + * + * @param mem_ctx A memory context to allocate the ccache_name. + * + * @param ccache_name A pointer to a string to store the ccache name. + * + * @param obtained A pointer to store the information how the ccache was + * obtained. + * + * @return True if a credential cache is attached, false if not or an error + * occurred. + */ +_PUBLIC_ bool cli_credentials_get_ccache_name_obtained( + struct cli_credentials *cred, + TALLOC_CTX *mem_ctx, + char **ccache_name, + enum credentials_obtained *obtained) +{ + if (ccache_name != NULL) { + *ccache_name = NULL; + } + + if (obtained != NULL) { + *obtained = CRED_UNINITIALISED; + } + + if (cred->machine_account_pending) { + return false; + } + + if (cred->ccache_obtained == CRED_UNINITIALISED) { + return false; + } + + if (cred->ccache_obtained >= cred->ccache_threshold) { + krb5_context k5ctx = cred->ccache->smb_krb5_context->krb5_context; + krb5_ccache k5ccache = cred->ccache->ccache; + krb5_error_code ret; + time_t lifetime = 0; + + ret = smb_krb5_cc_get_lifetime(k5ctx, k5ccache, &lifetime); + if (ret == KRB5_CC_END || ret == ENOENT) { + return false; + } + if (ret != 0) { + return false; + } + if (lifetime == 0) { + return false; + } else if (lifetime < 300) { + if (cred->password_obtained >= cred->ccache_obtained) { + /* + * we have a password to re-kinit + * so let the caller try that. + */ + return false; + } + } + + if (ccache_name != NULL) { + char *name = NULL; + + ret = krb5_cc_get_full_name(k5ctx, k5ccache, &name); + if (ret != 0) { + return false; + } + + *ccache_name = talloc_strdup(mem_ctx, name); + SAFE_FREE(name); + if (*ccache_name == NULL) { + return false; + } + } + + if (obtained != NULL) { + *obtained = cred->ccache_obtained; + } + + return true; + } + + return false; +} + /* We have good reason to think the ccache in these credentials is invalid - blow it away */ static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials *cred) { @@ -1070,7 +1141,6 @@ static int cli_credentials_shallow_ccache(struct cli_credentials *cred) const struct ccache_container *old_ccc = NULL; enum credentials_obtained old_obtained; struct ccache_container *ccc = NULL; - char *ccache_name = NULL; krb5_principal princ; old_obtained = cred->ccache_obtained; @@ -1103,10 +1173,10 @@ static int cli_credentials_shallow_ccache(struct cli_credentials *cred) *ccc = *old_ccc; ccc->ccache = NULL; - ccache_name = talloc_asprintf(ccc, "MEMORY:%p", ccc); - - ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, - ccache_name, &ccc->ccache); + ret = smb_krb5_cc_new_unique_memory(ccc->smb_krb5_context->krb5_context, + NULL, + NULL, + &ccc->ccache); if (ret != 0) { TALLOC_FREE(ccc); return ret; @@ -1114,8 +1184,6 @@ static int cli_credentials_shallow_ccache(struct cli_credentials *cred) talloc_set_destructor(ccc, free_mccache); - TALLOC_FREE(ccache_name); - ret = smb_krb5_cc_copy_creds(ccc->smb_krb5_context->krb5_context, old_ccc->ccache, ccc->ccache); if (ret != 0) { diff --git a/auth/credentials/tests/test_creds.c b/auth/credentials/tests/test_creds.c index 2cb2e6d0e34..054b7321ce4 100644 --- a/auth/credentials/tests/test_creds.c +++ b/auth/credentials/tests/test_creds.c @@ -166,6 +166,9 @@ static void torture_creds_parse_string(void **state) { TALLOC_CTX *mem_ctx = *state; struct cli_credentials *creds = NULL; + enum credentials_obtained princ_obtained = CRED_UNINITIALISED; + enum credentials_obtained usr_obtained = CRED_UNINITIALISED; + enum credentials_obtained pwd_obtained = CRED_UNINITIALISED; creds = cli_credentials_init(mem_ctx); assert_non_null(creds); @@ -213,13 +216,17 @@ static void torture_creds_parse_string(void **state) assert_int_equal(creds->domain_obtained, CRED_SPECIFIED); assert_string_equal(creds->username, "wurst@brot.realm"); - assert_int_equal(creds->username_obtained, CRED_SPECIFIED); + usr_obtained = cli_credentials_get_username_obtained(creds); + assert_int_equal(usr_obtained, CRED_SPECIFIED); assert_string_equal(creds->principal, "wurst@brot.realm"); - assert_int_equal(creds->principal_obtained, CRED_SPECIFIED); + princ_obtained = cli_credentials_get_principal_obtained(creds); + assert_int_equal(princ_obtained, CRED_SPECIFIED); assert_string_equal(creds->password, "BROT"); - assert_int_equal(creds->password_obtained, CRED_SPECIFIED); + pwd_obtained = cli_credentials_get_password_obtained(creds); + assert_int_equal(pwd_obtained, CRED_SPECIFIED); + } static void torture_creds_krb5_state(void **state) diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h index 4d8eca99881..8454eef32a0 100644 --- a/auth/gensec/gensec_internal.h +++ b/auth/gensec/gensec_internal.h @@ -198,4 +198,8 @@ NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security, NTTIME gensec_child_expire_time(struct gensec_security *gensec_security); const char *gensec_child_final_auth_type(struct gensec_security *gensec_security); +char *gensec_get_unparsed_target_principal(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx); +NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security); + #endif /* __GENSEC_H__ */ diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c index b6b4a722f27..0c7688d33d2 100644 --- a/auth/gensec/gensec_util.c +++ b/auth/gensec/gensec_util.c @@ -23,10 +23,14 @@ #include "includes.h" #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_internal.h" +#include "auth/credentials/credentials.h" #include "auth/common_auth.h" #include "../lib/util/asn1.h" #include "param/param.h" #include "libds/common/roles.h" +#include "lib/util/util_net.h" + +#undef strcasecmp #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -336,3 +340,80 @@ const char *gensec_child_final_auth_type(struct gensec_security *gensec_security return gensec_final_auth_type(gensec_security->child_security); } + +char *gensec_get_unparsed_target_principal(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx) +{ + const char *target_principal = gensec_get_target_principal(gensec_security); + const char *service = gensec_get_target_service(gensec_security); + const char *hostname = gensec_get_target_hostname(gensec_security); + + if (target_principal != NULL) { + return talloc_strdup(mem_ctx, target_principal); + } else if (service != NULL && hostname != NULL) { + return talloc_asprintf(mem_ctx, "%s/%s", service, hostname); + } else if (hostname != NULL) { + return talloc_strdup(mem_ctx, target_principal); + } + + return NULL; +} + +NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security) +{ + struct cli_credentials *creds = gensec_get_credentials(gensec_security); + bool auth_requested = cli_credentials_authentication_requested(creds); + enum credentials_use_kerberos krb5_state = + cli_credentials_get_kerberos_state(creds); + char *user_principal = NULL; + const char *client_realm = cli_credentials_get_realm(creds); + const char *target_principal = gensec_get_target_principal(gensec_security); + const char *hostname = gensec_get_target_hostname(gensec_security); + + if (!auth_requested) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (krb5_state == CRED_USE_KERBEROS_DISABLED) { -- Samba Shared Repository