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

Reply via email to