summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
committerColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
commitdf03186a4f9e0c2ece398b5c0571cb6263d7a752 (patch)
tree1aab079441dff9615274769b19f2d734ddf508dd /sshconnect2.c
parent6ad6994c288662fca6949f42bf91fec2aff00bca (diff)
parent99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (diff)
* New upstream release (closes: #536182). Yes, I know 5.3p1 has been out
for a while, but there's no GSSAPI patch available for it yet. - Change the default cipher order to prefer the AES CTR modes and the revised "arcfour256" mode to CBC mode ciphers that are susceptible to CPNI-957037 "Plaintext Recovery Attack Against SSH". - Add countermeasures to mitigate CPNI-957037-style attacks against the SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid packet length or Message Authentication Code, ssh/sshd will continue reading up to the maximum supported packet length rather than immediately terminating the connection. This eliminates most of the known differences in behaviour that leaked information about the plaintext of injected data which formed the basis of this attack (closes: #506115, LP: #379329). - ForceCommand directive now accepts commandline arguments for the internal-sftp server (closes: #524423, LP: #362511). - Add AllowAgentForwarding to available Match keywords list (closes: #540623). - Make ssh(1) send the correct channel number for SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to avoid triggering 'Non-public channel' error messages on sshd(8) in openssh-5.1. - Avoid printing 'Non-public channel' warnings in sshd(8), since the ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a behaviour introduced in openssh-5.1; closes: #496017). * Update to GSSAPI patch from http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch, including cascading credentials support (LP: #416958).
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c353
1 files changed, 336 insertions, 17 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 185e7b204..bb72db5dd 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: sshconnect2.c,v 1.166 2008/07/17 08:48:00 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.170 2008/11/04 08:22:13 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
@@ -67,6 +68,7 @@
67#include "msg.h" 68#include "msg.h"
68#include "pathnames.h" 69#include "pathnames.h"
69#include "uidswap.h" 70#include "uidswap.h"
71#include "jpake.h"
70 72
71#ifdef GSSAPI 73#ifdef GSSAPI
72#include "ssh-gss.h" 74#include "ssh-gss.h"
@@ -121,7 +123,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
121 else 123 else
122 gss_host = host; 124 gss_host = host;
123 125
124 gss = ssh_gssapi_client_mechanisms(gss_host); 126 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
125 if (gss) { 127 if (gss) {
126 debug("Offering GSSAPI proposal: %s", gss); 128 debug("Offering GSSAPI proposal: %s", gss);
127 xasprintf(&myproposal[PROPOSAL_KEX_ALGS], 129 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
@@ -164,6 +166,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
164 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; 166 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
165 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 167 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
166 "%s,null", orig); 168 "%s,null", orig);
169 xfree(gss);
167 } 170 }
168#endif 171#endif
169 172
@@ -177,18 +180,23 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
177 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 180 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
178 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 181 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
179#ifdef GSSAPI 182#ifdef GSSAPI
180 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; 183 if (options.gss_keyex) {
181 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; 184 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
182 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; 185 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
186 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
187 }
183#endif 188#endif
184 kex->client_version_string=client_version_string; 189 kex->client_version_string=client_version_string;
185 kex->server_version_string=server_version_string; 190 kex->server_version_string=server_version_string;
186 kex->verify_host_key=&verify_host_key_callback; 191 kex->verify_host_key=&verify_host_key_callback;
187 192
188#ifdef GSSAPI 193#ifdef GSSAPI
189 kex->gss_deleg_creds = options.gss_deleg_creds; 194 if (options.gss_keyex) {
190 kex->gss_trust_dns = options.gss_trust_dns; 195 kex->gss_deleg_creds = options.gss_deleg_creds;
191 kex->gss_host = gss_host; 196 kex->gss_trust_dns = options.gss_trust_dns;
197 kex->gss_client = options.gss_client_identity;
198 kex->gss_host = gss_host;
199 }
192#endif 200#endif
193 201
194 xxx_kex = kex; 202 xxx_kex = kex;
@@ -247,6 +255,7 @@ struct Authctxt {
247struct Authmethod { 255struct Authmethod {
248 char *name; /* string to compare against server's list */ 256 char *name; /* string to compare against server's list */
249 int (*userauth)(Authctxt *authctxt); 257 int (*userauth)(Authctxt *authctxt);
258 void (*cleanup)(Authctxt *authctxt);
250 int *enabled; /* flag in option struct that enables method */ 259 int *enabled; /* flag in option struct that enables method */
251 int *batch_flag; /* flag in option struct that disables method */ 260 int *batch_flag; /* flag in option struct that disables method */
252}; 261};
@@ -258,13 +267,18 @@ void input_userauth_error(int, u_int32_t, void *);
258void input_userauth_info_req(int, u_int32_t, void *); 267void input_userauth_info_req(int, u_int32_t, void *);
259void input_userauth_pk_ok(int, u_int32_t, void *); 268void input_userauth_pk_ok(int, u_int32_t, void *);
260void input_userauth_passwd_changereq(int, u_int32_t, void *); 269void input_userauth_passwd_changereq(int, u_int32_t, void *);
270void input_userauth_jpake_server_step1(int, u_int32_t, void *);
271void input_userauth_jpake_server_step2(int, u_int32_t, void *);
272void input_userauth_jpake_server_confirm(int, u_int32_t, void *);
261 273
262int userauth_none(Authctxt *); 274int userauth_none(Authctxt *);
263int userauth_pubkey(Authctxt *); 275int userauth_pubkey(Authctxt *);
264int userauth_passwd(Authctxt *); 276int userauth_passwd(Authctxt *);
265int userauth_kbdint(Authctxt *); 277int userauth_kbdint(Authctxt *);
266int userauth_hostbased(Authctxt *); 278int userauth_hostbased(Authctxt *);
267int userauth_kerberos(Authctxt *); 279int userauth_jpake(Authctxt *);
280
281void userauth_jpake_cleanup(Authctxt *);
268 282
269#ifdef GSSAPI 283#ifdef GSSAPI
270int userauth_gssapi(Authctxt *authctxt); 284int userauth_gssapi(Authctxt *authctxt);
@@ -295,6 +309,7 @@ Authmethod authmethods[] = {
295 NULL}, 309 NULL},
296 {"gssapi-with-mic", 310 {"gssapi-with-mic",
297 userauth_gssapi, 311 userauth_gssapi,
312 NULL,
298 &options.gss_authentication, 313 &options.gss_authentication,
299 NULL}, 314 NULL},
300 {"gssapi", 315 {"gssapi",
@@ -304,25 +319,37 @@ Authmethod authmethods[] = {
304#endif 319#endif
305 {"hostbased", 320 {"hostbased",
306 userauth_hostbased, 321 userauth_hostbased,
322 NULL,
307 &options.hostbased_authentication, 323 &options.hostbased_authentication,
308 NULL}, 324 NULL},
309 {"publickey", 325 {"publickey",
310 userauth_pubkey, 326 userauth_pubkey,
327 NULL,
311 &options.pubkey_authentication, 328 &options.pubkey_authentication,
312 NULL}, 329 NULL},
330#ifdef JPAKE
331 {"jpake-01@openssh.com",
332 userauth_jpake,
333 userauth_jpake_cleanup,
334 &options.zero_knowledge_password_authentication,
335 &options.batch_mode},
336#endif
313 {"keyboard-interactive", 337 {"keyboard-interactive",
314 userauth_kbdint, 338 userauth_kbdint,
339 NULL,
315 &options.kbd_interactive_authentication, 340 &options.kbd_interactive_authentication,
316 &options.batch_mode}, 341 &options.batch_mode},
317 {"password", 342 {"password",
318 userauth_passwd, 343 userauth_passwd,
344 NULL,
319 &options.password_authentication, 345 &options.password_authentication,
320 &options.batch_mode}, 346 &options.batch_mode},
321 {"none", 347 {"none",
322 userauth_none, 348 userauth_none,
323 NULL, 349 NULL,
350 NULL,
324 NULL}, 351 NULL},
325 {NULL, NULL, NULL, NULL} 352 {NULL, NULL, NULL, NULL, NULL}
326}; 353};
327 354
328void 355void
@@ -390,6 +417,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
390void 417void
391userauth(Authctxt *authctxt, char *authlist) 418userauth(Authctxt *authctxt, char *authlist)
392{ 419{
420 if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
421 authctxt->method->cleanup(authctxt);
422
393 if (authctxt->methoddata) { 423 if (authctxt->methoddata) {
394 xfree(authctxt->methoddata); 424 xfree(authctxt->methoddata);
395 authctxt->methoddata = NULL; 425 authctxt->methoddata = NULL;
@@ -422,6 +452,7 @@ userauth(Authctxt *authctxt, char *authlist)
422 } 452 }
423} 453}
424 454
455/* ARGSUSED */
425void 456void
426input_userauth_error(int type, u_int32_t seq, void *ctxt) 457input_userauth_error(int type, u_int32_t seq, void *ctxt)
427{ 458{
@@ -429,6 +460,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt)
429 "type %d", type); 460 "type %d", type);
430} 461}
431 462
463/* ARGSUSED */
432void 464void
433input_userauth_banner(int type, u_int32_t seq, void *ctxt) 465input_userauth_banner(int type, u_int32_t seq, void *ctxt)
434{ 466{
@@ -438,12 +470,11 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
438 debug3("input_userauth_banner"); 470 debug3("input_userauth_banner");
439 raw = packet_get_string(&len); 471 raw = packet_get_string(&len);
440 lang = packet_get_string(NULL); 472 lang = packet_get_string(NULL);
441 if (options.log_level >= SYSLOG_LEVEL_INFO) { 473 if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
442 if (len > 65536) 474 if (len > 65536)
443 len = 65536; 475 len = 65536;
444 msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */ 476 msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
445 strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL); 477 strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL);
446 msg[len*4] = '\0';
447 fprintf(stderr, "%s", msg); 478 fprintf(stderr, "%s", msg);
448 xfree(msg); 479 xfree(msg);
449 } 480 }
@@ -451,6 +482,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
451 xfree(lang); 482 xfree(lang);
452} 483}
453 484
485/* ARGSUSED */
454void 486void
455input_userauth_success(int type, u_int32_t seq, void *ctxt) 487input_userauth_success(int type, u_int32_t seq, void *ctxt)
456{ 488{
@@ -468,6 +500,7 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
468 authctxt->success = 1; /* break out */ 500 authctxt->success = 1; /* break out */
469} 501}
470 502
503/* ARGSUSED */
471void 504void
472input_userauth_failure(int type, u_int32_t seq, void *ctxt) 505input_userauth_failure(int type, u_int32_t seq, void *ctxt)
473{ 506{
@@ -488,6 +521,8 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt)
488 521
489 userauth(authctxt, authlist); 522 userauth(authctxt, authlist);
490} 523}
524
525/* ARGSUSED */
491void 526void
492input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) 527input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
493{ 528{
@@ -567,26 +602,30 @@ userauth_gssapi(Authctxt *authctxt)
567 static u_int mech = 0; 602 static u_int mech = 0;
568 OM_uint32 min; 603 OM_uint32 min;
569 int ok = 0; 604 int ok = 0;
570 char *gss_host = NULL; 605 const char *gss_host;
571 int old_gssapi_method; 606 int old_gssapi_method;
572 607
573 if (options.gss_trust_dns) 608 if (options.gss_trust_dns)
574 gss_host = (char *)get_canonical_hostname(1); 609 gss_host = get_canonical_hostname(1);
575 else 610 else
576 gss_host = (char *)authctxt->host; 611 gss_host = authctxt->host;
577 612
578 /* Try one GSSAPI method at a time, rather than sending them all at 613 /* Try one GSSAPI method at a time, rather than sending them all at
579 * once. */ 614 * once. */
580 615
581 if (gss_supported == NULL) 616 if (gss_supported == NULL)
582 gss_indicate_mechs(&min, &gss_supported); 617 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
618 gss_supported = NULL;
619 return 0;
620 }
583 621
584 /* Check to see if the mechanism is usable before we offer it */ 622 /* Check to see if the mechanism is usable before we offer it */
585 while (mech < gss_supported->count && !ok) { 623 while (mech < gss_supported->count && !ok) {
586 /* My DER encoding requires length<128 */ 624 /* My DER encoding requires length<128 */
587 if (gss_supported->elements[mech].length < 128 && 625 if (gss_supported->elements[mech].length < 128 &&
588 ssh_gssapi_check_mechanism(&gssctxt, 626 ssh_gssapi_check_mechanism(&gssctxt,
589 &gss_supported->elements[mech], gss_host)) { 627 &gss_supported->elements[mech], gss_host,
628 options.gss_client_identity)) {
590 ok = 1; /* Mechanism works */ 629 ok = 1; /* Mechanism works */
591 } else { 630 } else {
592 mech++; 631 mech++;
@@ -691,6 +730,7 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
691 return status; 730 return status;
692} 731}
693 732
733/* ARGSUSED */
694void 734void
695input_gssapi_response(int type, u_int32_t plen, void *ctxt) 735input_gssapi_response(int type, u_int32_t plen, void *ctxt)
696{ 736{
@@ -736,6 +776,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
736 } 776 }
737} 777}
738 778
779/* ARGSUSED */
739void 780void
740input_gssapi_token(int type, u_int32_t plen, void *ctxt) 781input_gssapi_token(int type, u_int32_t plen, void *ctxt)
741{ 782{
@@ -763,6 +804,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
763 } 804 }
764} 805}
765 806
807/* ARGSUSED */
766void 808void
767input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 809input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
768{ 810{
@@ -792,6 +834,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
792 /* Server will be returning a failed packet after this one */ 834 /* Server will be returning a failed packet after this one */
793} 835}
794 836
837/* ARGSUSED */
795void 838void
796input_gssapi_error(int type, u_int32_t plen, void *ctxt) 839input_gssapi_error(int type, u_int32_t plen, void *ctxt)
797{ 840{
@@ -898,9 +941,11 @@ userauth_passwd(Authctxt *authctxt)
898 941
899 return 1; 942 return 1;
900} 943}
944
901/* 945/*
902 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST 946 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
903 */ 947 */
948/* ARGSUSED */
904void 949void
905input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) 950input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
906{ 951{
@@ -965,6 +1010,209 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
965 &input_userauth_passwd_changereq); 1010 &input_userauth_passwd_changereq);
966} 1011}
967 1012
1013#ifdef JPAKE
1014static char *
1015pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
1016{
1017 /* OpenBSD crypt(3) handles all of these */
1018 if (strcmp(crypt_scheme, "crypt") == 0 ||
1019 strcmp(crypt_scheme, "bcrypt") == 0 ||
1020 strcmp(crypt_scheme, "md5crypt") == 0 ||
1021 strcmp(crypt_scheme, "crypt-extended") == 0)
1022 return xstrdup(crypt(password, salt));
1023 error("%s: unsupported password encryption scheme \"%.100s\"",
1024 __func__, crypt_scheme);
1025 return NULL;
1026}
1027
1028static BIGNUM *
1029jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
1030 const char *salt)
1031{
1032 char prompt[256], *password, *crypted;
1033 u_char *secret;
1034 u_int secret_len;
1035 BIGNUM *ret;
1036
1037 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
1038 authctxt->server_user, authctxt->host);
1039 password = read_passphrase(prompt, 0);
1040
1041 if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
1042 logit("Disabling %s authentication", authctxt->method->name);
1043 authctxt->method->enabled = NULL;
1044 /* Continue with an empty password to fail gracefully */
1045 crypted = xstrdup("");
1046 }
1047
1048#ifdef JPAKE_DEBUG
1049 debug3("%s: salt = %s", __func__, salt);
1050 debug3("%s: scheme = %s", __func__, crypt_scheme);
1051 debug3("%s: crypted = %s", __func__, crypted);
1052#endif
1053
1054 if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
1055 &secret, &secret_len) != 0)
1056 fatal("%s: hash_buffer", __func__);
1057
1058 bzero(password, strlen(password));
1059 bzero(crypted, strlen(crypted));
1060 xfree(password);
1061 xfree(crypted);
1062
1063 if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
1064 fatal("%s: BN_bin2bn (secret)", __func__);
1065 bzero(secret, secret_len);
1066 xfree(secret);
1067
1068 return ret;
1069}
1070
1071/* ARGSUSED */
1072void
1073input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
1074{
1075 Authctxt *authctxt = ctxt;
1076 struct jpake_ctx *pctx = authctxt->methoddata;
1077 u_char *x3_proof, *x4_proof, *x2_s_proof;
1078 u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
1079 char *crypt_scheme, *salt;
1080
1081 /* Disable this message */
1082 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
1083
1084 if ((pctx->g_x3 = BN_new()) == NULL ||
1085 (pctx->g_x4 = BN_new()) == NULL)
1086 fatal("%s: BN_new", __func__);
1087
1088 /* Fetch step 1 values */
1089 crypt_scheme = packet_get_string(NULL);
1090 salt = packet_get_string(NULL);
1091 pctx->server_id = packet_get_string(&pctx->server_id_len);
1092 packet_get_bignum2(pctx->g_x3);
1093 packet_get_bignum2(pctx->g_x4);
1094 x3_proof = packet_get_string(&x3_proof_len);
1095 x4_proof = packet_get_string(&x4_proof_len);
1096 packet_check_eom();
1097
1098 JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
1099
1100 /* Obtain password and derive secret */
1101 pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
1102 bzero(crypt_scheme, strlen(crypt_scheme));
1103 bzero(salt, strlen(salt));
1104 xfree(crypt_scheme);
1105 xfree(salt);
1106 JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
1107
1108 /* Calculate step 2 values */
1109 jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
1110 pctx->g_x3, pctx->g_x4, pctx->x2,
1111 pctx->server_id, pctx->server_id_len,
1112 pctx->client_id, pctx->client_id_len,
1113 x3_proof, x3_proof_len,
1114 x4_proof, x4_proof_len,
1115 &pctx->a,
1116 &x2_s_proof, &x2_s_proof_len);
1117
1118 bzero(x3_proof, x3_proof_len);
1119 bzero(x4_proof, x4_proof_len);
1120 xfree(x3_proof);
1121 xfree(x4_proof);
1122
1123 JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
1124
1125 /* Send values for step 2 */
1126 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
1127 packet_put_bignum2(pctx->a);
1128 packet_put_string(x2_s_proof, x2_s_proof_len);
1129 packet_send();
1130
1131 bzero(x2_s_proof, x2_s_proof_len);
1132 xfree(x2_s_proof);
1133
1134 /* Expect step 2 packet from peer */
1135 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
1136 input_userauth_jpake_server_step2);
1137}
1138
1139/* ARGSUSED */
1140void
1141input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
1142{
1143 Authctxt *authctxt = ctxt;
1144 struct jpake_ctx *pctx = authctxt->methoddata;
1145 u_char *x4_s_proof;
1146 u_int x4_s_proof_len;
1147
1148 /* Disable this message */
1149 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
1150
1151 if ((pctx->b = BN_new()) == NULL)
1152 fatal("%s: BN_new", __func__);
1153
1154 /* Fetch step 2 values */
1155 packet_get_bignum2(pctx->b);
1156 x4_s_proof = packet_get_string(&x4_s_proof_len);
1157 packet_check_eom();
1158
1159 JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
1160
1161 /* Derive shared key and calculate confirmation hash */
1162 jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
1163 pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
1164 pctx->client_id, pctx->client_id_len,
1165 pctx->server_id, pctx->server_id_len,
1166 session_id2, session_id2_len,
1167 x4_s_proof, x4_s_proof_len,
1168 &pctx->k,
1169 &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
1170
1171 bzero(x4_s_proof, x4_s_proof_len);
1172 xfree(x4_s_proof);
1173
1174 JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
1175
1176 /* Send key confirmation proof */
1177 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
1178 packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
1179 packet_send();
1180
1181 /* Expect confirmation from peer */
1182 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
1183 input_userauth_jpake_server_confirm);
1184}
1185
1186/* ARGSUSED */
1187void
1188input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
1189{
1190 Authctxt *authctxt = ctxt;
1191 struct jpake_ctx *pctx = authctxt->methoddata;
1192
1193 /* Disable this message */
1194 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
1195
1196 pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
1197 packet_check_eom();
1198
1199 JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
1200
1201 /* Verify expected confirmation hash */
1202 if (jpake_check_confirm(pctx->k,
1203 pctx->server_id, pctx->server_id_len,
1204 session_id2, session_id2_len,
1205 pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
1206 debug("%s: %s success", __func__, authctxt->method->name);
1207 else {
1208 debug("%s: confirmation mismatch", __func__);
1209 /* XXX stash this so if auth succeeds then we can warn/kill */
1210 }
1211
1212 userauth_jpake_cleanup(authctxt);
1213}
1214#endif /* JPAKE */
1215
968static int 1216static int
969identity_sign(Identity *id, u_char **sigp, u_int *lenp, 1217identity_sign(Identity *id, u_char **sigp, u_int *lenp,
970 u_char *data, u_int datalen) 1218 u_char *data, u_int datalen)
@@ -1541,6 +1789,76 @@ userauth_hostbased(Authctxt *authctxt)
1541 return 1; 1789 return 1;
1542} 1790}
1543 1791
1792#ifdef JPAKE
1793int
1794userauth_jpake(Authctxt *authctxt)
1795{
1796 struct jpake_ctx *pctx;
1797 u_char *x1_proof, *x2_proof;
1798 u_int x1_proof_len, x2_proof_len;
1799 static int attempt = 0; /* XXX share with userauth_password's? */
1800
1801 if (attempt++ >= options.number_of_password_prompts)
1802 return 0;
1803 if (attempt != 1)
1804 error("Permission denied, please try again.");
1805
1806 if (authctxt->methoddata != NULL)
1807 fatal("%s: authctxt->methoddata already set (%p)",
1808 __func__, authctxt->methoddata);
1809
1810 authctxt->methoddata = pctx = jpake_new();
1811
1812 /*
1813 * Send request immediately, to get the protocol going while
1814 * we do the initial computations.
1815 */
1816 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1817 packet_put_cstring(authctxt->server_user);
1818 packet_put_cstring(authctxt->service);
1819 packet_put_cstring(authctxt->method->name);
1820 packet_send();
1821 packet_write_wait();
1822
1823 jpake_step1(pctx->grp,
1824 &pctx->client_id, &pctx->client_id_len,
1825 &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
1826 &x1_proof, &x1_proof_len,
1827 &x2_proof, &x2_proof_len);
1828
1829 JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
1830
1831 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
1832 packet_put_string(pctx->client_id, pctx->client_id_len);
1833 packet_put_bignum2(pctx->g_x1);
1834 packet_put_bignum2(pctx->g_x2);
1835 packet_put_string(x1_proof, x1_proof_len);
1836 packet_put_string(x2_proof, x2_proof_len);
1837 packet_send();
1838
1839 bzero(x1_proof, x1_proof_len);
1840 bzero(x2_proof, x2_proof_len);
1841 xfree(x1_proof);
1842 xfree(x2_proof);
1843
1844 /* Expect step 1 packet from peer */
1845 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
1846 input_userauth_jpake_server_step1);
1847
1848 return 1;
1849}
1850
1851void
1852userauth_jpake_cleanup(Authctxt *authctxt)
1853{
1854 debug3("%s: clean up", __func__);
1855 if (authctxt->methoddata != NULL) {
1856 jpake_free(authctxt->methoddata);
1857 authctxt->methoddata = NULL;
1858 }
1859}
1860#endif /* JPAKE */
1861
1544/* find auth method */ 1862/* find auth method */
1545 1863
1546/* 1864/*
@@ -1642,3 +1960,4 @@ authmethods_get(void)
1642 buffer_free(&b); 1960 buffer_free(&b);
1643 return list; 1961 return list;
1644} 1962}
1963