diff options
author | Simon Wilkinson <simon@sxw.org.uk> | 2014-02-09 16:09:48 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2014-03-19 16:39:52 +0000 |
commit | 429c595dbaff7f7c2b3a53fe4235211f6d788025 (patch) | |
tree | 085cf7273c133b74238c968c9c9f591f8fb0308e /sshd.c | |
parent | 9a975a9faed7c4f334e8c8490db3e77e102f2b21 (diff) |
GSSAPI key exchange support
This patch has been rejected upstream: "None of the OpenSSH developers are
in favour of adding this, and this situation has not changed for several
years. This is not a slight on Simon's patch, which is of fine quality, but
just that a) we don't trust GSSAPI implementations that much and b) we don't
like adding new KEX since they are pre-auth attack surface. This one is
particularly scary, since it requires hooks out to typically root-owned
system resources."
However, quite a lot of people rely on this in Debian, and it's better to
have it merged into the main openssh package rather than having separate
-krb5 packages (as we used to have). It seems to have a generally good
security history.
Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
Last-Updated: 2014-03-19
Patch-Name: gssapi.patch
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 110 |
1 files changed, 110 insertions, 0 deletions
@@ -122,6 +122,10 @@ | |||
122 | #include "ssh-sandbox.h" | 122 | #include "ssh-sandbox.h" |
123 | #include "version.h" | 123 | #include "version.h" |
124 | 124 | ||
125 | #ifdef USE_SECURITY_SESSION_API | ||
126 | #include <Security/AuthSession.h> | ||
127 | #endif | ||
128 | |||
125 | #ifdef LIBWRAP | 129 | #ifdef LIBWRAP |
126 | #include <tcpd.h> | 130 | #include <tcpd.h> |
127 | #include <syslog.h> | 131 | #include <syslog.h> |
@@ -1721,10 +1725,13 @@ main(int ac, char **av) | |||
1721 | logit("Disabling protocol version 1. Could not load host key"); | 1725 | logit("Disabling protocol version 1. Could not load host key"); |
1722 | options.protocol &= ~SSH_PROTO_1; | 1726 | options.protocol &= ~SSH_PROTO_1; |
1723 | } | 1727 | } |
1728 | #ifndef GSSAPI | ||
1729 | /* The GSSAPI key exchange can run without a host key */ | ||
1724 | if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { | 1730 | if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { |
1725 | logit("Disabling protocol version 2. Could not load host key"); | 1731 | logit("Disabling protocol version 2. Could not load host key"); |
1726 | options.protocol &= ~SSH_PROTO_2; | 1732 | options.protocol &= ~SSH_PROTO_2; |
1727 | } | 1733 | } |
1734 | #endif | ||
1728 | if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { | 1735 | if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { |
1729 | logit("sshd: no hostkeys available -- exiting."); | 1736 | logit("sshd: no hostkeys available -- exiting."); |
1730 | exit(1); | 1737 | exit(1); |
@@ -2051,6 +2058,60 @@ main(int ac, char **av) | |||
2051 | remote_ip, remote_port, | 2058 | remote_ip, remote_port, |
2052 | get_local_ipaddr(sock_in), get_local_port()); | 2059 | get_local_ipaddr(sock_in), get_local_port()); |
2053 | 2060 | ||
2061 | #ifdef USE_SECURITY_SESSION_API | ||
2062 | /* | ||
2063 | * Create a new security session for use by the new user login if | ||
2064 | * the current session is the root session or we are not launched | ||
2065 | * by inetd (eg: debugging mode or server mode). We do not | ||
2066 | * necessarily need to create a session if we are launched from | ||
2067 | * inetd because Panther xinetd will create a session for us. | ||
2068 | * | ||
2069 | * The only case where this logic will fail is if there is an | ||
2070 | * inetd running in a non-root session which is not creating | ||
2071 | * new sessions for us. Then all the users will end up in the | ||
2072 | * same session (bad). | ||
2073 | * | ||
2074 | * When the client exits, the session will be destroyed for us | ||
2075 | * automatically. | ||
2076 | * | ||
2077 | * We must create the session before any credentials are stored | ||
2078 | * (including AFS pags, which happens a few lines below). | ||
2079 | */ | ||
2080 | { | ||
2081 | OSStatus err = 0; | ||
2082 | SecuritySessionId sid = 0; | ||
2083 | SessionAttributeBits sattrs = 0; | ||
2084 | |||
2085 | err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); | ||
2086 | if (err) | ||
2087 | error("SessionGetInfo() failed with error %.8X", | ||
2088 | (unsigned) err); | ||
2089 | else | ||
2090 | debug("Current Session ID is %.8X / Session Attributes are %.8X", | ||
2091 | (unsigned) sid, (unsigned) sattrs); | ||
2092 | |||
2093 | if (inetd_flag && !(sattrs & sessionIsRoot)) | ||
2094 | debug("Running in inetd mode in a non-root session... " | ||
2095 | "assuming inetd created the session for us."); | ||
2096 | else { | ||
2097 | debug("Creating new security session..."); | ||
2098 | err = SessionCreate(0, sessionHasTTY | sessionIsRemote); | ||
2099 | if (err) | ||
2100 | error("SessionCreate() failed with error %.8X", | ||
2101 | (unsigned) err); | ||
2102 | |||
2103 | err = SessionGetInfo(callerSecuritySession, &sid, | ||
2104 | &sattrs); | ||
2105 | if (err) | ||
2106 | error("SessionGetInfo() failed with error %.8X", | ||
2107 | (unsigned) err); | ||
2108 | else | ||
2109 | debug("New Session ID is %.8X / Session Attributes are %.8X", | ||
2110 | (unsigned) sid, (unsigned) sattrs); | ||
2111 | } | ||
2112 | } | ||
2113 | #endif | ||
2114 | |||
2054 | /* | 2115 | /* |
2055 | * We don't want to listen forever unless the other side | 2116 | * We don't want to listen forever unless the other side |
2056 | * successfully authenticates itself. So we set up an alarm which is | 2117 | * successfully authenticates itself. So we set up an alarm which is |
@@ -2456,6 +2517,48 @@ do_ssh2_kex(void) | |||
2456 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( | 2517 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( |
2457 | list_hostkey_types()); | 2518 | list_hostkey_types()); |
2458 | 2519 | ||
2520 | #ifdef GSSAPI | ||
2521 | { | ||
2522 | char *orig; | ||
2523 | char *gss = NULL; | ||
2524 | char *newstr = NULL; | ||
2525 | orig = myproposal[PROPOSAL_KEX_ALGS]; | ||
2526 | |||
2527 | /* | ||
2528 | * If we don't have a host key, then there's no point advertising | ||
2529 | * the other key exchange algorithms | ||
2530 | */ | ||
2531 | |||
2532 | if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) | ||
2533 | orig = NULL; | ||
2534 | |||
2535 | if (options.gss_keyex) | ||
2536 | gss = ssh_gssapi_server_mechanisms(); | ||
2537 | else | ||
2538 | gss = NULL; | ||
2539 | |||
2540 | if (gss && orig) | ||
2541 | xasprintf(&newstr, "%s,%s", gss, orig); | ||
2542 | else if (gss) | ||
2543 | newstr = gss; | ||
2544 | else if (orig) | ||
2545 | newstr = orig; | ||
2546 | |||
2547 | /* | ||
2548 | * If we've got GSSAPI mechanisms, then we've got the 'null' host | ||
2549 | * key alg, but we can't tell people about it unless its the only | ||
2550 | * host key algorithm we support | ||
2551 | */ | ||
2552 | if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) | ||
2553 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; | ||
2554 | |||
2555 | if (newstr) | ||
2556 | myproposal[PROPOSAL_KEX_ALGS] = newstr; | ||
2557 | else | ||
2558 | fatal("No supported key exchange algorithms"); | ||
2559 | } | ||
2560 | #endif | ||
2561 | |||
2459 | /* start key exchange */ | 2562 | /* start key exchange */ |
2460 | kex = kex_setup(myproposal); | 2563 | kex = kex_setup(myproposal); |
2461 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2564 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
@@ -2464,6 +2567,13 @@ do_ssh2_kex(void) | |||
2464 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2567 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2465 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2568 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
2466 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2569 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
2570 | #ifdef GSSAPI | ||
2571 | if (options.gss_keyex) { | ||
2572 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | ||
2573 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | ||
2574 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; | ||
2575 | } | ||
2576 | #endif | ||
2467 | kex->server = 1; | 2577 | kex->server = 1; |
2468 | kex->client_version_string=client_version_string; | 2578 | kex->client_version_string=client_version_string; |
2469 | kex->server_version_string=server_version_string; | 2579 | kex->server_version_string=server_version_string; |