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>2020-02-21 12:01:36 +0000
commit34aff3aa136e5a65f441b25811dd466488fda087 (patch)
treee2170faeed03d67545255d3d3c9d62280414c0b2 /kex.c
parentf0de78bd4f29fa688c5df116f3f9cd43543a76d0 (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: 2020-02-21 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 ce85f0439..574c76093 100644
--- a/kex.c
+++ b/kex.c
@@ -57,11 +57,16 @@
57#include "misc.h" 57#include "misc.h"
58#include "dispatch.h" 58#include "dispatch.h"
59#include "monitor.h" 59#include "monitor.h"
60#include "xmalloc.h"
60 61
61#include "ssherr.h" 62#include "ssherr.h"
62#include "sshbuf.h" 63#include "sshbuf.h"
63#include "digest.h" 64#include "digest.h"
64 65
66#ifdef GSSAPI
67#include "ssh-gss.h"
68#endif
69
65/* prototype */ 70/* prototype */
66static int kex_choose_conf(struct ssh *); 71static int kex_choose_conf(struct ssh *);
67static int kex_input_newkeys(int, u_int32_t, struct ssh *); 72static int kex_input_newkeys(int, u_int32_t, struct ssh *);
@@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = {
115#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ 120#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
116 { NULL, 0, -1, -1}, 121 { NULL, 0, -1, -1},
117}; 122};
123static const struct kexalg gss_kexalgs[] = {
124#ifdef GSSAPI
125 { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
126 { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
127 { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
128 { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
129 { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
130 { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256,
131 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
132 { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
133#endif
134 { NULL, 0, -1, -1},
135};
118 136
119char * 137static char *
120kex_alg_list(char sep) 138kex_alg_list_internal(char sep, const struct kexalg *algs)
121{ 139{
122 char *ret = NULL, *tmp; 140 char *ret = NULL, *tmp;
123 size_t nlen, rlen = 0; 141 size_t nlen, rlen = 0;
124 const struct kexalg *k; 142 const struct kexalg *k;
125 143
126 for (k = kexalgs; k->name != NULL; k++) { 144 for (k = algs; k->name != NULL; k++) {
127 if (ret != NULL) 145 if (ret != NULL)
128 ret[rlen++] = sep; 146 ret[rlen++] = sep;
129 nlen = strlen(k->name); 147 nlen = strlen(k->name);
@@ -138,6 +156,18 @@ kex_alg_list(char sep)
138 return ret; 156 return ret;
139} 157}
140 158
159char *
160kex_alg_list(char sep)
161{
162 return kex_alg_list_internal(sep, kexalgs);
163}
164
165char *
166kex_gss_alg_list(char sep)
167{
168 return kex_alg_list_internal(sep, gss_kexalgs);
169}
170
141static const struct kexalg * 171static const struct kexalg *
142kex_alg_by_name(const char *name) 172kex_alg_by_name(const char *name)
143{ 173{
@@ -147,6 +177,10 @@ kex_alg_by_name(const char *name)
147 if (strcmp(k->name, name) == 0) 177 if (strcmp(k->name, name) == 0)
148 return k; 178 return k;
149 } 179 }
180 for (k = gss_kexalgs; k->name != NULL; k++) {
181 if (strncmp(k->name, name, strlen(k->name)) == 0)
182 return k;
183 }
150 return NULL; 184 return NULL;
151} 185}
152 186
@@ -315,6 +349,29 @@ kex_assemble_names(char **listp, const char *def, const char *all)
315 return r; 349 return r;
316} 350}
317 351
352/* Validate GSS KEX method name list */
353int
354kex_gss_names_valid(const char *names)
355{
356 char *s, *cp, *p;
357
358 if (names == NULL || *names == '\0')
359 return 0;
360 s = cp = xstrdup(names);
361 for ((p = strsep(&cp, ",")); p && *p != '\0';
362 (p = strsep(&cp, ","))) {
363 if (strncmp(p, "gss-", 4) != 0
364 || kex_alg_by_name(p) == NULL) {
365 error("Unsupported KEX algorithm \"%.100s\"", p);
366 free(s);
367 return 0;
368 }
369 }
370 debug3("gss kex names ok: [%s]", names);
371 free(s);
372 return 1;
373}
374
318/* put algorithm proposal into buffer */ 375/* put algorithm proposal into buffer */
319int 376int
320kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) 377kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
@@ -698,6 +755,9 @@ kex_free(struct kex *kex)
698 sshbuf_free(kex->server_version); 755 sshbuf_free(kex->server_version);
699 sshbuf_free(kex->client_pub); 756 sshbuf_free(kex->client_pub);
700 free(kex->session_id); 757 free(kex->session_id);
758#ifdef GSSAPI
759 free(kex->gss_host);
760#endif /* GSSAPI */
701 free(kex->failed_choice); 761 free(kex->failed_choice);
702 free(kex->hostkey_alg); 762 free(kex->hostkey_alg);
703 free(kex->name); 763 free(kex->name);