From patchwork Mon Aug 22 12:29:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 9293445 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 45FD3607D0 for ; Mon, 22 Aug 2016 12:29:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3513E28977 for ; Mon, 22 Aug 2016 12:29:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A27928987; Mon, 22 Aug 2016 12:29:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A2F7C28977 for ; Mon, 22 Aug 2016 12:29:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752401AbcHVM30 (ORCPT ); Mon, 22 Aug 2016 08:29:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51048 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752299AbcHVM3Z (ORCPT ); Mon, 22 Aug 2016 08:29:25 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B85BF3B717; Mon, 22 Aug 2016 12:29:24 +0000 (UTC) Received: from tlielax.poochiereds.net (ovpn-116-47.rdu2.redhat.com [10.10.116.47]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u7MCTNMP019328; Mon, 22 Aug 2016 08:29:24 -0400 From: Jeff Layton To: linux-cifs@vger.kernel.org Cc: "Dey, John F" Subject: [cifs-utils PATCH 2/3] cifs.upcall: use krb5 routines to get default ccname Date: Mon, 22 Aug 2016 08:29:21 -0400 Message-Id: <1471868962-7312-3-git-send-email-jlayton@samba.org> In-Reply-To: <1471868962-7312-1-git-send-email-jlayton@samba.org> References: <1471868962-7312-1-git-send-email-jlayton@samba.org> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 22 Aug 2016 12:29:24 +0000 (UTC) Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently we end up groveling around in /tmp, trying to guess what the credcache will be. Instead, just get the default ccname for the user, and then see if it has a valid tgt. If it doesn't then we try to use the keytab to init the credcache before proceeding. Signed-off-by: Jeff Layton --- cifs.upcall.c | 148 +++++++++++----------------------------------------------- 1 file changed, 27 insertions(+), 121 deletions(-) diff --git a/cifs.upcall.c b/cifs.upcall.c index e8544c2b68ad..d0f6d089d8e1 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -52,12 +52,6 @@ #include "spnego.h" #include "cifs_spnego.h" -#define CIFS_DEFAULT_KRB5_DIR "/tmp" -#define CIFS_DEFAULT_KRB5_USER_DIR "/run/user/%U" -#define CIFS_DEFAULT_KRB5_PREFIX "krb5cc" - -#define MAX_CCNAME_LEN PATH_MAX + 5 - static const char *prog = "cifs.upcall"; typedef enum _sectype { NONE = 0, @@ -178,13 +172,34 @@ err_cache: return credtime; } -static int krb5cc_filter(const struct dirent *dirent) +static char * +get_default_cc(void) { - /* subtract 1 for the null terminator */ - return !strncmp(dirent->d_name, CIFS_DEFAULT_KRB5_PREFIX, - sizeof(CIFS_DEFAULT_KRB5_PREFIX) - 1); + krb5_error_code ret; + const char *ccname; + char *rcc = NULL; + krb5_context context = NULL; + + ret = krb5_init_context(&context); + if (ret) { + syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret); + return NULL; + } + + ccname = krb5_cc_default_name(context); + if (!ccname) { + syslog(LOG_DEBUG, "krb5_cc_default returned NULL."); + goto out_free_context; + } + + if (get_tgt_time(ccname)) + rcc = strdup(ccname); +out_free_context: + krb5_free_context(context); + return rcc; } + static char * init_cc_from_keytab(const char *keytab_name, const char *user) { @@ -263,109 +278,6 @@ icfk_cleanup: return ccname; } -/* resolve a pattern to an actual directory path */ -static char *resolve_krb5_dir(const char *pattern, uid_t uid) -{ - char name[MAX_CCNAME_LEN]; - int i; - size_t j; - for (i = 0, j = 0; (pattern[i] != '\0') && (j < sizeof(name)); i++) { - switch (pattern[i]) { - case '%': - switch (pattern[i + 1]) { - case '%': - name[j++] = pattern[i]; - i++; - break; - case 'U': - j += snprintf(name + j, sizeof(name) - j, - "%lu", (unsigned long) uid); - i++; - break; - } - break; - default: - name[j++] = pattern[i]; - break; - } - } - if ((j > 0) && (j < sizeof(name))) - return strndup(name, MAX_CCNAME_LEN); - else - return NULL; -} - -/* search for a credcache that looks like a likely candidate */ -static char *find_krb5_cc(const char *dirname, uid_t uid, - char **best_cache, time_t *best_time) -{ - struct dirent **namelist; - struct stat sbuf; - char ccname[MAX_CCNAME_LEN], *credpath; - int i, n; - time_t cred_time; - - n = scandir(dirname, &namelist, krb5cc_filter, NULL); - if (n < 0) { - syslog(LOG_DEBUG, "%s: scandir error on directory '%s': %s", - __func__, dirname, strerror(errno)); - return NULL; - } - - for (i = 0; i < n; i++) { - snprintf(ccname, sizeof(ccname), "FILE:%s/%s", dirname, - namelist[i]->d_name); - credpath = ccname + 5; - syslog(LOG_DEBUG, "%s: considering %s", __func__, credpath); - - if (lstat(credpath, &sbuf)) { - syslog(LOG_DEBUG, "%s: stat error on '%s': %s", - __func__, credpath, strerror(errno)); - free(namelist[i]); - continue; - } - if (sbuf.st_uid != uid) { - syslog(LOG_DEBUG, "%s: %s is owned by %u, not %u", - __func__, credpath, sbuf.st_uid, uid); - free(namelist[i]); - continue; - } - if (S_ISDIR(sbuf.st_mode)) { - snprintf(ccname, sizeof(ccname), "DIR:%s/%s", dirname, - namelist[i]->d_name); - credpath = ccname + 4; - } else - if (!S_ISREG(sbuf.st_mode)) { - syslog(LOG_DEBUG, "%s: %s is not a regular file", - __func__, credpath); - free(namelist[i]); - continue; - } - if (!(cred_time = get_tgt_time(ccname))) { - syslog(LOG_DEBUG, "%s: %s is not a valid credcache.", - __func__, ccname); - free(namelist[i]); - continue; - } - - if (cred_time <= *best_time) { - syslog(LOG_DEBUG, "%s: %s expires sooner than current " - "best.", __func__, ccname); - free(namelist[i]); - continue; - } - - syslog(LOG_DEBUG, "%s: %s is valid ccache", __func__, ccname); - free(*best_cache); - *best_cache = strndup(ccname, MAX_CCNAME_LEN); - *best_time = cred_time; - free(namelist[i]); - } - free(namelist); - - return *best_cache; -} - static int cifs_krb5_get_req(const char *host, const char *ccname, DATA_BLOB * mechtoken, DATA_BLOB * sess_key) @@ -841,13 +753,12 @@ int main(const int argc, char *const argv[]) unsigned int have; long rc = 1; int c, try_dns = 0, legacy_uid = 0; - char *buf, *ccdir = NULL, *ccname = NULL, *best_cache = NULL; + char *buf, *ccname = NULL; char hostbuf[NI_MAXHOST], *host; struct decoded_args arg; const char *oid; uid_t uid; char *keytab_name = NULL; - time_t best_time = 0; hostbuf[0] = '\0'; memset(&arg, 0, sizeof(arg)); @@ -954,13 +865,8 @@ int main(const int argc, char *const argv[]) syslog(LOG_ERR, "setuid: %s", strerror(errno)); goto out; } - ccdir = resolve_krb5_dir(CIFS_DEFAULT_KRB5_USER_DIR, uid); - if (ccdir != NULL) - find_krb5_cc(ccdir, uid, &best_cache, &best_time); - ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, uid, &best_cache, - &best_time); - SAFE_FREE(ccdir); + ccname = get_default_cc(); /* Couldn't find credcache? Try to use keytab */ if (ccname == NULL && arg.username != NULL) ccname = init_cc_from_keytab(keytab_name, arg.username);