summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-01-01 17:15:23 +0000
committerColin Watson <cjwatson@debian.org>2010-01-01 17:15:23 +0000
commit99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (patch)
tree1d24ce54c9981ea8cbb4c5a9309964a0e4c4b320 /sshconnect2.c
parent87552344215a38d3a2b0d4d63dc151e05978bbe1 (diff)
parent54af7a4ae8d455791a631bdfaade4b64436ae16a (diff)
import openssh-5.2p1-gsskex-all-20090726.patch
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c356
1 files changed, 338 insertions, 18 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index f7d34bf02..a96153903 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,30 +309,43 @@ 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#endif 315#endif
301 {"hostbased", 316 {"hostbased",
302 userauth_hostbased, 317 userauth_hostbased,
318 NULL,
303 &options.hostbased_authentication, 319 &options.hostbased_authentication,
304 NULL}, 320 NULL},
305 {"publickey", 321 {"publickey",
306 userauth_pubkey, 322 userauth_pubkey,
323 NULL,
307 &options.pubkey_authentication, 324 &options.pubkey_authentication,
308 NULL}, 325 NULL},
326#ifdef JPAKE
327 {"jpake-01@openssh.com",
328 userauth_jpake,
329 userauth_jpake_cleanup,
330 &options.zero_knowledge_password_authentication,
331 &options.batch_mode},
332#endif
309 {"keyboard-interactive", 333 {"keyboard-interactive",
310 userauth_kbdint, 334 userauth_kbdint,
335 NULL,
311 &options.kbd_interactive_authentication, 336 &options.kbd_interactive_authentication,
312 &options.batch_mode}, 337 &options.batch_mode},
313 {"password", 338 {"password",
314 userauth_passwd, 339 userauth_passwd,
340 NULL,
315 &options.password_authentication, 341 &options.password_authentication,
316 &options.batch_mode}, 342 &options.batch_mode},
317 {"none", 343 {"none",
318 userauth_none, 344 userauth_none,
319 NULL, 345 NULL,
346 NULL,
320 NULL}, 347 NULL},
321 {NULL, NULL, NULL, NULL} 348 {NULL, NULL, NULL, NULL, NULL}
322}; 349};
323 350
324void 351void
@@ -386,6 +413,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
386void 413void
387userauth(Authctxt *authctxt, char *authlist) 414userauth(Authctxt *authctxt, char *authlist)
388{ 415{
416 if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
417 authctxt->method->cleanup(authctxt);
418
389 if (authctxt->methoddata) { 419 if (authctxt->methoddata) {
390 xfree(authctxt->methoddata); 420 xfree(authctxt->methoddata);
391 authctxt->methoddata = NULL; 421 authctxt->methoddata = NULL;
@@ -418,6 +448,7 @@ userauth(Authctxt *authctxt, char *authlist)
418 } 448 }
419} 449}
420 450
451/* ARGSUSED */
421void 452void
422input_userauth_error(int type, u_int32_t seq, void *ctxt) 453input_userauth_error(int type, u_int32_t seq, void *ctxt)
423{ 454{
@@ -425,6 +456,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt)
425 "type %d", type); 456 "type %d", type);
426} 457}
427 458
459/* ARGSUSED */
428void 460void
429input_userauth_banner(int type, u_int32_t seq, void *ctxt) 461input_userauth_banner(int type, u_int32_t seq, void *ctxt)
430{ 462{
@@ -434,11 +466,11 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
434 debug3("input_userauth_banner"); 466 debug3("input_userauth_banner");
435 raw = packet_get_string(&len); 467 raw = packet_get_string(&len);
436 lang = packet_get_string(NULL); 468 lang = packet_get_string(NULL);
437 if (options.log_level >= SYSLOG_LEVEL_INFO) { 469 if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
438 if (len > 65536) 470 if (len > 65536)
439 len = 65536; 471 len = 65536;
440 msg = xmalloc(len * 4); /* max expansion from strnvis() */ 472 msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
441 strnvis(msg, raw, len * 4, VIS_SAFE|VIS_OCTAL); 473 strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL);
442 fprintf(stderr, "%s", msg); 474 fprintf(stderr, "%s", msg);
443 xfree(msg); 475 xfree(msg);
444 } 476 }
@@ -446,6 +478,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
446 xfree(lang); 478 xfree(lang);
447} 479}
448 480
481/* ARGSUSED */
449void 482void
450input_userauth_success(int type, u_int32_t seq, void *ctxt) 483input_userauth_success(int type, u_int32_t seq, void *ctxt)
451{ 484{
@@ -463,6 +496,7 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
463 authctxt->success = 1; /* break out */ 496 authctxt->success = 1; /* break out */
464} 497}
465 498
499/* ARGSUSED */
466void 500void
467input_userauth_failure(int type, u_int32_t seq, void *ctxt) 501input_userauth_failure(int type, u_int32_t seq, void *ctxt)
468{ 502{
@@ -483,6 +517,8 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt)
483 517
484 userauth(authctxt, authlist); 518 userauth(authctxt, authlist);
485} 519}
520
521/* ARGSUSED */
486void 522void
487input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) 523input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
488{ 524{
@@ -562,25 +598,29 @@ userauth_gssapi(Authctxt *authctxt)
562 static u_int mech = 0; 598 static u_int mech = 0;
563 OM_uint32 min; 599 OM_uint32 min;
564 int ok = 0; 600 int ok = 0;
565 char *gss_host = NULL; 601 const char *gss_host;
566 602
567 if (options.gss_trust_dns) 603 if (options.gss_trust_dns)
568 gss_host = (char *)get_canonical_hostname(1); 604 gss_host = get_canonical_hostname(1);
569 else 605 else
570 gss_host = (char *)authctxt->host; 606 gss_host = authctxt->host;
571 607
572 /* Try one GSSAPI method at a time, rather than sending them all at 608 /* Try one GSSAPI method at a time, rather than sending them all at
573 * once. */ 609 * once. */
574 610
575 if (gss_supported == NULL) 611 if (gss_supported == NULL)
576 gss_indicate_mechs(&min, &gss_supported); 612 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
613 gss_supported = NULL;
614 return 0;
615 }
577 616
578 /* Check to see if the mechanism is usable before we offer it */ 617 /* Check to see if the mechanism is usable before we offer it */
579 while (mech < gss_supported->count && !ok) { 618 while (mech < gss_supported->count && !ok) {
580 /* My DER encoding requires length<128 */ 619 /* My DER encoding requires length<128 */
581 if (gss_supported->elements[mech].length < 128 && 620 if (gss_supported->elements[mech].length < 128 &&
582 ssh_gssapi_check_mechanism(&gssctxt, 621 ssh_gssapi_check_mechanism(&gssctxt,
583 &gss_supported->elements[mech], gss_host)) { 622 &gss_supported->elements[mech], gss_host,
623 options.gss_client_identity)) {
584 ok = 1; /* Mechanism works */ 624 ok = 1; /* Mechanism works */
585 } else { 625 } else {
586 mech++; 626 mech++;
@@ -671,6 +711,7 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
671 return status; 711 return status;
672} 712}
673 713
714/* ARGSUSED */
674void 715void
675input_gssapi_response(int type, u_int32_t plen, void *ctxt) 716input_gssapi_response(int type, u_int32_t plen, void *ctxt)
676{ 717{
@@ -710,6 +751,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
710 } 751 }
711} 752}
712 753
754/* ARGSUSED */
713void 755void
714input_gssapi_token(int type, u_int32_t plen, void *ctxt) 756input_gssapi_token(int type, u_int32_t plen, void *ctxt)
715{ 757{
@@ -737,6 +779,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
737 } 779 }
738} 780}
739 781
782/* ARGSUSED */
740void 783void
741input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 784input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
742{ 785{
@@ -766,6 +809,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
766 /* Server will be returning a failed packet after this one */ 809 /* Server will be returning a failed packet after this one */
767} 810}
768 811
812/* ARGSUSED */
769void 813void
770input_gssapi_error(int type, u_int32_t plen, void *ctxt) 814input_gssapi_error(int type, u_int32_t plen, void *ctxt)
771{ 815{
@@ -872,9 +916,11 @@ userauth_passwd(Authctxt *authctxt)
872 916
873 return 1; 917 return 1;
874} 918}
919
875/* 920/*
876 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST 921 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
877 */ 922 */
923/* ARGSUSED */
878void 924void
879input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) 925input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
880{ 926{
@@ -939,6 +985,209 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
939 &input_userauth_passwd_changereq); 985 &input_userauth_passwd_changereq);
940} 986}
941 987
988#ifdef JPAKE
989static char *
990pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
991{
992 /* OpenBSD crypt(3) handles all of these */
993 if (strcmp(crypt_scheme, "crypt") == 0 ||
994 strcmp(crypt_scheme, "bcrypt") == 0 ||
995 strcmp(crypt_scheme, "md5crypt") == 0 ||
996 strcmp(crypt_scheme, "crypt-extended") == 0)
997 return xstrdup(crypt(password, salt));
998 error("%s: unsupported password encryption scheme \"%.100s\"",
999 __func__, crypt_scheme);
1000 return NULL;
1001}
1002
1003static BIGNUM *
1004jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
1005 const char *salt)
1006{
1007 char prompt[256], *password, *crypted;
1008 u_char *secret;
1009 u_int secret_len;
1010 BIGNUM *ret;
1011
1012 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
1013 authctxt->server_user, authctxt->host);
1014 password = read_passphrase(prompt, 0);
1015
1016 if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
1017 logit("Disabling %s authentication", authctxt->method->name);
1018 authctxt->method->enabled = NULL;
1019 /* Continue with an empty password to fail gracefully */
1020 crypted = xstrdup("");
1021 }
1022
1023#ifdef JPAKE_DEBUG
1024 debug3("%s: salt = %s", __func__, salt);
1025 debug3("%s: scheme = %s", __func__, crypt_scheme);
1026 debug3("%s: crypted = %s", __func__, crypted);
1027#endif
1028
1029 if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
1030 &secret, &secret_len) != 0)
1031 fatal("%s: hash_buffer", __func__);
1032
1033 bzero(password, strlen(password));
1034 bzero(crypted, strlen(crypted));
1035 xfree(password);
1036 xfree(crypted);
1037
1038 if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
1039 fatal("%s: BN_bin2bn (secret)", __func__);
1040 bzero(secret, secret_len);
1041 xfree(secret);
1042
1043 return ret;
1044}
1045
1046/* ARGSUSED */
1047void
1048input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
1049{
1050 Authctxt *authctxt = ctxt;
1051 struct jpake_ctx *pctx = authctxt->methoddata;
1052 u_char *x3_proof, *x4_proof, *x2_s_proof;
1053 u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
1054 char *crypt_scheme, *salt;
1055
1056 /* Disable this message */
1057 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
1058
1059 if ((pctx->g_x3 = BN_new()) == NULL ||
1060 (pctx->g_x4 = BN_new()) == NULL)
1061 fatal("%s: BN_new", __func__);
1062
1063 /* Fetch step 1 values */
1064 crypt_scheme = packet_get_string(NULL);
1065 salt = packet_get_string(NULL);
1066 pctx->server_id = packet_get_string(&pctx->server_id_len);
1067 packet_get_bignum2(pctx->g_x3);
1068 packet_get_bignum2(pctx->g_x4);
1069 x3_proof = packet_get_string(&x3_proof_len);
1070 x4_proof = packet_get_string(&x4_proof_len);
1071 packet_check_eom();
1072
1073 JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
1074
1075 /* Obtain password and derive secret */
1076 pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
1077 bzero(crypt_scheme, strlen(crypt_scheme));
1078 bzero(salt, strlen(salt));
1079 xfree(crypt_scheme);
1080 xfree(salt);
1081 JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
1082
1083 /* Calculate step 2 values */
1084 jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
1085 pctx->g_x3, pctx->g_x4, pctx->x2,
1086 pctx->server_id, pctx->server_id_len,
1087 pctx->client_id, pctx->client_id_len,
1088 x3_proof, x3_proof_len,
1089 x4_proof, x4_proof_len,
1090 &pctx->a,
1091 &x2_s_proof, &x2_s_proof_len);
1092
1093 bzero(x3_proof, x3_proof_len);
1094 bzero(x4_proof, x4_proof_len);
1095 xfree(x3_proof);
1096 xfree(x4_proof);
1097
1098 JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
1099
1100 /* Send values for step 2 */
1101 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
1102 packet_put_bignum2(pctx->a);
1103 packet_put_string(x2_s_proof, x2_s_proof_len);
1104 packet_send();
1105
1106 bzero(x2_s_proof, x2_s_proof_len);
1107 xfree(x2_s_proof);
1108
1109 /* Expect step 2 packet from peer */
1110 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
1111 input_userauth_jpake_server_step2);
1112}
1113
1114/* ARGSUSED */
1115void
1116input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
1117{
1118 Authctxt *authctxt = ctxt;
1119 struct jpake_ctx *pctx = authctxt->methoddata;
1120 u_char *x4_s_proof;
1121 u_int x4_s_proof_len;
1122
1123 /* Disable this message */
1124 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
1125
1126 if ((pctx->b = BN_new()) == NULL)
1127 fatal("%s: BN_new", __func__);
1128
1129 /* Fetch step 2 values */
1130 packet_get_bignum2(pctx->b);
1131 x4_s_proof = packet_get_string(&x4_s_proof_len);
1132 packet_check_eom();
1133
1134 JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
1135
1136 /* Derive shared key and calculate confirmation hash */
1137 jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
1138 pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
1139 pctx->client_id, pctx->client_id_len,
1140 pctx->server_id, pctx->server_id_len,
1141 session_id2, session_id2_len,
1142 x4_s_proof, x4_s_proof_len,
1143 &pctx->k,
1144 &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
1145
1146 bzero(x4_s_proof, x4_s_proof_len);
1147 xfree(x4_s_proof);
1148
1149 JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
1150
1151 /* Send key confirmation proof */
1152 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
1153 packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
1154 packet_send();
1155
1156 /* Expect confirmation from peer */
1157 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
1158 input_userauth_jpake_server_confirm);
1159}
1160
1161/* ARGSUSED */
1162void
1163input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
1164{
1165 Authctxt *authctxt = ctxt;
1166 struct jpake_ctx *pctx = authctxt->methoddata;
1167
1168 /* Disable this message */
1169 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
1170
1171 pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
1172 packet_check_eom();
1173
1174 JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
1175
1176 /* Verify expected confirmation hash */
1177 if (jpake_check_confirm(pctx->k,
1178 pctx->server_id, pctx->server_id_len,
1179 session_id2, session_id2_len,
1180 pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
1181 debug("%s: %s success", __func__, authctxt->method->name);
1182 else {
1183 debug("%s: confirmation mismatch", __func__);
1184 /* XXX stash this so if auth succeeds then we can warn/kill */
1185 }
1186
1187 userauth_jpake_cleanup(authctxt);
1188}
1189#endif /* JPAKE */
1190
942static int 1191static int
943identity_sign(Identity *id, u_char **sigp, u_int *lenp, 1192identity_sign(Identity *id, u_char **sigp, u_int *lenp,
944 u_char *data, u_int datalen) 1193 u_char *data, u_int datalen)
@@ -1513,6 +1762,76 @@ userauth_hostbased(Authctxt *authctxt)
1513 return 1; 1762 return 1;
1514} 1763}
1515 1764
1765#ifdef JPAKE
1766int
1767userauth_jpake(Authctxt *authctxt)
1768{
1769 struct jpake_ctx *pctx;
1770 u_char *x1_proof, *x2_proof;
1771 u_int x1_proof_len, x2_proof_len;
1772 static int attempt = 0; /* XXX share with userauth_password's? */
1773
1774 if (attempt++ >= options.number_of_password_prompts)
1775 return 0;
1776 if (attempt != 1)
1777 error("Permission denied, please try again.");
1778
1779 if (authctxt->methoddata != NULL)
1780 fatal("%s: authctxt->methoddata already set (%p)",
1781 __func__, authctxt->methoddata);
1782
1783 authctxt->methoddata = pctx = jpake_new();
1784
1785 /*
1786 * Send request immediately, to get the protocol going while
1787 * we do the initial computations.
1788 */
1789 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1790 packet_put_cstring(authctxt->server_user);
1791 packet_put_cstring(authctxt->service);
1792 packet_put_cstring(authctxt->method->name);
1793 packet_send();
1794 packet_write_wait();
1795
1796 jpake_step1(pctx->grp,
1797 &pctx->client_id, &pctx->client_id_len,
1798 &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
1799 &x1_proof, &x1_proof_len,
1800 &x2_proof, &x2_proof_len);
1801
1802 JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
1803
1804 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
1805 packet_put_string(pctx->client_id, pctx->client_id_len);
1806 packet_put_bignum2(pctx->g_x1);
1807 packet_put_bignum2(pctx->g_x2);
1808 packet_put_string(x1_proof, x1_proof_len);
1809 packet_put_string(x2_proof, x2_proof_len);
1810 packet_send();
1811
1812 bzero(x1_proof, x1_proof_len);
1813 bzero(x2_proof, x2_proof_len);
1814 xfree(x1_proof);
1815 xfree(x2_proof);
1816
1817 /* Expect step 1 packet from peer */
1818 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
1819 input_userauth_jpake_server_step1);
1820
1821 return 1;
1822}
1823
1824void
1825userauth_jpake_cleanup(Authctxt *authctxt)
1826{
1827 debug3("%s: clean up", __func__);
1828 if (authctxt->methoddata != NULL) {
1829 jpake_free(authctxt->methoddata);
1830 authctxt->methoddata = NULL;
1831 }
1832}
1833#endif /* JPAKE */
1834
1516/* find auth method */ 1835/* find auth method */
1517 1836
1518/* 1837/*
@@ -1614,3 +1933,4 @@ authmethods_get(void)
1614 buffer_free(&b); 1933 buffer_free(&b);
1615 return list; 1934 return list;
1616} 1935}
1936