diff mbox series

cifs-utils: Skip TGT check if valid service ticket is already available

Message ID 20241126172744.25894-1-bharathsm.hsk@gmail.com (mailing list archive)
State New, archived
Headers show
Series cifs-utils: Skip TGT check if valid service ticket is already available | expand

Commit Message

Bharath SM Nov. 26, 2024, 5:27 p.m. UTC
From: Bharath SM <bharathsm@microsoft.com>

When handling upcalls from the kernel for SMB session setup requests using
Kerberos authentication, if the credential cache already contains a valid
service ticket, it can be used directly without checking for the TGT again.

Signed-off-by: Bharath SM <bharathsm@microsoft.com>
---
 cifs.upcall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 6 deletions(-)

Comments

Steve French Dec. 5, 2024, 5:47 a.m. UTC | #1
Have tentatively merged this and the two from Meetakshi (for
password/password2 handling) and the one from Ritvik (for namespace
handling) to smb3-utils for-next branch.   Let me know if any
objections, or problems found testing.   Current four next has five
changesets post cifs-utils version 7.1

968311d (HEAD -> for-next, origin/for-next) CIFS.upcall to accomodate
new namespace mount opt
a80dac4 cifs-utils: Skip TGT check if valid service ticket is already available
777ac65 use enums to check password or password2 in set_password,
get_password_from_file and minor documentation additions
82db1d6 cifs-utils: support and document password2 mount option
55dde41 smbinfo: add bash completion support for filestreaminfo, keys,
gettconinfo

On Tue, Nov 26, 2024 at 11:28 AM <bharathsm.hsk@gmail.com> wrote:
>
> From: Bharath SM <bharathsm@microsoft.com>
>
> When handling upcalls from the kernel for SMB session setup requests using
> Kerberos authentication, if the credential cache already contains a valid
> service ticket, it can be used directly without checking for the TGT again.
>
> Signed-off-by: Bharath SM <bharathsm@microsoft.com>
> ---
>  cifs.upcall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 58 insertions(+), 6 deletions(-)
>
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index ff6f2bd..4ad0c8e 100644
> --- a/cifs.upcall.c
> +++ b/cifs.upcall.c
> @@ -552,11 +552,6 @@ get_existing_cc(const char *env_cachename)
>                 syslog(LOG_DEBUG, "%s: default ccache is %s\n", __func__, cachename);
>                 krb5_free_string(context, cachename);
>         }
> -
> -       if (!get_tgt_time(cc)) {
> -               krb5_cc_close(context, cc);
> -               cc = NULL;
> -       }
>         return cc;
>  }
>
> @@ -638,6 +633,49 @@ icfk_cleanup:
>
>  #define CIFS_SERVICE_NAME "cifs"
>
> +static krb5_error_code check_service_ticket_exists(krb5_ccache ccache,
> +               const char *hostname) {
> +
> +       krb5_error_code rc;
> +       krb5_creds mcreds, out_creds;
> +
> +       memset(&mcreds, 0, sizeof(mcreds));
> +
> +       rc = krb5_cc_get_principal(context, ccache, &mcreds.client);
> +       if (rc) {
> +               syslog(LOG_DEBUG, "%s: unable to get client principal from cache: %s",
> +                                       __func__, krb5_get_error_message(context, rc));
> +               return rc;
> +       }
> +
> +       rc = krb5_sname_to_principal(context, hostname, CIFS_SERVICE_NAME,
> +                       KRB5_NT_UNKNOWN, &mcreds.server);
> +       if (rc) {
> +               syslog(LOG_DEBUG, "%s: unable to convert service name (%s) to principal: %s",
> +                                       __func__, hostname, krb5_get_error_message(context, rc));
> +               krb5_free_principal(context, mcreds.client);
> +               return rc;
> +       }
> +
> +       rc = krb5_timeofday(context, &mcreds.times.endtime);
> +       if (rc) {
> +               syslog(LOG_DEBUG, "%s: unable to get time: %s",
> +                       __func__, krb5_get_error_message(context, rc));
> +               goto out_free_principal;
> +       }
> +
> +       rc = krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_TIMES, &mcreds, &out_creds);
> +
> +       if (!rc)
> +               krb5_free_cred_contents(context, &out_creds);
> +
> +out_free_principal:
> +       krb5_free_principal(context, mcreds.server);
> +       krb5_free_principal(context, mcreds.client);
> +
> +       return rc;
> +}
> +
>  static int
>  cifs_krb5_get_req(const char *host, krb5_ccache ccache,
>                   DATA_BLOB * mechtoken, DATA_BLOB * sess_key)
> @@ -1516,12 +1554,26 @@ int main(const int argc, char *const argv[])
>                 goto out;
>         }
>
> +       host = arg->hostname;
>         ccache = get_existing_cc(env_cachename);
> +       if (ccache != NULL) {
> +               rc = check_service_ticket_exists(ccache, host);
> +               if(rc == 0) {
> +                        syslog(LOG_DEBUG, "%s: valid service ticket exists in credential cache",
> +                                        __func__);
> +               } else {
> +                        if (!get_tgt_time(ccache)) {
> +                               syslog(LOG_DEBUG, "%s: valid TGT is not present in credential cache",
> +                                               __func__);
> +                               krb5_cc_close(context, ccache);
> +                               ccache = NULL;
> +                       }
> +               }
> +       }
>         /* Couldn't find credcache? Try to use keytab */
>         if (ccache == NULL && arg->username[0] != '\0')
>                 ccache = init_cc_from_keytab(keytab_name, arg->username);
>
> -       host = arg->hostname;
>
>         // do mech specific authorization
>         switch (arg->sec) {
> --
> 2.43.0
>
>
diff mbox series

Patch

diff --git a/cifs.upcall.c b/cifs.upcall.c
index ff6f2bd..4ad0c8e 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -552,11 +552,6 @@  get_existing_cc(const char *env_cachename)
 		syslog(LOG_DEBUG, "%s: default ccache is %s\n", __func__, cachename);
 		krb5_free_string(context, cachename);
 	}
