diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 322 |
1 files changed, 316 insertions, 6 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 389bec9e4..a762eec3b 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" |
@@ -201,6 +203,7 @@ struct Authctxt { | |||
201 | struct Authmethod { | 203 | struct Authmethod { |
202 | char *name; /* string to compare against server's list */ | 204 | char *name; /* string to compare against server's list */ |
203 | int (*userauth)(Authctxt *authctxt); | 205 | int (*userauth)(Authctxt *authctxt); |
206 | void (*cleanup)(Authctxt *authctxt); | ||
204 | int *enabled; /* flag in option struct that enables method */ | 207 | int *enabled; /* flag in option struct that enables method */ |
205 | int *batch_flag; /* flag in option struct that disables method */ | 208 | int *batch_flag; /* flag in option struct that disables method */ |
206 | }; | 209 | }; |
@@ -212,13 +215,18 @@ void input_userauth_error(int, u_int32_t, void *); | |||
212 | void input_userauth_info_req(int, u_int32_t, void *); | 215 | void input_userauth_info_req(int, u_int32_t, void *); |
213 | void input_userauth_pk_ok(int, u_int32_t, void *); | 216 | void input_userauth_pk_ok(int, u_int32_t, void *); |
214 | void input_userauth_passwd_changereq(int, u_int32_t, void *); | 217 | void input_userauth_passwd_changereq(int, u_int32_t, void *); |
218 | void input_userauth_jpake_server_step1(int, u_int32_t, void *); | ||
219 | void input_userauth_jpake_server_step2(int, u_int32_t, void *); | ||
220 | void input_userauth_jpake_server_confirm(int, u_int32_t, void *); | ||
215 | 221 | ||
216 | int userauth_none(Authctxt *); | 222 | int userauth_none(Authctxt *); |
217 | int userauth_pubkey(Authctxt *); | 223 | int userauth_pubkey(Authctxt *); |
218 | int userauth_passwd(Authctxt *); | 224 | int userauth_passwd(Authctxt *); |
219 | int userauth_kbdint(Authctxt *); | 225 | int userauth_kbdint(Authctxt *); |
220 | int userauth_hostbased(Authctxt *); | 226 | int userauth_hostbased(Authctxt *); |
221 | int userauth_kerberos(Authctxt *); | 227 | int userauth_jpake(Authctxt *); |
228 | |||
229 | void userauth_jpake_cleanup(Authctxt *); | ||
222 | 230 | ||
223 | #ifdef GSSAPI | 231 | #ifdef GSSAPI |
224 | int userauth_gssapi(Authctxt *authctxt); | 232 | int userauth_gssapi(Authctxt *authctxt); |
@@ -244,30 +252,43 @@ Authmethod authmethods[] = { | |||
244 | #ifdef GSSAPI | 252 | #ifdef GSSAPI |
245 | {"gssapi-with-mic", | 253 | {"gssapi-with-mic", |
246 | userauth_gssapi, | 254 | userauth_gssapi, |
255 | NULL, | ||
247 | &options.gss_authentication, | 256 | &options.gss_authentication, |
248 | NULL}, | 257 | NULL}, |
249 | #endif | 258 | #endif |
250 | {"hostbased", | 259 | {"hostbased", |
251 | userauth_hostbased, | 260 | userauth_hostbased, |
261 | NULL, | ||
252 | &options.hostbased_authentication, | 262 | &options.hostbased_authentication, |
253 | NULL}, | 263 | NULL}, |
254 | {"publickey", | 264 | {"publickey", |
255 | userauth_pubkey, | 265 | userauth_pubkey, |
266 | NULL, | ||
256 | &options.pubkey_authentication, | 267 | &options.pubkey_authentication, |
257 | NULL}, | 268 | NULL}, |
269 | #ifdef JPAKE | ||
270 | {"jpake-01@openssh.com", | ||
271 | userauth_jpake, | ||
272 | userauth_jpake_cleanup, | ||
273 | &options.zero_knowledge_password_authentication, | ||
274 | &options.batch_mode}, | ||
275 | #endif | ||
258 | {"keyboard-interactive", | 276 | {"keyboard-interactive", |
259 | userauth_kbdint, | 277 | userauth_kbdint, |
278 | NULL, | ||
260 | &options.kbd_interactive_authentication, | 279 | &options.kbd_interactive_authentication, |
261 | &options.batch_mode}, | 280 | &options.batch_mode}, |
262 | {"password", | 281 | {"password", |
263 | userauth_passwd, | 282 | userauth_passwd, |
283 | NULL, | ||
264 | &options.password_authentication, | 284 | &options.password_authentication, |
265 | &options.batch_mode}, | 285 | &options.batch_mode}, |
266 | {"none", | 286 | {"none", |
267 | userauth_none, | 287 | userauth_none, |
268 | NULL, | 288 | NULL, |
289 | NULL, | ||
269 | NULL}, | 290 | NULL}, |
270 | {NULL, NULL, NULL, NULL} | 291 | {NULL, NULL, NULL, NULL, NULL} |
271 | }; | 292 | }; |
272 | 293 | ||
273 | void | 294 | void |
@@ -335,6 +356,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, | |||
335 | void | 356 | void |
336 | userauth(Authctxt *authctxt, char *authlist) | 357 | userauth(Authctxt *authctxt, char *authlist) |
337 | { | 358 | { |
359 | if (authctxt->method != NULL && authctxt->method->cleanup != NULL) | ||
360 | authctxt->method->cleanup(authctxt); | ||
361 | |||
338 | if (authctxt->methoddata) { | 362 | if (authctxt->methoddata) { |
339 | xfree(authctxt->methoddata); | 363 | xfree(authctxt->methoddata); |
340 | authctxt->methoddata = NULL; | 364 | authctxt->methoddata = NULL; |
@@ -367,6 +391,7 @@ userauth(Authctxt *authctxt, char *authlist) | |||
367 | } | 391 | } |
368 | } | 392 | } |
369 | 393 | ||
394 | /* ARGSUSED */ | ||
370 | void | 395 | void |
371 | input_userauth_error(int type, u_int32_t seq, void *ctxt) | 396 | input_userauth_error(int type, u_int32_t seq, void *ctxt) |
372 | { | 397 | { |
@@ -374,6 +399,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt) | |||
374 | "type %d", type); | 399 | "type %d", type); |
375 | } | 400 | } |
376 | 401 | ||
402 | /* ARGSUSED */ | ||
377 | void | 403 | void |
378 | input_userauth_banner(int type, u_int32_t seq, void *ctxt) | 404 | input_userauth_banner(int type, u_int32_t seq, void *ctxt) |
379 | { | 405 | { |
@@ -383,11 +409,11 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) | |||
383 | debug3("input_userauth_banner"); | 409 | debug3("input_userauth_banner"); |
384 | raw = packet_get_string(&len); | 410 | raw = packet_get_string(&len); |
385 | lang = packet_get_string(NULL); | 411 | lang = packet_get_string(NULL); |
386 | if (options.log_level >= SYSLOG_LEVEL_INFO) { | 412 | if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) { |
387 | if (len > 65536) | 413 | if (len > 65536) |
388 | len = 65536; | 414 | len = 65536; |
389 | msg = xmalloc(len * 4); /* max expansion from strnvis() */ | 415 | msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */ |
390 | strnvis(msg, raw, len * 4, VIS_SAFE|VIS_OCTAL); | 416 | strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL); |
391 | fprintf(stderr, "%s", msg); | 417 | fprintf(stderr, "%s", msg); |
392 | xfree(msg); | 418 | xfree(msg); |
393 | } | 419 | } |
@@ -395,6 +421,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) | |||
395 | xfree(lang); | 421 | xfree(lang); |
396 | } | 422 | } |
397 | 423 | ||
424 | /* ARGSUSED */ | ||
398 | void | 425 | void |
399 | input_userauth_success(int type, u_int32_t seq, void *ctxt) | 426 | input_userauth_success(int type, u_int32_t seq, void *ctxt) |
400 | { | 427 | { |
@@ -412,6 +439,7 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt) | |||
412 | authctxt->success = 1; /* break out */ | 439 | authctxt->success = 1; /* break out */ |
413 | } | 440 | } |
414 | 441 | ||
442 | /* ARGSUSED */ | ||
415 | void | 443 | void |
416 | input_userauth_failure(int type, u_int32_t seq, void *ctxt) | 444 | input_userauth_failure(int type, u_int32_t seq, void *ctxt) |
417 | { | 445 | { |
@@ -432,6 +460,8 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt) | |||
432 | 460 | ||
433 | userauth(authctxt, authlist); | 461 | userauth(authctxt, authlist); |
434 | } | 462 | } |
463 | |||
464 | /* ARGSUSED */ | ||
435 | void | 465 | void |
436 | input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) | 466 | input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) |
437 | { | 467 | { |
@@ -614,6 +644,7 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) | |||
614 | return status; | 644 | return status; |
615 | } | 645 | } |
616 | 646 | ||
647 | /* ARGSUSED */ | ||
617 | void | 648 | void |
618 | input_gssapi_response(int type, u_int32_t plen, void *ctxt) | 649 | input_gssapi_response(int type, u_int32_t plen, void *ctxt) |
619 | { | 650 | { |
@@ -653,6 +684,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | |||
653 | } | 684 | } |
654 | } | 685 | } |
655 | 686 | ||
687 | /* ARGSUSED */ | ||
656 | void | 688 | void |
657 | input_gssapi_token(int type, u_int32_t plen, void *ctxt) | 689 | input_gssapi_token(int type, u_int32_t plen, void *ctxt) |
658 | { | 690 | { |
@@ -680,6 +712,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) | |||
680 | } | 712 | } |
681 | } | 713 | } |
682 | 714 | ||
715 | /* ARGSUSED */ | ||
683 | void | 716 | void |
684 | input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) | 717 | input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) |
685 | { | 718 | { |
@@ -709,6 +742,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) | |||
709 | /* Server will be returning a failed packet after this one */ | 742 | /* Server will be returning a failed packet after this one */ |
710 | } | 743 | } |
711 | 744 | ||
745 | /* ARGSUSED */ | ||
712 | void | 746 | void |
713 | input_gssapi_error(int type, u_int32_t plen, void *ctxt) | 747 | input_gssapi_error(int type, u_int32_t plen, void *ctxt) |
714 | { | 748 | { |
@@ -773,9 +807,11 @@ userauth_passwd(Authctxt *authctxt) | |||
773 | 807 | ||
774 | return 1; | 808 | return 1; |
775 | } | 809 | } |
810 | |||
776 | /* | 811 | /* |
777 | * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST | 812 | * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST |
778 | */ | 813 | */ |
814 | /* ARGSUSED */ | ||
779 | void | 815 | void |
780 | input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) | 816 | input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) |
781 | { | 817 | { |
@@ -840,6 +876,209 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) | |||
840 | &input_userauth_passwd_changereq); | 876 | &input_userauth_passwd_changereq); |
841 | } | 877 | } |
842 | 878 | ||
879 | #ifdef JPAKE | ||
880 | static char * | ||
881 | pw_encrypt(const char *password, const char *crypt_scheme, const char *salt) | ||
882 | { | ||
883 | /* OpenBSD crypt(3) handles all of these */ | ||
884 | if (strcmp(crypt_scheme, "crypt") == 0 || | ||
885 | strcmp(crypt_scheme, "bcrypt") == 0 || | ||
886 | strcmp(crypt_scheme, "md5crypt") == 0 || | ||
887 | strcmp(crypt_scheme, "crypt-extended") == 0) | ||
888 | return xstrdup(crypt(password, salt)); | ||
889 | error("%s: unsupported password encryption scheme \"%.100s\"", | ||
890 | __func__, crypt_scheme); | ||
891 | return NULL; | ||
892 | } | ||
893 | |||
894 | static BIGNUM * | ||
895 | jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme, | ||
896 | const char *salt) | ||
897 | { | ||
898 | char prompt[256], *password, *crypted; | ||
899 | u_char *secret; | ||
900 | u_int secret_len; | ||
901 | BIGNUM *ret; | ||
902 | |||
903 | snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ", | ||
904 | authctxt->server_user, authctxt->host); | ||
905 | password = read_passphrase(prompt, 0); | ||
906 | |||
907 | if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) { | ||
908 | logit("Disabling %s authentication", authctxt->method->name); | ||
909 | authctxt->method->enabled = NULL; | ||
910 | /* Continue with an empty password to fail gracefully */ | ||
911 | crypted = xstrdup(""); | ||
912 | } | ||
913 | |||
914 | #ifdef JPAKE_DEBUG | ||
915 | debug3("%s: salt = %s", __func__, salt); | ||
916 | debug3("%s: scheme = %s", __func__, crypt_scheme); | ||
917 | debug3("%s: crypted = %s", __func__, crypted); | ||
918 | #endif | ||
919 | |||
920 | if (hash_buffer(crypted, strlen(crypted), EVP_sha256(), | ||
921 | &secret, &secret_len) != 0) | ||
922 | fatal("%s: hash_buffer", __func__); | ||
923 | |||
924 | bzero(password, strlen(password)); | ||
925 | bzero(crypted, strlen(crypted)); | ||
926 | xfree(password); | ||
927 | xfree(crypted); | ||
928 | |||
929 | if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL) | ||
930 | fatal("%s: BN_bin2bn (secret)", __func__); | ||
931 | bzero(secret, secret_len); | ||
932 | xfree(secret); | ||
933 | |||
934 | return ret; | ||
935 | } | ||
936 | |||
937 | /* ARGSUSED */ | ||
938 | void | ||
939 | input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt) | ||
940 | { | ||
941 | Authctxt *authctxt = ctxt; | ||
942 | struct jpake_ctx *pctx = authctxt->methoddata; | ||
943 | u_char *x3_proof, *x4_proof, *x2_s_proof; | ||
944 | u_int x3_proof_len, x4_proof_len, x2_s_proof_len; | ||
945 | char *crypt_scheme, *salt; | ||
946 | |||
947 | /* Disable this message */ | ||
948 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL); | ||
949 | |||
950 | if ((pctx->g_x3 = BN_new()) == NULL || | ||
951 | (pctx->g_x4 = BN_new()) == NULL) | ||
952 | fatal("%s: BN_new", __func__); | ||
953 | |||
954 | /* Fetch step 1 values */ | ||
955 | crypt_scheme = packet_get_string(NULL); | ||
956 | salt = packet_get_string(NULL); | ||
957 | pctx->server_id = packet_get_string(&pctx->server_id_len); | ||
958 | packet_get_bignum2(pctx->g_x3); | ||
959 | packet_get_bignum2(pctx->g_x4); | ||
960 | x3_proof = packet_get_string(&x3_proof_len); | ||
961 | x4_proof = packet_get_string(&x4_proof_len); | ||
962 | packet_check_eom(); | ||
963 | |||
964 | JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__)); | ||
965 | |||
966 | /* Obtain password and derive secret */ | ||
967 | pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt); | ||
968 | bzero(crypt_scheme, strlen(crypt_scheme)); | ||
969 | bzero(salt, strlen(salt)); | ||
970 | xfree(crypt_scheme); | ||
971 | xfree(salt); | ||
972 | JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__)); | ||
973 | |||
974 | /* Calculate step 2 values */ | ||
975 | jpake_step2(pctx->grp, pctx->s, pctx->g_x1, | ||
976 | pctx->g_x3, pctx->g_x4, pctx->x2, | ||
977 | pctx->server_id, pctx->server_id_len, | ||
978 | pctx->client_id, pctx->client_id_len, | ||
979 | x3_proof, x3_proof_len, | ||
980 | x4_proof, x4_proof_len, | ||
981 | &pctx->a, | ||
982 | &x2_s_proof, &x2_s_proof_len); | ||
983 | |||
984 | bzero(x3_proof, x3_proof_len); | ||
985 | bzero(x4_proof, x4_proof_len); | ||
986 | xfree(x3_proof); | ||
987 | xfree(x4_proof); | ||
988 | |||
989 | JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__)); | ||
990 | |||
991 | /* Send values for step 2 */ | ||
992 | packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2); | ||
993 | packet_put_bignum2(pctx->a); | ||
994 | packet_put_string(x2_s_proof, x2_s_proof_len); | ||
995 | packet_send(); | ||
996 | |||
997 | bzero(x2_s_proof, x2_s_proof_len); | ||
998 | xfree(x2_s_proof); | ||
999 | |||
1000 | /* Expect step 2 packet from peer */ | ||
1001 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, | ||
1002 | input_userauth_jpake_server_step2); | ||
1003 | } | ||
1004 | |||
1005 | /* ARGSUSED */ | ||
1006 | void | ||
1007 | input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt) | ||
1008 | { | ||
1009 | Authctxt *authctxt = ctxt; | ||
1010 | struct jpake_ctx *pctx = authctxt->methoddata; | ||
1011 | u_char *x4_s_proof; | ||
1012 | u_int x4_s_proof_len; | ||
1013 | |||
1014 | /* Disable this message */ | ||
1015 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL); | ||
1016 | |||
1017 | if ((pctx->b = BN_new()) == NULL) | ||
1018 | fatal("%s: BN_new", __func__); | ||
1019 | |||
1020 | /* Fetch step 2 values */ | ||
1021 | packet_get_bignum2(pctx->b); | ||
1022 | x4_s_proof = packet_get_string(&x4_s_proof_len); | ||
1023 | packet_check_eom(); | ||
1024 | |||
1025 | JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__)); | ||
1026 | |||
1027 | /* Derive shared key and calculate confirmation hash */ | ||
1028 | jpake_key_confirm(pctx->grp, pctx->s, pctx->b, | ||
1029 | pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4, | ||
1030 | pctx->client_id, pctx->client_id_len, | ||
1031 | pctx->server_id, pctx->server_id_len, | ||
1032 | session_id2, session_id2_len, | ||
1033 | x4_s_proof, x4_s_proof_len, | ||
1034 | &pctx->k, | ||
1035 | &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len); | ||
1036 | |||
1037 | bzero(x4_s_proof, x4_s_proof_len); | ||
1038 | xfree(x4_s_proof); | ||
1039 | |||
1040 | JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__)); | ||
1041 | |||
1042 | /* Send key confirmation proof */ | ||
1043 | packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM); | ||
1044 | packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len); | ||
1045 | packet_send(); | ||
1046 | |||
1047 | /* Expect confirmation from peer */ | ||
1048 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, | ||
1049 | input_userauth_jpake_server_confirm); | ||
1050 | } | ||
1051 | |||
1052 | /* ARGSUSED */ | ||
1053 | void | ||
1054 | input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt) | ||
1055 | { | ||
1056 | Authctxt *authctxt = ctxt; | ||
1057 | struct jpake_ctx *pctx = authctxt->methoddata; | ||
1058 | |||
1059 | /* Disable this message */ | ||
1060 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL); | ||
1061 | |||
1062 | pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len); | ||
1063 | packet_check_eom(); | ||
1064 | |||
1065 | JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__)); | ||
1066 | |||
1067 | /* Verify expected confirmation hash */ | ||
1068 | if (jpake_check_confirm(pctx->k, | ||
1069 | pctx->server_id, pctx->server_id_len, | ||
1070 | session_id2, session_id2_len, | ||
1071 | pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1) | ||
1072 | debug("%s: %s success", __func__, authctxt->method->name); | ||
1073 | else { | ||
1074 | debug("%s: confirmation mismatch", __func__); | ||
1075 | /* XXX stash this so if auth succeeds then we can warn/kill */ | ||
1076 | } | ||
1077 | |||
1078 | userauth_jpake_cleanup(authctxt); | ||
1079 | } | ||
1080 | #endif /* JPAKE */ | ||
1081 | |||
843 | static int | 1082 | static int |
844 | identity_sign(Identity *id, u_char **sigp, u_int *lenp, | 1083 | identity_sign(Identity *id, u_char **sigp, u_int *lenp, |
845 | u_char *data, u_int datalen) | 1084 | u_char *data, u_int datalen) |
@@ -1414,6 +1653,76 @@ userauth_hostbased(Authctxt *authctxt) | |||
1414 | return 1; | 1653 | return 1; |
1415 | } | 1654 | } |
1416 | 1655 | ||
1656 | #ifdef JPAKE | ||
1657 | int | ||
1658 | userauth_jpake(Authctxt *authctxt) | ||
1659 | { | ||
1660 | struct jpake_ctx *pctx; | ||
1661 | u_char *x1_proof, *x2_proof; | ||
1662 | u_int x1_proof_len, x2_proof_len; | ||
1663 | static int attempt = 0; /* XXX share with userauth_password's? */ | ||
1664 | |||
1665 | if (attempt++ >= options.number_of_password_prompts) | ||
1666 | return 0; | ||
1667 | if (attempt != 1) | ||
1668 | error("Permission denied, please try again."); | ||
1669 | |||
1670 | if (authctxt->methoddata != NULL) | ||
1671 | fatal("%s: authctxt->methoddata already set (%p)", | ||
1672 | __func__, authctxt->methoddata); | ||
1673 | |||
1674 | authctxt->methoddata = pctx = jpake_new(); | ||
1675 | |||
1676 | /* | ||
1677 | * Send request immediately, to get the protocol going while | ||
1678 | * we do the initial computations. | ||
1679 | */ | ||
1680 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | ||
1681 | packet_put_cstring(authctxt->server_user); | ||
1682 | packet_put_cstring(authctxt->service); | ||
1683 | packet_put_cstring(authctxt->method->name); | ||
1684 | packet_send(); | ||
1685 | packet_write_wait(); | ||
1686 | |||
1687 | jpake_step1(pctx->grp, | ||
1688 | &pctx->client_id, &pctx->client_id_len, | ||
1689 | &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2, | ||
1690 | &x1_proof, &x1_proof_len, | ||
1691 | &x2_proof, &x2_proof_len); | ||
1692 | |||
1693 | JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__)); | ||
1694 | |||
1695 | packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1); | ||
1696 | packet_put_string(pctx->client_id, pctx->client_id_len); | ||
1697 | packet_put_bignum2(pctx->g_x1); | ||
1698 | packet_put_bignum2(pctx->g_x2); | ||
1699 | packet_put_string(x1_proof, x1_proof_len); | ||
1700 | packet_put_string(x2_proof, x2_proof_len); | ||
1701 | packet_send(); | ||
1702 | |||
1703 | bzero(x1_proof, x1_proof_len); | ||
1704 | bzero(x2_proof, x2_proof_len); | ||
1705 | xfree(x1_proof); | ||
1706 | xfree(x2_proof); | ||
1707 | |||
1708 | /* Expect step 1 packet from peer */ | ||
1709 | dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, | ||
1710 | input_userauth_jpake_server_step1); | ||
1711 | |||
1712 | return 1; | ||
1713 | } | ||
1714 | |||
1715 | void | ||
1716 | userauth_jpake_cleanup(Authctxt *authctxt) | ||
1717 | { | ||
1718 | debug3("%s: clean up", __func__); | ||
1719 | if (authctxt->methoddata != NULL) { | ||
1720 | jpake_free(authctxt->methoddata); | ||
1721 | authctxt->methoddata = NULL; | ||
1722 | } | ||
1723 | } | ||
1724 | #endif /* JPAKE */ | ||
1725 | |||
1417 | /* find auth method */ | 1726 | /* find auth method */ |
1418 | 1727 | ||
1419 | /* | 1728 | /* |
@@ -1515,3 +1824,4 @@ authmethods_get(void) | |||
1515 | buffer_free(&b); | 1824 | buffer_free(&b); |
1516 | return list; | 1825 | return list; |
1517 | } | 1826 | } |
1827 | |||