summaryrefslogtreecommitdiff
path: root/kexgssc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexgssc.c')
-rw-r--r--kexgssc.c613
1 files changed, 439 insertions, 174 deletions
diff --git a/kexgssc.c b/kexgssc.c
index 3c8ae08dd..f6e1405eb 100644
--- a/kexgssc.c
+++ b/kexgssc.c
@@ -24,7 +24,7 @@
24 24
25#include "includes.h" 25#include "includes.h"
26 26
27#ifdef GSSAPI 27#if defined(GSSAPI) && defined(WITH_OPENSSL)
28 28
29#include "includes.h" 29#include "includes.h"
30 30
@@ -43,113 +43,88 @@
43#include "packet.h" 43#include "packet.h"
44#include "dh.h" 44#include "dh.h"
45#include "digest.h" 45#include "digest.h"
46#include "ssherr.h"
46 47
47#include "ssh-gss.h" 48#include "ssh-gss.h"
48 49
49int 50int
50kexgss_client(struct ssh *ssh) { 51kexgss_client(struct ssh *ssh)
51 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 52{
52 gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; 53 struct kex *kex = ssh->kex;
54 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
55 recv_tok = GSS_C_EMPTY_BUFFER,
56 gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
53 Gssctxt *ctxt; 57 Gssctxt *ctxt;
54 OM_uint32 maj_status, min_status, ret_flags; 58 OM_uint32 maj_status, min_status, ret_flags;
55 u_int klen, kout, slen = 0, strlen; 59 struct sshbuf *server_blob = NULL;
56 DH *dh; 60 struct sshbuf *shared_secret = NULL;
57 BIGNUM *dh_server_pub = NULL; 61 struct sshbuf *server_host_key_blob = NULL;
58 BIGNUM *shared_secret = NULL; 62 struct sshbuf *empty = NULL;
59 const BIGNUM *pub_key, *dh_p, *dh_g; 63 u_char *msg;
60 BIGNUM *p = NULL;
61 BIGNUM *g = NULL;
62 u_char *kbuf;
63 u_char *serverhostkey = NULL;
64 u_char *empty = "";
65 char *msg;
66 int type = 0; 64 int type = 0;
67 int first = 1; 65 int first = 1;
68 int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
69 u_char hash[SSH_DIGEST_MAX_LENGTH]; 66 u_char hash[SSH_DIGEST_MAX_LENGTH];
70 size_t hashlen; 67 size_t hashlen;
68 u_char c;
69 int r;
71 70
72 /* Initialise our GSSAPI world */ 71 /* Initialise our GSSAPI world */
73 ssh_gssapi_build_ctx(&ctxt); 72 ssh_gssapi_build_ctx(&ctxt);
74 if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) 73 if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
75 == GSS_C_NO_OID) 74 == GSS_C_NO_OID)
76 fatal("Couldn't identify host exchange"); 75 fatal("Couldn't identify host exchange");
77 76
78 if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host)) 77 if (ssh_gssapi_import_name(ctxt, kex->gss_host))
79 fatal("Couldn't import hostname"); 78 fatal("Couldn't import hostname");
80 79
81 if (ssh->kex->gss_client && 80 if (kex->gss_client &&
82 ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client)) 81 ssh_gssapi_client_identity(ctxt, kex->gss_client))
83 fatal("Couldn't acquire client credentials"); 82 fatal("Couldn't acquire client credentials");
84 83
85 switch (ssh->kex->kex_type) { 84 /* Step 1 */
85 switch (kex->kex_type) {
86 case KEX_GSS_GRP1_SHA1: 86 case KEX_GSS_GRP1_SHA1:
87 dh = dh_new_group1();
88 break;
89 case KEX_GSS_GRP14_SHA1: 87 case KEX_GSS_GRP14_SHA1:
90 dh = dh_new_group14(); 88 case KEX_GSS_GRP14_SHA256:
89 case KEX_GSS_GRP16_SHA512:
90 r = kex_dh_keypair(kex);
91 break; 91 break;
92 case KEX_GSS_GEX_SHA1: 92 case KEX_GSS_NISTP256_SHA256:
93 debug("Doing group exchange\n"); 93 r = kex_ecdh_keypair(kex);
94 nbits = dh_estimate(ssh->kex->we_need * 8); 94 break;
95 packet_start(SSH2_MSG_KEXGSS_GROUPREQ); 95 case KEX_GSS_C25519_SHA256:
96 packet_put_int(min); 96 r = kex_c25519_keypair(kex);
97 packet_put_int(nbits);
98 packet_put_int(max);
99
100 packet_send();
101
102 packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
103
104 if ((p = BN_new()) == NULL)
105 fatal("BN_new() failed");
106 packet_get_bignum2(p);
107 if ((g = BN_new()) == NULL)
108 fatal("BN_new() failed");
109 packet_get_bignum2(g);
110 packet_check_eom();
111
112 if (BN_num_bits(p) < min || BN_num_bits(p) > max)
113 fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
114 min, BN_num_bits(p), max);
115
116 dh = dh_new_group(g, p);
117 break; 97 break;
118 default: 98 default:
119 fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); 99 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
120 } 100 }
121 101 if (r != 0)
122 /* Step 1 - e is dh->pub_key */ 102 return r;
123 dh_gen_key(dh, ssh->kex->we_need * 8);
124 DH_get0_key(dh, &pub_key, NULL);
125 DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
126
127 /* This is f, we initialise it now to make life easier */
128 dh_server_pub = BN_new();
129 if (dh_server_pub == NULL)
130 fatal("dh_server_pub == NULL");
131 103
132 token_ptr = GSS_C_NO_BUFFER; 104 token_ptr = GSS_C_NO_BUFFER;
133 105
134 do { 106 do {
135 debug("Calling gss_init_sec_context"); 107 debug("Calling gss_init_sec_context");
136 108
137 maj_status = ssh_gssapi_init_ctx(ctxt, 109 maj_status = ssh_gssapi_init_ctx(ctxt,
138 ssh->kex->gss_deleg_creds, token_ptr, &send_tok, 110 kex->gss_deleg_creds, token_ptr, &send_tok,
139 &ret_flags); 111 &ret_flags);
140 112
141 if (GSS_ERROR(maj_status)) { 113 if (GSS_ERROR(maj_status)) {
114 /* XXX Useles code: Missing send? */
142 if (send_tok.length != 0) { 115 if (send_tok.length != 0) {
143 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 116 if ((r = sshpkt_start(ssh,
144 packet_put_string(send_tok.value, 117 SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
145 send_tok.length); 118 (r = sshpkt_put_string(ssh, send_tok.value,
119 send_tok.length)) != 0)
120 fatal("sshpkt failed: %s", ssh_err(r));
146 } 121 }
147 fatal("gss_init_context failed"); 122 fatal("gss_init_context failed");
148 } 123 }
149 124
150 /* If we've got an old receive buffer get rid of it */ 125 /* If we've got an old receive buffer get rid of it */
151 if (token_ptr != GSS_C_NO_BUFFER) 126 if (token_ptr != GSS_C_NO_BUFFER)
152 free(recv_tok.value); 127 gss_release_buffer(&min_status, &recv_tok);
153 128
154 if (maj_status == GSS_S_COMPLETE) { 129 if (maj_status == GSS_S_COMPLETE) {
155 /* If mutual state flag is not true, kex fails */ 130 /* If mutual state flag is not true, kex fails */
@@ -161,75 +136,90 @@ kexgss_client(struct ssh *ssh) {
161 fatal("Integrity check failed"); 136 fatal("Integrity check failed");
162 } 137 }
163 138
164 /* 139 /*
165 * If we have data to send, then the last message that we 140 * If we have data to send, then the last message that we
166 * received cannot have been a 'complete'. 141 * received cannot have been a 'complete'.
167 */ 142 */
168 if (send_tok.length != 0) { 143 if (send_tok.length != 0) {
169 if (first) { 144 if (first) {
170 packet_start(SSH2_MSG_KEXGSS_INIT); 145 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
171 packet_put_string(send_tok.value, 146 (r = sshpkt_put_string(ssh, send_tok.value,
172 send_tok.length); 147 send_tok.length)) != 0 ||
173 packet_put_bignum2(pub_key); 148 (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0)
149 fatal("failed to construct packet: %s", ssh_err(r));
174 first = 0; 150 first = 0;
175 } else { 151 } else {
176 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 152 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
177 packet_put_string(send_tok.value, 153 (r = sshpkt_put_string(ssh, send_tok.value,
178 send_tok.length); 154 send_tok.length)) != 0)
155 fatal("failed to construct packet: %s", ssh_err(r));
179 } 156 }
180 packet_send(); 157 if ((r = sshpkt_send(ssh)) != 0)
158 fatal("failed to send packet: %s", ssh_err(r));
181 gss_release_buffer(&min_status, &send_tok); 159 gss_release_buffer(&min_status, &send_tok);
182 160
183 /* If we've sent them data, they should reply */ 161 /* If we've sent them data, they should reply */
184 do { 162 do {
185 type = packet_read(); 163 type = ssh_packet_read(ssh);
186 if (type == SSH2_MSG_KEXGSS_HOSTKEY) { 164 if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
187 debug("Received KEXGSS_HOSTKEY"); 165 debug("Received KEXGSS_HOSTKEY");
188 if (serverhostkey) 166 if (server_host_key_blob)
189 fatal("Server host key received more than once"); 167 fatal("Server host key received more than once");
190 serverhostkey = 168 if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
191 packet_get_string(&slen); 169 fatal("Failed to read server host key: %s", ssh_err(r));
192 } 170 }
193 } while (type == SSH2_MSG_KEXGSS_HOSTKEY); 171 } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
194 172
195 switch (type) { 173 switch (type) {
196 case SSH2_MSG_KEXGSS_CONTINUE: 174 case SSH2_MSG_KEXGSS_CONTINUE:
197 debug("Received GSSAPI_CONTINUE"); 175 debug("Received GSSAPI_CONTINUE");
198 if (maj_status == GSS_S_COMPLETE) 176 if (maj_status == GSS_S_COMPLETE)
199 fatal("GSSAPI Continue received from server when complete"); 177 fatal("GSSAPI Continue received from server when complete");
200 recv_tok.value = packet_get_string(&strlen); 178 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
201 recv_tok.length = strlen; 179 &recv_tok)) != 0 ||
180 (r = sshpkt_get_end(ssh)) != 0)
181 fatal("Failed to read token: %s", ssh_err(r));
202 break; 182 break;
203 case SSH2_MSG_KEXGSS_COMPLETE: 183 case SSH2_MSG_KEXGSS_COMPLETE:
204 debug("Received GSSAPI_COMPLETE"); 184 debug("Received GSSAPI_COMPLETE");
205 packet_get_bignum2(dh_server_pub); 185 if (msg_tok.value != NULL)
206 msg_tok.value = packet_get_string(&strlen); 186 fatal("Received GSSAPI_COMPLETE twice?");
207 msg_tok.length = strlen; 187 if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
188 (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
189 &msg_tok)) != 0)
190 fatal("Failed to read message: %s", ssh_err(r));
208 191
209 /* Is there a token included? */ 192 /* Is there a token included? */
210 if (packet_get_char()) { 193 if ((r = sshpkt_get_u8(ssh, &c)) != 0)
211 recv_tok.value= 194 fatal("sshpkt failed: %s", ssh_err(r));
212 packet_get_string(&strlen); 195 if (c) {
213 recv_tok.length = strlen; 196 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
197 ssh, &recv_tok)) != 0)
198 fatal("Failed to read token: %s", ssh_err(r));
214 /* If we're already complete - protocol error */ 199 /* If we're already complete - protocol error */
215 if (maj_status == GSS_S_COMPLETE) 200 if (maj_status == GSS_S_COMPLETE)
216 packet_disconnect("Protocol error: received token when complete"); 201 sshpkt_disconnect(ssh, "Protocol error: received token when complete");
217 } else { 202 } else {
218 /* No token included */ 203 /* No token included */
219 if (maj_status != GSS_S_COMPLETE) 204 if (maj_status != GSS_S_COMPLETE)
220 packet_disconnect("Protocol error: did not receive final token"); 205 sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
206 }
207 if ((r = sshpkt_get_end(ssh)) != 0) {
208 fatal("Expecting end of packet.");
221 } 209 }
222 break; 210 break;
223 case SSH2_MSG_KEXGSS_ERROR: 211 case SSH2_MSG_KEXGSS_ERROR:
224 debug("Received Error"); 212 debug("Received Error");
225 maj_status = packet_get_int(); 213 if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
226 min_status = packet_get_int(); 214 (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
227 msg = packet_get_string(NULL); 215 (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
228 (void) packet_get_string_ptr(NULL); 216 (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
229 fatal("GSSAPI Error: \n%.400s",msg); 217 (r = sshpkt_get_end(ssh)) != 0)
218 fatal("sshpkt_get failed: %s", ssh_err(r));
219 fatal("GSSAPI Error: \n%.400s", msg);
230 default: 220 default:
231 packet_disconnect("Protocol error: didn't expect packet type %d", 221 sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
232 type); 222 type);
233 } 223 }
234 token_ptr = &recv_tok; 224 token_ptr = &recv_tok;
235 } else { 225 } else {
@@ -239,93 +229,358 @@ kexgss_client(struct ssh *ssh) {
239 } 229 }
240 } while (maj_status & GSS_S_CONTINUE_NEEDED); 230 } while (maj_status & GSS_S_CONTINUE_NEEDED);
241 231
242 /* 232 /*
243 * We _must_ have received a COMPLETE message in reply from the 233 * We _must_ have received a COMPLETE message in reply from the
244 * server, which will have set dh_server_pub and msg_tok 234 * server, which will have set server_blob and msg_tok
245 */ 235 */
246 236
247 if (type != SSH2_MSG_KEXGSS_COMPLETE) 237 if (type != SSH2_MSG_KEXGSS_COMPLETE)
248 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); 238 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
249 239
250 /* Check f in range [1, p-1] */ 240 /* compute shared secret */
251 if (!dh_pub_is_valid(dh, dh_server_pub)) 241 switch (kex->kex_type) {
252 packet_disconnect("bad server public DH value");
253
254 /* compute K=f^x mod p */
255 klen = DH_size(dh);
256 kbuf = xmalloc(klen);
257 kout = DH_compute_key(kbuf, dh_server_pub, dh);
258 if (kout < 0)
259 fatal("DH_compute_key: failed");
260
261 shared_secret = BN_new();
262 if (shared_secret == NULL)
263 fatal("kexgss_client: BN_new failed");
264
265 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
266 fatal("kexdh_client: BN_bin2bn failed");
267
268 memset(kbuf, 0, klen);
269 free(kbuf);
270
271 hashlen = sizeof(hash);
272 switch (ssh->kex->kex_type) {
273 case KEX_GSS_GRP1_SHA1: 242 case KEX_GSS_GRP1_SHA1:
274 case KEX_GSS_GRP14_SHA1: 243 case KEX_GSS_GRP14_SHA1:
275 kex_dh_hash( 244 case KEX_GSS_GRP14_SHA256:
276 ssh->kex->hash_alg, 245 case KEX_GSS_GRP16_SHA512:
277 ssh->kex->client_version_string, 246 r = kex_dh_dec(kex, server_blob, &shared_secret);
278 ssh->kex->server_version_string, 247 break;
279 sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 248 case KEX_GSS_C25519_SHA256:
280 sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 249 if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80)
281 (serverhostkey ? serverhostkey : empty), slen, 250 fatal("The received key has MSB of last octet set!");
282 pub_key, /* e */ 251 r = kex_c25519_dec(kex, server_blob, &shared_secret);
283 dh_server_pub, /* f */
284 shared_secret, /* K */
285 hash, &hashlen
286 );
287 break; 252 break;
288 case KEX_GSS_GEX_SHA1: 253 case KEX_GSS_NISTP256_SHA256:
289 kexgex_hash( 254 if (sshbuf_len(server_blob) != 65)
290 ssh->kex->hash_alg, 255 fatal("The received NIST-P256 key did not match"
291 ssh->kex->client_version_string, 256 "expected length (expected 65, got %zu)", sshbuf_len(server_blob));
292 ssh->kex->server_version_string, 257
293 sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 258 if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED)
294 sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 259 fatal("The received NIST-P256 key does not have first octet 0x04");
295 (serverhostkey ? serverhostkey : empty), slen, 260
296 min, nbits, max, 261 r = kex_ecdh_dec(kex, server_blob, &shared_secret);
297 dh_p, dh_g,
298 pub_key,
299 dh_server_pub,
300 shared_secret,
301 hash, &hashlen
302 );
303 break; 262 break;
304 default: 263 default:
305 fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); 264 r = SSH_ERR_INVALID_ARGUMENT;
265 break;
266 }
267 if (r != 0)
268 goto out;
269
270 if ((empty = sshbuf_new()) == NULL) {
271 r = SSH_ERR_ALLOC_FAIL;
272 goto out;
306 } 273 }
307 274
275 hashlen = sizeof(hash);
276 if ((r = kex_gen_hash(
277 kex->hash_alg,
278 kex->client_version,
279 kex->server_version,
280 kex->my,
281 kex->peer,
282 (server_host_key_blob ? server_host_key_blob : empty),
283 kex->client_pub,
284 server_blob,
285 shared_secret,
286 hash, &hashlen)) != 0)
287 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
288
308 gssbuf.value = hash; 289 gssbuf.value = hash;
309 gssbuf.length = hashlen; 290 gssbuf.length = hashlen;
310 291
311 /* Verify that the hash matches the MIC we just got. */ 292 /* Verify that the hash matches the MIC we just got. */
312 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) 293 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
313 packet_disconnect("Hash's MIC didn't verify"); 294 sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
314 295
315 free(msg_tok.value); 296 gss_release_buffer(&min_status, &msg_tok);
316 297
317 DH_free(dh); 298 if (kex->gss_deleg_creds)
318 free(serverhostkey); 299 ssh_gssapi_credentials_updated(ctxt);
319 BN_clear_free(dh_server_pub); 300
301 if (gss_kex_context == NULL)
302 gss_kex_context = ctxt;
303 else
304 ssh_gssapi_delete_ctx(&ctxt);
305
306 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
307 r = kex_send_newkeys(ssh);
308
309out:
310 explicit_bzero(hash, sizeof(hash));
311 explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
312 sshbuf_free(empty);
313 sshbuf_free(server_host_key_blob);
314 sshbuf_free(server_blob);
315 sshbuf_free(shared_secret);
316 sshbuf_free(kex->client_pub);
317 kex->client_pub = NULL;
318 return r;
319}
320
321int
322kexgssgex_client(struct ssh *ssh)
323{
324 struct kex *kex = ssh->kex;
325 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
326 recv_tok = GSS_C_EMPTY_BUFFER, gssbuf,
327 msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
328 Gssctxt *ctxt;
329 OM_uint32 maj_status, min_status, ret_flags;
330 struct sshbuf *shared_secret = NULL;
331 BIGNUM *p = NULL;
332 BIGNUM *g = NULL;
333 struct sshbuf *buf = NULL;
334 struct sshbuf *server_host_key_blob = NULL;
335 struct sshbuf *server_blob = NULL;
336 BIGNUM *dh_server_pub = NULL;
337 u_char *msg;
338 int type = 0;
339 int first = 1;
340 u_char hash[SSH_DIGEST_MAX_LENGTH];
341 size_t hashlen;
342 const BIGNUM *pub_key, *dh_p, *dh_g;
343 int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
344 struct sshbuf *empty = NULL;
345 u_char c;
346 int r;
347
348 /* Initialise our GSSAPI world */
349 ssh_gssapi_build_ctx(&ctxt);
350 if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
351 == GSS_C_NO_OID)
352 fatal("Couldn't identify host exchange");
353
354 if (ssh_gssapi_import_name(ctxt, kex->gss_host))
355 fatal("Couldn't import hostname");
356
357 if (kex->gss_client &&
358 ssh_gssapi_client_identity(ctxt, kex->gss_client))
359 fatal("Couldn't acquire client credentials");
360
361 debug("Doing group exchange");
362 nbits = dh_estimate(kex->dh_need * 8);
363
364 kex->min = DH_GRP_MIN;
365 kex->max = DH_GRP_MAX;
366 kex->nbits = nbits;
367 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 ||
368 (r = sshpkt_put_u32(ssh, min)) != 0 ||
369 (r = sshpkt_put_u32(ssh, nbits)) != 0 ||
370 (r = sshpkt_put_u32(ssh, max)) != 0 ||
371 (r = sshpkt_send(ssh)) != 0)
372 fatal("Failed to construct a packet: %s", ssh_err(r));
373
374 if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0)
375 fatal("Error: %s", ssh_err(r));
376
377 if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
378 (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
379 (r = sshpkt_get_end(ssh)) != 0)
380 fatal("shpkt_get_bignum2 failed: %s", ssh_err(r));
381
382 if (BN_num_bits(p) < min || BN_num_bits(p) > max)
383 fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
384 min, BN_num_bits(p), max);
385
386 if ((kex->dh = dh_new_group(g, p)) == NULL)
387 fatal("dn_new_group() failed");
388 p = g = NULL; /* belong to kex->dh now */
389
390 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
391 goto out;
392 DH_get0_key(kex->dh, &pub_key, NULL);
393
394 token_ptr = GSS_C_NO_BUFFER;
395
396 do {
397 /* Step 2 - call GSS_Init_sec_context() */
398 debug("Calling gss_init_sec_context");
399
400 maj_status = ssh_gssapi_init_ctx(ctxt,
401 kex->gss_deleg_creds, token_ptr, &send_tok,
402 &ret_flags);
403
404 if (GSS_ERROR(maj_status)) {
405 /* XXX Useles code: Missing send? */
406 if (send_tok.length != 0) {
407 if ((r = sshpkt_start(ssh,
408 SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
409 (r = sshpkt_put_string(ssh, send_tok.value,
410 send_tok.length)) != 0)
411 fatal("sshpkt failed: %s", ssh_err(r));
412 }
413 fatal("gss_init_context failed");
414 }
415
416 /* If we've got an old receive buffer get rid of it */
417 if (token_ptr != GSS_C_NO_BUFFER)
418 gss_release_buffer(&min_status, &recv_tok);
419
420 if (maj_status == GSS_S_COMPLETE) {
421 /* If mutual state flag is not true, kex fails */
422 if (!(ret_flags & GSS_C_MUTUAL_FLAG))
423 fatal("Mutual authentication failed");
424
425 /* If integ avail flag is not true kex fails */
426 if (!(ret_flags & GSS_C_INTEG_FLAG))
427 fatal("Integrity check failed");
428 }
429
430 /*
431 * If we have data to send, then the last message that we
432 * received cannot have been a 'complete'.
433 */
434 if (send_tok.length != 0) {
435 if (first) {
436 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
437 (r = sshpkt_put_string(ssh, send_tok.value,
438 send_tok.length)) != 0 ||
439 (r = sshpkt_put_bignum2(ssh, pub_key)) != 0)
440 fatal("sshpkt failed: %s", ssh_err(r));
441 first = 0;
442 } else {
443 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
444 (r = sshpkt_put_string(ssh,send_tok.value,
445 send_tok.length)) != 0)
446 fatal("sshpkt failed: %s", ssh_err(r));
447 }
448 if ((r = sshpkt_send(ssh)) != 0)
449 fatal("sshpkt_send failed: %s", ssh_err(r));
450 gss_release_buffer(&min_status, &send_tok);
451
452 /* If we've sent them data, they should reply */
453 do {
454 type = ssh_packet_read(ssh);
455 if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
456 debug("Received KEXGSS_HOSTKEY");
457 if (server_host_key_blob)
458 fatal("Server host key received more than once");
459 if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
460 fatal("sshpkt failed: %s", ssh_err(r));
461 }
462 } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
463
464 switch (type) {
465 case SSH2_MSG_KEXGSS_CONTINUE:
466 debug("Received GSSAPI_CONTINUE");
467 if (maj_status == GSS_S_COMPLETE)
468 fatal("GSSAPI Continue received from server when complete");
469 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
470 &recv_tok)) != 0 ||
471 (r = sshpkt_get_end(ssh)) != 0)
472 fatal("sshpkt failed: %s", ssh_err(r));
473 break;
474 case SSH2_MSG_KEXGSS_COMPLETE:
475 debug("Received GSSAPI_COMPLETE");
476 if (msg_tok.value != NULL)
477 fatal("Received GSSAPI_COMPLETE twice?");
478 if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
479 (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
480 &msg_tok)) != 0)
481 fatal("sshpkt failed: %s", ssh_err(r));
482
483 /* Is there a token included? */
484 if ((r = sshpkt_get_u8(ssh, &c)) != 0)
485 fatal("sshpkt failed: %s", ssh_err(r));
486 if (c) {
487 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
488 ssh, &recv_tok)) != 0 ||
489 (r = sshpkt_get_end(ssh)) != 0)
490 fatal("sshpkt failed: %s", ssh_err(r));
491 /* If we're already complete - protocol error */
492 if (maj_status == GSS_S_COMPLETE)
493 sshpkt_disconnect(ssh, "Protocol error: received token when complete");
494 } else {
495 /* No token included */
496 if (maj_status != GSS_S_COMPLETE)
497 sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
498 }
499 break;
500 case SSH2_MSG_KEXGSS_ERROR:
501 debug("Received Error");
502 if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
503 (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
504 (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
505 (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
506 (r = sshpkt_get_end(ssh)) != 0)
507 fatal("sshpkt failed: %s", ssh_err(r));
508 fatal("GSSAPI Error: \n%.400s", msg);
509 default:
510 sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
511 type);
512 }
513 token_ptr = &recv_tok;
514 } else {
515 /* No data, and not complete */
516 if (maj_status != GSS_S_COMPLETE)
517 fatal("Not complete, and no token output");
518 }
519 } while (maj_status & GSS_S_CONTINUE_NEEDED);
520
521 /*
522 * We _must_ have received a COMPLETE message in reply from the
523 * server, which will have set dh_server_pub and msg_tok
524 */
525
526 if (type != SSH2_MSG_KEXGSS_COMPLETE)
527 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
528
529 /* 7. C verifies that the key Q_S is valid */
530 /* 8. C computes shared secret */
531 if ((buf = sshbuf_new()) == NULL ||
532 (r = sshbuf_put_stringb(buf, server_blob)) != 0 ||
533 (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0)
534 goto out;
535 sshbuf_free(buf);
536 buf = NULL;
537
538 if ((shared_secret = sshbuf_new()) == NULL) {
539 r = SSH_ERR_ALLOC_FAIL;
540 goto out;
541 }
542
543 if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
544 goto out;
545 if ((empty = sshbuf_new()) == NULL) {
546 r = SSH_ERR_ALLOC_FAIL;
547 goto out;
548 }
549
550 DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
551 hashlen = sizeof(hash);
552 if ((r = kexgex_hash(
553 kex->hash_alg,
554 kex->client_version,
555 kex->server_version,
556 kex->my,
557 kex->peer,
558 (server_host_key_blob ? server_host_key_blob : empty),
559 kex->min, kex->nbits, kex->max,
560 dh_p, dh_g,
561 pub_key,
562 dh_server_pub,
563 sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
564 hash, &hashlen)) != 0)
565 fatal("Failed to calculate hash: %s", ssh_err(r));
566
567 gssbuf.value = hash;
568 gssbuf.length = hashlen;
569
570 /* Verify that the hash matches the MIC we just got. */
571 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
572 sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
573
574 gss_release_buffer(&min_status, &msg_tok);
320 575
321 /* save session id */ 576 /* save session id */
322 if (ssh->kex->session_id == NULL) { 577 if (kex->session_id == NULL) {
323 ssh->kex->session_id_len = hashlen; 578 kex->session_id_len = hashlen;
324 ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); 579 kex->session_id = xmalloc(kex->session_id_len);
325 memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); 580 memcpy(kex->session_id, hash, kex->session_id_len);
326 } 581 }
327 582
328 if (ssh->kex->gss_deleg_creds) 583 if (kex->gss_deleg_creds)
329 ssh_gssapi_credentials_updated(ctxt); 584 ssh_gssapi_credentials_updated(ctxt);
330 585
331 if (gss_kex_context == NULL) 586 if (gss_kex_context == NULL)
@@ -333,9 +588,19 @@ kexgss_client(struct ssh *ssh) {
333 else 588 else
334 ssh_gssapi_delete_ctx(&ctxt); 589 ssh_gssapi_delete_ctx(&ctxt);
335 590
336 kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); 591 /* Finally derive the keys and send them */
337 BN_clear_free(shared_secret); 592 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
338 return kex_send_newkeys(ssh); 593 r = kex_send_newkeys(ssh);
594out:
595 sshbuf_free(buf);
596 sshbuf_free(server_blob);
597 sshbuf_free(empty);
598 explicit_bzero(hash, sizeof(hash));
599 DH_free(kex->dh);
600 kex->dh = NULL;
601 BN_clear_free(dh_server_pub);
602 sshbuf_free(shared_secret);
603 sshbuf_free(server_host_key_blob);
604 return r;
339} 605}
340 606#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */
341#endif /* GSSAPI */