|
1 # |
|
2 # GSS-API key exchange support |
|
3 # |
|
4 # Based on https://github.com/SimonWilkinson/gss-openssh/commit/ffae842 |
|
5 # Updated to apply to OpenSSH 6.5. |
|
6 # Default value for GSSAPIKeyExchange changed to yes to match SunSSH behavior. |
|
7 # New files kexgssc.c and kexgsss.c moved to ../sources/ and made cstyle clean. |
|
8 # |
|
9 # Upstream rejected GSS-API key exchange several times before. |
|
10 # |
|
11 diff -pur old/Makefile.in new/Makefile.in |
|
12 --- old/Makefile.in 2014-11-19 08:19:53.525006324 -0800 |
|
13 +++ new/Makefile.in 2014-11-19 08:28:29.235999361 -0800 |
|
14 @@ -72,6 +72,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o |
|
15 atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ |
|
16 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ |
|
17 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ |
|
18 + kexgssc.o \ |
|
19 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ |
|
20 jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ |
|
21 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ |
|
22 @@ -92,7 +93,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw |
|
23 auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ |
|
24 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ |
|
25 kexc25519s.o auth-krb5.o \ |
|
26 - auth2-gss.o gss-serv.o gss-serv-krb5.o \ |
|
27 + auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ |
|
28 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ |
|
29 sftp-server.o sftp-common.o \ |
|
30 roaming_common.o roaming_serv.o \ |
|
31 Only in new/: Makefile.in.orig |
|
32 Only in new/: Makefile.in.rej |
|
33 diff -pur old/auth2-gss.c new/auth2-gss.c |
|
34 --- old/auth2-gss.c 2014-11-19 08:19:53.432431374 -0800 |
|
35 +++ new/auth2-gss.c 2014-11-20 07:46:37.640415003 -0800 |
|
36 @@ -1,7 +1,7 @@ |
|
37 /* $OpenBSD: auth2-gss.c,v 1.20 2013/05/17 00:13:13 djm Exp $ */ |
|
38 |
|
39 /* |
|
40 - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. |
|
41 + * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. |
|
42 * |
|
43 * Redistribution and use in source and binary forms, with or without |
|
44 * modification, are permitted provided that the following conditions |
|
45 @@ -56,6 +56,39 @@ static void input_gssapi_mic(int type, u |
|
46 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); |
|
47 static void input_gssapi_errtok(int, u_int32_t, void *); |
|
48 |
|
49 +/* |
|
50 + * The 'gssapi_keyex' userauth mechanism. |
|
51 + */ |
|
52 +static int |
|
53 +userauth_gsskeyex(Authctxt *authctxt) |
|
54 +{ |
|
55 + int authenticated = 0; |
|
56 + Buffer b; |
|
57 + gss_buffer_desc mic, gssbuf; |
|
58 + u_int len; |
|
59 + |
|
60 + mic.value = packet_get_string(&len); |
|
61 + mic.length = len; |
|
62 + |
|
63 + packet_check_eom(); |
|
64 + |
|
65 + ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, |
|
66 + "gssapi-keyex"); |
|
67 + |
|
68 + gssbuf.value = buffer_ptr(&b); |
|
69 + gssbuf.length = buffer_len(&b); |
|
70 + |
|
71 + /* gss_kex_context is NULL with privsep, so we can't check it here */ |
|
72 + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, |
|
73 + &gssbuf, &mic)))) |
|
74 + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); |
|
75 + |
|
76 + buffer_free(&b); |
|
77 + free(mic.value); |
|
78 + |
|
79 + return (authenticated); |
|
80 +} |
|
81 + |
|
82 /* |
|
83 * We only support those mechanisms that we know about (ie ones that we know |
|
84 * how to check local user kuserok and the like) |
|
85 @@ -300,6 +333,12 @@ input_gssapi_mic(int type, u_int32_t ple |
|
86 userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); |
|
87 } |
|
88 |
|
89 +Authmethod method_gsskeyex = { |
|
90 + "gssapi-keyex", |
|
91 + userauth_gsskeyex, |
|
92 + &options.gss_authentication |
|
93 +}; |
|
94 + |
|
95 Authmethod method_gssapi = { |
|
96 "gssapi-with-mic", |
|
97 userauth_gssapi, |
|
98 Only in new/: auth2-gss.c.orig |
|
99 Only in new/: auth2-gss.c~ |
|
100 diff -pur old/auth2.c new/auth2.c |
|
101 --- old/auth2.c 2014-11-19 08:19:53.555080638 -0800 |
|
102 +++ new/auth2.c 2014-11-19 08:19:53.614409503 -0800 |
|
103 @@ -69,6 +69,7 @@ extern Authmethod method_passwd; |
|
104 extern Authmethod method_kbdint; |
|
105 extern Authmethod method_hostbased; |
|
106 #ifdef GSSAPI |
|
107 +extern Authmethod method_gsskeyex; |
|
108 extern Authmethod method_gssapi; |
|
109 #endif |
|
110 #ifdef JPAKE |
|
111 @@ -79,6 +80,7 @@ Authmethod *authmethods[] = { |
|
112 &method_none, |
|
113 &method_pubkey, |
|
114 #ifdef GSSAPI |
|
115 + &method_gsskeyex, |
|
116 &method_gssapi, |
|
117 #endif |
|
118 #ifdef JPAKE |
|
119 diff -pur old/gss-genr.c new/gss-genr.c |
|
120 --- old/gss-genr.c 2013-11-07 17:19:57.000000000 -0800 |
|
121 +++ new/gss-genr.c 2014-11-20 04:06:38.323380064 -0800 |
|
122 @@ -1,7 +1,7 @@ |
|
123 /* $OpenBSD: gss-genr.c,v 1.22 2013/11/08 00:39:15 djm Exp $ */ |
|
124 |
|
125 /* |
|
126 - * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. |
|
127 + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. |
|
128 * |
|
129 * Redistribution and use in source and binary forms, with or without |
|
130 * modification, are permitted provided that the following conditions |
|
131 @@ -39,12 +39,167 @@ |
|
132 #include "buffer.h" |
|
133 #include "log.h" |
|
134 #include "ssh2.h" |
|
135 +#include "cipher.h" |
|
136 +#include "key.h" |
|
137 +#include "kex.h" |
|
138 +#include <openssl/evp.h> |
|
139 |
|
140 #include "ssh-gss.h" |
|
141 |
|
142 extern u_char *session_id2; |
|
143 extern u_int session_id2_len; |
|
144 |
|
145 +typedef struct { |
|
146 + char *encoded; |
|
147 + gss_OID oid; |
|
148 +} ssh_gss_kex_mapping; |
|
149 + |
|
150 +/* |
|
151 + * XXX - It would be nice to find a more elegant way of handling the |
|
152 + * XXX passing of the key exchange context to the userauth routines |
|
153 + */ |
|
154 + |
|
155 +Gssctxt *gss_kex_context = NULL; |
|
156 + |
|
157 +static ssh_gss_kex_mapping *gss_enc2oid = NULL; |
|
158 + |
|
159 +int |
|
160 +ssh_gssapi_oid_table_ok() { |
|
161 + return (gss_enc2oid != NULL); |
|
162 +} |
|
163 + |
|
164 +/* |
|
165 + * Return a list of the gss-group1-sha1 mechanisms supported by this program |
|
166 + * |
|
167 + * We test mechanisms to ensure that we can use them, to avoid starting |
|
168 + * a key exchange with a bad mechanism |
|
169 + */ |
|
170 + |
|
171 +char * |
|
172 +ssh_gssapi_client_mechanisms(const char *host) { |
|
173 + gss_OID_set gss_supported; |
|
174 + OM_uint32 min_status; |
|
175 + |
|
176 + if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) |
|
177 + return NULL; |
|
178 + |
|
179 + return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, |
|
180 + host)); |
|
181 +} |
|
182 + |
|
183 +char * |
|
184 +ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, |
|
185 + const char *data) { |
|
186 + Buffer buf; |
|
187 + size_t i; |
|
188 + int oidpos, enclen; |
|
189 + char *mechs, *encoded; |
|
190 + u_char digest[EVP_MAX_MD_SIZE]; |
|
191 + char deroid[2]; |
|
192 + const EVP_MD *evp_md = EVP_md5(); |
|
193 + EVP_MD_CTX md; |
|
194 + |
|
195 + if (gss_enc2oid != NULL) { |
|
196 + for (i = 0; gss_enc2oid[i].encoded != NULL; i++) |
|
197 + free(gss_enc2oid[i].encoded); |
|
198 + free(gss_enc2oid); |
|
199 + } |
|
200 + |
|
201 + gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * |
|
202 + (gss_supported->count + 1)); |
|
203 + |
|
204 + buffer_init(&buf); |
|
205 + |
|
206 + oidpos = 0; |
|
207 + for (i = 0; i < gss_supported->count; i++) { |
|
208 + if (gss_supported->elements[i].length < 128 && |
|
209 + (*check)(NULL, &(gss_supported->elements[i]), data)) { |
|
210 + |
|
211 + deroid[0] = SSH_GSS_OIDTYPE; |
|
212 + deroid[1] = gss_supported->elements[i].length; |
|
213 + |
|
214 + EVP_DigestInit(&md, evp_md); |
|
215 + EVP_DigestUpdate(&md, deroid, 2); |
|
216 + EVP_DigestUpdate(&md, |
|
217 + gss_supported->elements[i].elements, |
|
218 + gss_supported->elements[i].length); |
|
219 + EVP_DigestFinal(&md, digest, NULL); |
|
220 + |
|
221 + encoded = xmalloc(EVP_MD_size(evp_md) * 2); |
|
222 + enclen = __b64_ntop(digest, EVP_MD_size(evp_md), |
|
223 + encoded, EVP_MD_size(evp_md) * 2); |
|
224 + |
|
225 + if (oidpos != 0) |
|
226 + buffer_put_char(&buf, ','); |
|
227 + |
|
228 + buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, |
|
229 + sizeof(KEX_GSS_GEX_SHA1_ID) - 1); |
|
230 + buffer_append(&buf, encoded, enclen); |
|
231 + buffer_put_char(&buf, ','); |
|
232 + buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, |
|
233 + sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); |
|
234 + buffer_append(&buf, encoded, enclen); |
|
235 + buffer_put_char(&buf, ','); |
|
236 + buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, |
|
237 + sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); |
|
238 + buffer_append(&buf, encoded, enclen); |
|
239 + |
|
240 + gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); |
|
241 + gss_enc2oid[oidpos].encoded = encoded; |
|
242 + oidpos++; |
|
243 + } |
|
244 + } |
|
245 + gss_enc2oid[oidpos].oid = NULL; |
|
246 + gss_enc2oid[oidpos].encoded = NULL; |
|
247 + |
|
248 + buffer_put_char(&buf, '\0'); |
|
249 + |
|
250 + mechs = xmalloc(buffer_len(&buf)); |
|
251 + buffer_get(&buf, mechs, buffer_len(&buf)); |
|
252 + buffer_free(&buf); |
|
253 + |
|
254 + if (strlen(mechs) == 0) { |
|
255 + free(mechs); |
|
256 + mechs = NULL; |
|
257 + } |
|
258 + |
|
259 + return (mechs); |
|
260 +} |
|
261 + |
|
262 +gss_OID |
|
263 +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { |
|
264 + int i = 0; |
|
265 + |
|
266 + switch (kex_type) { |
|
267 + case KEX_GSS_GRP1_SHA1: |
|
268 + if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) |
|
269 + return GSS_C_NO_OID; |
|
270 + name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; |
|
271 + break; |
|
272 + case KEX_GSS_GRP14_SHA1: |
|
273 + if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) |
|
274 + return GSS_C_NO_OID; |
|
275 + name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; |
|
276 + break; |
|
277 + case KEX_GSS_GEX_SHA1: |
|
278 + if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) |
|
279 + return GSS_C_NO_OID; |
|
280 + name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; |
|
281 + break; |
|
282 + default: |
|
283 + return GSS_C_NO_OID; |
|
284 + } |
|
285 + |
|
286 + while (gss_enc2oid[i].encoded != NULL && |
|
287 + strcmp(name, gss_enc2oid[i].encoded) != 0) |
|
288 + i++; |
|
289 + |
|
290 + if (gss_enc2oid[i].oid != NULL && ctx != NULL) |
|
291 + ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); |
|
292 + |
|
293 + return gss_enc2oid[i].oid; |
|
294 +} |
|
295 + |
|
296 /* Check that the OID in a data stream matches that in the context */ |
|
297 int |
|
298 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) |
|
299 @@ -229,6 +384,9 @@ ssh_gssapi_import_name(Gssctxt *ctx, con |
|
300 OM_uint32 |
|
301 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) |
|
302 { |
|
303 + if (ctx == NULL) |
|
304 + return -1; |
|
305 + |
|
306 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, |
|
307 GSS_C_QOP_DEFAULT, buffer, hash))) |
|
308 ssh_gssapi_error(ctx); |
|
309 @@ -236,6 +394,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer |
|
310 return (ctx->major); |
|
311 } |
|
312 |
|
313 +/* Priviledged when used by server */ |
|
314 +OM_uint32 |
|
315 +ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) |
|
316 +{ |
|
317 + if (ctx == NULL) |
|
318 + return -1; |
|
319 + |
|
320 + ctx->major = gss_verify_mic(&ctx->minor, ctx->context, |
|
321 + gssbuf, gssmic, NULL); |
|
322 + |
|
323 + return (ctx->major); |
|
324 +} |
|
325 + |
|
326 void |
|
327 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, |
|
328 const char *context) |
|
329 @@ -254,6 +425,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx |
|
330 gss_buffer_desc token = GSS_C_EMPTY_BUFFER; |
|
331 OM_uint32 major, minor; |
|
332 gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; |
|
333 + Gssctxt *intctx = NULL; |
|
334 + |
|
335 + if (ctx == NULL) |
|
336 + ctx = &intctx; |
|
337 |
|
338 /* RFC 4462 says we MUST NOT do SPNEGO */ |
|
339 if (oid->length == spnego_oid.length && |
|
340 @@ -272,7 +447,7 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx |
|
341 GSS_C_NO_BUFFER); |
|
342 } |
|
343 |
|
344 - if (GSS_ERROR(major)) |
|
345 + if (GSS_ERROR(major) || intctx != NULL) |
|
346 ssh_gssapi_delete_ctx(ctx); |
|
347 |
|
348 return (!GSS_ERROR(major)); |
|
349 Only in new/: gss-genr.c.orig |
|
350 Only in new/: gss-genr.c~ |
|
351 diff -pur old/gss-serv.c new/gss-serv.c |
|
352 --- old/gss-serv.c 2014-11-19 08:19:53.495994604 -0800 |
|
353 +++ new/gss-serv.c 2014-11-19 08:19:53.614894916 -0800 |
|
354 @@ -1,7 +1,7 @@ |
|
355 /* $OpenBSD: gss-serv.c,v 1.24 2013/07/20 01:55:13 djm Exp $ */ |
|
356 |
|
357 /* |
|
358 - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. |
|
359 + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. |
|
360 * |
|
361 * Redistribution and use in source and binary forms, with or without |
|
362 * modification, are permitted provided that the following conditions |
|
363 @@ -47,6 +47,7 @@ |
|
364 #include "misc.h" |
|
365 |
|
366 #include "ssh-gss.h" |
|
367 +#include "monitor_wrap.h" |
|
368 |
|
369 static ssh_gssapi_client gssapi_client = |
|
370 { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, |
|
371 @@ -114,6 +115,28 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss |
|
372 } |
|
373 |
|
374 /* Unprivileged */ |
|
375 +char * |
|
376 +ssh_gssapi_server_mechanisms() { |
|
377 + gss_OID_set supported; |
|
378 + |
|
379 + ssh_gssapi_supported_oids(&supported); |
|
380 + return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, |
|
381 + NULL)); |
|
382 +} |
|
383 + |
|
384 +/* Unprivileged */ |
|
385 +int |
|
386 +ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data) { |
|
387 + Gssctxt *ctx = NULL; |
|
388 + int res; |
|
389 + |
|
390 + res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); |
|
391 + ssh_gssapi_delete_ctx(&ctx); |
|
392 + |
|
393 + return (res); |
|
394 +} |
|
395 + |
|
396 +/* Unprivileged */ |
|
397 void |
|
398 ssh_gssapi_supported_oids(gss_OID_set *oidset) |
|
399 { |
|
400 @@ -123,7 +146,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o |
|
401 gss_OID_set supported; |
|
402 |
|
403 gss_create_empty_oid_set(&min_status, oidset); |
|
404 - gss_indicate_mechs(&min_status, &supported); |
|
405 + |
|
406 + if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) |
|
407 + return; |
|
408 |
|
409 while (supported_mechs[i]->name != NULL) { |
|
410 if (GSS_ERROR(gss_test_oid_set_member(&min_status, |
|
411 @@ -398,14 +423,4 @@ ssh_gssapi_userok(char *user) |
|
412 return (0); |
|
413 } |
|
414 |
|
415 -/* Privileged */ |
|
416 -OM_uint32 |
|
417 -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) |
|
418 -{ |
|
419 - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, |
|
420 - gssbuf, gssmic, NULL); |
|
421 - |
|
422 - return (ctx->major); |
|
423 -} |
|
424 - |
|
425 #endif |
|
426 Only in new/: gss-serv.c.orig |
|
427 diff -pur old/kex.c new/kex.c |
|
428 --- old/kex.c 2014-01-25 14:38:04.000000000 -0800 |
|
429 +++ new/kex.c 2014-11-20 06:10:14.432397588 -0800 |
|
430 @@ -51,6 +51,10 @@ |
|
431 #include "roaming.h" |
|
432 #include "digest.h" |
|
433 |
|
434 +#ifdef GSSAPI |
|
435 +#include "ssh-gss.h" |
|
436 +#endif |
|
437 + |
|
438 #if OPENSSL_VERSION_NUMBER >= 0x00907000L |
|
439 # if defined(HAVE_EVP_SHA256) |
|
440 # define evp_ssh_sha256 EVP_sha256 |
|
441 @@ -90,6 +94,11 @@ static const struct kexalg kexalgs[] = { |
|
442 #ifdef HAVE_EVP_SHA256 |
|
443 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, |
|
444 #endif |
|
445 +#ifdef GSSAPI |
|
446 + { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, |
|
447 + { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, |
|
448 + { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, |
|
449 +#endif |
|
450 { NULL, -1, -1, -1}, |
|
451 }; |
|
452 |
|
453 @@ -117,7 +126,7 @@ kex_alg_by_name(const char *name) |
|
454 const struct kexalg *k; |
|
455 |
|
456 for (k = kexalgs; k->name != NULL; k++) { |
|
457 - if (strcmp(k->name, name) == 0) |
|
458 + if (strncmp(k->name, name, strlen(k->name)) == 0) |
|
459 return k; |
|
460 } |
|
461 return NULL; |
|
462 Only in new/: kex.c.orig |
|
463 Only in new/: kex.c.rej |
|
464 Only in new/: kex.c~ |
|
465 diff -pur old/kex.h new/kex.h |
|
466 --- old/kex.h 2014-01-25 14:37:26.000000000 -0800 |
|
467 +++ new/kex.h 2014-11-20 00:26:26.185459758 -0800 |
|
468 @@ -76,6 +76,9 @@ enum kex_exchange { |
|
469 KEX_DH_GEX_SHA256, |
|
470 KEX_ECDH_SHA2, |
|
471 KEX_C25519_SHA256, |
|
472 + KEX_GSS_GRP1_SHA1, |
|
473 + KEX_GSS_GRP14_SHA1, |
|
474 + KEX_GSS_GEX_SHA1, |
|
475 KEX_MAX |
|
476 }; |
|
477 |
|
478 @@ -136,6 +139,10 @@ struct Kex { |
|
479 int flags; |
|
480 int hash_alg; |
|
481 int ec_nid; |
|
482 +#ifdef GSSAPI |
|
483 + int gss_deleg_creds; |
|
484 + char *gss_host; |
|
485 +#endif |
|
486 char *client_version_string; |
|
487 char *server_version_string; |
|
488 int (*verify_host_key)(Key *); |
|
489 @@ -168,6 +175,11 @@ void kexecdh_server(Kex *); |
|
490 void kexc25519_client(Kex *); |
|
491 void kexc25519_server(Kex *); |
|
492 |
|
493 +#ifdef GSSAPI |
|
494 +void kexgss_client(Kex *); |
|
495 +void kexgss_server(Kex *); |
|
496 +#endif |
|
497 + |
|
498 void |
|
499 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, |
|
500 BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); |
|
501 Only in new/: kex.h.orig |
|
502 Only in new/: kex.h.rej |
|
503 Only in new/: kex.h~ |
|
504 Only in new/: kexgssc.c |
|
505 Only in new/: kexgssc.c~ |
|
506 Only in new/: kexgsss.c |
|
507 Only in new/: kexgsss.c~ |
|
508 diff -pur old/key.c new/key.c |
|
509 --- old/key.c 2014-01-09 15:58:53.000000000 -0800 |
|
510 +++ new/key.c 2014-11-19 11:03:01.227859791 -0800 |
|
511 @@ -985,6 +985,7 @@ static const struct keytype keytypes[] = |
|
512 KEY_DSA_CERT_V00, 0, 1 }, |
|
513 { "[email protected]", "ED25519-CERT", |
|
514 KEY_ED25519_CERT, 0, 1 }, |
|
515 + { "null", "null", KEY_NULL, 0, 0 }, |
|
516 { NULL, NULL, -1, -1, 0 } |
|
517 }; |
|
518 |
|
519 Only in new/: key.c.orig |
|
520 Only in new/: key.c.rej |
|
521 Only in new/: key.c~ |
|
522 diff -pur old/key.h new/key.h |
|
523 --- old/key.h 2014-01-09 15:58:53.000000000 -0800 |
|
524 +++ new/key.h 2014-11-19 08:19:53.616502306 -0800 |
|
525 @@ -46,6 +46,7 @@ enum types { |
|
526 KEY_ED25519_CERT, |
|
527 KEY_RSA_CERT_V00, |
|
528 KEY_DSA_CERT_V00, |
|
529 + KEY_NULL, |
|
530 KEY_UNSPEC |
|
531 }; |
|
532 enum fp_type { |
|
533 Only in new/: key.h.orig |
|
534 diff -pur old/monitor.c new/monitor.c |
|
535 --- old/monitor.c 2014-11-19 08:19:53.555737643 -0800 |
|
536 +++ new/monitor.c 2014-11-20 04:07:05.882669648 -0800 |
|
537 @@ -184,6 +184,7 @@ int mm_answer_gss_setup_ctx(int, Buffer |
|
538 int mm_answer_gss_accept_ctx(int, Buffer *); |
|
539 int mm_answer_gss_userok(int, Buffer *); |
|
540 int mm_answer_gss_checkmic(int, Buffer *); |
|
541 +int mm_answer_gss_sign(int, Buffer *); |
|
542 #endif |
|
543 |
|
544 #ifdef SSH_AUDIT_EVENTS |
|
545 @@ -263,6 +264,7 @@ struct mon_table mon_dispatch_proto20[] |
|
546 {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, |
|
547 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, |
|
548 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, |
|
549 + {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, |
|
550 #endif |
|
551 #ifdef JPAKE |
|
552 {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, |
|
553 @@ -275,6 +277,11 @@ struct mon_table mon_dispatch_proto20[] |
|
554 }; |
|
555 |
|
556 struct mon_table mon_dispatch_postauth20[] = { |
|
557 +#ifdef GSSAPI |
|
558 + {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, |
|
559 + {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, |
|
560 + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, |
|
561 +#endif |
|
562 {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, |
|
563 {MONITOR_REQ_SIGN, 0, mm_answer_sign}, |
|
564 {MONITOR_REQ_PTY, 0, mm_answer_pty}, |
|
565 @@ -383,6 +390,10 @@ monitor_child_preauth(Authctxt *_authctx |
|
566 /* Permit requests for moduli and signatures */ |
|
567 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
|
568 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
|
569 +#ifdef GSSAPI |
|
570 + /* and for the GSSAPI key exchange */ |
|
571 + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); |
|
572 +#endif |
|
573 } else { |
|
574 mon_dispatch = mon_dispatch_proto15; |
|
575 |
|
576 @@ -497,6 +508,10 @@ monitor_child_postauth(struct monitor *p |
|
577 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
|
578 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
|
579 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
|
580 +#ifdef GSSAPI |
|
581 + /* and for the GSSAPI key exchange */ |
|
582 + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); |
|
583 +#endif |
|
584 } else { |
|
585 mon_dispatch = mon_dispatch_postauth15; |
|
586 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
|
587 @@ -1888,6 +1903,13 @@ mm_get_kex(Buffer *m) |
|
588 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
|
589 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
|
590 kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
|
591 +#ifdef GSSAPI |
|
592 + if (options.gss_keyex) { |
|
593 + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; |
|
594 + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; |
|
595 + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; |
|
596 + } |
|
597 +#endif |
|
598 kex->server = 1; |
|
599 kex->hostkey_type = buffer_get_int(m); |
|
600 kex->kex_type = buffer_get_int(m); |
|
601 @@ -2095,6 +2117,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer |
|
602 OM_uint32 major; |
|
603 u_int len; |
|
604 |
|
605 + if (!options.gss_authentication && !options.gss_keyex) |
|
606 + fatal("In GSSAPI monitor when GSSAPI is disabled"); |
|
607 + |
|
608 goid.elements = buffer_get_string(m, &len); |
|
609 goid.length = len; |
|
610 |
|
611 @@ -2122,6 +2147,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe |
|
612 OM_uint32 flags = 0; /* GSI needs this */ |
|
613 u_int len; |
|
614 |
|
615 + if (!options.gss_authentication && !options.gss_keyex) |
|
616 + fatal("In GSSAPI monitor when GSSAPI is disabled"); |
|
617 + |
|
618 in.value = buffer_get_string(m, &len); |
|
619 in.length = len; |
|
620 major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); |
|
621 @@ -2139,6 +2167,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe |
|
622 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); |
|
623 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); |
|
624 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); |
|
625 + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); |
|
626 } |
|
627 return (0); |
|
628 } |
|
629 @@ -2150,6 +2179,9 @@ mm_answer_gss_checkmic(int sock, Buffer |
|
630 OM_uint32 ret; |
|
631 u_int len; |
|
632 |
|
633 + if (!options.gss_authentication && !options.gss_keyex) |
|
634 + fatal("In GSSAPI monitor when GSSAPI is disabled"); |
|
635 + |
|
636 gssbuf.value = buffer_get_string(m, &len); |
|
637 gssbuf.length = len; |
|
638 mic.value = buffer_get_string(m, &len); |
|
639 @@ -2176,6 +2208,9 @@ mm_answer_gss_userok(int sock, Buffer *m |
|
640 { |
|
641 int authenticated; |
|
642 |
|
643 + if (!options.gss_authentication && !options.gss_keyex) |
|
644 + fatal("In GSSAPI monitor when GSSAPI is disabled"); |
|
645 + |
|
646 authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); |
|
647 |
|
648 buffer_clear(m); |
|
649 @@ -2189,6 +2224,48 @@ mm_answer_gss_userok(int sock, Buffer *m |
|
650 /* Monitor loop will terminate if authenticated */ |
|
651 return (authenticated); |
|
652 } |
|
653 + |
|
654 +int |
|
655 +mm_answer_gss_sign(int socket, Buffer *m) |
|
656 +{ |
|
657 + gss_buffer_desc data; |
|
658 + gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; |
|
659 + OM_uint32 major, minor; |
|
660 + u_int len; |
|
661 + |
|
662 + if (!options.gss_authentication && !options.gss_keyex) |
|
663 + fatal("In GSSAPI monitor when GSSAPI is disabled"); |
|
664 + |
|
665 + data.value = buffer_get_string(m, &len); |
|
666 + data.length = len; |
|
667 + if (data.length != 20) |
|
668 + fatal("%s: data length incorrect: %d", __func__, |
|
669 + (int) data.length); |
|
670 + |
|
671 + /* Save the session ID on the first time around */ |
|
672 + if (session_id2_len == 0) { |
|
673 + session_id2_len = data.length; |
|
674 + session_id2 = xmalloc(session_id2_len); |
|
675 + memcpy(session_id2, data.value, session_id2_len); |
|
676 + } |
|
677 + major = ssh_gssapi_sign(gsscontext, &data, &hash); |
|
678 + |
|
679 + free(data.value); |
|
680 + |
|
681 + buffer_clear(m); |
|
682 + buffer_put_int(m, major); |
|
683 + buffer_put_string(m, hash.value, hash.length); |
|
684 + |
|
685 + mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); |
|
686 + |
|
687 + gss_release_buffer(&minor, &hash); |
|
688 + |
|
689 + /* Turn on getpwnam permissions */ |
|
690 + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); |
|
691 + |
|
692 + return (0); |
|
693 +} |
|
694 + |
|
695 #endif /* GSSAPI */ |
|
696 |
|
697 #ifdef JPAKE |
|
698 Only in new/: monitor.c.orig |
|
699 Only in new/: monitor.c.rej |
|
700 Only in new/: monitor.c~ |
|
701 diff -pur old/monitor.h new/monitor.h |
|
702 --- old/monitor.h 2014-11-19 08:19:53.555841204 -0800 |
|
703 +++ new/monitor.h 2014-11-19 09:27:51.185925631 -0800 |
|
704 @@ -73,6 +73,9 @@ enum monitor_reqtype { |
|
705 #ifdef PAM_ENHANCEMENT |
|
706 MONITOR_REQ_AUTHMETHOD = 114, |
|
707 #endif |
|
708 +#ifdef GSSAPI |
|
709 + MONITOR_REQ_GSSSIGN = 130, MONITOR_ANS_GSSSIGN = 131, |
|
710 +#endif |
|
711 }; |
|
712 |
|
713 struct mm_master; |
|
714 Only in new/: monitor.h.orig |
|
715 Only in new/: monitor.h.rej |
|
716 diff -pur old/monitor_wrap.c new/monitor_wrap.c |
|
717 --- old/monitor_wrap.c 2014-11-19 08:19:53.555313040 -0800 |
|
718 +++ new/monitor_wrap.c 2014-11-19 08:19:53.617470451 -0800 |
|
719 @@ -1308,6 +1308,29 @@ mm_ssh_gssapi_userok(char *user) |
|
720 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); |
|
721 return (authenticated); |
|
722 } |
|
723 + |
|
724 +OM_uint32 |
|
725 +mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) |
|
726 +{ |
|
727 + Buffer m; |
|
728 + OM_uint32 major; |
|
729 + u_int len; |
|
730 + |
|
731 + buffer_init(&m); |
|
732 + buffer_put_string(&m, data->value, data->length); |
|
733 + |
|
734 + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); |
|
735 + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); |
|
736 + |
|
737 + major = buffer_get_int(&m); |
|
738 + hash->value = buffer_get_string(&m, &len); |
|
739 + hash->length = len; |
|
740 + |
|
741 + buffer_free(&m); |
|
742 + |
|
743 + return(major); |
|
744 +} |
|
745 + |
|
746 #endif /* GSSAPI */ |
|
747 |
|
748 #ifdef JPAKE |
|
749 Only in new/: monitor_wrap.c.orig |
|
750 diff -pur old/monitor_wrap.h new/monitor_wrap.h |
|
751 --- old/monitor_wrap.h 2011-06-19 21:42:23.000000000 -0700 |
|
752 +++ new/monitor_wrap.h 2014-11-19 08:19:53.617555551 -0800 |
|
753 @@ -60,6 +60,7 @@ OM_uint32 mm_ssh_gssapi_accept_ctx(Gssct |
|
754 gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); |
|
755 int mm_ssh_gssapi_userok(char *user); |
|
756 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); |
|
757 +OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); |
|
758 #endif |
|
759 |
|
760 #ifdef USE_PAM |
|
761 Only in new/: monitor_wrap.h.orig |
|
762 diff -pur old/readconf.c new/readconf.c |
|
763 --- old/readconf.c 2014-11-19 08:19:53.577815170 -0800 |
|
764 +++ new/readconf.c 2014-11-19 09:42:12.825342175 -0800 |
|
765 @@ -140,6 +140,7 @@ typedef enum { |
|
766 oClearAllForwardings, oNoHostAuthenticationForLocalhost, |
|
767 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, |
|
768 oAddressFamily, oGssAuthentication, oGssDelegateCreds, |
|
769 + oGssKeyEx, |
|
770 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, |
|
771 oSendEnv, oControlPath, oControlMaster, oControlPersist, |
|
772 oHashKnownHosts, |
|
773 @@ -187,9 +188,11 @@ static struct { |
|
774 #if defined(GSSAPI) |
|
775 { "gssapiauthentication", oGssAuthentication }, |
|
776 { "gssapidelegatecredentials", oGssDelegateCreds }, |
|
777 + { "gssapikeyexchange", oGssKeyEx }, |
|
778 #else |
|
779 { "gssapiauthentication", oUnsupported }, |
|
780 { "gssapidelegatecredentials", oUnsupported }, |
|
781 + { "gssapikeyexchange", oUnsupported }, |
|
782 #endif |
|
783 { "fallbacktorsh", oDeprecated }, |
|
784 { "usersh", oDeprecated }, |
|
785 @@ -876,6 +879,10 @@ parse_time: |
|
786 intptr = &options->gss_authentication; |
|
787 goto parse_flag; |
|
788 |
|
789 + case oGssKeyEx: |
|
790 + intptr = &options->gss_keyex; |
|
791 + goto parse_flag; |
|
792 + |
|
793 case oGssDelegateCreds: |
|
794 intptr = &options->gss_deleg_creds; |
|
795 goto parse_flag; |
|
796 @@ -1532,6 +1539,7 @@ initialize_options(Options * options) |
|
797 options->pubkey_authentication = -1; |
|
798 options->challenge_response_authentication = -1; |
|
799 options->gss_authentication = -1; |
|
800 + options->gss_keyex = -1; |
|
801 options->gss_deleg_creds = -1; |
|
802 options->password_authentication = -1; |
|
803 options->kbd_interactive_authentication = -1; |
|
804 @@ -1645,6 +1653,12 @@ fill_default_options(Options * options) |
|
805 #else |
|
806 options->gss_authentication = 0; |
|
807 #endif |
|
808 + if (options->gss_keyex == -1) |
|
809 +#ifdef OPTION_DEFAULT_VALUE |
|
810 + options->gss_keyex = 1; |
|
811 +#else |
|
812 + options->gss_keyex = 0; |
|
813 +#endif |
|
814 if (options->gss_deleg_creds == -1) |
|
815 options->gss_deleg_creds = 0; |
|
816 if (options->password_authentication == -1) |
|
817 Only in new/: readconf.c.orig |
|
818 Only in new/: readconf.c.rej |
|
819 diff -pur old/readconf.h new/readconf.h |
|
820 --- old/readconf.h 2014-11-19 08:19:53.536144272 -0800 |
|
821 +++ new/readconf.h 2014-11-19 08:19:53.618258278 -0800 |
|
822 @@ -54,6 +54,7 @@ typedef struct { |
|
823 int challenge_response_authentication; |
|
824 /* Try S/Key or TIS, authentication. */ |
|
825 int gss_authentication; /* Try GSS authentication */ |
|
826 + int gss_keyex; /* Try GSS key exchange */ |
|
827 int gss_deleg_creds; /* Delegate GSS credentials */ |
|
828 int password_authentication; /* Try password |
|
829 * authentication. */ |
|
830 Only in new/: readconf.h.orig |
|
831 diff -pur old/servconf.c new/servconf.c |
|
832 --- old/servconf.c 2014-11-19 08:19:53.589868411 -0800 |
|
833 +++ new/servconf.c 2014-11-20 04:15:47.500881329 -0800 |
|
834 @@ -108,6 +108,7 @@ initialize_server_options(ServerOptions |
|
835 options->kerberos_ticket_cleanup = -1; |
|
836 options->kerberos_get_afs_token = -1; |
|
837 options->gss_authentication=-1; |
|
838 + options->gss_keyex = -1; |
|
839 options->gss_cleanup_creds = -1; |
|
840 options->password_authentication = -1; |
|
841 options->kbd_interactive_authentication = -1; |
|
842 @@ -258,6 +259,12 @@ fill_default_server_options(ServerOption |
|
843 #else |
|
844 options->gss_authentication = 0; |
|
845 #endif |
|
846 + if (options->gss_keyex == -1) |
|
847 +#ifdef OPTION_DEFAULT_VALUE |
|
848 + options->gss_keyex = 1; |
|
849 +#else |
|
850 + options->gss_keyex = 0; |
|
851 +#endif |
|
852 if (options->gss_cleanup_creds == -1) |
|
853 options->gss_cleanup_creds = 1; |
|
854 if (options->password_authentication == -1) |
|
855 @@ -362,6 +369,7 @@ typedef enum { |
|
856 sBanner, sUseDNS, sHostbasedAuthentication, |
|
857 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, |
|
858 sClientAliveCountMax, sAuthorizedKeysFile, |
|
859 + sGssKeyEx, |
|
860 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, |
|
861 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, |
|
862 sUsePrivilegeSeparation, sAllowAgentForwarding, |
|
863 @@ -431,6 +439,7 @@ static struct { |
|
864 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, |
|
865 #ifdef GSSAPI |
|
866 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, |
|
867 + { "gssapikeyexchange", sGssKeyEx, SSHCFG_ALL }, |
|
868 #ifdef USE_GSS_STORE_CRED |
|
869 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, |
|
870 #else /* USE_GSS_STORE_CRED */ |
|
871 @@ -438,6 +447,7 @@ static struct { |
|
872 #endif /* USE_GSS_STORE_CRED */ |
|
873 #else |
|
874 { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, |
|
875 + { "gssapikeyexchange", sUnsupported, SSHCFG_ALL }, |
|
876 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, |
|
877 #endif |
|
878 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, |
|
879 @@ -1159,6 +1169,10 @@ process_server_config_line(ServerOptions |
|
880 intptr = &options->gss_authentication; |
|
881 goto parse_flag; |
|
882 |
|
883 + case sGssKeyEx: |
|
884 + intptr = &options->gss_keyex; |
|
885 + goto parse_flag; |
|
886 + |
|
887 case sGssCleanupCreds: |
|
888 intptr = &options->gss_cleanup_creds; |
|
889 goto parse_flag; |
|
890 @@ -2097,6 +2111,7 @@ dump_config(ServerOptions *o) |
|
891 #endif |
|
892 #ifdef GSSAPI |
|
893 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); |
|
894 + dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); |
|
895 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); |
|
896 #endif |
|
897 #ifdef JPAKE |
|
898 Only in new/: servconf.c.orig |
|
899 Only in new/: servconf.c.rej |
|
900 Only in new/: servconf.c~ |
|
901 diff -pur old/servconf.h new/servconf.h |
|
902 --- old/servconf.h 2014-11-19 08:19:53.556446909 -0800 |
|
903 +++ new/servconf.h 2014-11-19 08:19:53.619133205 -0800 |
|
904 @@ -116,6 +116,7 @@ typedef struct { |
|
905 int kerberos_get_afs_token; /* If true, try to get AFS token if |
|
906 * authenticated with Kerberos. */ |
|
907 int gss_authentication; /* If true, permit GSSAPI authentication */ |
|
908 + int gss_keyex; /* If true, permit GSSAPI key exchange */ |
|
909 int gss_cleanup_creds; /* If true, destroy cred cache on logout */ |
|
910 int password_authentication; /* If true, permit password |
|
911 * authentication. */ |
|
912 Only in new/: servconf.h.orig |
|
913 diff -pur old/ssh-gss.h new/ssh-gss.h |
|
914 --- old/ssh-gss.h 2013-02-24 16:24:44.000000000 -0800 |
|
915 +++ new/ssh-gss.h 2014-11-19 08:19:53.619269786 -0800 |
|
916 @@ -61,6 +61,17 @@ |
|
917 |
|
918 #define SSH_GSS_OIDTYPE 0x06 |
|
919 |
|
920 +#define SSH2_MSG_KEXGSS_INIT 30 |
|
921 +#define SSH2_MSG_KEXGSS_CONTINUE 31 |
|
922 +#define SSH2_MSG_KEXGSS_COMPLETE 32 |
|
923 +#define SSH2_MSG_KEXGSS_HOSTKEY 33 |
|
924 +#define SSH2_MSG_KEXGSS_ERROR 34 |
|
925 +#define SSH2_MSG_KEXGSS_GROUPREQ 40 |
|
926 +#define SSH2_MSG_KEXGSS_GROUP 41 |
|
927 +#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" |
|
928 +#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" |
|
929 +#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" |
|
930 + |
|
931 typedef struct { |
|
932 char *filename; |
|
933 char *envvar; |
|
934 @@ -98,6 +109,7 @@ typedef struct { |
|
935 } Gssctxt; |
|
936 |
|
937 extern ssh_gssapi_mech *supported_mechs[]; |
|
938 +extern Gssctxt *gss_kex_context; |
|
939 |
|
940 int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); |
|
941 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); |
|
942 @@ -120,6 +132,11 @@ void ssh_gssapi_buildmic(Buffer *, const |
|
943 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); |
|
944 |
|
945 /* In the server */ |
|
946 +typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *); |
|
947 +char *ssh_gssapi_client_mechanisms(const char *host); |
|
948 +char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *); |
|
949 +gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); |
|
950 +int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *); |
|
951 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); |
|
952 int ssh_gssapi_userok(char *name); |
|
953 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); |
|
954 @@ -127,6 +144,8 @@ void ssh_gssapi_do_child(char ***, u_int |
|
955 void ssh_gssapi_cleanup_creds(void); |
|
956 void ssh_gssapi_storecreds(void); |
|
957 |
|
958 +char *ssh_gssapi_server_mechanisms(void); |
|
959 +int ssh_gssapi_oid_table_ok(); |
|
960 #endif /* GSSAPI */ |
|
961 |
|
962 #endif /* _SSH_GSS_H */ |
|
963 Only in new/: ssh-gss.h.orig |
|
964 diff -pur old/ssh_config new/ssh_config |
|
965 --- old/ssh_config 2013-10-09 16:24:12.000000000 -0700 |
|
966 +++ new/ssh_config 2014-11-20 08:14:10.251613588 -0800 |
|
967 @@ -26,6 +26,7 @@ |
|
968 # HostbasedAuthentication no |
|
969 # GSSAPIAuthentication no |
|
970 # GSSAPIDelegateCredentials no |
|
971 +# GSSAPIKeyExchange yes |
|
972 # BatchMode no |
|
973 # CheckHostIP yes |
|
974 # AddressFamily any |
|
975 diff -pur old/ssh_config.5 new/ssh_config.5 |
|
976 --- old/ssh_config.5 2014-11-19 08:19:53.578521210 -0800 |
|
977 +++ new/ssh_config.5 2014-11-20 08:15:58.760019866 -0800 |
|
978 @@ -684,6 +684,12 @@ Specifies whether user authentication ba |
|
979 The default on Solaris is |
|
980 .Dq yes . |
|
981 Note that this option applies to protocol version 2 only. |
|
982 +.It Cm GSSAPIKeyExchange |
|
983 +Specifies whether key exchange based on GSSAPI may be used. When using |
|
984 +GSSAPI key exchange the server need not have a host key. |
|
985 +The default on Solaris is |
|
986 +.Dq yes . |
|
987 +Note that this option applies to protocol version 2 only. |
|
988 .It Cm GSSAPIDelegateCredentials |
|
989 Forward (delegate) credentials to the server. |
|
990 The default is |
|
991 Only in new/: ssh_config.5.orig |
|
992 Only in new/: ssh_config.5~ |
|
993 Only in new/: ssh_config~ |
|
994 diff -pur old/sshconnect2.c new/sshconnect2.c |
|
995 --- old/sshconnect2.c 2014-11-19 08:19:53.536674289 -0800 |
|
996 +++ new/sshconnect2.c 2014-11-20 04:01:10.016195028 -0800 |
|
997 @@ -164,9 +164,31 @@ ssh_kex2(char *host, struct sockaddr *ho |
|
998 { |
|
999 Kex *kex; |
|
1000 |
|
1001 +#ifdef GSSAPI |
|
1002 + char *orig = NULL, *gss = NULL; |
|
1003 + char *gss_host = NULL; |
|
1004 +#endif |
|
1005 + |
|
1006 xxx_host = host; |
|
1007 xxx_hostaddr = hostaddr; |
|
1008 |
|
1009 +#ifdef GSSAPI |
|
1010 + if (options.gss_keyex) { |
|
1011 + /* Add the GSSAPI mechanisms currently supported on this |
|
1012 + * client to the key exchange algorithm proposal */ |
|
1013 + orig = myproposal[PROPOSAL_KEX_ALGS]; |
|
1014 + |
|
1015 + gss_host = (char *)get_canonical_hostname(1); |
|
1016 + |
|
1017 + gss = ssh_gssapi_client_mechanisms(gss_host); |
|
1018 + if (gss) { |
|
1019 + debug("Offering GSSAPI proposal: %s", gss); |
|
1020 + xasprintf(&myproposal[PROPOSAL_KEX_ALGS], |
|
1021 + "%s,%s", gss, orig); |
|
1022 + } |
|
1023 + } |
|
1024 +#endif |
|
1025 + |
|
1026 if (options.ciphers == (char *)-1) { |
|
1027 logit("No valid ciphers for protocol version 2 given, using defaults."); |
|
1028 options.ciphers = NULL; |
|
1029 @@ -202,6 +224,17 @@ ssh_kex2(char *host, struct sockaddr *ho |
|
1030 if (options.kex_algorithms != NULL) |
|
1031 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; |
|
1032 |
|
1033 +#ifdef GSSAPI |
|
1034 + /* If we've got GSSAPI algorithms, then we also support the |
|
1035 + * 'null' hostkey, as a last resort */ |
|
1036 + if (options.gss_keyex && gss) { |
|
1037 + orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; |
|
1038 + xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], |
|
1039 + "%s,null", orig); |
|
1040 + free(gss); |
|
1041 + } |
|
1042 +#endif |
|
1043 + |
|
1044 if (options.rekey_limit || options.rekey_interval) |
|
1045 packet_set_rekey_limits((u_int32_t)options.rekey_limit, |
|
1046 (time_t)options.rekey_interval); |
|
1047 @@ -214,9 +247,22 @@ ssh_kex2(char *host, struct sockaddr *ho |
|
1048 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; |
|
1049 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; |
|
1050 kex->kex[KEX_C25519_SHA256] = kexc25519_client; |
|
1051 +#ifdef GSSAPI |
|
1052 + if (options.gss_keyex) { |
|
1053 + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; |
|
1054 + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; |
|
1055 + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; |
|
1056 + } |
|
1057 +#endif |
|
1058 kex->client_version_string=client_version_string; |
|
1059 kex->server_version_string=server_version_string; |
|
1060 kex->verify_host_key=&verify_host_key_callback; |
|
1061 +#ifdef GSSAPI |
|
1062 + if (options.gss_keyex) { |
|
1063 + kex->gss_deleg_creds = options.gss_deleg_creds; |
|
1064 + kex->gss_host = gss_host; |
|
1065 + } |
|
1066 +#endif |
|
1067 |
|
1068 xxx_kex = kex; |
|
1069 |
|
1070 @@ -313,6 +359,7 @@ void input_gssapi_token(int type, u_int3 |
|
1071 void input_gssapi_hash(int type, u_int32_t, void *); |
|
1072 void input_gssapi_error(int, u_int32_t, void *); |
|
1073 void input_gssapi_errtok(int, u_int32_t, void *); |
|
1074 +int userauth_gsskeyex(Authctxt *authctxt); |
|
1075 #endif |
|
1076 |
|
1077 void userauth(Authctxt *, char *); |
|
1078 @@ -328,6 +375,11 @@ static char *authmethods_get(void); |
|
1079 |
|
1080 Authmethod authmethods[] = { |
|
1081 #ifdef GSSAPI |
|
1082 + {"gssapi-keyex", |
|
1083 + userauth_gsskeyex, |
|
1084 + NULL, |
|
1085 + &options.gss_authentication, |
|
1086 + NULL}, |
|
1087 {"gssapi-with-mic", |
|
1088 userauth_gssapi, |
|
1089 NULL, |
|
1090 @@ -649,7 +701,10 @@ userauth_gssapi(Authctxt *authctxt) |
|
1091 * once. */ |
|
1092 |
|
1093 if (gss_supported == NULL) |
|
1094 - gss_indicate_mechs(&min, &gss_supported); |
|
1095 + if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { |
|
1096 + gss_supported = NULL; |
|
1097 + return 0; |
|
1098 + } |
|
1099 |
|
1100 /* Check to see if the mechanism is usable before we offer it */ |
|
1101 while (mech < gss_supported->count && !ok) { |
|
1102 @@ -753,8 +808,8 @@ input_gssapi_response(int type, u_int32_ |
|
1103 { |
|
1104 Authctxt *authctxt = ctxt; |
|
1105 Gssctxt *gssctxt; |
|
1106 - int oidlen; |
|
1107 - char *oidv; |
|
1108 + u_int oidlen; |
|
1109 + u_char *oidv; |
|
1110 |
|
1111 if (authctxt == NULL) |
|
1112 fatal("input_gssapi_response: no authentication context"); |
|
1113 @@ -863,6 +918,48 @@ input_gssapi_error(int type, u_int32_t p |
|
1114 free(msg); |
|
1115 free(lang); |
|
1116 } |
|
1117 + |
|
1118 +int |
|
1119 +userauth_gsskeyex(Authctxt *authctxt) |
|
1120 +{ |
|
1121 + Buffer b; |
|
1122 + gss_buffer_desc gssbuf; |
|
1123 + gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; |
|
1124 + OM_uint32 ms; |
|
1125 + |
|
1126 + static int attempt = 0; |
|
1127 + if (attempt++ >= 1) |
|
1128 + return (0); |
|
1129 + |
|
1130 + if (gss_kex_context == NULL) { |
|
1131 + debug("No valid Key exchange context"); |
|
1132 + return (0); |
|
1133 + } |
|
1134 + |
|
1135 + ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, |
|
1136 + "gssapi-keyex"); |
|
1137 + |
|
1138 + gssbuf.value = buffer_ptr(&b); |
|
1139 + gssbuf.length = buffer_len(&b); |
|
1140 + |
|
1141 + if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { |
|
1142 + buffer_free(&b); |
|
1143 + return (0); |
|
1144 + } |
|
1145 + |
|
1146 + packet_start(SSH2_MSG_USERAUTH_REQUEST); |
|
1147 + packet_put_cstring(authctxt->server_user); |
|
1148 + packet_put_cstring(authctxt->service); |
|
1149 + packet_put_cstring(authctxt->method->name); |
|
1150 + packet_put_string(mic.value, mic.length); |
|
1151 + packet_send(); |
|
1152 + |
|
1153 + buffer_free(&b); |
|
1154 + gss_release_buffer(&ms, &mic); |
|
1155 + |
|
1156 + return (1); |
|
1157 +} |
|
1158 + |
|
1159 #endif /* GSSAPI */ |
|
1160 |
|
1161 int |
|
1162 Only in new/: sshconnect2.c.orig |
|
1163 Only in new/: sshconnect2.c.rej |
|
1164 Only in new/: sshconnect2.c~ |
|
1165 diff -pur old/sshd.c new/sshd.c |
|
1166 --- old/sshd.c 2014-11-19 08:19:53.496741742 -0800 |
|
1167 +++ new/sshd.c 2014-11-19 10:39:10.594013263 -0800 |
|
1168 @@ -1730,10 +1730,13 @@ main(int ac, char **av) |
|
1169 logit("Disabling protocol version 1. Could not load host key"); |
|
1170 options.protocol &= ~SSH_PROTO_1; |
|
1171 } |
|
1172 +#ifndef GSSAPI |
|
1173 + /* The GSSAPI key exchange can run without a host key */ |
|
1174 if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { |
|
1175 logit("Disabling protocol version 2. Could not load host key"); |
|
1176 options.protocol &= ~SSH_PROTO_2; |
|
1177 } |
|
1178 +#endif |
|
1179 if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { |
|
1180 logit("sshd: no hostkeys available -- exiting."); |
|
1181 exit(1); |
|
1182 @@ -2488,6 +2491,48 @@ do_ssh2_kex(void) |
|
1183 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( |
|
1184 list_hostkey_types()); |
|
1185 |
|
1186 +#ifdef GSSAPI |
|
1187 + { |
|
1188 + char *orig; |
|
1189 + char *gss = NULL; |
|
1190 + char *newstr = NULL; |
|
1191 + orig = myproposal[PROPOSAL_KEX_ALGS]; |
|
1192 + |
|
1193 + /* |
|
1194 + * If we don't have a host key, then there's no point advertising |
|
1195 + * the other key exchange algorithms |
|
1196 + */ |
|
1197 + |
|
1198 + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) |
|
1199 + orig = NULL; |
|
1200 + |
|
1201 + if (options.gss_keyex) |
|
1202 + gss = ssh_gssapi_server_mechanisms(); |
|
1203 + else |
|
1204 + gss = NULL; |
|
1205 + |
|
1206 + if (gss && orig) |
|
1207 + xasprintf(&newstr, "%s,%s", gss, orig); |
|
1208 + else if (gss) |
|
1209 + newstr = gss; |
|
1210 + else if (orig) |
|
1211 + newstr = orig; |
|
1212 + |
|
1213 + /* |
|
1214 + * If we've got GSSAPI mechanisms, then we've got the 'null' host |
|
1215 + * key alg, but we can't tell people about it unless its the only |
|
1216 + * host key algorithm we support |
|
1217 + */ |
|
1218 + if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) |
|
1219 + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; |
|
1220 + |
|
1221 + if (newstr) |
|
1222 + myproposal[PROPOSAL_KEX_ALGS] = newstr; |
|
1223 + else |
|
1224 + fatal("No supported key exchange algorithms"); |
|
1225 + } |
|
1226 +#endif |
|
1227 + |
|
1228 /* start key exchange */ |
|
1229 kex = kex_setup(myproposal); |
|
1230 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
|
1231 @@ -2496,6 +2541,13 @@ do_ssh2_kex(void) |
|
1232 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
|
1233 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
|
1234 kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
|
1235 +#ifdef GSSAPI |
|
1236 + if (options.gss_keyex) { |
|
1237 + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; |
|
1238 + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; |
|
1239 + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; |
|
1240 + } |
|
1241 +#endif |
|
1242 kex->server = 1; |
|
1243 kex->client_version_string=client_version_string; |
|
1244 kex->server_version_string=server_version_string; |
|
1245 Only in new/: sshd.c.orig |
|
1246 Only in new/: sshd.c.rej |
|
1247 diff -pur old/sshd_config new/sshd_config |
|
1248 --- old/sshd_config 2014-01-12 00:20:47.000000000 -0800 |
|
1249 +++ new/sshd_config 2014-11-20 08:14:48.893785772 -0800 |
|
1250 @@ -82,8 +82,9 @@ AuthorizedKeysFile .ssh/authorized_keys |
|
1251 #KerberosGetAFSToken no |
|
1252 |
|
1253 # GSSAPI options |
|
1254 -#GSSAPIAuthentication no |
|
1255 +#GSSAPIAuthentication yes |
|
1256 #GSSAPICleanupCredentials yes |
|
1257 +#GSSAPIKeyExchange yes |
|
1258 |
|
1259 # Set this to 'yes' to enable PAM authentication, account processing, |
|
1260 # and session processing. If this is enabled, PAM authentication will |
|
1261 diff -pur old/sshd_config.5 new/sshd_config.5 |
|
1262 --- old/sshd_config.5 2014-11-19 08:19:53.578781556 -0800 |
|
1263 +++ new/sshd_config.5 2014-11-20 08:17:21.116195335 -0800 |
|
1264 @@ -493,6 +493,12 @@ Specifies whether user authentication ba |
|
1265 The default on Solaris is |
|
1266 .Dq yes . |
|
1267 Note that this option applies to protocol version 2 only. |
|
1268 +.It Cm GSSAPIKeyExchange |
|
1269 +Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange |
|
1270 +doesn't rely on ssh keys to verify host identity. |
|
1271 +The default on Solaris is |
|
1272 +.Dq yes . |
|
1273 +Note that this option applies to protocol version 2 only. |
|
1274 .It Cm GSSAPICleanupCredentials |
|
1275 Specifies whether to automatically destroy the user's credentials cache |
|
1276 on logout. |
|
1277 Only in new/: sshd_config.5.orig |
|
1278 Only in new/: sshd_config.5~ |
|
1279 Only in new/: sshd_config.orig |
|
1280 Only in new/: sshd_config.rej |
|
1281 Only in new/: sshd_config~ |