1258343Sdes/* $OpenBSD: monitor_wrap.c,v 1.77 2013/11/06 16:52:11 markus Exp $ */
298675Sdes/*
398675Sdes * Copyright 2002 Niels Provos <provos@citi.umich.edu>
498675Sdes * Copyright 2002 Markus Friedl <markus@openbsd.org>
598675Sdes * All rights reserved.
698675Sdes *
798675Sdes * Redistribution and use in source and binary forms, with or without
898675Sdes * modification, are permitted provided that the following conditions
998675Sdes * are met:
1098675Sdes * 1. Redistributions of source code must retain the above copyright
1198675Sdes *    notice, this list of conditions and the following disclaimer.
1298675Sdes * 2. Redistributions in binary form must reproduce the above copyright
1398675Sdes *    notice, this list of conditions and the following disclaimer in the
1498675Sdes *    documentation and/or other materials provided with the distribution.
1598675Sdes *
1698675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1798675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1898675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1998675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2098675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2198675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2298675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2398675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2498675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2598675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2698675Sdes */
2798675Sdes
2898675Sdes#include "includes.h"
2998675Sdes
30162856Sdes#include <sys/types.h>
31162856Sdes#include <sys/uio.h>
32162856Sdes
33162856Sdes#include <errno.h>
34162856Sdes#include <pwd.h>
35162856Sdes#include <signal.h>
36162856Sdes#include <stdarg.h>
37162856Sdes#include <stdio.h>
38162856Sdes#include <string.h>
39162856Sdes#include <unistd.h>
40162856Sdes
4198675Sdes#include <openssl/bn.h>
4298675Sdes#include <openssl/dh.h>
43192595Sdes#include <openssl/evp.h>
4498675Sdes
45181111Sdes#include "openbsd-compat/sys-queue.h"
46162856Sdes#include "xmalloc.h"
4798675Sdes#include "ssh.h"
4898675Sdes#include "dh.h"
49162856Sdes#include "buffer.h"
50162856Sdes#include "key.h"
51162856Sdes#include "cipher.h"
5298675Sdes#include "kex.h"
53162856Sdes#include "hostfile.h"
5498675Sdes#include "auth.h"
55113911Sdes#include "auth-options.h"
5698675Sdes#include "packet.h"
5798675Sdes#include "mac.h"
5898675Sdes#include "log.h"
59128460Sdes#ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
60128460Sdes#undef TARGET_OS_MAC
6198675Sdes#include "zlib.h"
62128460Sdes#define TARGET_OS_MAC 1
63128460Sdes#else
64128460Sdes#include "zlib.h"
65128460Sdes#endif
6698675Sdes#include "monitor.h"
67162856Sdes#ifdef GSSAPI
68162856Sdes#include "ssh-gss.h"
69162856Sdes#endif
7098675Sdes#include "monitor_wrap.h"
7198675Sdes#include "atomicio.h"
7298675Sdes#include "monitor_fdpass.h"
73162856Sdes#include "misc.h"
74197679Sdes#include "schnorr.h"
75192595Sdes#include "jpake.h"
76221420Sdes#include "uuencode.h"
7798675Sdes
7898675Sdes#include "channels.h"
7998675Sdes#include "session.h"
80181111Sdes#include "servconf.h"
81197679Sdes#include "roaming.h"
8298675Sdes
8398675Sdes/* Imports */
8498675Sdesextern int compat20;
8598675Sdesextern z_stream incoming_stream;
8698675Sdesextern z_stream outgoing_stream;
8798675Sdesextern struct monitor *pmonitor;
88137019Sdesextern Buffer loginmsg;
89124211Sdesextern ServerOptions options;
9098675Sdes
91226046Sdesvoid
92226046Sdesmm_log_handler(LogLevel level, const char *msg, void *ctx)
93226046Sdes{
94226046Sdes	Buffer log_msg;
95226046Sdes	struct monitor *mon = (struct monitor *)ctx;
96226046Sdes
97226046Sdes	if (mon->m_log_sendfd == -1)
98226046Sdes		fatal("%s: no log channel", __func__);
99226046Sdes
100226046Sdes	buffer_init(&log_msg);
101226046Sdes	/*
102226046Sdes	 * Placeholder for packet length. Will be filled in with the actual
103226046Sdes	 * packet length once the packet has been constucted. This saves
104226046Sdes	 * fragile math.
105226046Sdes	 */
106226046Sdes	buffer_put_int(&log_msg, 0);
107226046Sdes
108226046Sdes	buffer_put_int(&log_msg, level);
109226046Sdes	buffer_put_cstring(&log_msg, msg);
110226046Sdes	put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
111226046Sdes	if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
112226046Sdes	    buffer_len(&log_msg)) != buffer_len(&log_msg))
113226046Sdes		fatal("%s: write: %s", __func__, strerror(errno));
114226046Sdes	buffer_free(&log_msg);
115226046Sdes}
116226046Sdes
117126277Sdesint
118126277Sdesmm_is_monitor(void)
119126277Sdes{
120126277Sdes	/*
121126277Sdes	 * m_pid is only set in the privileged part, and
122126277Sdes	 * points to the unprivileged child.
123126277Sdes	 */
124126277Sdes	return (pmonitor && pmonitor->m_pid > 0);
125126277Sdes}
126126277Sdes
12798675Sdesvoid
128137019Sdesmm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
12998675Sdes{
130106130Sdes	u_int mlen = buffer_len(m);
13198675Sdes	u_char buf[5];
13298675Sdes
13398675Sdes	debug3("%s entering: type %d", __func__, type);
13498675Sdes
135162856Sdes	put_u32(buf, mlen + 1);
13698675Sdes	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
137137019Sdes	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
138149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
139137019Sdes	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
140149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
14198675Sdes}
14298675Sdes
14398675Sdesvoid
144137019Sdesmm_request_receive(int sock, Buffer *m)
14598675Sdes{
14698675Sdes	u_char buf[4];
147106130Sdes	u_int msg_len;
14898675Sdes
14998675Sdes	debug3("%s entering", __func__);
15098675Sdes
151149753Sdes	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
152149753Sdes		if (errno == EPIPE)
153126277Sdes			cleanup_exit(255);
154149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
15598675Sdes	}
156162856Sdes	msg_len = get_u32(buf);
15798675Sdes	if (msg_len > 256 * 1024)
15898675Sdes		fatal("%s: read: bad msg_len %d", __func__, msg_len);
15998675Sdes	buffer_clear(m);
16098675Sdes	buffer_append_space(m, msg_len);
161149753Sdes	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
162149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
16398675Sdes}
16498675Sdes
16598675Sdesvoid
166137019Sdesmm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
16798675Sdes{
16898675Sdes	u_char rtype;
16998675Sdes
17098675Sdes	debug3("%s entering: type %d", __func__, type);
17198675Sdes
172137019Sdes	mm_request_receive(sock, m);
17398675Sdes	rtype = buffer_get_char(m);
17498675Sdes	if (rtype != type)
17598675Sdes		fatal("%s: read: rtype %d != type %d", __func__,
17698675Sdes		    rtype, type);
17798675Sdes}
17898675Sdes
17998675SdesDH *
18098675Sdesmm_choose_dh(int min, int nbits, int max)
18198675Sdes{
18298675Sdes	BIGNUM *p, *g;
18398675Sdes	int success = 0;
18498675Sdes	Buffer m;
18598675Sdes
18698675Sdes	buffer_init(&m);
18798675Sdes	buffer_put_int(&m, min);
18898675Sdes	buffer_put_int(&m, nbits);
18998675Sdes	buffer_put_int(&m, max);
19098675Sdes
19198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
19298675Sdes
19398675Sdes	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
19498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
19598675Sdes
19698675Sdes	success = buffer_get_char(&m);
19798675Sdes	if (success == 0)
19898675Sdes		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
19998675Sdes
20098675Sdes	if ((p = BN_new()) == NULL)
20198675Sdes		fatal("%s: BN_new failed", __func__);
20298675Sdes	if ((g = BN_new()) == NULL)
20398675Sdes		fatal("%s: BN_new failed", __func__);
20498675Sdes	buffer_get_bignum2(&m, p);
20598675Sdes	buffer_get_bignum2(&m, g);
20698675Sdes
20798675Sdes	debug3("%s: remaining %d", __func__, buffer_len(&m));
20898675Sdes	buffer_free(&m);
20998675Sdes
21098675Sdes	return (dh_new_group(g, p));
21198675Sdes}
21298675Sdes
21398675Sdesint
21498675Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
21598675Sdes{
21698675Sdes	Kex *kex = *pmonitor->m_pkex;
21798675Sdes	Buffer m;
21898675Sdes
21998675Sdes	debug3("%s entering", __func__);
22098675Sdes
22198675Sdes	buffer_init(&m);
22298675Sdes	buffer_put_int(&m, kex->host_key_index(key));
22398675Sdes	buffer_put_string(&m, data, datalen);
22498675Sdes
22598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
22698675Sdes
22798675Sdes	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
22898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
22998675Sdes	*sigp  = buffer_get_string(&m, lenp);
23098675Sdes	buffer_free(&m);
23198675Sdes
23298675Sdes	return (0);
23398675Sdes}
23498675Sdes
23598675Sdesstruct passwd *
236137019Sdesmm_getpwnamallow(const char *username)
23798675Sdes{
23898675Sdes	Buffer m;
23998675Sdes	struct passwd *pw;
240226046Sdes	u_int len, i;
241181111Sdes	ServerOptions *newopts;
24298675Sdes
24398675Sdes	debug3("%s entering", __func__);
24498675Sdes
24598675Sdes	buffer_init(&m);
246137019Sdes	buffer_put_cstring(&m, username);
24798675Sdes
24898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
24998675Sdes
25098675Sdes	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
25198675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
25298675Sdes
25398675Sdes	if (buffer_get_char(&m) == 0) {
254181111Sdes		pw = NULL;
255181111Sdes		goto out;
25698675Sdes	}
257181111Sdes	pw = buffer_get_string(&m, &len);
258181111Sdes	if (len != sizeof(struct passwd))
25998675Sdes		fatal("%s: struct passwd size mismatch", __func__);
26098675Sdes	pw->pw_name = buffer_get_string(&m, NULL);
26198675Sdes	pw->pw_passwd = buffer_get_string(&m, NULL);
262255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
26398675Sdes	pw->pw_gecos = buffer_get_string(&m, NULL);
264255767Sdes#endif
265255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
26698675Sdes	pw->pw_class = buffer_get_string(&m, NULL);
26798937Sdes#endif
26898675Sdes	pw->pw_dir = buffer_get_string(&m, NULL);
26998675Sdes	pw->pw_shell = buffer_get_string(&m, NULL);
270181111Sdes
271181111Sdesout:
272181111Sdes	/* copy options block as a Match directive may have changed some */
273181111Sdes	newopts = buffer_get_string(&m, &len);
274181111Sdes	if (len != sizeof(*newopts))
275181111Sdes		fatal("%s: option block size mismatch", __func__);
276226046Sdes
277226046Sdes#define M_CP_STROPT(x) do { \
278226046Sdes		if (newopts->x != NULL) \
279226046Sdes			newopts->x = buffer_get_string(&m, NULL); \
280226046Sdes	} while (0)
281226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \
282226046Sdes		for (i = 0; i < newopts->nx; i++) \
283226046Sdes			newopts->x[i] = buffer_get_string(&m, NULL); \
284226046Sdes	} while (0)
285226046Sdes	/* See comment in servconf.h */
286226046Sdes	COPY_MATCH_STRING_OPTS();
287226046Sdes#undef M_CP_STROPT
288226046Sdes#undef M_CP_STRARRAYOPT
289226046Sdes
290181111Sdes	copy_set_server_options(&options, newopts, 1);
291255767Sdes	free(newopts);
292181111Sdes
29398675Sdes	buffer_free(&m);
29498675Sdes
29598675Sdes	return (pw);
29698675Sdes}
29798675Sdes
298126277Sdeschar *
299126277Sdesmm_auth2_read_banner(void)
30098675Sdes{
30198675Sdes	Buffer m;
30298675Sdes	char *banner;
30398675Sdes
30498675Sdes	debug3("%s entering", __func__);
30598675Sdes
30698675Sdes	buffer_init(&m);
30798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
30898675Sdes	buffer_clear(&m);
30998675Sdes
310126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
311126277Sdes	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
31298675Sdes	banner = buffer_get_string(&m, NULL);
31398675Sdes	buffer_free(&m);
31498675Sdes
315126277Sdes	/* treat empty banner as missing banner */
316126277Sdes	if (strlen(banner) == 0) {
317255767Sdes		free(banner);
318126277Sdes		banner = NULL;
319126277Sdes	}
32098675Sdes	return (banner);
32198675Sdes}
32298675Sdes
32398675Sdes/* Inform the privileged process about service and style */
32498675Sdes
32598675Sdesvoid
32698675Sdesmm_inform_authserv(char *service, char *style)
32798675Sdes{
32898675Sdes	Buffer m;
32998675Sdes
33098675Sdes	debug3("%s entering", __func__);
33198675Sdes
33298675Sdes	buffer_init(&m);
33398675Sdes	buffer_put_cstring(&m, service);
33498675Sdes	buffer_put_cstring(&m, style ? style : "");
33598675Sdes
33698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
33798675Sdes
33898675Sdes	buffer_free(&m);
33998675Sdes}
34098675Sdes
34198675Sdes/* Do the password authentication */
34298675Sdesint
34398675Sdesmm_auth_password(Authctxt *authctxt, char *password)
34498675Sdes{
34598675Sdes	Buffer m;
34698675Sdes	int authenticated = 0;
34798675Sdes
34898675Sdes	debug3("%s entering", __func__);
34998675Sdes
35098675Sdes	buffer_init(&m);
35198675Sdes	buffer_put_cstring(&m, password);
35298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
35398675Sdes
35498675Sdes	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
35598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
35698675Sdes
35798675Sdes	authenticated = buffer_get_int(&m);
35898675Sdes
35998675Sdes	buffer_free(&m);
36098675Sdes
36198675Sdes	debug3("%s: user %sauthenticated",
36298675Sdes	    __func__, authenticated ? "" : "not ");
36398675Sdes	return (authenticated);
36498675Sdes}
36598675Sdes
36698675Sdesint
36798675Sdesmm_user_key_allowed(struct passwd *pw, Key *key)
36898675Sdes{
36998675Sdes	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
37098675Sdes}
37198675Sdes
37298675Sdesint
37398675Sdesmm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
37498675Sdes    Key *key)
37598675Sdes{
37698675Sdes	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
37798675Sdes}
37898675Sdes
37998675Sdesint
38098675Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
38198675Sdes    char *host, Key *key)
38298675Sdes{
38398675Sdes	int ret;
38498675Sdes
38598675Sdes	key->type = KEY_RSA; /* XXX hack for key_to_blob */
38698675Sdes	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
38798675Sdes	key->type = KEY_RSA1;
38898675Sdes	return (ret);
38998675Sdes}
39098675Sdes
39198675Sdesint
39298675Sdesmm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
39398675Sdes{
39498675Sdes	Buffer m;
39598675Sdes	u_char *blob;
39698675Sdes	u_int len;
397113911Sdes	int allowed = 0, have_forced = 0;
39898675Sdes
39998675Sdes	debug3("%s entering", __func__);
40098675Sdes
40198675Sdes	/* Convert the key to a blob and the pass it over */
40298675Sdes	if (!key_to_blob(key, &blob, &len))
40398675Sdes		return (0);
40498675Sdes
40598675Sdes	buffer_init(&m);
40698675Sdes	buffer_put_int(&m, type);
40798675Sdes	buffer_put_cstring(&m, user ? user : "");
40898675Sdes	buffer_put_cstring(&m, host ? host : "");
40998675Sdes	buffer_put_string(&m, blob, len);
410255767Sdes	free(blob);
41198675Sdes
41298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
41398675Sdes
41498675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
41598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
41698675Sdes
41798675Sdes	allowed = buffer_get_int(&m);
41898675Sdes
419113911Sdes	/* fake forced command */
420113911Sdes	auth_clear_options();
421113911Sdes	have_forced = buffer_get_int(&m);
422113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
423113911Sdes
42498675Sdes	buffer_free(&m);
42598675Sdes
42698675Sdes	return (allowed);
42798675Sdes}
42898675Sdes
42998675Sdes/*
43098675Sdes * This key verify needs to send the key type along, because the
43198675Sdes * privileged parent makes the decision if the key is allowed
43298675Sdes * for authentication.
43398675Sdes */
43498675Sdes
43598675Sdesint
43698675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
43798675Sdes{
43898675Sdes	Buffer m;
43998675Sdes	u_char *blob;
44098675Sdes	u_int len;
44198675Sdes	int verified = 0;
44298675Sdes
44398675Sdes	debug3("%s entering", __func__);
44498675Sdes
44598675Sdes	/* Convert the key to a blob and the pass it over */
44698675Sdes	if (!key_to_blob(key, &blob, &len))
44798675Sdes		return (0);
44898675Sdes
44998675Sdes	buffer_init(&m);
45098675Sdes	buffer_put_string(&m, blob, len);
45198675Sdes	buffer_put_string(&m, sig, siglen);
45298675Sdes	buffer_put_string(&m, data, datalen);
453255767Sdes	free(blob);
45498675Sdes
45598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
45698675Sdes
45798675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
45898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
45998675Sdes
46098675Sdes	verified = buffer_get_int(&m);
46198675Sdes
46298675Sdes	buffer_free(&m);
46398675Sdes
46498675Sdes	return (verified);
46598675Sdes}
46698675Sdes
46798675Sdes/* Export key state after authentication */
46898675SdesNewkeys *
46998675Sdesmm_newkeys_from_blob(u_char *blob, int blen)
47098675Sdes{
47198675Sdes	Buffer b;
47298675Sdes	u_int len;
47398675Sdes	Newkeys *newkey = NULL;
47498675Sdes	Enc *enc;
47598675Sdes	Mac *mac;
47698675Sdes	Comp *comp;
47798675Sdes
47898675Sdes	debug3("%s: %p(%d)", __func__, blob, blen);
47998675Sdes#ifdef DEBUG_PK
48098675Sdes	dump_base64(stderr, blob, blen);
48198675Sdes#endif
48298675Sdes	buffer_init(&b);
48398675Sdes	buffer_append(&b, blob, blen);
48498675Sdes
485258335Sdes	newkey = xcalloc(1, sizeof(*newkey));
48698675Sdes	enc = &newkey->enc;
48798675Sdes	mac = &newkey->mac;
48898675Sdes	comp = &newkey->comp;
48998675Sdes
49098675Sdes	/* Enc structure */
49198675Sdes	enc->name = buffer_get_string(&b, NULL);
49298675Sdes	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
49398675Sdes	enc->enabled = buffer_get_int(&b);
49498675Sdes	enc->block_size = buffer_get_int(&b);
49598675Sdes	enc->key = buffer_get_string(&b, &enc->key_len);
496248619Sdes	enc->iv = buffer_get_string(&b, &enc->iv_len);
49798675Sdes
49898675Sdes	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
49998675Sdes		fatal("%s: bad cipher name %s or pointer %p", __func__,
50098675Sdes		    enc->name, enc->cipher);
50198675Sdes
50298675Sdes	/* Mac structure */
503248619Sdes	if (cipher_authlen(enc->cipher) == 0) {
504248619Sdes		mac->name = buffer_get_string(&b, NULL);
505248619Sdes		if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
506248619Sdes			fatal("%s: can not setup mac %s", __func__, mac->name);
507248619Sdes		mac->enabled = buffer_get_int(&b);
508248619Sdes		mac->key = buffer_get_string(&b, &len);
509248619Sdes		if (len > mac->key_len)
510248619Sdes			fatal("%s: bad mac key length: %u > %d", __func__, len,
511248619Sdes			    mac->key_len);
512248619Sdes		mac->key_len = len;
513248619Sdes	}
51498675Sdes
51598675Sdes	/* Comp structure */
51698675Sdes	comp->type = buffer_get_int(&b);
51798675Sdes	comp->enabled = buffer_get_int(&b);
51898675Sdes	comp->name = buffer_get_string(&b, NULL);
51998675Sdes
52098675Sdes	len = buffer_len(&b);
52198675Sdes	if (len != 0)
522106130Sdes		error("newkeys_from_blob: remaining bytes in blob %u", len);
52398675Sdes	buffer_free(&b);
52498675Sdes	return (newkey);
52598675Sdes}
52698675Sdes
52798675Sdesint
52898675Sdesmm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
52998675Sdes{
53098675Sdes	Buffer b;
53198675Sdes	int len;
53298675Sdes	Enc *enc;
53398675Sdes	Mac *mac;
53498675Sdes	Comp *comp;
535197679Sdes	Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
53698675Sdes
53798675Sdes	debug3("%s: converting %p", __func__, newkey);
53898675Sdes
53998675Sdes	if (newkey == NULL) {
54098675Sdes		error("%s: newkey == NULL", __func__);
54198675Sdes		return 0;
54298675Sdes	}
54398675Sdes	enc = &newkey->enc;
54498675Sdes	mac = &newkey->mac;
54598675Sdes	comp = &newkey->comp;
54698675Sdes
54798675Sdes	buffer_init(&b);
54898675Sdes	/* Enc structure */
54998675Sdes	buffer_put_cstring(&b, enc->name);
55098675Sdes	/* The cipher struct is constant and shared, you export pointer */
55198675Sdes	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
55298675Sdes	buffer_put_int(&b, enc->enabled);
55398675Sdes	buffer_put_int(&b, enc->block_size);
55498675Sdes	buffer_put_string(&b, enc->key, enc->key_len);
555248619Sdes	packet_get_keyiv(mode, enc->iv, enc->iv_len);
556248619Sdes	buffer_put_string(&b, enc->iv, enc->iv_len);
55798675Sdes
55898675Sdes	/* Mac structure */
559248619Sdes	if (cipher_authlen(enc->cipher) == 0) {
560248619Sdes		buffer_put_cstring(&b, mac->name);
561248619Sdes		buffer_put_int(&b, mac->enabled);
562248619Sdes		buffer_put_string(&b, mac->key, mac->key_len);
563248619Sdes	}
56498675Sdes
56598675Sdes	/* Comp structure */
56698675Sdes	buffer_put_int(&b, comp->type);
56798675Sdes	buffer_put_int(&b, comp->enabled);
56898675Sdes	buffer_put_cstring(&b, comp->name);
56998675Sdes
57098675Sdes	len = buffer_len(&b);
571106130Sdes	if (lenp != NULL)
572106130Sdes		*lenp = len;
573106130Sdes	if (blobp != NULL) {
574106130Sdes		*blobp = xmalloc(len);
575106130Sdes		memcpy(*blobp, buffer_ptr(&b), len);
576106130Sdes	}
57798675Sdes	memset(buffer_ptr(&b), 0, len);
57898675Sdes	buffer_free(&b);
57998675Sdes	return len;
58098675Sdes}
58198675Sdes
58298675Sdesstatic void
58398675Sdesmm_send_kex(Buffer *m, Kex *kex)
58498675Sdes{
58598675Sdes	buffer_put_string(m, kex->session_id, kex->session_id_len);
58698675Sdes	buffer_put_int(m, kex->we_need);
58798675Sdes	buffer_put_int(m, kex->hostkey_type);
58898675Sdes	buffer_put_int(m, kex->kex_type);
58998675Sdes	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
59098675Sdes	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
59198675Sdes	buffer_put_int(m, kex->flags);
59298675Sdes	buffer_put_cstring(m, kex->client_version_string);
59398675Sdes	buffer_put_cstring(m, kex->server_version_string);
59498675Sdes}
59598675Sdes
59698675Sdesvoid
597137019Sdesmm_send_keystate(struct monitor *monitor)
59898675Sdes{
599197679Sdes	Buffer m, *input, *output;
60098675Sdes	u_char *blob, *p;
60198675Sdes	u_int bloblen, plen;
602124211Sdes	u_int32_t seqnr, packets;
603181111Sdes	u_int64_t blocks, bytes;
60498675Sdes
60598675Sdes	buffer_init(&m);
60698675Sdes
60798675Sdes	if (!compat20) {
60898675Sdes		u_char iv[24];
60998675Sdes		u_char *key;
61098675Sdes		u_int ivlen, keylen;
61198675Sdes
61298675Sdes		buffer_put_int(&m, packet_get_protocol_flags());
61398675Sdes
61498675Sdes		buffer_put_int(&m, packet_get_ssh1_cipher());
61598675Sdes
61698675Sdes		debug3("%s: Sending ssh1 KEY+IV", __func__);
61798675Sdes		keylen = packet_get_encryption_key(NULL);
61898675Sdes		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
61998675Sdes		keylen = packet_get_encryption_key(key);
62098675Sdes		buffer_put_string(&m, key, keylen);
62198675Sdes		memset(key, 0, keylen);
622255767Sdes		free(key);
62398675Sdes
62498675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
62598675Sdes		packet_get_keyiv(MODE_OUT, iv, ivlen);
62698675Sdes		buffer_put_string(&m, iv, ivlen);
627248619Sdes		ivlen = packet_get_keyiv_len(MODE_IN);
62898675Sdes		packet_get_keyiv(MODE_IN, iv, ivlen);
62998675Sdes		buffer_put_string(&m, iv, ivlen);
63098675Sdes		goto skip;
63198675Sdes	} else {
63298675Sdes		/* Kex for rekeying */
633137019Sdes		mm_send_kex(&m, *monitor->m_pkex);
63498675Sdes	}
63598675Sdes
63698675Sdes	debug3("%s: Sending new keys: %p %p",
637197679Sdes	    __func__, packet_get_newkeys(MODE_OUT),
638197679Sdes	    packet_get_newkeys(MODE_IN));
63998675Sdes
64098675Sdes	/* Keys from Kex */
64198675Sdes	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
64298675Sdes		fatal("%s: conversion of newkeys failed", __func__);
64398675Sdes
64498675Sdes	buffer_put_string(&m, blob, bloblen);
645255767Sdes	free(blob);
64698675Sdes
64798675Sdes	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
64898675Sdes		fatal("%s: conversion of newkeys failed", __func__);
64998675Sdes
65098675Sdes	buffer_put_string(&m, blob, bloblen);
651255767Sdes	free(blob);
65298675Sdes
653181111Sdes	packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
654124211Sdes	buffer_put_int(&m, seqnr);
655124211Sdes	buffer_put_int64(&m, blocks);
656124211Sdes	buffer_put_int(&m, packets);
657181111Sdes	buffer_put_int64(&m, bytes);
658181111Sdes	packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
659124211Sdes	buffer_put_int(&m, seqnr);
660124211Sdes	buffer_put_int64(&m, blocks);
661124211Sdes	buffer_put_int(&m, packets);
662181111Sdes	buffer_put_int64(&m, bytes);
66398675Sdes
66498675Sdes	debug3("%s: New keys have been sent", __func__);
66598675Sdes skip:
66698675Sdes	/* More key context */
66798675Sdes	plen = packet_get_keycontext(MODE_OUT, NULL);
66898675Sdes	p = xmalloc(plen+1);
66998675Sdes	packet_get_keycontext(MODE_OUT, p);
67098675Sdes	buffer_put_string(&m, p, plen);
671255767Sdes	free(p);
67298675Sdes
67398675Sdes	plen = packet_get_keycontext(MODE_IN, NULL);
67498675Sdes	p = xmalloc(plen+1);
67598675Sdes	packet_get_keycontext(MODE_IN, p);
67698675Sdes	buffer_put_string(&m, p, plen);
677255767Sdes	free(p);
67898675Sdes
67998675Sdes	/* Compression state */
68098675Sdes	debug3("%s: Sending compression state", __func__);
68198675Sdes	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
68298675Sdes	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
68398675Sdes
68498675Sdes	/* Network I/O buffers */
685197679Sdes	input = (Buffer *)packet_get_input();
686197679Sdes	output = (Buffer *)packet_get_output();
687197679Sdes	buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
688197679Sdes	buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
68998675Sdes
690197679Sdes	/* Roaming */
691197679Sdes	if (compat20) {
692197679Sdes		buffer_put_int64(&m, get_sent_bytes());
693197679Sdes		buffer_put_int64(&m, get_recv_bytes());
694197679Sdes	}
695197679Sdes
696137019Sdes	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
69798675Sdes	debug3("%s: Finished sending state", __func__);
69898675Sdes
69998675Sdes	buffer_free(&m);
70098675Sdes}
70198675Sdes
70298675Sdesint
703162856Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
70498675Sdes{
70598675Sdes	Buffer m;
706137019Sdes	char *p, *msg;
707181111Sdes	int success = 0, tmp1 = -1, tmp2 = -1;
70898675Sdes
709181111Sdes	/* Kludge: ensure there are fds free to receive the pty/tty */
710181111Sdes	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
711181111Sdes	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
712181111Sdes		error("%s: cannot allocate fds for pty", __func__);
713181111Sdes		if (tmp1 > 0)
714181111Sdes			close(tmp1);
715181111Sdes		if (tmp2 > 0)
716181111Sdes			close(tmp2);
717181111Sdes		return 0;
718181111Sdes	}
719181111Sdes	close(tmp1);
720181111Sdes	close(tmp2);
721181111Sdes
72298675Sdes	buffer_init(&m);
72398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
72498675Sdes
72598675Sdes	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
72698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
72798675Sdes
72898675Sdes	success = buffer_get_int(&m);
72998675Sdes	if (success == 0) {
73098675Sdes		debug3("%s: pty alloc failed", __func__);
73198675Sdes		buffer_free(&m);
73298675Sdes		return (0);
73398675Sdes	}
73498675Sdes	p = buffer_get_string(&m, NULL);
735137019Sdes	msg = buffer_get_string(&m, NULL);
73698675Sdes	buffer_free(&m);
73798675Sdes
73898675Sdes	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
739255767Sdes	free(p);
74098675Sdes
741137019Sdes	buffer_append(&loginmsg, msg, strlen(msg));
742255767Sdes	free(msg);
743137019Sdes
744181111Sdes	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
745181111Sdes	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
746181111Sdes		fatal("%s: receive fds failed", __func__);
74798675Sdes
74898675Sdes	/* Success */
74998675Sdes	return (1);
75098675Sdes}
75198675Sdes
75298675Sdesvoid
753126277Sdesmm_session_pty_cleanup2(Session *s)
75498675Sdes{
75598675Sdes	Buffer m;
75698675Sdes
75798675Sdes	if (s->ttyfd == -1)
75898675Sdes		return;
75998675Sdes	buffer_init(&m);
76098675Sdes	buffer_put_cstring(&m, s->tty);
76198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
76298675Sdes	buffer_free(&m);
76398675Sdes
76498675Sdes	/* closed dup'ed master */
765181111Sdes	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
766181111Sdes		error("close(s->ptymaster/%d): %s",
767181111Sdes		    s->ptymaster, strerror(errno));
76898675Sdes
76998675Sdes	/* unlink pty from session */
77098675Sdes	s->ttyfd = -1;
77198675Sdes}
77298675Sdes
77398937Sdes#ifdef USE_PAM
77498937Sdesvoid
775128460Sdesmm_start_pam(Authctxt *authctxt)
77698937Sdes{
77798937Sdes	Buffer m;
77898937Sdes
77998937Sdes	debug3("%s entering", __func__);
780124211Sdes	if (!options.use_pam)
781124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
78298937Sdes
78398937Sdes	buffer_init(&m);
78498937Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
78598937Sdes
78698937Sdes	buffer_free(&m);
78798937Sdes}
78899052Sdes
789124211Sdesu_int
790124211Sdesmm_do_pam_account(void)
791124211Sdes{
792124211Sdes	Buffer m;
793124211Sdes	u_int ret;
794147005Sdes	char *msg;
795124211Sdes
796124211Sdes	debug3("%s entering", __func__);
797124211Sdes	if (!options.use_pam)
798124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
799124211Sdes
800124211Sdes	buffer_init(&m);
801124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
802124211Sdes
803126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
804124211Sdes	    MONITOR_ANS_PAM_ACCOUNT, &m);
805124211Sdes	ret = buffer_get_int(&m);
806147005Sdes	msg = buffer_get_string(&m, NULL);
807147005Sdes	buffer_append(&loginmsg, msg, strlen(msg));
808255767Sdes	free(msg);
809124211Sdes
810124211Sdes	buffer_free(&m);
811126277Sdes
812124211Sdes	debug3("%s returning %d", __func__, ret);
813124211Sdes
814124211Sdes	return (ret);
815124211Sdes}
816124211Sdes
81799052Sdesvoid *
818124211Sdesmm_sshpam_init_ctx(Authctxt *authctxt)
81999052Sdes{
82099052Sdes	Buffer m;
82199052Sdes	int success;
82299052Sdes
82399052Sdes	debug3("%s", __func__);
82499052Sdes	buffer_init(&m);
82599052Sdes	buffer_put_cstring(&m, authctxt->user);
82699052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
82799052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
82899052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
82999052Sdes	success = buffer_get_int(&m);
83099052Sdes	if (success == 0) {
83199052Sdes		debug3("%s: pam_init_ctx failed", __func__);
83299052Sdes		buffer_free(&m);
83399052Sdes		return (NULL);
83499052Sdes	}
83599052Sdes	buffer_free(&m);
83699052Sdes	return (authctxt);
83799052Sdes}
83899052Sdes
83999052Sdesint
840124211Sdesmm_sshpam_query(void *ctx, char **name, char **info,
84199052Sdes    u_int *num, char ***prompts, u_int **echo_on)
84299052Sdes{
84399052Sdes	Buffer m;
844149753Sdes	u_int i;
845149753Sdes	int ret;
84699052Sdes
84799052Sdes	debug3("%s", __func__);
84899052Sdes	buffer_init(&m);
84999052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
85099052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
85199052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
85299052Sdes	ret = buffer_get_int(&m);
85399052Sdes	debug3("%s: pam_query returned %d", __func__, ret);
85499052Sdes	*name = buffer_get_string(&m, NULL);
85599052Sdes	*info = buffer_get_string(&m, NULL);
85699052Sdes	*num = buffer_get_int(&m);
857162856Sdes	if (*num > PAM_MAX_NUM_MSG)
858162856Sdes		fatal("%s: recieved %u PAM messages, expected <= %u",
859162856Sdes		    __func__, *num, PAM_MAX_NUM_MSG);
860162856Sdes	*prompts = xcalloc((*num + 1), sizeof(char *));
861162856Sdes	*echo_on = xcalloc((*num + 1), sizeof(u_int));
86299052Sdes	for (i = 0; i < *num; ++i) {
86399052Sdes		(*prompts)[i] = buffer_get_string(&m, NULL);
86499052Sdes		(*echo_on)[i] = buffer_get_int(&m);
86599052Sdes	}
86699052Sdes	buffer_free(&m);
86799052Sdes	return (ret);
86899052Sdes}
86999052Sdes
87099052Sdesint
871124211Sdesmm_sshpam_respond(void *ctx, u_int num, char **resp)
87299052Sdes{
87399052Sdes	Buffer m;
874149753Sdes	u_int i;
875149753Sdes	int ret;
87699052Sdes
87799052Sdes	debug3("%s", __func__);
87899052Sdes	buffer_init(&m);
87999052Sdes	buffer_put_int(&m, num);
88099052Sdes	for (i = 0; i < num; ++i)
88199052Sdes		buffer_put_cstring(&m, resp[i]);
88299052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
88399052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
88499052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
88599052Sdes	ret = buffer_get_int(&m);
88699052Sdes	debug3("%s: pam_respond returned %d", __func__, ret);
88799052Sdes	buffer_free(&m);
88899052Sdes	return (ret);
88999052Sdes}
89099052Sdes
89199052Sdesvoid
892124211Sdesmm_sshpam_free_ctx(void *ctxtp)
89399052Sdes{
89499052Sdes	Buffer m;
89599052Sdes
89699052Sdes	debug3("%s", __func__);
89799052Sdes	buffer_init(&m);
89899052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
89999052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
90099052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
90199052Sdes	buffer_free(&m);
90299052Sdes}
90398937Sdes#endif /* USE_PAM */
90498937Sdes
90598675Sdes/* Request process termination */
90698675Sdes
90798675Sdesvoid
90898675Sdesmm_terminate(void)
90998675Sdes{
91098675Sdes	Buffer m;
91198675Sdes
91298675Sdes	buffer_init(&m);
91398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
91498675Sdes	buffer_free(&m);
91598675Sdes}
91698675Sdes
91798675Sdesint
91898675Sdesmm_ssh1_session_key(BIGNUM *num)
91998675Sdes{
92098675Sdes	int rsafail;
92198675Sdes	Buffer m;
92298675Sdes
92398675Sdes	buffer_init(&m);
92498675Sdes	buffer_put_bignum2(&m, num);
92598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
92698675Sdes
92798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
92898675Sdes
92998675Sdes	rsafail = buffer_get_int(&m);
93098675Sdes	buffer_get_bignum2(&m, num);
93198675Sdes
93298675Sdes	buffer_free(&m);
93398675Sdes
93498675Sdes	return (rsafail);
93598675Sdes}
93698675Sdes
93798675Sdesstatic void
93898675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts,
93998675Sdes    char ***prompts, u_int **echo_on)
94098675Sdes{
94198675Sdes	*name = xstrdup("");
94298675Sdes	*infotxt = xstrdup("");
94398675Sdes	*numprompts = 1;
944162856Sdes	*prompts = xcalloc(*numprompts, sizeof(char *));
945162856Sdes	*echo_on = xcalloc(*numprompts, sizeof(u_int));
94698675Sdes	(*echo_on)[0] = 0;
94798675Sdes}
94898675Sdes
94998675Sdesint
95098675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt,
95198675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
95298675Sdes{
95398675Sdes	Buffer m;
954113911Sdes	u_int success;
95598675Sdes	char *challenge;
95698675Sdes
95798675Sdes	debug3("%s: entering", __func__);
95898675Sdes
95998675Sdes	buffer_init(&m);
96098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
96198675Sdes
96298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
96398675Sdes	    &m);
964113911Sdes	success = buffer_get_int(&m);
965113911Sdes	if (success == 0) {
96698675Sdes		debug3("%s: no challenge", __func__);
96798675Sdes		buffer_free(&m);
96898675Sdes		return (-1);
96998675Sdes	}
97098675Sdes
97198675Sdes	/* Get the challenge, and format the response */
97298675Sdes	challenge  = buffer_get_string(&m, NULL);
97398675Sdes	buffer_free(&m);
97498675Sdes
97598675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
97698675Sdes	(*prompts)[0] = challenge;
97798675Sdes
97898675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
97998675Sdes
98098675Sdes	return (0);
98198675Sdes}
98298675Sdes
98398675Sdesint
98498675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
98598675Sdes{
98698675Sdes	Buffer m;
98798675Sdes	int authok;
98898675Sdes
98998675Sdes	debug3("%s: entering", __func__);
99098675Sdes	if (numresponses != 1)
99198675Sdes		return (-1);
99298675Sdes
99398675Sdes	buffer_init(&m);
99498675Sdes	buffer_put_cstring(&m, responses[0]);
99598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
99698675Sdes
99798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
99898675Sdes	    MONITOR_ANS_BSDAUTHRESPOND, &m);
99998675Sdes
100098675Sdes	authok = buffer_get_int(&m);
100198675Sdes	buffer_free(&m);
100298675Sdes
100398675Sdes	return ((authok == 0) ? -1 : 0);
100498675Sdes}
100598675Sdes
100699046Sdes#ifdef SKEY
100798675Sdesint
100898675Sdesmm_skey_query(void *ctx, char **name, char **infotxt,
100998675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
101098675Sdes{
101198675Sdes	Buffer m;
1012113911Sdes	u_int success;
1013162856Sdes	char *challenge;
101498675Sdes
101598675Sdes	debug3("%s: entering", __func__);
101698675Sdes
101798675Sdes	buffer_init(&m);
101898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
101998675Sdes
102098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
102198675Sdes	    &m);
1022113911Sdes	success = buffer_get_int(&m);
1023113911Sdes	if (success == 0) {
102498675Sdes		debug3("%s: no challenge", __func__);
102598675Sdes		buffer_free(&m);
102698675Sdes		return (-1);
102798675Sdes	}
102898675Sdes
102998675Sdes	/* Get the challenge, and format the response */
103098675Sdes	challenge  = buffer_get_string(&m, NULL);
103198675Sdes	buffer_free(&m);
103298675Sdes
103398675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
103498675Sdes
103598675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
103698675Sdes
1037162856Sdes	xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
1038255767Sdes	free(challenge);
103998675Sdes
104098675Sdes	return (0);
104198675Sdes}
104298675Sdes
104398675Sdesint
104498675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses)
104598675Sdes{
104698675Sdes	Buffer m;
104798675Sdes	int authok;
104898675Sdes
104998675Sdes	debug3("%s: entering", __func__);
105098675Sdes	if (numresponses != 1)
105198675Sdes		return (-1);
105298675Sdes
105398675Sdes	buffer_init(&m);
105498675Sdes	buffer_put_cstring(&m, responses[0]);
105598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
105698675Sdes
105798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
105898675Sdes	    MONITOR_ANS_SKEYRESPOND, &m);
105998675Sdes
106098675Sdes	authok = buffer_get_int(&m);
106198675Sdes	buffer_free(&m);
106298675Sdes
106398675Sdes	return ((authok == 0) ? -1 : 0);
106498675Sdes}
1065137019Sdes#endif /* SKEY */
106698675Sdes
106798675Sdesvoid
106898675Sdesmm_ssh1_session_id(u_char session_id[16])
106998675Sdes{
107098675Sdes	Buffer m;
107198675Sdes	int i;
107298675Sdes
107398675Sdes	debug3("%s entering", __func__);
107498675Sdes
107598675Sdes	buffer_init(&m);
107698675Sdes	for (i = 0; i < 16; i++)
107798675Sdes		buffer_put_char(&m, session_id[i]);
107898675Sdes
107998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
108098675Sdes	buffer_free(&m);
108198675Sdes}
108298675Sdes
108398675Sdesint
108498675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
108598675Sdes{
108698675Sdes	Buffer m;
108798675Sdes	Key *key;
108898675Sdes	u_char *blob;
108998675Sdes	u_int blen;
1090113911Sdes	int allowed = 0, have_forced = 0;
109198675Sdes
109298675Sdes	debug3("%s entering", __func__);
109398675Sdes
109498675Sdes	buffer_init(&m);
109598675Sdes	buffer_put_bignum2(&m, client_n);
109698675Sdes
109798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
109898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
109998675Sdes
110098675Sdes	allowed = buffer_get_int(&m);
110198675Sdes
1102113911Sdes	/* fake forced command */
1103113911Sdes	auth_clear_options();
1104113911Sdes	have_forced = buffer_get_int(&m);
1105113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
1106113911Sdes
110798675Sdes	if (allowed && rkey != NULL) {
110898675Sdes		blob = buffer_get_string(&m, &blen);
110998675Sdes		if ((key = key_from_blob(blob, blen)) == NULL)
111098675Sdes			fatal("%s: key_from_blob failed", __func__);
111198675Sdes		*rkey = key;
1112255767Sdes		free(blob);
111398675Sdes	}
111498675Sdes	buffer_free(&m);
111598675Sdes
111698675Sdes	return (allowed);
111798675Sdes}
111898675Sdes
111998675SdesBIGNUM *
112098675Sdesmm_auth_rsa_generate_challenge(Key *key)
112198675Sdes{
112298675Sdes	Buffer m;
112398675Sdes	BIGNUM *challenge;
112498675Sdes	u_char *blob;
112598675Sdes	u_int blen;
112698675Sdes
112798675Sdes	debug3("%s entering", __func__);
112898675Sdes
112998675Sdes	if ((challenge = BN_new()) == NULL)
113098675Sdes		fatal("%s: BN_new failed", __func__);
113198675Sdes
113298675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
113398675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
113498675Sdes		fatal("%s: key_to_blob failed", __func__);
113598675Sdes	key->type = KEY_RSA1;
113698675Sdes
113798675Sdes	buffer_init(&m);
113898675Sdes	buffer_put_string(&m, blob, blen);
1139255767Sdes	free(blob);
114098675Sdes
114198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
114298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
114398675Sdes
114498675Sdes	buffer_get_bignum2(&m, challenge);
114598675Sdes	buffer_free(&m);
114698675Sdes
114798675Sdes	return (challenge);
114898675Sdes}
114998675Sdes
115098675Sdesint
115198675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
115298675Sdes{
115398675Sdes	Buffer m;
115498675Sdes	u_char *blob;
115598675Sdes	u_int blen;
115698675Sdes	int success = 0;
115798675Sdes
115898675Sdes	debug3("%s entering", __func__);
115998675Sdes
116098675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
116198675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
116298675Sdes		fatal("%s: key_to_blob failed", __func__);
116398675Sdes	key->type = KEY_RSA1;
116498675Sdes
116598675Sdes	buffer_init(&m);
116698675Sdes	buffer_put_string(&m, blob, blen);
116798675Sdes	buffer_put_string(&m, response, 16);
1168255767Sdes	free(blob);
116998675Sdes
117098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
117198675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
117298675Sdes
117398675Sdes	success = buffer_get_int(&m);
117498675Sdes	buffer_free(&m);
117598675Sdes
117698675Sdes	return (success);
117798675Sdes}
1178106130Sdes
1179147005Sdes#ifdef SSH_AUDIT_EVENTS
1180147005Sdesvoid
1181147005Sdesmm_audit_event(ssh_audit_event_t event)
1182147005Sdes{
1183147005Sdes	Buffer m;
1184147005Sdes
1185147005Sdes	debug3("%s entering", __func__);
1186147005Sdes
1187147005Sdes	buffer_init(&m);
1188147005Sdes	buffer_put_int(&m, event);
1189147005Sdes
1190147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
1191147005Sdes	buffer_free(&m);
1192147005Sdes}
1193147005Sdes
1194147005Sdesvoid
1195147005Sdesmm_audit_run_command(const char *command)
1196147005Sdes{
1197147005Sdes	Buffer m;
1198147005Sdes
1199147005Sdes	debug3("%s entering command %s", __func__, command);
1200147005Sdes
1201147005Sdes	buffer_init(&m);
1202147005Sdes	buffer_put_cstring(&m, command);
1203147005Sdes
1204147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
1205147005Sdes	buffer_free(&m);
1206147005Sdes}
1207147005Sdes#endif /* SSH_AUDIT_EVENTS */
1208147005Sdes
1209124211Sdes#ifdef GSSAPI
1210124211SdesOM_uint32
1211137019Sdesmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
1212106130Sdes{
1213124211Sdes	Buffer m;
1214124211Sdes	OM_uint32 major;
1215106130Sdes
1216124211Sdes	/* Client doesn't get to see the context */
1217124211Sdes	*ctx = NULL;
1218106130Sdes
1219106130Sdes	buffer_init(&m);
1220137019Sdes	buffer_put_string(&m, goid->elements, goid->length);
1221106130Sdes
1222124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1223124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1224106130Sdes
1225124211Sdes	major = buffer_get_int(&m);
1226124211Sdes
1227106130Sdes	buffer_free(&m);
1228124211Sdes	return (major);
1229106130Sdes}
1230106130Sdes
1231124211SdesOM_uint32
1232124211Sdesmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1233124211Sdes    gss_buffer_desc *out, OM_uint32 *flags)
1234124211Sdes{
1235124211Sdes	Buffer m;
1236124211Sdes	OM_uint32 major;
1237124211Sdes	u_int len;
1238124211Sdes
1239124211Sdes	buffer_init(&m);
1240124211Sdes	buffer_put_string(&m, in->value, in->length);
1241124211Sdes
1242124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1243124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1244124211Sdes
1245124211Sdes	major = buffer_get_int(&m);
1246124211Sdes	out->value = buffer_get_string(&m, &len);
1247124211Sdes	out->length = len;
1248124211Sdes	if (flags)
1249124211Sdes		*flags = buffer_get_int(&m);
1250124211Sdes
1251124211Sdes	buffer_free(&m);
1252124211Sdes
1253124211Sdes	return (major);
1254124211Sdes}
1255124211Sdes
1256126277SdesOM_uint32
1257126277Sdesmm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
1258126277Sdes{
1259126277Sdes	Buffer m;
1260126277Sdes	OM_uint32 major;
1261126277Sdes
1262126277Sdes	buffer_init(&m);
1263126277Sdes	buffer_put_string(&m, gssbuf->value, gssbuf->length);
1264126277Sdes	buffer_put_string(&m, gssmic->value, gssmic->length);
1265126277Sdes
1266126277Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
1267126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
1268126277Sdes	    &m);
1269126277Sdes
1270126277Sdes	major = buffer_get_int(&m);
1271126277Sdes	buffer_free(&m);
1272126277Sdes	return(major);
1273126277Sdes}
1274126277Sdes
1275106130Sdesint
1276124211Sdesmm_ssh_gssapi_userok(char *user)
1277106130Sdes{
1278106130Sdes	Buffer m;
1279124211Sdes	int authenticated = 0;
1280106130Sdes
1281106130Sdes	buffer_init(&m);
1282106130Sdes
1283124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1284124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1285124211Sdes				  &m);
1286106130Sdes
1287124211Sdes	authenticated = buffer_get_int(&m);
1288106130Sdes
1289106130Sdes	buffer_free(&m);
1290124211Sdes	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1291124211Sdes	return (authenticated);
1292106130Sdes}
1293124211Sdes#endif /* GSSAPI */
1294192595Sdes
1295192595Sdes#ifdef JPAKE
1296192595Sdesvoid
1297192595Sdesmm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
1298192595Sdes    char **hash_scheme, char **salt)
1299192595Sdes{
1300192595Sdes	Buffer m;
1301192595Sdes
1302192595Sdes	debug3("%s entering", __func__);
1303192595Sdes
1304192595Sdes	buffer_init(&m);
1305192595Sdes	mm_request_send(pmonitor->m_recvfd,
1306192595Sdes	    MONITOR_REQ_JPAKE_GET_PWDATA, &m);
1307192595Sdes
1308192595Sdes	debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
1309192595Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
1310192595Sdes	    MONITOR_ANS_JPAKE_GET_PWDATA, &m);
1311192595Sdes
1312192595Sdes	*hash_scheme = buffer_get_string(&m, NULL);
1313192595Sdes	*salt = buffer_get_string(&m, NULL);
1314192595Sdes
1315192595Sdes	buffer_free(&m);
1316192595Sdes}
1317192595Sdes
1318192595Sdesvoid
1319197679Sdesmm_jpake_step1(struct modp_group *grp,
1320192595Sdes    u_char **id, u_int *id_len,
1321192595Sdes    BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
1322192595Sdes    u_char **priv1_proof, u_int *priv1_proof_len,
1323192595Sdes    u_char **priv2_proof, u_int *priv2_proof_len)
1324192595Sdes{
1325192595Sdes	Buffer m;
1326192595Sdes
1327192595Sdes	debug3("%s entering", __func__);
1328192595Sdes
1329192595Sdes	buffer_init(&m);
1330192595Sdes	mm_request_send(pmonitor->m_recvfd,
1331192595Sdes	    MONITOR_REQ_JPAKE_STEP1, &m);
1332192595Sdes
1333192595Sdes	debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
1334192595Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
1335192595Sdes	    MONITOR_ANS_JPAKE_STEP1, &m);
1336192595Sdes
1337192595Sdes	if ((*priv1 = BN_new()) == NULL ||
1338192595Sdes	    (*priv2 = BN_new()) == NULL ||
1339192595Sdes	    (*g_priv1 = BN_new()) == NULL ||
1340192595Sdes	    (*g_priv2 = BN_new()) == NULL)
1341192595Sdes		fatal("%s: BN_new", __func__);
1342192595Sdes
1343192595Sdes	*id = buffer_get_string(&m, id_len);
1344192595Sdes	/* priv1 and priv2 are, well, private */
1345192595Sdes	buffer_get_bignum2(&m, *g_priv1);
1346192595Sdes	buffer_get_bignum2(&m, *g_priv2);
1347192595Sdes	*priv1_proof = buffer_get_string(&m, priv1_proof_len);
1348192595Sdes	*priv2_proof = buffer_get_string(&m, priv2_proof_len);
1349192595Sdes
1350192595Sdes	buffer_free(&m);
1351192595Sdes}
1352192595Sdes
1353192595Sdesvoid
1354197679Sdesmm_jpake_step2(struct modp_group *grp, BIGNUM *s,
1355192595Sdes    BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
1356192595Sdes    const u_char *theirid, u_int theirid_len,
1357192595Sdes    const u_char *myid, u_int myid_len,
1358192595Sdes    const u_char *theirpub1_proof, u_int theirpub1_proof_len,
1359192595Sdes    const u_char *theirpub2_proof, u_int theirpub2_proof_len,
1360192595Sdes    BIGNUM **newpub,
1361192595Sdes    u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
1362192595Sdes{
1363192595Sdes	Buffer m;
1364192595Sdes
1365192595Sdes	debug3("%s entering", __func__);
1366192595Sdes
1367192595Sdes	buffer_init(&m);
1368192595Sdes	/* monitor already has all bignums except theirpub1, theirpub2 */
1369192595Sdes	buffer_put_bignum2(&m, theirpub1);
1370192595Sdes	buffer_put_bignum2(&m, theirpub2);
1371192595Sdes	/* monitor already knows our id */
1372192595Sdes	buffer_put_string(&m, theirid, theirid_len);
1373192595Sdes	buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
1374192595Sdes	buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
1375192595Sdes
1376192595Sdes	mm_request_send(pmonitor->m_recvfd,
1377192595Sdes	    MONITOR_REQ_JPAKE_STEP2, &m);
1378192595Sdes
1379192595Sdes	debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
1380192595Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
1381192595Sdes	    MONITOR_ANS_JPAKE_STEP2, &m);
1382192595Sdes
1383192595Sdes	if ((*newpub = BN_new()) == NULL)
1384192595Sdes		fatal("%s: BN_new", __func__);
1385192595Sdes
1386192595Sdes	buffer_get_bignum2(&m, *newpub);
1387192595Sdes	*newpub_exponent_proof = buffer_get_string(&m,
1388192595Sdes	    newpub_exponent_proof_len);
1389192595Sdes
1390192595Sdes	buffer_free(&m);
1391192595Sdes}
1392192595Sdes
1393192595Sdesvoid
1394197679Sdesmm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
1395192595Sdes    BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
1396192595Sdes    BIGNUM *theirpub1, BIGNUM *theirpub2,
1397192595Sdes    const u_char *my_id, u_int my_id_len,
1398192595Sdes    const u_char *their_id, u_int their_id_len,
1399192595Sdes    const u_char *sess_id, u_int sess_id_len,
1400192595Sdes    const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
1401192595Sdes    BIGNUM **k,
1402192595Sdes    u_char **confirm_hash, u_int *confirm_hash_len)
1403192595Sdes{
1404192595Sdes	Buffer m;
1405192595Sdes
1406192595Sdes	debug3("%s entering", __func__);
1407192595Sdes
1408192595Sdes	buffer_init(&m);
1409192595Sdes	/* monitor already has all bignums except step2_val */
1410192595Sdes	buffer_put_bignum2(&m, step2_val);
1411192595Sdes	/* monitor already knows all the ids */
1412192595Sdes	buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
1413192595Sdes
1414192595Sdes	mm_request_send(pmonitor->m_recvfd,
1415192595Sdes	    MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
1416192595Sdes
1417192595Sdes	debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
1418192595Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
1419192595Sdes	    MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
1420192595Sdes
1421192595Sdes	/* 'k' is sensitive and stays in the monitor */
1422192595Sdes	*confirm_hash = buffer_get_string(&m, confirm_hash_len);
1423192595Sdes
1424192595Sdes	buffer_free(&m);
1425192595Sdes}
1426192595Sdes
1427192595Sdesint
1428192595Sdesmm_jpake_check_confirm(const BIGNUM *k,
1429192595Sdes    const u_char *peer_id, u_int peer_id_len,
1430192595Sdes    const u_char *sess_id, u_int sess_id_len,
1431192595Sdes    const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
1432192595Sdes{
1433192595Sdes	Buffer m;
1434192595Sdes	int success = 0;
1435192595Sdes
1436192595Sdes	debug3("%s entering", __func__);
1437192595Sdes
1438192595Sdes	buffer_init(&m);
1439192595Sdes	/* k is dummy in slave, ignored */
1440192595Sdes	/* monitor knows all the ids */
1441192595Sdes	buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
1442192595Sdes	mm_request_send(pmonitor->m_recvfd,
1443192595Sdes	    MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
1444192595Sdes
1445192595Sdes	debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
1446192595Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
1447192595Sdes	    MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
1448192595Sdes
1449192595Sdes	success = buffer_get_int(&m);
1450192595Sdes	buffer_free(&m);
1451192595Sdes
1452192595Sdes	debug3("%s: success = %d", __func__, success);
1453192595Sdes	return success;
1454192595Sdes}
1455192595Sdes#endif /* JPAKE */
1456