[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue May 7 12:34:01 UTC 2024


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 <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Tue May  7 12:33:29 UTC 2024 on atb-devel-224

commit e6c693b705686a590d2fa8f434ff015d8926a349
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 147565232dc7cc3127e09268000723c5a3eea62b
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 16a5279e2918e7348f1695629bf3fa61c9007424
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 176c55efb202f1f218c6c4ddf69d2d357488e25f
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 5d385ab691f21bdd4524c41560c7f53653cf179d
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 92bebeb58ef5ab91937d29640bf7a3c7929518ca
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 21b96f010a4f9472a03aca5f4c1ed5a658530f52
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 48bcc218c980e9478e2a3479e889766e6ca7f1dd
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit e3f97f35b18f9c11d718223b64de87ce1c08f64c
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 6ced3c6af22a5e8f7d84e52c769029ea8a265724
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit ce05fe3b718a5d242f31f1acb25f5d7c5a6e4e0a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 5 15:33:51 2024 +0100

    s3:gse: make use of gensec_kerberos_possible()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 4dd2468d5bcd704d8a745f9f3e487e539ae66bbb
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit a3c87bf440457c59cdad8883fca142b5f06da587
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 996fd13949b9c4aa842971520a6a6d3059559caa
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 5 14:41:39 2024 +0100

    auth/gensec: add gensec_kerberos_possible() helper
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 1275e77933f74b5b8551aa9c5e5f84fbd561de04
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit b9cf6c8dd4d256300df170b1b21a86fe02416018
Author: Andreas Schneider <asn at 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 <asn at samba.org>

commit f9afd24c907eaecd65a3b7a1387139472876047d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 13 17:50:34 2024 +0100

    auth/credentials: add cli_credentials_get_username_obtained()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 7f0aff468256415c76bbcd5c7249f909de9f3b91
Author: Andreas Schneider <asn at 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 <asn at samba.org>

commit c14366cce45a437584d9050067a34fffb847e134
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit a85f1b6facd2b641f98dcea9b997a02d8f276882
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit c7d3946659ff9ce167f68f3f052fae02a8907869
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 4723d695608e7737176e4f6eb407885a38989fc8
Author: Andreas Schneider <asn at 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 <asn at samba.org>

commit 1e5546748cd22c9e654ed066ab1d27aadec0d3d3
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at 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 at 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 at 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



More information about the samba-cvs mailing list