From: Lukas Hejtmanek Date: Thu, 27 Aug 2009 15:42:24 +0000 (-0400) Subject: Gssd blindly caches machine credentials X-Git-Tag: nfs-utils-1-2-1-rc5~7 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=bd947185cfc7978c562fddf2f14f602c44a5cac9;p=nfs-utils.git Gssd blindly caches machine credentials We have a problem with rpc.gssd which blindly caches machine credentials. E.g., if someone deletes /tmp/krb5cc_machine_REALM, rpc.gss does not create new one until the old one expires. Also, it has problems with clock skew, if time goes back and gssd thinks that machine credentials are not expired yet. The following patch tries to use cache but in case of failure, it tries it again without cache. Any comments? Signed-off-by: Lukas Hejtmanek Acked-by: Kevin Coffman Signed-off-by: Steve Dickson --- diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index 02239d2..37e2aa5 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -840,42 +840,48 @@ handle_krb5_upcall(struct clnt_info *clp) } if (create_resp != 0) { if (uid == 0 && root_uses_machine_creds == 1) { + int nocache = 0; int success = 0; - - gssd_refresh_krb5_machine_credential(clp->servername, - NULL); - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all - */ - if (gssd_get_krb5_machine_cred_list(&credlist)) { - printerr(0, "ERROR: No credentials found " - "for connection to server %s\n", - clp->servername); - goto out_return_error; - } - for (ccname = credlist; ccname && *ccname; ccname++) { - gssd_setup_krb5_machine_gss_ccache(*ccname); - if ((create_auth_rpc_client(clp, &rpc_clnt, - &auth, uid, - AUTHTYPE_KRB5)) == 0) { - /* Success! */ - success++; - break; + do { + gssd_refresh_krb5_machine_credential(clp->servername, + NULL, nocache); + /* + * Get a list of credential cache names and try each + * of them until one works or we've tried them all + */ + if (gssd_get_krb5_machine_cred_list(&credlist)) { + printerr(0, "ERROR: No credentials found " + "for connection to server %s\n", + clp->servername); + goto out_return_error; } - printerr(2, "WARNING: Failed to create krb5 context " - "for user with uid %d with credentials " - "cache %s for server %s\n", - uid, *ccname, clp->servername); - } - gssd_free_krb5_machine_cred_list(credlist); - if (!success) { - printerr(1, "WARNING: Failed to create krb5 context " - "for user with uid %d with any " - "credentials cache for server %s\n", - uid, clp->servername); - goto out_return_error; - } + for (ccname = credlist; ccname && *ccname; ccname++) { + gssd_setup_krb5_machine_gss_ccache(*ccname); + if ((create_auth_rpc_client(clp, &rpc_clnt, + &auth, uid, + AUTHTYPE_KRB5)) == 0) { + /* Success! */ + success++; + break; + } + printerr(2, "WARNING: Failed to create machine krb5 context " + "with credentials cache %s for server %s\n", + *ccname, clp->servername); + } + gssd_free_krb5_machine_cred_list(credlist); + if (!success) { + if(nocache == 0) { + nocache++; + printerr(2, "WARNING: Machine cache is prematurely expired or corrupted " + "trying to recreate cache for server %s\n", clp->servername); + } else { + printerr(1, "WARNING: Failed to create machine krb5 context " + "with any credentials cache for server %s\n", + clp->servername); + goto out_return_error; + } + } + } while(!success); } else { printerr(1, "WARNING: Failed to create krb5 context " "for user with uid %d for server %s\n", diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index 3009cc5..78e9775 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -137,7 +137,7 @@ static int select_krb5_ccache(const struct dirent *d); static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d); static int gssd_get_single_krb5_cred(krb5_context context, - krb5_keytab kt, struct gssd_k5_kt_princ *ple); + krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache); static int query_krb5_ccache(const char* cred_cache, char **ret_princname, char **ret_realm); @@ -359,7 +359,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt, - struct gssd_k5_kt_princ *ple) + struct gssd_k5_kt_princ *ple, + int nocache) { #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS krb5_get_init_creds_opt *init_opts = NULL; @@ -379,7 +380,7 @@ gssd_get_single_krb5_cred(krb5_context context, memset(&my_creds, 0, sizeof(my_creds)); - if (ple->ccname && ple->endtime > now) { + if (ple->ccname && ple->endtime > now && !nocache) { printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", ple->ccname, ple->endtime); code = 0; @@ -1095,7 +1096,7 @@ gssd_get_krb5_machine_cred_list(char ***list) for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) { if (ple->ccname) { /* Make sure cred is up-to-date before returning it */ - retval = gssd_refresh_krb5_machine_credential(NULL, ple); + retval = gssd_refresh_krb5_machine_credential(NULL, ple, 0); if (retval) continue; if (i + 1 > listsize) { @@ -1185,7 +1186,7 @@ gssd_destroy_krb5_machine_creds(void) */ int gssd_refresh_krb5_machine_credential(char *hostname, - struct gssd_k5_kt_princ *ple) + struct gssd_k5_kt_princ *ple, int nocache) { krb5_error_code code = 0; krb5_context context; @@ -1240,7 +1241,7 @@ gssd_refresh_krb5_machine_credential(char *hostname, goto out; } } - retval = gssd_get_single_krb5_cred(context, kt, ple); + retval = gssd_get_single_krb5_cred(context, kt, ple, nocache); out: if (kt) krb5_kt_close(context, kt); diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h index 3d39300..4b6b281 100644 --- a/utils/gssd/krb5_util.h +++ b/utils/gssd/krb5_util.h @@ -30,7 +30,7 @@ void gssd_free_krb5_machine_cred_list(char **list); void gssd_setup_krb5_machine_gss_ccache(char *servername); void gssd_destroy_krb5_machine_creds(void); int gssd_refresh_krb5_machine_credential(char *hostname, - struct gssd_k5_kt_princ *ple); + struct gssd_k5_kt_princ *ple, int nocache); char *gssd_k5_err_msg(krb5_context context, krb5_error_code code); void gssd_k5_get_default_realm(char **def_realm);