diff --git a/openssh-6.2p1-gsskex.patch b/openssh-6.2p1-gsskex.patch index 3934dcf..d6f0810 100644 --- a/openssh-6.2p1-gsskex.patch +++ b/openssh-6.2p1-gsskex.patch @@ -105,56 +105,79 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c #include 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; + +@@ -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; +- 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); - snprintf(authctxt->krb5_ccname, len, "FILE:%s", ++ +#ifdef USE_CCAPI + snprintf(authctxt->krb5_ccname, len, "API:%s", authctxt->krb5_ticket_file); +#else -+ snprintf(authctxt->krb5_ccname, len, "DIR:%s", -+ authctxt->krb5_ticket_file); ++ snprintf(authctxt->krb5_ccname, len, "%s:%s", ++ ccache_type, authctxt->krb5_ticket_file); +#endif ++ ++ if (strcmp(ccache_type, "DIR") == 0) { ++ char *p; ++ p = strrchr(authctxt->krb5_ccname, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ #ifdef 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 krb5_cleanup_proc(Authctxt *authctxt) { + 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"); if (authctxt->krb5_fwd_ccache) { krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); authctxt->krb5_fwd_ccache = NULL; + -+ /* assume ticket cache type DIR - DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */ -+ strncpy(krb5_ccname, authctxt->krb5_ccname + strlen("DIR::"), sizeof(krb5_ccname) - 10); ++ strncpy(krb5_ccname, authctxt->krb5_ccname, 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 (krb5_ccname_dir_end != NULL) { -+ strcpy(krb5_ccname_dir_end, "/primary"); -+ -+ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { -+ if (unlink(krb5_ccname) == 0) { -+ *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) -+ ); ++ 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) ++ ); + } } if (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 krb5_error_code 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]; + int ret, oerrno; + char ccname[128]; - mode_t old_umask; +#ifdef USE_CCAPI + char cctemplate[] = "API:krb5cc_%d"; +#else -+ char cctemplate[] = "DIR:/tmp/krb5cc_%d_XXXXXXXXXX"; + mode_t old_umask; ++ char cctemplate[] = "DIR:/run/user/%d/krb5cc_XXXXXXXXXX"; + char *tmpdir; +#endif - ret = snprintf(ccname, sizeof(ccname), +- ret = snprintf(ccname, sizeof(ccname), - "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ cctemplate, geteuid()); ++ ret = snprintf(ccname, sizeof(ccname), cctemplate, geteuid()); if (ret < 0 || (size_t)ret >= sizeof(ccname)) 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); + tmpdir = mkdtemp(ccname + strlen("DIR:")); 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); - if (tmpfd == -1) { - logit("mkstemp(): %.100s", strerror(oerrno)); + if (tmpdir == NULL) { -+ logit("mkdtemp(): %.100s", strerror(oerrno)); ++ logit("mkdtemp(): %s - %.100s", ccname, strerror(oerrno)); return oerrno; } @@ -195,7 +227,7 @@ diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c oerrno = errno; - logit("fchmod(): %.100s", strerror(oerrno)); - close(tmpfd); -+ logit("chmod(): %.100s", strerror(oerrno)); ++ logit("chmod(): %s - %.100s", ccname, strerror(oerrno)); return oerrno; } - 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); 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 */ + strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10); + 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 * 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; OM_uint32 maj_status, min_status; - int len; -+ const char *new_ccname; +- int len; ++ const char *new_ccname, *new_cctype; if (client->creds == NULL) { 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; } - 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); + 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); + client->store.filename = NULL; +#else -+ xasprintf(&client->store.envval, "DIR:%s", new_ccname); + 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'; ++ } + client->store.filename = xstrdup(new_ccname); +#endif #ifdef 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; } @@ -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 = { "toWM5Slw5Ew8Mqkay+al2g==", "Kerberos", -@@ -191,7 +264,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { +@@ -191,7 +270,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { NULL, &ssh_gssapi_krb5_userok, NULL, @@ -2273,7 +2313,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c #endif { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, -@@ -483,10 +494,30 @@ parse_flag: +@@ -503,10 +514,30 @@ parse_flag: intptr = &options->gss_authentication; goto parse_flag; @@ -2304,7 +2344,7 @@ diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -1139,7 +1170,12 @@ initialize_options(Options * options) +@@ -1158,7 +1189,12 @@ initialize_options(Options * options) options->pubkey_authentication = -1; options->challenge_response_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->kbd_interactive_authentication = -1; 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; if (options->gss_authentication == -1) 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 * 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(); @@ -2855,7 +2924,7 @@ diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c /* start key exchange */ kex = kex_setup(myproposal); 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_SHA256] = kexgex_server; kex->kex[KEX_ECDH_SHA2] = kexecdh_server;