Fix rpc.gssd creating machine credcache with dup entries for the nfs service principal
Resolves: RHEL-62422 Signed-off-by: Scott Mayhew <smayhew@redhat.com>
This commit is contained in:
parent
a0154bb448
commit
99360e6f4c
208
nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
Normal file
208
nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
Normal file
@ -0,0 +1,208 @@
|
||||
From ad4eafccd244e87af315c432d076b4f988dde52a Mon Sep 17 00:00:00 2001
|
||||
From: Olga Kornievskaia <okorniev@redhat.com>
|
||||
Date: Mon, 24 Mar 2025 08:43:43 -0400
|
||||
Subject: [PATCH 2/2] gssd: do not use krb5_cc_initialize
|
||||
|
||||
Note: This patch differs from the upstream version in several places
|
||||
because RHEL 8 does not have c8659457 ("gssd: We never use the nocache
|
||||
param of gssd_check_if_cc_exists()") or f066f87b ("gssd: enable forcing
|
||||
cred renewal using the keytab").
|
||||
|
||||
Original commit message:
|
||||
|
||||
When gssd refreshes machine credentials, it uses the
|
||||
krb5_get_init_creds_keytab() and then to save the received credentials
|
||||
in a ticket cache, it proceeds to initialize the credential cache via
|
||||
a krb5_cc_initialize() before storing the received credentials into it.
|
||||
|
||||
krb5_cc_initialize() is not concurrency safe. two gssd upcalls by
|
||||
uid=0, one for krb5i auth flavor and another for krb5p, would enter
|
||||
into krb5_cc_initialize() and one of them would fail, leading to
|
||||
an upcall failure and NFS operation error.
|
||||
|
||||
Instead it was proposed that gssd changes its design to do what
|
||||
kinit does and forgo the use of krb5_cc_initialize and instead setup
|
||||
the output cache via krb5_get_init_creds_opt_set_out_cache() prior
|
||||
to calling krb5_get_init_creds_keytab() which would then store
|
||||
credentials automatically.
|
||||
|
||||
https://mailman.mit.edu/pipermail/krbdev/2025-February/013708.html
|
||||
|
||||
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
(cherry picked from commit 1cd9e3c0d290646e80750249914396566dd6b800)
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
utils/gssd/krb5_util.c | 103 ++++++++++++++++++++---------------------
|
||||
1 file changed, 50 insertions(+), 53 deletions(-)
|
||||
|
||||
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||
index 871add74..43bc8744 100644
|
||||
--- a/utils/gssd/krb5_util.c
|
||||
+++ b/utils/gssd/krb5_util.c
|
||||
@@ -161,7 +161,8 @@ static int select_krb5_ccache(const struct dirent *d);
|
||||
static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
|
||||
const char **cctype, struct dirent **d);
|
||||
static int gssd_get_single_krb5_cred(krb5_context context,
|
||||
- krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache);
|
||||
+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache,
|
||||
+ krb5_ccache ccache);
|
||||
static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
|
||||
char **ret_realm);
|
||||
|
||||
@@ -368,16 +369,14 @@ static int
|
||||
gssd_get_single_krb5_cred(krb5_context context,
|
||||
krb5_keytab kt,
|
||||
struct gssd_k5_kt_princ *ple,
|
||||
- int nocache)
|
||||
+ int nocache,
|
||||
+ krb5_ccache ccache)
|
||||
{
|
||||
krb5_get_init_creds_opt *opts = NULL;
|
||||
krb5_creds my_creds;
|
||||
- krb5_ccache ccache = NULL;
|
||||
char kt_name[BUFSIZ];
|
||||
- char cc_name[BUFSIZ];
|
||||
int code;
|
||||
time_t now = time(0);
|
||||
- char *cache_type;
|
||||
char *pname = NULL;
|
||||
char *k5err = NULL;
|
||||
pthread_t tid = pthread_self();
|
||||
@@ -427,6 +426,14 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
krb5_get_init_creds_opt_set_tkt_life(opts, 5*60);
|
||||
#endif
|
||||
|
||||
+ if ((code = krb5_get_init_creds_opt_set_out_ccache(context, opts,
|
||||
+ ccache))) {
|
||||
+ k5err = gssd_k5_err_msg(context, code);
|
||||
+ printerr(1, "WARNING: %s while initializing ccache for "
|
||||
+ "principal '%s' using keytab '%s'\n", k5err,
|
||||
+ pname ? pname : "<unparsable>", kt_name);
|
||||
+ goto out;
|
||||
+ }
|
||||
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
|
||||
kt, 0, NULL, opts))) {
|
||||
k5err = gssd_k5_err_msg(context, code);
|
||||
@@ -436,61 +443,18 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Initialize cache file which we're going to be using
|
||||
- */
|
||||
-
|
||||
pthread_mutex_lock(&ple_lock);
|
||||
- if (use_memcache)
|
||||
- cache_type = "MEMORY";
|
||||
- else
|
||||
- cache_type = "FILE";
|
||||
- snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
|
||||
- cache_type,
|
||||
- ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
|
||||
- GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
|
||||
ple->endtime = my_creds.times.endtime;
|
||||
- if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) {
|
||||
- free(ple->ccname);
|
||||
- ple->ccname = strdup(cc_name);
|
||||
- if (ple->ccname == NULL) {
|
||||
- printerr(0, "ERROR: no storage to duplicate credentials "
|
||||
- "cache name '%s'\n", cc_name);
|
||||
- code = ENOMEM;
|
||||
- pthread_mutex_unlock(&ple_lock);
|
||||
- goto out;
|
||||
- }
|
||||
- }
|
||||
pthread_mutex_unlock(&ple_lock);
|
||||
- if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
|
||||
- k5err = gssd_k5_err_msg(context, code);
|
||||
- printerr(0, "ERROR: %s while opening credential cache '%s'\n",
|
||||
- k5err, cc_name);
|
||||
- goto out;
|
||||
- }
|
||||
- if ((code = krb5_cc_initialize(context, ccache, ple->princ))) {
|
||||
- k5err = gssd_k5_err_msg(context, code);
|
||||
- printerr(0, "ERROR: %s while initializing credential "
|
||||
- "cache '%s'\n", k5err, cc_name);
|
||||
- goto out;
|
||||
- }
|
||||
- if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) {
|
||||
- k5err = gssd_k5_err_msg(context, code);
|
||||
- printerr(0, "ERROR: %s while storing credentials in '%s'\n",
|
||||
- k5err, cc_name);
|
||||
- goto out;
|
||||
- }
|
||||
|
||||
code = 0;
|
||||
- printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||
- __func__, tid, pname, cc_name);
|
||||
+ printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||
+ __func__, tid, pname, ple->ccname);
|
||||
out:
|
||||
if (opts)
|
||||
krb5_get_init_creds_opt_free(context, opts);
|
||||
if (pname)
|
||||
k5_free_unparsed_name(context, pname);
|
||||
- if (ccache)
|
||||
- krb5_cc_close(context, ccache);
|
||||
krb5_free_cred_contents(context, &my_creds);
|
||||
krb5_free_string(context, k5err);
|
||||
return (code);
|
||||
@@ -1108,10 +1072,12 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||
{
|
||||
krb5_error_code code = 0;
|
||||
krb5_context context;
|
||||
- krb5_keytab kt = NULL;;
|
||||
+ krb5_keytab kt = NULL;
|
||||
+ krb5_ccache ccache = NULL;
|
||||
int retval = 0;
|
||||
- char *k5err = NULL;
|
||||
+ char *k5err = NULL, *cache_type;
|
||||
const char *svcnames[] = { "$", "root", "nfs", "host", NULL };
|
||||
+ char cc_name[BUFSIZ];
|
||||
|
||||
/*
|
||||
* If a specific service name was specified, use it.
|
||||
@@ -1170,7 +1136,38 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||
goto out_free_kt;
|
||||
}
|
||||
}
|
||||
- retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
|
||||
+
|
||||
+ if (use_memcache)
|
||||
+ cache_type = "MEMORY";
|
||||
+ else
|
||||
+ cache_type = "FILE";
|
||||
+ snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
|
||||
+ cache_type,
|
||||
+ ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
|
||||
+ GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
|
||||
+
|
||||
+ pthread_mutex_lock(&ple_lock);
|
||||
+ if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) {
|
||||
+ free(ple->ccname);
|
||||
+ ple->ccname = strdup(cc_name);
|
||||
+ if (ple->ccname == NULL) {
|
||||
+ printerr(0, "ERROR: no storage to duplicate credentials "
|
||||
+ "cache name '%s'\n", cc_name);
|
||||
+ code = ENOMEM;
|
||||
+ pthread_mutex_unlock(&ple_lock);
|
||||
+ goto out_free_kt;
|
||||
+ }
|
||||
+ }
|
||||
+ pthread_mutex_unlock(&ple_lock);
|
||||
+ if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
|
||||
+ k5err = gssd_k5_err_msg(context, code);
|
||||
+ printerr(0, "ERROR: %s while opening credential cache '%s'\n",
|
||||
+ k5err, cc_name);
|
||||
+ goto out_free_kt;
|
||||
+ }
|
||||
+
|
||||
+ retval = gssd_get_single_krb5_cred(context, kt, ple, 0, ccache);
|
||||
+ krb5_cc_close(context, ccache);
|
||||
out_free_kt:
|
||||
krb5_kt_close(context, kt);
|
||||
out_free_context:
|
||||
--
|
||||
2.43.0
|
||||
|
@ -0,0 +1,98 @@
|
||||
From 55d9bf151b100db9bf52e8f968e33f3ae1d234f5 Mon Sep 17 00:00:00 2001
|
||||
From: Olga Kornievskaia <okorniev@redhat.com>
|
||||
Date: Mon, 24 Mar 2025 08:40:32 -0400
|
||||
Subject: [PATCH 1/2] gssd: unconditionally use krb5_get_init_creds_opt_alloc
|
||||
|
||||
Note: This patch has a context difference from the upstream version
|
||||
because RHEL 8 does not have c8659457 ("gssd: We never use the nocache
|
||||
param of gssd_check_if_cc_exists()") or f066f87b ("gssd: enable forcing
|
||||
cred renewal using the keytab").
|
||||
|
||||
Original commit message:
|
||||
|
||||
Modern kerberos API uses krb5_get_init_creds_opt_alloc() for managing
|
||||
its options for credential data structure.
|
||||
|
||||
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
(cherry picked from commit 9b3f949331c6541a358fc28bac323533f94d7e0b)
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
utils/gssd/krb5_util.c | 37 ++++++++++---------------------------
|
||||
1 file changed, 10 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||
index a1a77a2f..871add74 100644
|
||||
--- a/utils/gssd/krb5_util.c
|
||||
+++ b/utils/gssd/krb5_util.c
|
||||
@@ -370,12 +370,7 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
struct gssd_k5_kt_princ *ple,
|
||||
int nocache)
|
||||
{
|
||||
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||
- krb5_get_init_creds_opt *init_opts = NULL;
|
||||
-#else
|
||||
- krb5_get_init_creds_opt options;
|
||||
-#endif
|
||||
- krb5_get_init_creds_opt *opts;
|
||||
+ krb5_get_init_creds_opt *opts = NULL;
|
||||
krb5_creds my_creds;
|
||||
krb5_ccache ccache = NULL;
|
||||
char kt_name[BUFSIZ];
|
||||
@@ -413,33 +408,23 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
if ((krb5_unparse_name(context, ple->princ, &pname)))
|
||||
pname = NULL;
|
||||
|
||||
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||
- code = krb5_get_init_creds_opt_alloc(context, &init_opts);
|
||||
+ code = krb5_get_init_creds_opt_alloc(context, &opts);
|
||||
if (code) {
|
||||
k5err = gssd_k5_err_msg(context, code);
|
||||
printerr(0, "ERROR: %s allocating gic options\n", k5err);
|
||||
goto out;
|
||||
}
|
||||
- if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
|
||||
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||
+ if (krb5_get_init_creds_opt_set_addressless(context, opts, 1))
|
||||
printerr(1, "WARNING: Unable to set option for addressless "
|
||||
"tickets. May have problems behind a NAT.\n");
|
||||
-#ifdef TEST_SHORT_LIFETIME
|
||||
- /* set a short lifetime (for debugging only!) */
|
||||
- printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||
- krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60);
|
||||
+#else
|
||||
+ krb5_get_init_creds_opt_set_address_list(opts, NULL);
|
||||
#endif
|
||||
- opts = init_opts;
|
||||
-
|
||||
-#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */
|
||||
-
|
||||
- krb5_get_init_creds_opt_init(&options);
|
||||
- krb5_get_init_creds_opt_set_address_list(&options, NULL);
|
||||
#ifdef TEST_SHORT_LIFETIME
|
||||
/* set a short lifetime (for debugging only!) */
|
||||
- printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||
- krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
|
||||
-#endif
|
||||
- opts = &options;
|
||||
+ printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||
+ krb5_get_init_creds_opt_set_tkt_life(opts, 5*60);
|
||||
#endif
|
||||
|
||||
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
|
||||
@@ -500,10 +485,8 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||
__func__, tid, pname, cc_name);
|
||||
out:
|
||||
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||
- if (init_opts)
|
||||
- krb5_get_init_creds_opt_free(context, init_opts);
|
||||
-#endif
|
||||
+ if (opts)
|
||||
+ krb5_get_init_creds_opt_free(context, opts);
|
||||
if (pname)
|
||||
k5_free_unparsed_name(context, pname);
|
||||
if (ccache)
|
||||
--
|
||||
2.43.0
|
||||
|
@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser
|
||||
Name: nfs-utils
|
||||
URL: http://linux-nfs.org/
|
||||
Version: 2.3.3
|
||||
Release: 60%{?dist}
|
||||
Release: 61%{?dist}
|
||||
Epoch: 1
|
||||
|
||||
# group all 32bit related archs
|
||||
@ -113,6 +113,8 @@ Patch057: nfs-utils-2.3.3-covscan-return-value.patch
|
||||
# RHEL 8.10.z
|
||||
#
|
||||
Patch058: nfs-utils-2.3.3-gssd-man-document-use-gss-proxy.patch
|
||||
Patch059: nfs-utils-2.3.3-gssd-unconditionally-use-krb5_get_init_creds_opt_all.patch
|
||||
Patch060: nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
|
||||
|
||||
Patch100: nfs-utils-1.2.1-statdpath-man.patch
|
||||
Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
|
||||
@ -391,6 +393,10 @@ fi
|
||||
%{_libdir}/libnfsidmap.so
|
||||
|
||||
%changelog
|
||||
* Mon Apr 28 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-61
|
||||
- gssd: unconditionally use krb5_get_init_creds_opt_alloc (RHEL-62422)
|
||||
- gssd: do not use krb5_cc_initialize (RHEL-62422)
|
||||
|
||||
* Tue Apr 15 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-60
|
||||
- gssd.man: add documentation for use-gss-proxy (RHEL-13085)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user