summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authorSimon Wilkinson <simon@sxw.org.uk>2014-02-09 16:09:48 +0000
committerColin Watson <cjwatson@debian.org>2019-10-09 23:06:20 +0100
commit9da806e67101afdc0d3a1d304659927acf18f5c5 (patch)
tree4cb56e13b3b3b14147366a04a7ff691f76908bf7 /kex.c
parent4213eec74e74de6310c27a40c3e9759a08a73996 (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. Origin: other, https://github.com/openssh-gsskex/openssh-gsskex/commits/debian/master Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 Last-Updated: 2019-10-09 Patch-Name: gssapi.patch
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c66
1 files changed, 63 insertions, 3 deletions
diff --git a/kex.c b/kex.c
index 49d701568..e09355dbd 100644
--- a/kex.c
+++ b/kex.c
@@ -55,11 +55,16 @@
55#include "misc.h" 55#include "misc.h"
56#include "dispatch.h" 56#include "dispatch.h"
57#include "monitor.h" 57#include "monitor.h"
58#include "xmalloc.h"
58 59
59#include "ssherr.h" 60#include "ssherr.h"
60#include "sshbuf.h" 61#include "sshbuf.h"
61#include "digest.h" 62#include "digest.h"
62 63
64#ifdef GSSAPI
65#include "ssh-gss.h"
66#endif
67
63/* prototype */ 68/* prototype */
64static int kex_choose_conf(struct ssh *); 69static int kex_choose_conf(struct ssh *);
65static int kex_input_newkeys(int, u_int32_t, struct ssh *); 70static int kex_input_newkeys(int, u_int32_t, struct ssh *);
@@ -113,15 +118,28 @@ static const struct kexalg kexalgs[] = {
113#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ 118#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
114 { NULL, 0, -1, -1}, 119 { NULL, 0, -1, -1},
115}; 120};
121static const struct kexalg gss_kexalgs[] = {
122#ifdef GSSAPI
123 { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
124 { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
125 { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
126 { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
127 { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
128 { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256,
129 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
130 { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
131#endif
132 { NULL, 0, -1, -1 },
133};
116 134
117char * 135static char *
118kex_alg_list(char sep) 136kex_alg_list_internal(char sep, const struct kexalg *algs)
119{ 137{
120 char *ret = NULL, *tmp; 138 char *ret = NULL, *tmp;
121 size_t nlen, rlen = 0; 139 size_t nlen, rlen = 0;
122 const struct kexalg *k; 140 const struct kexalg *k;
123 141
124 for (k = kexalgs; k->name != NULL; k++) { 142 for (k = algs; k->name != NULL; k++) {
125 if (ret != NULL) 143 if (ret != NULL)
126 ret[rlen++] = sep; 144 ret[rlen++] = sep;
127 nlen = strlen(k->name); 145 nlen = strlen(k->name);
@@ -136,6 +154,18 @@ kex_alg_list(char sep)
136 return ret; 154 return ret;
137} 155}
138 156
157char *
158kex_alg_list(char sep)
159{
160 return kex_alg_list_internal(sep, kexalgs);
161}
162
163char *
164kex_gss_alg_list(char sep)
165{
166 return kex_alg_list_internal(sep, gss_kexalgs);
167}
168
139static const struct kexalg * 169static const struct kexalg *
140kex_alg_by_name(const char *name) 170kex_alg_by_name(const char *name)
141{ 171{
@@ -145,6 +175,10 @@ kex_alg_by_name(const char *name)
145 if (strcmp(k->name, name) == 0) 175 if (strcmp(k->name, name) == 0)
146 return k; 176 return k;
147 } 177 }
178 for (k = gss_kexalgs; k->name != NULL; k++) {
179 if (strncmp(k->name, name, strlen(k->name)) == 0)
180 return k;
181 }
148 return NULL; 182 return NULL;
149} 183}
150 184
@@ -313,6 +347,29 @@ kex_assemble_names(char **listp, const char *def, const char *all)
313 return r; 347 return r;
314} 348}
315 349
350/* Validate GSS KEX method name list */
351int
352kex_gss_names_valid(const char *names)
353{
354 char *s, *cp, *p;
355
356 if (names == NULL || *names == '\0')
357 return 0;
358 s = cp = xstrdup(names);
359 for ((p = strsep(&cp, ",")); p && *p != '\0';
360 (p = strsep(&cp, ","))) {
361 if (strncmp(p, "gss-", 4) != 0
362 || kex_alg_by_name(p) == NULL) {
363 error("Unsupported KEX algorithm \"%.100s\"", p);
364 free(s);
365 return 0;
366 }
367 }
368 debug3("gss kex names ok: [%s]", names);
369 free(s);
370 return 1;
371}
372
316/* put algorithm proposal into buffer */ 373/* put algorithm proposal into buffer */
317int 374int
318kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) 375kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
@@ -696,6 +753,9 @@ kex_free(struct kex *kex)
696 sshbuf_free(kex->server_version); 753 sshbuf_free(kex->server_version);
697 sshbuf_free(kex->client_pub); 754 sshbuf_free(kex->client_pub);
698 free(kex->session_id); 755 free(kex->session_id);
756#ifdef GSSAPI
757 free(kex->gss_host);
758#endif /* GSSAPI */
699 free(kex->failed_choice); 759 free(kex->failed_choice);
700 free(kex->hostkey_alg); 760 free(kex->hostkey_alg);
701 free(kex->name); 761 free(kex->name);