summaryrefslogtreecommitdiff
path: root/backport-openssh-7.7p1-gssapi-new-unique.patch
diff options
context:
space:
mode:
Diffstat (limited to 'backport-openssh-7.7p1-gssapi-new-unique.patch')
-rw-r--r--backport-openssh-7.7p1-gssapi-new-unique.patch643
1 files changed, 643 insertions, 0 deletions
diff --git a/backport-openssh-7.7p1-gssapi-new-unique.patch b/backport-openssh-7.7p1-gssapi-new-unique.patch
new file mode 100644
index 0000000..3ff1b89
--- /dev/null
+++ b/backport-openssh-7.7p1-gssapi-new-unique.patch
@@ -0,0 +1,643 @@
+diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h
+--- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200
++++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -83,6 +83,7 @@ struct Authctxt {
+ krb5_principal krb5_user;
+ char *krb5_ticket_file;
+ char *krb5_ccname;
++ int krb5_set_env;
+ #endif
+ struct sshbuf *loginmsg;
+
+@@ -231,7 +232,7 @@ struct passwd *fakepw(void);
+ int sys_auth_passwd(struct ssh *, const char *);
+
+ #if defined(KRB5) && !defined(HEIMDAL)
+-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
++krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
+ #endif
+
+ #endif /* AUTH_H */
+diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c
+--- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200
++++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -51,6 +51,7 @@
+ #include <unistd.h>
+ #include <string.h>
+ #include <krb5.h>
++#include <profile.h>
+
+ extern ServerOptions options;
+
+@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c
+ #endif
+ krb5_error_code problem;
+ krb5_ccache ccache = NULL;
+- int len;
++ char *ticket_name = NULL;
+ char *client, *platform_client;
+ const char *errmsg;
+
+@@ -163,8 +164,8 @@ auth_krb5_password(Authctxt *authctxt, c
+ goto out;
+ }
+
+- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx,
+- &authctxt->krb5_fwd_ccache);
++ problem = ssh_krb5_cc_new_unique(authctxt->krb5_ctx,
++ &authctxt->krb5_fwd_ccache, &authctxt->krb5_set_env);
+ if (problem)
+ goto out;
+
+@@ -179,15 +180,14 @@ auth_krb5_password(Authctxt *authctxt, c
+ goto out;
+ #endif
+
+- authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
++ problem = krb5_cc_get_full_name(authctxt->krb5_ctx,
++ authctxt->krb5_fwd_ccache, &ticket_name);
+
+- len = strlen(authctxt->krb5_ticket_file) + 6;
+- authctxt->krb5_ccname = xmalloc(len);
+- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
+- authctxt->krb5_ticket_file);
++ authctxt->krb5_ccname = xstrdup(ticket_name);
++ krb5_free_string(authctxt->krb5_ctx, ticket_name);
+
+ #ifdef USE_PAM
+- if (options.use_pam)
++ if (options.use_pam && authctxt->krb5_set_env)
+ do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
+ #endif
+
+@@ -223,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, c
+ void
+ krb5_cleanup_proc(Authctxt *authctxt)
+ {
++ struct stat krb5_ccname_stat;
++ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
++
+ debug("krb5_cleanup_proc called");
+ if (authctxt->krb5_fwd_ccache) {
+- krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
++ krb5_context ctx = authctxt->krb5_ctx;
++ krb5_cccol_cursor cursor;
++ krb5_ccache ccache;
++ int ret;
++
++ krb5_cc_destroy(ctx, authctxt->krb5_fwd_ccache);
+ authctxt->krb5_fwd_ccache = NULL;
++
++ ret = krb5_cccol_cursor_new(ctx, &cursor);
++ if (ret)
++ goto out;
++
++ ret = krb5_cccol_cursor_next(ctx, cursor, &ccache);
++ if (ret == 0 && ccache != NULL) {
++ /* There is at least one other ccache in collection
++ * we can switch to */
++ krb5_cc_switch(ctx, ccache);
++ } else if (authctxt->krb5_ccname != NULL) {
++ /* Clean up the collection too */
++ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
++ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
++ *krb5_ccname_dir_start++ = '\0';
++ if (strcmp(krb5_ccname, "DIR") == 0) {
++
++ strcat(krb5_ccname_dir_start, "/primary");
++
++ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
++ if (unlink(krb5_ccname_dir_start) == 0) {
++ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
++ *krb5_ccname_dir_end = '\0';
++ if (rmdir(krb5_ccname_dir_start) == -1)
++ debug("cache dir '%s' remove failed: %s",
++ krb5_ccname_dir_start, strerror(errno));
++ }
++ else
++ debug("cache primary file '%s', remove failed: %s",
++ krb5_ccname_dir_start, strerror(errno));
++ }
++ }
++ }
++ krb5_cccol_cursor_free(ctx, &cursor);
+ }
++out:
+ if (authctxt->krb5_user) {
+ krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
+ authctxt->krb5_user = NULL;
+@@ -238,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt)
+ }
+ }
+
+-#ifndef HEIMDAL
++
++#if !defined(HEIMDAL)
++int
++ssh_asprintf_append(char **dsc, const char *fmt, ...) {
++ char *src, *old;
++ va_list ap;
++ int i;
++
++ va_start(ap, fmt);
++ i = vasprintf(&src, fmt, ap);
++ va_end(ap);
++
++ if (i == -1 || src == NULL)
++ return -1;
++
++ old = *dsc;
++
++ i = asprintf(dsc, "%s%s", *dsc, src);
++ if (i == -1 || src == NULL) {
++ free(src);
++ return -1;
++ }
++
++ free(old);
++ free(src);
++
++ return i;
++}
++
++int
++ssh_krb5_expand_template(char **result, const char *template) {
++ char *p_n, *p_o, *r, *tmp_template;
++
++ debug3_f("called, template = %s", template);
++ if (template == NULL)
++ return -1;
++
++ tmp_template = p_n = p_o = xstrdup(template);
++ r = xstrdup("");
++
++ while ((p_n = strstr(p_o, "%{")) != NULL) {
++
++ *p_n++ = '\0';
++ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
++ goto cleanup;
++
++ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 ||
++ strncmp(p_n, "{USERID}", 8) == 0) {
++ p_o = strchr(p_n, '}') + 1;
++ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1)
++ goto cleanup;
++ continue;
++ }
++ else if (strncmp(p_n, "{TEMP}", 6) == 0) {
++ p_o = strchr(p_n, '}') + 1;
++ if (ssh_asprintf_append(&r, "/tmp") == -1)
++ goto cleanup;
++ continue;
++ } else {
++ p_o = strchr(p_n, '}') + 1;
++ *p_o = '\0';
++ debug_f("unsupported token %s in %s", p_n, template);
++ /* unknown token, fallback to the default */
++ goto cleanup;
++ }
++ }
++
++ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
++ goto cleanup;
++
++ *result = r;
++ free(tmp_template);
++ return 0;
++
++cleanup:
++ free(r);
++ free(tmp_template);
++ return -1;
++}
++
++krb5_error_code
++ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
++ profile_t p;
++ int ret = 0;
++ char *value = NULL;
++
++ debug3_f("called");
++ ret = krb5_get_profile(ctx, &p);
++ if (ret)
++ return ret;
++
++ ret = profile_get_string(p, "libdefaults", "default_ccache_name", NULL, NULL, &value);
++ if (ret || !value)
++ return ret;
++
++ ret = ssh_krb5_expand_template(ccname, value);
++
++ debug3_f("returning with ccname = %s", *ccname);
++ return ret;
++}
++
+ krb5_error_code
+-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
+- int tmpfd, ret, oerrno;
+- char ccname[40];
++ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) {
++ int tmpfd, ret, oerrno, type_len;
++ char *ccname = NULL;
+ mode_t old_umask;
++ char *type = NULL, *colon = NULL;
+
+- ret = snprintf(ccname, sizeof(ccname),
+- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+- if (ret < 0 || (size_t)ret >= sizeof(ccname))
+- return ENOMEM;
+-
+- old_umask = umask(0177);
+- tmpfd = mkstemp(ccname + strlen("FILE:"));
+- oerrno = errno;
+- umask(old_umask);
+- if (tmpfd == -1) {
+- logit("mkstemp(): %.100s", strerror(oerrno));
+- return oerrno;
+- }
++ debug3_f("called");
++ if (need_environment)
++ *need_environment = 0;
++ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
++ if (ret || !ccname || options.kerberos_unique_ccache) {
++ /* Otherwise, go with the old method */
++ if (ccname)
++ free(ccname);
++ ccname = NULL;
++
++ ret = asprintf(&ccname,
++ "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
++ if (ret < 0)
++ return ENOMEM;
+
+- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
++ old_umask = umask(0177);
++ tmpfd = mkstemp(ccname + strlen("FILE:"));
+ oerrno = errno;
+- logit("fchmod(): %.100s", strerror(oerrno));
++ umask(old_umask);
++ if (tmpfd == -1) {
++ logit("mkstemp(): %.100s", strerror(oerrno));
++ return oerrno;
++ }
++
++ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
++ oerrno = errno;
++ logit("fchmod(): %.100s", strerror(oerrno));
++ close(tmpfd);
++ return oerrno;
++ }
++ /* make sure the KRB5CCNAME is set for non-standard location */
++ if (need_environment)
++ *need_environment = 1;
+ close(tmpfd);
+- return oerrno;
+ }
+- close(tmpfd);
+
+- return (krb5_cc_resolve(ctx, ccname, ccache));
++ debug3_f("setting default ccname to %s", ccname);
++ /* set the default with already expanded user IDs */
++ ret = krb5_cc_set_default_name(ctx, ccname);
++ if (ret)
++ return ret;
++
++ if ((colon = strstr(ccname, ":")) != NULL) {
++ type_len = colon - ccname;
++ type = malloc((type_len + 1) * sizeof(char));
++ if (type == NULL)
++ return ENOMEM;
++ strncpy(type, ccname, type_len);
++ type[type_len] = 0;
++ } else {
++ type = strdup(ccname);
++ }
++
++ /* If we have a credential cache from krb5.conf, we need to switch
++ * a primary cache for this collection, if it supports that (non-FILE)
++ */
++ if (krb5_cc_support_switch(ctx, type)) {
++ debug3_f("calling cc_new_unique(%s)", ccname);
++ ret = krb5_cc_new_unique(ctx, type, NULL, ccache);
++ free(type);
++ if (ret)
++ return ret;
++
++ debug3_f("calling cc_switch()");
++ return krb5_cc_switch(ctx, *ccache);
++ } else {
++ /* Otherwise, we can not create a unique ccname here (either
++ * it is already unique from above or the type does not support
++ * collections
++ */
++ free(type);
++ debug3_f("calling cc_resolve(%s)", ccname);
++ return (krb5_cc_resolve(ctx, ccname, ccache));
++ }
+ }
+ #endif /* !HEIMDAL */
+ #endif /* KRB5 */
+diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c
+--- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200
++++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -413,13 +413,15 @@ ssh_gssapi_cleanup_creds(void)
+ }
+
+ /* As user */
+-void
++int
+ ssh_gssapi_storecreds(void)
+ {
+ if (gssapi_client.mech && gssapi_client.mech->storecreds) {
+- (*gssapi_client.mech->storecreds)(&gssapi_client);
++ return (*gssapi_client.mech->storecreds)(&gssapi_client);
+ } else
+ debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
++
++ return 0;
+ }
+
+ /* This allows GSSAPI methods to do things to the child's environment based
+@@ -499,9 +501,7 @@ ssh_gssapi_rekey_creds(void) {
+ char *envstr;
+ #endif
+
+- if (gssapi_client.store.filename == NULL &&
+- gssapi_client.store.envval == NULL &&
+- gssapi_client.store.envvar == NULL)
++ if (gssapi_client.store.envval == NULL)
+ return;
+
+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
+diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c
+--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
++++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
+ /* This writes out any forwarded credentials from the structure populated
+ * during userauth. Called after we have setuid to the user */
+
+-static void
++static int
+ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
+ {
+ krb5_ccache ccache;
+@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ OM_uint32 maj_status, min_status;
+ const char *new_ccname, *new_cctype;
+ const char *errmsg;
++ int set_env = 0;
+
+ if (client->creds == NULL) {
+ debug("No credentials stored");
+- return;
++ return 0;
+ }
+
+ if (ssh_gssapi_krb5_init() == 0)
+- return;
++ return 0;
+
+ #ifdef HEIMDAL
+ # ifdef HAVE_KRB5_CC_NEW_UNIQUE
+@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ krb5_get_err_text(krb_context, problem));
+ # endif
+ krb5_free_error_message(krb_context, errmsg);
+- return;
++ return 0;
+ }
+ #else
+- if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) {
++ if ((problem = ssh_krb5_cc_new_unique(krb_context, &ccache, &set_env)) != 0) {
+ errmsg = krb5_get_error_message(krb_context, problem);
+- logit("ssh_krb5_cc_gen(): %.100s", errmsg);
++ logit("ssh_krb5_cc_new_unique(): %.100s", errmsg);
+ krb5_free_error_message(krb_context, errmsg);
+- return;
++ return 0;
+ }
+ #endif /* #ifdef HEIMDAL */
+
+@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ errmsg = krb5_get_error_message(krb_context, problem);
+ logit("krb5_parse_name(): %.100s", errmsg);
+ krb5_free_error_message(krb_context, errmsg);
+- return;
++ return 0;
+ }
+
+ if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
+@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ krb5_free_error_message(krb_context, errmsg);
+ krb5_free_principal(krb_context, princ);
+ krb5_cc_destroy(krb_context, ccache);
+- return;
++ return 0;
+ }
+
+ krb5_free_principal(krb_context, princ);
+@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+ client->creds, ccache))) {
+ logit("gss_krb5_copy_ccache() failed");
+ krb5_cc_destroy(krb_context, ccache);
+- return;
++ return 0;
+ }
+
+ new_cctype = krb5_cc_get_type(krb_context, ccache);
+ new_ccname = krb5_cc_get_name(krb_context, ccache);
+-
+- client->store.envvar = "KRB5CCNAME";
+-#ifdef USE_CCAPI
+- xasprintf(&client->store.envval, "API:%s", new_ccname);
+- client->store.filename = NULL;
+-#else
+- if (new_ccname[0] == ':')
+- new_ccname++;
+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
+- if (strcmp(new_cctype, "DIR") == 0) {
+- char *p;
+- p = strrchr(client->store.envval, '/');
+- if (p)
+- *p = '\0';
++
++ if (set_env) {
++ client->store.envvar = "KRB5CCNAME";
+ }
+ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0))
+ client->store.filename = xstrdup(new_ccname);
+-#endif
+
+ #ifdef USE_PAM
+- if (options.use_pam)
++ if (options.use_pam && set_env)
+ do_pam_putenv(client->store.envvar, client->store.envval);
+ #endif
+
+@@ -364,7 +354,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
+
+ client->store.data = krb_context;
+
+- return;
++ return set_env;
+ }
+
+ int
+diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c
+--- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200
++++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions
+ options->kerberos_or_local_passwd = -1;
+ options->kerberos_ticket_cleanup = -1;
+ options->kerberos_get_afs_token = -1;
++ options->kerberos_unique_ccache = -1;
+ options->gss_authentication=-1;
+ options->gss_keyex = -1;
+ options->gss_cleanup_creds = -1;
+@@ -359,6 +360,8 @@ fill_default_server_options(ServerOption
+ options->kerberos_ticket_cleanup = 1;
+ if (options->kerberos_get_afs_token == -1)
+ options->kerberos_get_afs_token = 0;
++ if (options->kerberos_unique_ccache == -1)
++ options->kerberos_unique_ccache = 0;
+ if (options->gss_authentication == -1)
+ options->gss_authentication = 0;
+ if (options->gss_keyex == -1)
+@@ -506,7 +509,8 @@ typedef enum {
+ sPort, sHostKeyFile, sLoginGraceTime,
+ sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
+ sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
+- sKerberosGetAFSToken, sPasswordAuthentication,
++ sKerberosGetAFSToken, sKerberosUniqueCCache,
++ sPasswordAuthentication,
+ sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
+ sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+ sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+@@ -593,11 +597,13 @@ static struct {
+ #else
+ { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ #endif
++ { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
+ #else
+ { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+ { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
++ { "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
+ #endif
+ { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+ { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+@@ -1573,6 +1579,10 @@ process_server_config_line_depth(ServerO
+ intptr = &options->kerberos_get_afs_token;
+ goto parse_flag;
+
++ case sKerberosUniqueCCache:
++ intptr = &options->kerberos_unique_ccache;
++ goto parse_flag;
++
+ case sGssAuthentication:
+ intptr = &options->gss_authentication;
+ goto parse_flag;
+@@ -2891,6 +2901,7 @@ dump_config(ServerOptions *o)
+ # ifdef USE_AFS
+ dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
+ # endif
++ dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
+ #endif
+ #ifdef GSSAPI
+ dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h
+--- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200
++++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -140,6 +140,8 @@ typedef struct {
+ * file on logout. */
+ int kerberos_get_afs_token; /* If true, try to get AFS token if
+ * authenticated with Kerberos. */
++ int kerberos_unique_ccache; /* If true, the acquired ticket will
++ * be stored in per-session ccache */
+ int gss_authentication; /* If true, permit GSSAPI authentication */
+ int gss_keyex; /* If true, permit GSSAPI key exchange */
+ int gss_cleanup_creds; /* If true, destroy cred cache on logout */
+diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c
+--- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
++++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s
+ /* Allow any GSSAPI methods that we've used to alter
+ * the child's environment as they see fit
+ */
+- ssh_gssapi_do_child(&env, &envsize);
++ if (s->authctxt->krb5_set_env)
++ ssh_gssapi_do_child(&env, &envsize);
+ #endif
+
+ /* Set basic environment. */
+@@ -1114,7 +1115,7 @@ do_setup_env(struct ssh *ssh, Session *s
+ }
+ #endif
+ #ifdef KRB5
+- if (s->authctxt->krb5_ccname)
++ if (s->authctxt->krb5_ccname && s->authctxt->krb5_set_env)
+ child_set_env(&env, &envsize, "KRB5CCNAME",
+ s->authctxt->krb5_ccname);
+ #endif
+diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c
+--- openssh-8.6p1/sshd.c.ccache_name 2021-04-19 14:05:10.849744540 +0200
++++ openssh-8.6p1/sshd.c 2021-04-19 14:05:10.855744584 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -2284,7 +2284,7 @@ main(int ac, char **av)
+ #ifdef GSSAPI
+ if (options.gss_authentication) {
+ temporarily_use_uid(authctxt->pw);
+- ssh_gssapi_storecreds();
++ authctxt->krb5_set_env = ssh_gssapi_storecreds();
+ restore_uid();
+ }
+ #endif
+diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5
+--- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200
++++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -939,6 +939,14 @@ Specifies whether to automatically destr
+ file on logout.
+ The default is
+ .Cm yes .
++.It Cm KerberosUniqueCCache
++Specifies whether to store the acquired tickets in the per-session credential
++cache under /tmp/ or whether to use per-user credential cache as configured in
++.Pa /etc/krb5.conf .
++The default value
++.Cm no
++can lead to overwriting previous tickets by subseqent connections to the same
++user account.
+ .It Cm KexAlgorithms
+ Specifies the available KEX (Key Exchange) algorithms.
+ Multiple algorithms must be comma-separated.
+diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h
+--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200
++++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200
+Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-7.7p1-gssapi-new-unique.patch
+@@ -114,7 +114,7 @@ typedef struct ssh_gssapi_mech_struct {
+ int (*dochild) (ssh_gssapi_client *);
+ int (*userok) (ssh_gssapi_client *, char *);
+ int (*localname) (ssh_gssapi_client *, char **);
+- void (*storecreds) (ssh_gssapi_client *);
++ int (*storecreds) (ssh_gssapi_client *);
+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
+ } ssh_gssapi_mech;
+
+@@ -175,7 +175,7 @@ int ssh_gssapi_userok(char *name, struct
+ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+ void ssh_gssapi_do_child(char ***, u_int *);
+ void ssh_gssapi_cleanup_creds(void);
+-void ssh_gssapi_storecreds(void);
++int ssh_gssapi_storecreds(void);
+ const char *ssh_gssapi_displayname(void);
+
+ char *ssh_gssapi_server_mechanisms(void);