-
-	if (!get_tgt_time(cc)) {
-		krb5_cc_close(context, cc);
-		cc = NULL;
-	}
 	return cc;
 }
 
@@ -638,6 +633,49 @@  icfk_cleanup:
 
 #define CIFS_SERVICE_NAME "cifs"
 
+static krb5_error_code check_service_ticket_exists(krb5_ccache ccache,
+		const char *hostname) {
+
+	krb5_error_code rc;
+	krb5_creds mcreds, out_creds;
+
+	memset(&mcreds, 0, sizeof(mcreds));
+
+	rc = krb5_cc_get_principal(context, ccache, &mcreds.client);
+	if (rc) {
+		syslog(LOG_DEBUG, "%s: unable to get client principal from cache: %s",
+					__func__, krb5_get_error_message(context, rc));
+		return rc;
+	}
+
+	rc = krb5_sname_to_principal(context, hostname, CIFS_SERVICE_NAME,
+			KRB5_NT_UNKNOWN, &mcreds.server);
+	if (rc) {
+		syslog(LOG_DEBUG, "%s: unable to convert service name (%s) to principal: %s",
+					__func__, hostname, krb5_get_error_message(context, rc));
+		krb5_free_principal(context, mcreds.client);
+		return rc;
+	}
+
+	rc = krb5_timeofday(context, &mcreds.times.endtime);
+	if (rc) {
+		syslog(LOG_DEBUG, "%s: unable to get time: %s",
+			__func__, krb5_get_error_message(context, rc));
+		goto out_free_principal;
+	}
+
+	rc = krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_TIMES, &mcreds, &out_creds);
+
+	if (!rc)
+		krb5_free_cred_contents(context, &out_creds);
+
+out_free_principal:
+	krb5_free_principal(context, mcreds.server);
+	krb5_free_principal(context, mcreds.client);
+
+	return rc;
+}
+
 static int
 cifs_krb5_get_req(const char *host, krb5_ccache ccache,
 		  DATA_BLOB * mechtoken, DATA_BLOB * sess_key)
@@ -1516,12 +1554,26 @@  int main(const int argc, char *const argv[])
 		goto out;
 	}
 
+	host = arg->hostname;
 	ccache = get_existing_cc(env_cachename);
+	if (ccache != NULL) {
+		rc = check_service_ticket_exists(ccache, host);
+		if(rc == 0) {
+			 syslog(LOG_DEBUG, "%s: valid service ticket exists in credential cache",
+					 __func__);
+		} else {
+			 if (!get_tgt_time(ccache)) {
+				syslog(LOG_DEBUG, "%s: valid TGT is not present in credential cache",
+						__func__);
+				krb5_cc_close(context, ccache);
+				ccache = NULL;
+			}
+		}
+	}
 	/* Couldn't find credcache? Try to use keytab */
 	if (ccache == NULL && arg->username[0] != '\0')
 		ccache = init_cc_from_keytab(keytab_name, arg->username);
 
-	host = arg->hostname;
 
 	// do mech specific authorization
 	switch (arg->sec) {