diff options
author | Simon Wilkinson <simon@sxw.org.uk> | 2014-02-09 16:09:48 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2020-06-07 10:24:45 +0100 |
commit | 79f9d21b406c172878896ef41cdc2502fc2f84a7 (patch) | |
tree | 71507aaefd925223b1543b10f4342f2df9ea0ee3 /monitor.c | |
parent | 202f5a676221c244cd450086c334c2b59f339e86 (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.
Author: Simon Wilkinson <simon@sxw.org.uk>
Author: Colin Watson <cjwatson@debian.org>
Author: Jakub Jelen <jjelen@redhat.com>
Origin: other, https://github.com/openssh-gsskex/openssh-gsskex/commits/debian/master
Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
Last-Updated: 2020-06-07
Patch-Name: gssapi.patch
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 139 |
1 files changed, 128 insertions, 11 deletions
@@ -148,6 +148,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); | |||
148 | int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); | 148 | int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); |
149 | int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); | 149 | int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); |
150 | int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); | 150 | int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); |
151 | int mm_answer_gss_sign(struct ssh *, int, struct sshbuf *); | ||
152 | int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); | ||
151 | #endif | 153 | #endif |
152 | 154 | ||
153 | #ifdef SSH_AUDIT_EVENTS | 155 | #ifdef SSH_AUDIT_EVENTS |
@@ -220,11 +222,18 @@ struct mon_table mon_dispatch_proto20[] = { | |||
220 | {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, | 222 | {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, |
221 | {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, | 223 | {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, |
222 | {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, | 224 | {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, |
225 | {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, | ||
223 | #endif | 226 | #endif |
224 | {0, 0, NULL} | 227 | {0, 0, NULL} |
225 | }; | 228 | }; |
226 | 229 | ||
227 | struct mon_table mon_dispatch_postauth20[] = { | 230 | struct mon_table mon_dispatch_postauth20[] = { |
231 | #ifdef GSSAPI | ||
232 | {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, | ||
233 | {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, | ||
234 | {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, | ||
235 | {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, | ||
236 | #endif | ||
228 | #ifdef WITH_OPENSSL | 237 | #ifdef WITH_OPENSSL |
229 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, | 238 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, |
230 | #endif | 239 | #endif |
@@ -293,6 +302,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) | |||
293 | /* Permit requests for moduli and signatures */ | 302 | /* Permit requests for moduli and signatures */ |
294 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); | 303 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
295 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 304 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
305 | #ifdef GSSAPI | ||
306 | /* and for the GSSAPI key exchange */ | ||
307 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); | ||
308 | #endif | ||
296 | 309 | ||
297 | /* The first few requests do not require asynchronous access */ | 310 | /* The first few requests do not require asynchronous access */ |
298 | while (!authenticated) { | 311 | while (!authenticated) { |
@@ -406,6 +419,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) | |||
406 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); | 419 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
407 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 420 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
408 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); | 421 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
422 | #ifdef GSSAPI | ||
423 | /* and for the GSSAPI key exchange */ | ||
424 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); | ||
425 | #endif | ||
409 | 426 | ||
410 | if (auth_opts->permit_pty_flag) { | 427 | if (auth_opts->permit_pty_flag) { |
411 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); | 428 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); |
@@ -1712,6 +1729,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) | |||
1712 | # ifdef OPENSSL_HAS_ECC | 1729 | # ifdef OPENSSL_HAS_ECC |
1713 | kex->kex[KEX_ECDH_SHA2] = kex_gen_server; | 1730 | kex->kex[KEX_ECDH_SHA2] = kex_gen_server; |
1714 | # endif | 1731 | # endif |
1732 | # ifdef GSSAPI | ||
1733 | if (options.gss_keyex) { | ||
1734 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | ||
1735 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | ||
1736 | kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; | ||
1737 | kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; | ||
1738 | kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; | ||
1739 | kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; | ||
1740 | kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; | ||
1741 | } | ||
1742 | # endif | ||
1715 | #endif /* WITH_OPENSSL */ | 1743 | #endif /* WITH_OPENSSL */ |
1716 | kex->kex[KEX_C25519_SHA256] = kex_gen_server; | 1744 | kex->kex[KEX_C25519_SHA256] = kex_gen_server; |
1717 | kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; | 1745 | kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; |
@@ -1805,8 +1833,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1805 | u_char *p; | 1833 | u_char *p; |
1806 | int r; | 1834 | int r; |
1807 | 1835 | ||
1808 | if (!options.gss_authentication) | 1836 | if (!options.gss_authentication && !options.gss_keyex) |
1809 | fatal("%s: GSSAPI authentication not enabled", __func__); | 1837 | fatal("%s: GSSAPI not enabled", __func__); |
1810 | 1838 | ||
1811 | if ((r = sshbuf_get_string(m, &p, &len)) != 0) | 1839 | if ((r = sshbuf_get_string(m, &p, &len)) != 0) |
1812 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 1840 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
@@ -1838,8 +1866,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1838 | OM_uint32 flags = 0; /* GSI needs this */ | 1866 | OM_uint32 flags = 0; /* GSI needs this */ |
1839 | int r; | 1867 | int r; |
1840 | 1868 | ||
1841 | if (!options.gss_authentication) | 1869 | if (!options.gss_authentication && !options.gss_keyex) |
1842 | fatal("%s: GSSAPI authentication not enabled", __func__); | 1870 | fatal("%s: GSSAPI not enabled", __func__); |
1843 | 1871 | ||
1844 | if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) | 1872 | if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) |
1845 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 1873 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
@@ -1859,6 +1887,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1859 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); | 1887 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); |
1860 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); | 1888 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); |
1861 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); | 1889 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); |
1890 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); | ||
1862 | } | 1891 | } |
1863 | return (0); | 1892 | return (0); |
1864 | } | 1893 | } |
@@ -1870,8 +1899,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1870 | OM_uint32 ret; | 1899 | OM_uint32 ret; |
1871 | int r; | 1900 | int r; |
1872 | 1901 | ||
1873 | if (!options.gss_authentication) | 1902 | if (!options.gss_authentication && !options.gss_keyex) |
1874 | fatal("%s: GSSAPI authentication not enabled", __func__); | 1903 | fatal("%s: GSSAPI not enabled", __func__); |
1875 | 1904 | ||
1876 | if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || | 1905 | if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || |
1877 | (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) | 1906 | (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) |
@@ -1897,13 +1926,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1897 | int | 1926 | int |
1898 | mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) | 1927 | mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) |
1899 | { | 1928 | { |
1900 | int r, authenticated; | 1929 | int r, authenticated, kex; |
1901 | const char *displayname; | 1930 | const char *displayname; |
1902 | 1931 | ||
1903 | if (!options.gss_authentication) | 1932 | if (!options.gss_authentication && !options.gss_keyex) |
1904 | fatal("%s: GSSAPI authentication not enabled", __func__); | 1933 | fatal("%s: GSSAPI not enabled", __func__); |
1905 | 1934 | ||
1906 | authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); | 1935 | if ((r = sshbuf_get_u32(m, &kex)) != 0) |
1936 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1937 | |||
1938 | authenticated = authctxt->valid && | ||
1939 | ssh_gssapi_userok(authctxt->user, authctxt->pw, kex); | ||
1907 | 1940 | ||
1908 | sshbuf_reset(m); | 1941 | sshbuf_reset(m); |
1909 | if ((r = sshbuf_put_u32(m, authenticated)) != 0) | 1942 | if ((r = sshbuf_put_u32(m, authenticated)) != 0) |
@@ -1912,7 +1945,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1912 | debug3("%s: sending result %d", __func__, authenticated); | 1945 | debug3("%s: sending result %d", __func__, authenticated); |
1913 | mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); | 1946 | mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); |
1914 | 1947 | ||
1915 | auth_method = "gssapi-with-mic"; | 1948 | if (kex) { |
1949 | auth_method = "gssapi-keyex"; | ||
1950 | } else { | ||
1951 | auth_method = "gssapi-with-mic"; | ||
1952 | } | ||
1916 | 1953 | ||
1917 | if ((displayname = ssh_gssapi_displayname()) != NULL) | 1954 | if ((displayname = ssh_gssapi_displayname()) != NULL) |
1918 | auth2_record_info(authctxt, "%s", displayname); | 1955 | auth2_record_info(authctxt, "%s", displayname); |
@@ -1920,5 +1957,85 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) | |||
1920 | /* Monitor loop will terminate if authenticated */ | 1957 | /* Monitor loop will terminate if authenticated */ |
1921 | return (authenticated); | 1958 | return (authenticated); |
1922 | } | 1959 | } |
1960 | |||
1961 | int | ||
1962 | mm_answer_gss_sign(struct ssh *ssh, int socket, struct sshbuf *m) | ||
1963 | { | ||
1964 | gss_buffer_desc data; | ||
1965 | gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; | ||
1966 | OM_uint32 major, minor; | ||
1967 | size_t len; | ||
1968 | u_char *p = NULL; | ||
1969 | int r; | ||
1970 | |||
1971 | if (!options.gss_authentication && !options.gss_keyex) | ||
1972 | fatal("%s: GSSAPI not enabled", __func__); | ||
1973 | |||
1974 | if ((r = sshbuf_get_string(m, &p, &len)) != 0) | ||
1975 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1976 | data.value = p; | ||
1977 | data.length = len; | ||
1978 | /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */ | ||
1979 | if (data.length != 20 && data.length != 32 && data.length != 64) | ||
1980 | fatal("%s: data length incorrect: %d", __func__, | ||
1981 | (int) data.length); | ||
1982 | |||
1983 | /* Save the session ID on the first time around */ | ||
1984 | if (session_id2_len == 0) { | ||
1985 | session_id2_len = data.length; | ||
1986 | session_id2 = xmalloc(session_id2_len); | ||
1987 | memcpy(session_id2, data.value, session_id2_len); | ||
1988 | } | ||
1989 | major = ssh_gssapi_sign(gsscontext, &data, &hash); | ||
1990 | |||
1991 | free(data.value); | ||
1992 | |||
1993 | sshbuf_reset(m); | ||
1994 | |||
1995 | if ((r = sshbuf_put_u32(m, major)) != 0 || | ||
1996 | (r = sshbuf_put_string(m, hash.value, hash.length)) != 0) | ||
1997 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1998 | |||
1999 | mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); | ||
2000 | |||
2001 | gss_release_buffer(&minor, &hash); | ||
2002 | |||
2003 | /* Turn on getpwnam permissions */ | ||
2004 | monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); | ||
2005 | |||
2006 | /* And credential updating, for when rekeying */ | ||
2007 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); | ||
2008 | |||
2009 | return (0); | ||
2010 | } | ||
2011 | |||
2012 | int | ||
2013 | mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { | ||
2014 | ssh_gssapi_ccache store; | ||
2015 | int r, ok; | ||
2016 | |||
2017 | if (!options.gss_authentication && !options.gss_keyex) | ||
2018 | fatal("%s: GSSAPI not enabled", __func__); | ||
2019 | |||
2020 | if ((r = sshbuf_get_string(m, (u_char **)&store.filename, NULL)) != 0 || | ||
2021 | (r = sshbuf_get_string(m, (u_char **)&store.envvar, NULL)) != 0 || | ||
2022 | (r = sshbuf_get_string(m, (u_char **)&store.envval, NULL)) != 0) | ||
2023 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
2024 | |||
2025 | ok = ssh_gssapi_update_creds(&store); | ||
2026 | |||
2027 | free(store.filename); | ||
2028 | free(store.envvar); | ||
2029 | free(store.envval); | ||
2030 | |||
2031 | sshbuf_reset(m); | ||
2032 | if ((r = sshbuf_put_u32(m, ok)) != 0) | ||
2033 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
2034 | |||
2035 | mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); | ||
2036 | |||
2037 | return(0); | ||
2038 | } | ||
2039 | |||
1923 | #endif /* GSSAPI */ | 2040 | #endif /* GSSAPI */ |
1924 | 2041 | ||