=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/monitor.c,v retrieving revision 1.99 retrieving revision 1.100 diff -u -r1.99 -r1.100 --- src/usr.bin/ssh/monitor.c 2008/07/10 18:08:11 1.99 +++ src/usr.bin/ssh/monitor.c 2008/11/04 08:22:13 1.100 @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.99 2008/07/10 18:08:11 markus Exp $ */ +/* $OpenBSD: monitor.c,v 1.100 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -72,6 +72,7 @@ #include "misc.h" #include "compat.h" #include "ssh2.h" +#include "jpake.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -134,6 +135,11 @@ int mm_answer_rsa_response(int, Buffer *); int mm_answer_sesskey(int, Buffer *); int mm_answer_sessid(int, Buffer *); +int mm_answer_jpake_get_pwdata(int, Buffer *); +int mm_answer_jpake_step1(int, Buffer *); +int mm_answer_jpake_step2(int, Buffer *); +int mm_answer_jpake_key_confirm(int, Buffer *); +int mm_answer_jpake_check_confirm(int, Buffer *); #ifdef GSSAPI int mm_answer_gss_setup_ctx(int, Buffer *); @@ -188,6 +194,13 @@ {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, #endif +#ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, + {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1}, + {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2}, + {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm}, + {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm}, +#endif {0, 0, NULL} }; @@ -294,6 +307,15 @@ if (!authenticated) authctxt->failures++; } +#ifdef JPAKE + /* Cleanup JPAKE context after authentication */ + if (ent->flags & MON_AUTHDECIDE) { + if (authctxt->jpake_ctx != NULL) { + jpake_free(authctxt->jpake_ctx); + authctxt->jpake_ctx = NULL; + } + } +#endif } if (!authctxt->valid) @@ -1644,3 +1666,206 @@ return (authenticated); } #endif /* GSSAPI */ + +#ifdef JPAKE +int +mm_answer_jpake_step1(int sock, Buffer *m) +{ + struct jpake_ctx *pctx; + u_char *x3_proof, *x4_proof; + u_int x3_proof_len, x4_proof_len; + + if (!options.zero_knowledge_password_authentication) + fatal("zero_knowledge_password_authentication disabled"); + + if (authctxt->jpake_ctx != NULL) + fatal("%s: authctxt->jpake_ctx already set (%p)", + __func__, authctxt->jpake_ctx); + authctxt->jpake_ctx = pctx = jpake_new(); + + jpake_step1(pctx->grp, + &pctx->server_id, &pctx->server_id_len, + &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4, + &x3_proof, &x3_proof_len, + &x4_proof, &x4_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__)); + + buffer_clear(m); + + buffer_put_string(m, pctx->server_id, pctx->server_id_len); + buffer_put_bignum2(m, pctx->g_x3); + buffer_put_bignum2(m, pctx->g_x4); + buffer_put_string(m, x3_proof, x3_proof_len); + buffer_put_string(m, x4_proof, x4_proof_len); + + debug3("%s: sending step1", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m); + + bzero(x3_proof, x3_proof_len); + bzero(x4_proof, x4_proof_len); + xfree(x3_proof); + xfree(x4_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0); + + return 0; +} + +int +mm_answer_jpake_get_pwdata(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + char *hash_scheme, *salt; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt); + + buffer_clear(m); + /* pctx->s is sensitive, not returned to slave */ + buffer_put_cstring(m, hash_scheme); + buffer_put_cstring(m, salt); + + debug3("%s: sending pwdata", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m); + + bzero(hash_scheme, strlen(hash_scheme)); + bzero(salt, strlen(salt)); + xfree(hash_scheme); + xfree(salt); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1); + + return 0; +} + +int +mm_answer_jpake_step2(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x1_proof, *x2_proof, *x4_s_proof; + u_int x1_proof_len, x2_proof_len, x4_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->g_x1 = BN_new()) == NULL || + (pctx->g_x2 = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->g_x1); + buffer_get_bignum2(m, pctx->g_x2); + pctx->client_id = buffer_get_string(m, &pctx->client_id_len); + x1_proof = buffer_get_string(m, &x1_proof_len); + x2_proof = buffer_get_string(m, &x2_proof_len); + + jpake_step2(pctx->grp, pctx->s, pctx->g_x3, + pctx->g_x1, pctx->g_x2, pctx->x4, + pctx->client_id, pctx->client_id_len, + pctx->server_id, pctx->server_id_len, + x1_proof, x1_proof_len, + x2_proof, x2_proof_len, + &pctx->b, + &x4_s_proof, &x4_s_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__)); + + bzero(x1_proof, x1_proof_len); + bzero(x2_proof, x2_proof_len); + xfree(x1_proof); + xfree(x2_proof); + + buffer_clear(m); + + buffer_put_bignum2(m, pctx->b); + buffer_put_string(m, x4_s_proof, x4_s_proof_len); + + debug3("%s: sending step2", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m); + + bzero(x4_s_proof, x4_s_proof_len); + xfree(x4_s_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_key_confirm(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x2_s_proof; + u_int x2_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->a = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->a); + x2_s_proof = buffer_get_string(m, &x2_s_proof_len); + + jpake_key_confirm(pctx->grp, pctx->s, pctx->a, + pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, + pctx->server_id, pctx->server_id_len, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + x2_s_proof, x2_s_proof_len, + &pctx->k, + &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len); + + JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__)); + + bzero(x2_s_proof, x2_s_proof_len); + buffer_clear(m); + + /* pctx->k is sensitive, not sent */ + buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); + + debug3("%s: sending confirmation hash", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_check_confirm(int sock, Buffer *m) +{ + int authenticated = 0; + u_char *peer_confirm_hash; + u_int peer_confirm_hash_len; + struct jpake_ctx *pctx = authctxt->jpake_ctx; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len); + + authenticated = jpake_check_confirm(pctx->k, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid; + + JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__)); + + bzero(peer_confirm_hash, peer_confirm_hash_len); + xfree(peer_confirm_hash); + + buffer_clear(m); + buffer_put_int(m, authenticated); + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); + + auth_method = "jpake-01@openssh.com"; + return authenticated; +} + +#endif /* JPAKE */