-/* $OpenBSD: monitor_wrap.c,v 1.51 2006/08/05 07:52:52 dtucker Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.68 2009/06/22 05:39:28 dtucker Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "dh.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
-#include "servconf.h"
+#include "schnorr.h"
+#include "jpake.h"
#include "channels.h"
#include "session.h"
+#include "servconf.h"
+#include "roaming.h"
/* Imports */
extern int compat20;
-extern Newkeys *newkeys[];
extern z_stream incoming_stream;
extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
-extern Buffer input, output;
extern Buffer loginmsg;
extern ServerOptions options;
{
Buffer m;
struct passwd *pw;
- u_int pwlen;
+ u_int len;
+ ServerOptions *newopts;
debug3("%s entering", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
if (buffer_get_char(&m) == 0) {
- buffer_free(&m);
- return (NULL);
+ pw = NULL;
+ goto out;
}
- pw = buffer_get_string(&m, &pwlen);
- if (pwlen != sizeof(struct passwd))
+ pw = buffer_get_string(&m, &len);
+ if (len != sizeof(struct passwd))
fatal("%s: struct passwd size mismatch", __func__);
pw->pw_name = buffer_get_string(&m, NULL);
pw->pw_passwd = buffer_get_string(&m, NULL);
#endif
pw->pw_dir = buffer_get_string(&m, NULL);
pw->pw_shell = buffer_get_string(&m, NULL);
+
+out:
+ /* copy options block as a Match directive may have changed some */
+ newopts = buffer_get_string(&m, &len);
+ if (len != sizeof(*newopts))
+ fatal("%s: option block size mismatch", __func__);
+ if (newopts->banner != NULL)
+ newopts->banner = buffer_get_string(&m, NULL);
+ copy_set_server_options(&options, newopts, 1);
+ xfree(newopts);
+
buffer_free(&m);
return (pw);
/* Mac structure */
mac->name = buffer_get_string(&b, NULL);
- if (mac->name == NULL || mac_init(mac, mac->name) == -1)
- fatal("%s: can not init mac %s", __func__, mac->name);
+ if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
+ fatal("%s: can not setup mac %s", __func__, mac->name);
mac->enabled = buffer_get_int(&b);
mac->key = buffer_get_string(&b, &len);
if (len > mac->key_len)
Enc *enc;
Mac *mac;
Comp *comp;
- Newkeys *newkey = newkeys[mode];
+ Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
debug3("%s: converting %p", __func__, newkey);
void
mm_send_keystate(struct monitor *monitor)
{
- Buffer m;
+ Buffer m, *input, *output;
u_char *blob, *p;
u_int bloblen, plen;
u_int32_t seqnr, packets;
- u_int64_t blocks;
+ u_int64_t blocks, bytes;
buffer_init(&m);
}
debug3("%s: Sending new keys: %p %p",
- __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
+ __func__, packet_get_newkeys(MODE_OUT),
+ packet_get_newkeys(MODE_IN));
/* Keys from Kex */
if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
buffer_put_string(&m, blob, bloblen);
xfree(blob);
- packet_get_state(MODE_OUT, &seqnr, &blocks, &packets);
+ packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
buffer_put_int(&m, seqnr);
buffer_put_int64(&m, blocks);
buffer_put_int(&m, packets);
- packet_get_state(MODE_IN, &seqnr, &blocks, &packets);
+ buffer_put_int64(&m, bytes);
+ packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
buffer_put_int(&m, seqnr);
buffer_put_int64(&m, blocks);
buffer_put_int(&m, packets);
+ buffer_put_int64(&m, bytes);
debug3("%s: New keys have been sent", __func__);
skip:
buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
/* Network I/O buffers */
- buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
- buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
+ input = (Buffer *)packet_get_input();
+ output = (Buffer *)packet_get_output();
+ buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
+ buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
+
+ /* Roaming */
+ if (compat20) {
+ buffer_put_int64(&m, get_sent_bytes());
+ buffer_put_int64(&m, get_recv_bytes());
+ }
mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
debug3("%s: Finished sending state", __func__);
{
Buffer m;
char *p, *msg;
- int success = 0;
+ int success = 0, tmp1 = -1, tmp2 = -1;
+
+ /* Kludge: ensure there are fds free to receive the pty/tty */
+ if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
+ (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
+ error("%s: cannot allocate fds for pty", __func__);
+ if (tmp1 > 0)
+ close(tmp1);
+ if (tmp2 > 0)
+ close(tmp2);
+ return 0;
+ }
+ close(tmp1);
+ close(tmp2);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
buffer_append(&loginmsg, msg, strlen(msg));
xfree(msg);
- *ptyfd = mm_receive_fd(pmonitor->m_recvfd);
- *ttyfd = mm_receive_fd(pmonitor->m_recvfd);
+ if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
+ (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
+ fatal("%s: receive fds failed", __func__);
/* Success */
return (1);
buffer_free(&m);
/* closed dup'ed master */
- if (close(s->ptymaster) < 0)
- error("close(s->ptymaster): %s", strerror(errno));
+ if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+ error("close(s->ptymaster/%d): %s",
+ s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
u_int *numprompts, char ***prompts, u_int **echo_on)
{
Buffer m;
- int len;
u_int success;
- char *p, *challenge;
+ char *challenge;
debug3("%s: entering", __func__);
return (authenticated);
}
#endif /* GSSAPI */
+
+#ifdef JPAKE
+void
+mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
+ char **hash_scheme, char **salt)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_JPAKE_GET_PWDATA, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_JPAKE_GET_PWDATA, &m);
+
+ *hash_scheme = buffer_get_string(&m, NULL);
+ *salt = buffer_get_string(&m, NULL);
+
+ buffer_free(&m);
+}
+
+void
+mm_jpake_step1(struct modp_group *grp,
+ u_char **id, u_int *id_len,
+ BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
+ u_char **priv1_proof, u_int *priv1_proof_len,
+ u_char **priv2_proof, u_int *priv2_proof_len)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_JPAKE_STEP1, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_JPAKE_STEP1, &m);
+
+ if ((*priv1 = BN_new()) == NULL ||
+ (*priv2 = BN_new()) == NULL ||
+ (*g_priv1 = BN_new()) == NULL ||
+ (*g_priv2 = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+
+ *id = buffer_get_string(&m, id_len);
+ /* priv1 and priv2 are, well, private */
+ buffer_get_bignum2(&m, *g_priv1);
+ buffer_get_bignum2(&m, *g_priv2);
+ *priv1_proof = buffer_get_string(&m, priv1_proof_len);
+ *priv2_proof = buffer_get_string(&m, priv2_proof_len);
+
+ buffer_free(&m);
+}
+
+void
+mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
+ BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
+ const u_char *theirid, u_int theirid_len,
+ const u_char *myid, u_int myid_len,
+ const u_char *theirpub1_proof, u_int theirpub1_proof_len,
+ const u_char *theirpub2_proof, u_int theirpub2_proof_len,
+ BIGNUM **newpub,
+ u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ /* monitor already has all bignums except theirpub1, theirpub2 */
+ buffer_put_bignum2(&m, theirpub1);
+ buffer_put_bignum2(&m, theirpub2);
+ /* monitor already knows our id */
+ buffer_put_string(&m, theirid, theirid_len);
+ buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
+ buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
+
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_JPAKE_STEP2, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_JPAKE_STEP2, &m);
+
+ if ((*newpub = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+
+ buffer_get_bignum2(&m, *newpub);
+ *newpub_exponent_proof = buffer_get_string(&m,
+ newpub_exponent_proof_len);
+
+ buffer_free(&m);
+}
+
+void
+mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
+ BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
+ BIGNUM *theirpub1, BIGNUM *theirpub2,
+ const u_char *my_id, u_int my_id_len,
+ const u_char *their_id, u_int their_id_len,
+ const u_char *sess_id, u_int sess_id_len,
+ const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
+ BIGNUM **k,
+ u_char **confirm_hash, u_int *confirm_hash_len)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ /* monitor already has all bignums except step2_val */
+ buffer_put_bignum2(&m, step2_val);
+ /* monitor already knows all the ids */
+ buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
+
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
+
+ /* 'k' is sensitive and stays in the monitor */
+ *confirm_hash = buffer_get_string(&m, confirm_hash_len);
+
+ buffer_free(&m);
+}
+
+int
+mm_jpake_check_confirm(const BIGNUM *k,
+ const u_char *peer_id, u_int peer_id_len,
+ const u_char *sess_id, u_int sess_id_len,
+ const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
+{
+ Buffer m;
+ int success = 0;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ /* k is dummy in slave, ignored */
+ /* monitor knows all the ids */
+ buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
+
+ success = buffer_get_int(&m);
+ buffer_free(&m);
+
+ debug3("%s: success = %d", __func__, success);
+ return success;
+}
+#endif /* JPAKE */