From: Bharath SM <bharathsm@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> --- 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