move kerberos cache to /run/user/<uid>/ by default (#848228)
fix kerberos cache handling to allow sucessful ticket forwarding
This commit is contained in:
parent
e6dbb83190
commit
aacd017a6d
@ -105,56 +105,79 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
|
|||||||
#include <krb5.h>
|
#include <krb5.h>
|
||||||
|
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
@@ -170,8 +171,13 @@ auth_krb5_password(Authctxt *authctxt, c
|
@@ -77,6 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c
|
||||||
|
#endif
|
||||||
|
krb5_error_code problem;
|
||||||
|
krb5_ccache ccache = NULL;
|
||||||
|
+ const char *ccache_type;
|
||||||
|
int len;
|
||||||
|
char *client, *platform_client;
|
||||||
|
|
||||||
len = strlen(authctxt->krb5_ticket_file) + 6;
|
@@ -166,12 +168,30 @@ auth_krb5_password(Authctxt *authctxt, c
|
||||||
|
goto out;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
||||||
|
authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
||||||
|
|
||||||
|
- len = strlen(authctxt->krb5_ticket_file) + 6;
|
||||||
|
+ if (authctxt->krb5_ticket_file[0] == ':')
|
||||||
|
+ authctxt->krb5_ticket_file++;
|
||||||
|
+
|
||||||
|
+ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type);
|
||||||
authctxt->krb5_ccname = xmalloc(len);
|
authctxt->krb5_ccname = xmalloc(len);
|
||||||
- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
|
- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
|
||||||
|
+
|
||||||
+#ifdef USE_CCAPI
|
+#ifdef USE_CCAPI
|
||||||
+ snprintf(authctxt->krb5_ccname, len, "API:%s",
|
+ snprintf(authctxt->krb5_ccname, len, "API:%s",
|
||||||
authctxt->krb5_ticket_file);
|
authctxt->krb5_ticket_file);
|
||||||
+#else
|
+#else
|
||||||
+ snprintf(authctxt->krb5_ccname, len, "DIR:%s",
|
+ snprintf(authctxt->krb5_ccname, len, "%s:%s",
|
||||||
+ authctxt->krb5_ticket_file);
|
+ ccache_type, authctxt->krb5_ticket_file);
|
||||||
+#endif
|
+#endif
|
||||||
|
+
|
||||||
|
+ if (strcmp(ccache_type, "DIR") == 0) {
|
||||||
|
+ char *p;
|
||||||
|
+ p = strrchr(authctxt->krb5_ccname, '/');
|
||||||
|
+ if (p)
|
||||||
|
+ *p = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
if (options.use_pam)
|
if (options.use_pam)
|
||||||
@@ -208,10 +214,33 @@ auth_krb5_password(Authctxt *authctxt, c
|
@@ -208,10 +228,30 @@ auth_krb5_password(Authctxt *authctxt, c
|
||||||
void
|
void
|
||||||
krb5_cleanup_proc(Authctxt *authctxt)
|
krb5_cleanup_proc(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
+ struct stat krb5_ccname_stat;
|
+ struct stat krb5_ccname_stat;
|
||||||
+ char krb5_ccname[128], *krb5_ccname_dir_end;
|
+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
|
||||||
+
|
+
|
||||||
debug("krb5_cleanup_proc called");
|
debug("krb5_cleanup_proc called");
|
||||||
if (authctxt->krb5_fwd_ccache) {
|
if (authctxt->krb5_fwd_ccache) {
|
||||||
krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
||||||
authctxt->krb5_fwd_ccache = NULL;
|
authctxt->krb5_fwd_ccache = NULL;
|
||||||
+
|
+
|
||||||
+ /* assume ticket cache type DIR - DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */
|
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
|
||||||
+ strncpy(krb5_ccname, authctxt->krb5_ccname + strlen("DIR::"), sizeof(krb5_ccname) - 10);
|
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
|
||||||
|
+ strcat(krb5_ccname_dir_start, "/primary");
|
||||||
+
|
+
|
||||||
+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/');
|
+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
|
||||||
+ if (krb5_ccname_dir_end != NULL) {
|
+ if (unlink(krb5_ccname_dir_start) == 0) {
|
||||||
+ strcpy(krb5_ccname_dir_end, "/primary");
|
+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
|
||||||
+
|
+ *krb5_ccname_dir_end = '\0';
|
||||||
+ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) {
|
+ if (rmdir(krb5_ccname_dir_start) == -1)
|
||||||
+ if (unlink(krb5_ccname) == 0) {
|
+ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno));
|
||||||
+ *krb5_ccname_dir_end = '\0';
|
|
||||||
+ if (rmdir(krb5_ccname) == -1)
|
|
||||||
+ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno));
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ debug("cache primary file '%s', remove failed: %s",
|
|
||||||
+ krb5_ccname, strerror(errno)
|
|
||||||
+ );
|
|
||||||
+ }
|
+ }
|
||||||
|
+ else
|
||||||
|
+ debug("cache primary file '%s', remove failed: %s",
|
||||||
|
+ krb5_ccname_dir_start, strerror(errno)
|
||||||
|
+ );
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
if (authctxt->krb5_user) {
|
if (authctxt->krb5_user) {
|
||||||
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
|
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
|
||||||
@@ -226,31 +255,37 @@ krb5_cleanup_proc(Authctxt *authctxt)
|
@@ -226,31 +266,45 @@ krb5_cleanup_proc(Authctxt *authctxt)
|
||||||
#ifndef HEIMDAL
|
#ifndef HEIMDAL
|
||||||
krb5_error_code
|
krb5_error_code
|
||||||
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
|
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
|
||||||
@ -162,17 +185,17 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
|
|||||||
- char ccname[40];
|
- char ccname[40];
|
||||||
+ int ret, oerrno;
|
+ int ret, oerrno;
|
||||||
+ char ccname[128];
|
+ char ccname[128];
|
||||||
mode_t old_umask;
|
|
||||||
+#ifdef USE_CCAPI
|
+#ifdef USE_CCAPI
|
||||||
+ char cctemplate[] = "API:krb5cc_%d";
|
+ char cctemplate[] = "API:krb5cc_%d";
|
||||||
+#else
|
+#else
|
||||||
+ char cctemplate[] = "DIR:/tmp/krb5cc_%d_XXXXXXXXXX";
|
mode_t old_umask;
|
||||||
|
+ char cctemplate[] = "DIR:/run/user/%d/krb5cc_XXXXXXXXXX";
|
||||||
+ char *tmpdir;
|
+ char *tmpdir;
|
||||||
+#endif
|
+#endif
|
||||||
|
|
||||||
ret = snprintf(ccname, sizeof(ccname),
|
- ret = snprintf(ccname, sizeof(ccname),
|
||||||
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
||||||
+ cctemplate, geteuid());
|
+ ret = snprintf(ccname, sizeof(ccname), cctemplate, geteuid());
|
||||||
if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
@ -182,11 +205,20 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
|
|||||||
+ old_umask = umask(0077);
|
+ old_umask = umask(0077);
|
||||||
+ tmpdir = mkdtemp(ccname + strlen("DIR:"));
|
+ tmpdir = mkdtemp(ccname + strlen("DIR:"));
|
||||||
oerrno = errno;
|
oerrno = errno;
|
||||||
|
+ if (tmpdir == NULL && errno == ENOENT) {
|
||||||
|
+ /* /run/user/uid doesn't exist -> fallback to /tmp */
|
||||||
|
+ ret = snprintf(ccname, sizeof(ccname), "DIR:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
||||||
|
+ if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
||||||
|
+ return ENOMEM;
|
||||||
|
+ tmpdir = mkdtemp(ccname + strlen("DIR:"));
|
||||||
|
+ oerrno = errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
umask(old_umask);
|
umask(old_umask);
|
||||||
- if (tmpfd == -1) {
|
- if (tmpfd == -1) {
|
||||||
- logit("mkstemp(): %.100s", strerror(oerrno));
|
- logit("mkstemp(): %.100s", strerror(oerrno));
|
||||||
+ if (tmpdir == NULL) {
|
+ if (tmpdir == NULL) {
|
||||||
+ logit("mkdtemp(): %.100s", strerror(oerrno));
|
+ logit("mkdtemp(): %s - %.100s", ccname, strerror(oerrno));
|
||||||
return oerrno;
|
return oerrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +227,7 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c
|
|||||||
oerrno = errno;
|
oerrno = errno;
|
||||||
- logit("fchmod(): %.100s", strerror(oerrno));
|
- logit("fchmod(): %.100s", strerror(oerrno));
|
||||||
- close(tmpfd);
|
- close(tmpfd);
|
||||||
+ logit("chmod(): %.100s", strerror(oerrno));
|
+ logit("chmod(): %s - %.100s", ccname, strerror(oerrno));
|
||||||
return oerrno;
|
return oerrno;
|
||||||
}
|
}
|
||||||
- close(tmpfd);
|
- close(tmpfd);
|
||||||
@ -934,7 +966,7 @@ diff -up openssh-6.2p1/gss-serv.c.gsskex openssh-6.2p1/gss-serv.c
|
|||||||
gssapi_client.store.filename);
|
gssapi_client.store.filename);
|
||||||
unlink(gssapi_client.store.filename);
|
unlink(gssapi_client.store.filename);
|
||||||
+
|
+
|
||||||
+ /* Ticket cache: DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */
|
+ /* Ticket cache: DIR::/run/user/13558/krb5cc_T9eDKSQvzb/tkt */
|
||||||
+ /* same code as in auth-krb5.c:krb5_cleanup_proc */
|
+ /* same code as in auth-krb5.c:krb5_cleanup_proc */
|
||||||
+ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10);
|
+ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10);
|
||||||
+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/');
|
+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/');
|
||||||
@ -1087,19 +1119,21 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
|
|||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
@@ -119,7 +119,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
||||||
|
krb5_error_code problem;
|
||||||
krb5_principal princ;
|
krb5_principal princ;
|
||||||
OM_uint32 maj_status, min_status;
|
OM_uint32 maj_status, min_status;
|
||||||
int len;
|
- int len;
|
||||||
+ const char *new_ccname;
|
+ const char *new_ccname, *new_cctype;
|
||||||
|
|
||||||
if (client->creds == NULL) {
|
if (client->creds == NULL) {
|
||||||
debug("No credentials stored");
|
debug("No credentials stored");
|
||||||
@@ -168,11 +169,18 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
@@ -168,11 +168,25 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
|
- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
|
||||||
|
+ new_cctype = krb5_cc_get_type(krb_context, ccache);
|
||||||
+ new_ccname = krb5_cc_get_name(krb_context, ccache);
|
+ new_ccname = krb5_cc_get_name(krb_context, ccache);
|
||||||
+
|
+
|
||||||
client->store.envvar = "KRB5CCNAME";
|
client->store.envvar = "KRB5CCNAME";
|
||||||
@ -1110,15 +1144,21 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
|
|||||||
+ xasprintf(&client->store.envval, "API:%s", new_ccname);
|
+ xasprintf(&client->store.envval, "API:%s", new_ccname);
|
||||||
+ client->store.filename = NULL;
|
+ client->store.filename = NULL;
|
||||||
+#else
|
+#else
|
||||||
+ xasprintf(&client->store.envval, "DIR:%s", new_ccname);
|
|
||||||
+ if (new_ccname[0] == ':')
|
+ if (new_ccname[0] == ':')
|
||||||
+ new_ccname++;
|
+ 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';
|
||||||
|
+ }
|
||||||
+ client->store.filename = xstrdup(new_ccname);
|
+ client->store.filename = xstrdup(new_ccname);
|
||||||
+#endif
|
+#endif
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
if (options.use_pam)
|
if (options.use_pam)
|
||||||
@@ -184,6 +192,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
@@ -184,6 +198,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1230,7 @@ diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c
|
|||||||
ssh_gssapi_mech gssapi_kerberos_mech = {
|
ssh_gssapi_mech gssapi_kerberos_mech = {
|
||||||
"toWM5Slw5Ew8Mqkay+al2g==",
|
"toWM5Slw5Ew8Mqkay+al2g==",
|
||||||
"Kerberos",
|
"Kerberos",
|
||||||
@@ -191,7 +264,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
|
@@ -191,7 +270,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
|
||||||
NULL,
|
NULL,
|
||||||
&ssh_gssapi_krb5_userok,
|
&ssh_gssapi_krb5_userok,
|
||||||
NULL,
|
NULL,
|
||||||
@ -2273,7 +2313,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
|
|||||||
#endif
|
#endif
|
||||||
{ "fallbacktorsh", oDeprecated },
|
{ "fallbacktorsh", oDeprecated },
|
||||||
{ "usersh", oDeprecated },
|
{ "usersh", oDeprecated },
|
||||||
@@ -483,10 +494,30 @@ parse_flag:
|
@@ -503,10 +514,30 @@ parse_flag:
|
||||||
intptr = &options->gss_authentication;
|
intptr = &options->gss_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
@ -2304,7 +2344,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
|
|||||||
case oBatchMode:
|
case oBatchMode:
|
||||||
intptr = &options->batch_mode;
|
intptr = &options->batch_mode;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
@@ -1139,7 +1170,12 @@ initialize_options(Options * options)
|
@@ -1158,7 +1189,12 @@ initialize_options(Options * options)
|
||||||
options->pubkey_authentication = -1;
|
options->pubkey_authentication = -1;
|
||||||
options->challenge_response_authentication = -1;
|
options->challenge_response_authentication = -1;
|
||||||
options->gss_authentication = -1;
|
options->gss_authentication = -1;
|
||||||
@ -2317,7 +2357,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c
|
|||||||
options->password_authentication = -1;
|
options->password_authentication = -1;
|
||||||
options->kbd_interactive_authentication = -1;
|
options->kbd_interactive_authentication = -1;
|
||||||
options->kbd_interactive_devices = NULL;
|
options->kbd_interactive_devices = NULL;
|
||||||
@@ -1239,8 +1275,14 @@ fill_default_options(Options * options)
|
@@ -1258,8 +1294,14 @@ fill_default_options(Options * options)
|
||||||
options->challenge_response_authentication = 1;
|
options->challenge_response_authentication = 1;
|
||||||
if (options->gss_authentication == -1)
|
if (options->gss_authentication == -1)
|
||||||
options->gss_authentication = 0;
|
options->gss_authentication = 0;
|
||||||
@ -2806,7 +2846,36 @@ diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c
|
|||||||
/*
|
/*
|
||||||
* We don't want to listen forever unless the other side
|
* We don't want to listen forever unless the other side
|
||||||
* successfully authenticates itself. So we set up an alarm which is
|
* successfully authenticates itself. So we set up an alarm which is
|
||||||
@@ -2466,6 +2527,48 @@ do_ssh2_kex(void)
|
@@ -2139,14 +2200,6 @@ main(int ac, char **av)
|
||||||
|
#ifdef SSH_AUDIT_EVENTS
|
||||||
|
audit_event(SSH_AUTH_SUCCESS);
|
||||||
|
#endif
|
||||||
|
-
|
||||||
|
-#ifdef GSSAPI
|
||||||
|
- if (options.gss_authentication) {
|
||||||
|
- temporarily_use_uid(authctxt->pw);
|
||||||
|
- ssh_gssapi_storecreds();
|
||||||
|
- restore_uid();
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
|
||||||
|
#endif
|
||||||
|
@@ -2156,6 +2209,13 @@ main(int ac, char **av)
|
||||||
|
do_pam_session();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
+#ifdef GSSAPI
|
||||||
|
+ if (options.gss_authentication) {
|
||||||
|
+ temporarily_use_uid(authctxt->pw);
|
||||||
|
+ ssh_gssapi_storecreds();
|
||||||
|
+ restore_uid();
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In privilege separation, we fork another child and prepare
|
||||||
|
@@ -2466,6 +2526,48 @@ do_ssh2_kex(void)
|
||||||
|
|
||||||
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
|
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
|
||||||
|
|
||||||
@ -2855,7 +2924,7 @@ diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c
|
|||||||
/* start key exchange */
|
/* start key exchange */
|
||||||
kex = kex_setup(myproposal);
|
kex = kex_setup(myproposal);
|
||||||
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
|
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
|
||||||
@@ -2473,6 +2576,13 @@ do_ssh2_kex(void)
|
@@ -2473,6 +2575,13 @@ do_ssh2_kex(void)
|
||||||
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
|
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
|
||||||
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
|
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
|
||||||
kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
|
kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
|
||||||
|
Loading…
Reference in New Issue
Block a user