1264377Sdes/* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm 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"
74221420Sdes#include "uuencode.h"
7598675Sdes
7698675Sdes#include "channels.h"
7798675Sdes#include "session.h"
78181111Sdes#include "servconf.h"
79197679Sdes#include "roaming.h"
8098675Sdes
8198675Sdes/* Imports */
8298675Sdesextern int compat20;
8398675Sdesextern z_stream incoming_stream;
8498675Sdesextern z_stream outgoing_stream;
8598675Sdesextern struct monitor *pmonitor;
86137019Sdesextern Buffer loginmsg;
87124211Sdesextern ServerOptions options;
8898675Sdes
89226046Sdesvoid
90226046Sdesmm_log_handler(LogLevel level, const char *msg, void *ctx)
91226046Sdes{
92226046Sdes	Buffer log_msg;
93226046Sdes	struct monitor *mon = (struct monitor *)ctx;
94226046Sdes
95226046Sdes	if (mon->m_log_sendfd == -1)
96226046Sdes		fatal("%s: no log channel", __func__);
97226046Sdes
98226046Sdes	buffer_init(&log_msg);
99226046Sdes	/*
100226046Sdes	 * Placeholder for packet length. Will be filled in with the actual
101226046Sdes	 * packet length once the packet has been constucted. This saves
102226046Sdes	 * fragile math.
103226046Sdes	 */
104226046Sdes	buffer_put_int(&log_msg, 0);
105226046Sdes
106226046Sdes	buffer_put_int(&log_msg, level);
107226046Sdes	buffer_put_cstring(&log_msg, msg);
108226046Sdes	put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
109226046Sdes	if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
110226046Sdes	    buffer_len(&log_msg)) != buffer_len(&log_msg))
111226046Sdes		fatal("%s: write: %s", __func__, strerror(errno));
112226046Sdes	buffer_free(&log_msg);
113226046Sdes}
114226046Sdes
115126277Sdesint
116126277Sdesmm_is_monitor(void)
117126277Sdes{
118126277Sdes	/*
119126277Sdes	 * m_pid is only set in the privileged part, and
120126277Sdes	 * points to the unprivileged child.
121126277Sdes	 */
122126277Sdes	return (pmonitor && pmonitor->m_pid > 0);
123126277Sdes}
124126277Sdes
12598675Sdesvoid
126137019Sdesmm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
12798675Sdes{
128106130Sdes	u_int mlen = buffer_len(m);
12998675Sdes	u_char buf[5];
13098675Sdes
13198675Sdes	debug3("%s entering: type %d", __func__, type);
13298675Sdes
133162856Sdes	put_u32(buf, mlen + 1);
13498675Sdes	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
135137019Sdes	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
136149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
137137019Sdes	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
138149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
13998675Sdes}
14098675Sdes
14198675Sdesvoid
142137019Sdesmm_request_receive(int sock, Buffer *m)
14398675Sdes{
14498675Sdes	u_char buf[4];
145106130Sdes	u_int msg_len;
14698675Sdes
14798675Sdes	debug3("%s entering", __func__);
14898675Sdes
149149753Sdes	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
150149753Sdes		if (errno == EPIPE)
151126277Sdes			cleanup_exit(255);
152149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
15398675Sdes	}
154162856Sdes	msg_len = get_u32(buf);
15598675Sdes	if (msg_len > 256 * 1024)
15698675Sdes		fatal("%s: read: bad msg_len %d", __func__, msg_len);
15798675Sdes	buffer_clear(m);
15898675Sdes	buffer_append_space(m, msg_len);
159149753Sdes	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
160149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
16198675Sdes}
16298675Sdes
16398675Sdesvoid
164137019Sdesmm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
16598675Sdes{
16698675Sdes	u_char rtype;
16798675Sdes
16898675Sdes	debug3("%s entering: type %d", __func__, type);
16998675Sdes
170137019Sdes	mm_request_receive(sock, m);
17198675Sdes	rtype = buffer_get_char(m);
17298675Sdes	if (rtype != type)
17398675Sdes		fatal("%s: read: rtype %d != type %d", __func__,
17498675Sdes		    rtype, type);
17598675Sdes}
17698675Sdes
17798675SdesDH *
17898675Sdesmm_choose_dh(int min, int nbits, int max)
17998675Sdes{
18098675Sdes	BIGNUM *p, *g;
18198675Sdes	int success = 0;
18298675Sdes	Buffer m;
18398675Sdes
18498675Sdes	buffer_init(&m);
18598675Sdes	buffer_put_int(&m, min);
18698675Sdes	buffer_put_int(&m, nbits);
18798675Sdes	buffer_put_int(&m, max);
18898675Sdes
18998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
19098675Sdes
19198675Sdes	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
19298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
19398675Sdes
19498675Sdes	success = buffer_get_char(&m);
19598675Sdes	if (success == 0)
19698675Sdes		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
19798675Sdes
19898675Sdes	if ((p = BN_new()) == NULL)
19998675Sdes		fatal("%s: BN_new failed", __func__);
20098675Sdes	if ((g = BN_new()) == NULL)
20198675Sdes		fatal("%s: BN_new failed", __func__);
20298675Sdes	buffer_get_bignum2(&m, p);
20398675Sdes	buffer_get_bignum2(&m, g);
20498675Sdes
20598675Sdes	debug3("%s: remaining %d", __func__, buffer_len(&m));
20698675Sdes	buffer_free(&m);
20798675Sdes
20898675Sdes	return (dh_new_group(g, p));
20998675Sdes}
21098675Sdes
21198675Sdesint
21298675Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
21398675Sdes{
21498675Sdes	Kex *kex = *pmonitor->m_pkex;
21598675Sdes	Buffer m;
21698675Sdes
21798675Sdes	debug3("%s entering", __func__);
21898675Sdes
21998675Sdes	buffer_init(&m);
22098675Sdes	buffer_put_int(&m, kex->host_key_index(key));
22198675Sdes	buffer_put_string(&m, data, datalen);
22298675Sdes
22398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
22498675Sdes
22598675Sdes	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
22698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
22798675Sdes	*sigp  = buffer_get_string(&m, lenp);
22898675Sdes	buffer_free(&m);
22998675Sdes
23098675Sdes	return (0);
23198675Sdes}
23298675Sdes
23398675Sdesstruct passwd *
234137019Sdesmm_getpwnamallow(const char *username)
23598675Sdes{
23698675Sdes	Buffer m;
23798675Sdes	struct passwd *pw;
238226046Sdes	u_int len, i;
239181111Sdes	ServerOptions *newopts;
24098675Sdes
24198675Sdes	debug3("%s entering", __func__);
24298675Sdes
24398675Sdes	buffer_init(&m);
244137019Sdes	buffer_put_cstring(&m, username);
24598675Sdes
24698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
24798675Sdes
24898675Sdes	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
24998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
25098675Sdes
25198675Sdes	if (buffer_get_char(&m) == 0) {
252181111Sdes		pw = NULL;
253181111Sdes		goto out;
25498675Sdes	}
255181111Sdes	pw = buffer_get_string(&m, &len);
256181111Sdes	if (len != sizeof(struct passwd))
25798675Sdes		fatal("%s: struct passwd size mismatch", __func__);
25898675Sdes	pw->pw_name = buffer_get_string(&m, NULL);
25998675Sdes	pw->pw_passwd = buffer_get_string(&m, NULL);
260255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
26198675Sdes	pw->pw_gecos = buffer_get_string(&m, NULL);
262255767Sdes#endif
263255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
26498675Sdes	pw->pw_class = buffer_get_string(&m, NULL);
26598937Sdes#endif
26698675Sdes	pw->pw_dir = buffer_get_string(&m, NULL);
26798675Sdes	pw->pw_shell = buffer_get_string(&m, NULL);
268181111Sdes
269181111Sdesout:
270181111Sdes	/* copy options block as a Match directive may have changed some */
271181111Sdes	newopts = buffer_get_string(&m, &len);
272181111Sdes	if (len != sizeof(*newopts))
273181111Sdes		fatal("%s: option block size mismatch", __func__);
274226046Sdes
275226046Sdes#define M_CP_STROPT(x) do { \
276226046Sdes		if (newopts->x != NULL) \
277226046Sdes			newopts->x = buffer_get_string(&m, NULL); \
278226046Sdes	} while (0)
279226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \
280226046Sdes		for (i = 0; i < newopts->nx; i++) \
281226046Sdes			newopts->x[i] = buffer_get_string(&m, NULL); \
282226046Sdes	} while (0)
283226046Sdes	/* See comment in servconf.h */
284226046Sdes	COPY_MATCH_STRING_OPTS();
285226046Sdes#undef M_CP_STROPT
286226046Sdes#undef M_CP_STRARRAYOPT
287226046Sdes
288181111Sdes	copy_set_server_options(&options, newopts, 1);
289255767Sdes	free(newopts);
290181111Sdes
29198675Sdes	buffer_free(&m);
29298675Sdes
29398675Sdes	return (pw);
29498675Sdes}
29598675Sdes
296126277Sdeschar *
297126277Sdesmm_auth2_read_banner(void)
29898675Sdes{
29998675Sdes	Buffer m;
30098675Sdes	char *banner;
30198675Sdes
30298675Sdes	debug3("%s entering", __func__);
30398675Sdes
30498675Sdes	buffer_init(&m);
30598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
30698675Sdes	buffer_clear(&m);
30798675Sdes
308126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
309126277Sdes	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
31098675Sdes	banner = buffer_get_string(&m, NULL);
31198675Sdes	buffer_free(&m);
31298675Sdes
313126277Sdes	/* treat empty banner as missing banner */
314126277Sdes	if (strlen(banner) == 0) {
315255767Sdes		free(banner);
316126277Sdes		banner = NULL;
317126277Sdes	}
31898675Sdes	return (banner);
31998675Sdes}
32098675Sdes
32198675Sdes/* Inform the privileged process about service and style */
32298675Sdes
32398675Sdesvoid
32498675Sdesmm_inform_authserv(char *service, char *style)
32598675Sdes{
32698675Sdes	Buffer m;
32798675Sdes
32898675Sdes	debug3("%s entering", __func__);
32998675Sdes
33098675Sdes	buffer_init(&m);
33198675Sdes	buffer_put_cstring(&m, service);
33298675Sdes	buffer_put_cstring(&m, style ? style : "");
33398675Sdes
33498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
33598675Sdes
33698675Sdes	buffer_free(&m);
33798675Sdes}
33898675Sdes
33998675Sdes/* Do the password authentication */
34098675Sdesint
34198675Sdesmm_auth_password(Authctxt *authctxt, char *password)
34298675Sdes{
34398675Sdes	Buffer m;
34498675Sdes	int authenticated = 0;
34598675Sdes
34698675Sdes	debug3("%s entering", __func__);
34798675Sdes
34898675Sdes	buffer_init(&m);
34998675Sdes	buffer_put_cstring(&m, password);
35098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
35198675Sdes
35298675Sdes	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
35398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
35498675Sdes
35598675Sdes	authenticated = buffer_get_int(&m);
35698675Sdes
35798675Sdes	buffer_free(&m);
35898675Sdes
35998675Sdes	debug3("%s: user %sauthenticated",
36098675Sdes	    __func__, authenticated ? "" : "not ");
36198675Sdes	return (authenticated);
36298675Sdes}
36398675Sdes
36498675Sdesint
36598675Sdesmm_user_key_allowed(struct passwd *pw, Key *key)
36698675Sdes{
36798675Sdes	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
36898675Sdes}
36998675Sdes
37098675Sdesint
37198675Sdesmm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
37298675Sdes    Key *key)
37398675Sdes{
37498675Sdes	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
37598675Sdes}
37698675Sdes
37798675Sdesint
37898675Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
37998675Sdes    char *host, Key *key)
38098675Sdes{
38198675Sdes	int ret;
38298675Sdes
38398675Sdes	key->type = KEY_RSA; /* XXX hack for key_to_blob */
38498675Sdes	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
38598675Sdes	key->type = KEY_RSA1;
38698675Sdes	return (ret);
38798675Sdes}
38898675Sdes
38998675Sdesint
39098675Sdesmm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
39198675Sdes{
39298675Sdes	Buffer m;
39398675Sdes	u_char *blob;
39498675Sdes	u_int len;
395113911Sdes	int allowed = 0, have_forced = 0;
39698675Sdes
39798675Sdes	debug3("%s entering", __func__);
39898675Sdes
39998675Sdes	/* Convert the key to a blob and the pass it over */
40098675Sdes	if (!key_to_blob(key, &blob, &len))
40198675Sdes		return (0);
40298675Sdes
40398675Sdes	buffer_init(&m);
40498675Sdes	buffer_put_int(&m, type);
40598675Sdes	buffer_put_cstring(&m, user ? user : "");
40698675Sdes	buffer_put_cstring(&m, host ? host : "");
40798675Sdes	buffer_put_string(&m, blob, len);
408255767Sdes	free(blob);
40998675Sdes
41098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
41198675Sdes
41298675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
41398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
41498675Sdes
41598675Sdes	allowed = buffer_get_int(&m);
41698675Sdes
417113911Sdes	/* fake forced command */
418113911Sdes	auth_clear_options();
419113911Sdes	have_forced = buffer_get_int(&m);
420113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
421113911Sdes
42298675Sdes	buffer_free(&m);
42398675Sdes
42498675Sdes	return (allowed);
42598675Sdes}
42698675Sdes
42798675Sdes/*
42898675Sdes * This key verify needs to send the key type along, because the
42998675Sdes * privileged parent makes the decision if the key is allowed
43098675Sdes * for authentication.
43198675Sdes */
43298675Sdes
43398675Sdesint
43498675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
43598675Sdes{
43698675Sdes	Buffer m;
43798675Sdes	u_char *blob;
43898675Sdes	u_int len;
43998675Sdes	int verified = 0;
44098675Sdes
44198675Sdes	debug3("%s entering", __func__);
44298675Sdes
44398675Sdes	/* Convert the key to a blob and the pass it over */
44498675Sdes	if (!key_to_blob(key, &blob, &len))
44598675Sdes		return (0);
44698675Sdes
44798675Sdes	buffer_init(&m);
44898675Sdes	buffer_put_string(&m, blob, len);
44998675Sdes	buffer_put_string(&m, sig, siglen);
45098675Sdes	buffer_put_string(&m, data, datalen);
451255767Sdes	free(blob);
45298675Sdes
45398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
45498675Sdes
45598675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
45698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
45798675Sdes
45898675Sdes	verified = buffer_get_int(&m);
45998675Sdes
46098675Sdes	buffer_free(&m);
46198675Sdes
46298675Sdes	return (verified);
46398675Sdes}
46498675Sdes
46598675Sdes/* Export key state after authentication */
46698675SdesNewkeys *
46798675Sdesmm_newkeys_from_blob(u_char *blob, int blen)
46898675Sdes{
46998675Sdes	Buffer b;
47098675Sdes	u_int len;
47198675Sdes	Newkeys *newkey = NULL;
47298675Sdes	Enc *enc;
47398675Sdes	Mac *mac;
47498675Sdes	Comp *comp;
47598675Sdes
47698675Sdes	debug3("%s: %p(%d)", __func__, blob, blen);
47798675Sdes#ifdef DEBUG_PK
47898675Sdes	dump_base64(stderr, blob, blen);
47998675Sdes#endif
48098675Sdes	buffer_init(&b);
48198675Sdes	buffer_append(&b, blob, blen);
48298675Sdes
483258335Sdes	newkey = xcalloc(1, sizeof(*newkey));
48498675Sdes	enc = &newkey->enc;
48598675Sdes	mac = &newkey->mac;
48698675Sdes	comp = &newkey->comp;
48798675Sdes
48898675Sdes	/* Enc structure */
48998675Sdes	enc->name = buffer_get_string(&b, NULL);
49098675Sdes	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
49198675Sdes	enc->enabled = buffer_get_int(&b);
49298675Sdes	enc->block_size = buffer_get_int(&b);
49398675Sdes	enc->key = buffer_get_string(&b, &enc->key_len);
494248619Sdes	enc->iv = buffer_get_string(&b, &enc->iv_len);
49598675Sdes
49698675Sdes	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
49798675Sdes		fatal("%s: bad cipher name %s or pointer %p", __func__,
49898675Sdes		    enc->name, enc->cipher);
49998675Sdes
50098675Sdes	/* Mac structure */
501248619Sdes	if (cipher_authlen(enc->cipher) == 0) {
502248619Sdes		mac->name = buffer_get_string(&b, NULL);
503248619Sdes		if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
504248619Sdes			fatal("%s: can not setup mac %s", __func__, mac->name);
505248619Sdes		mac->enabled = buffer_get_int(&b);
506248619Sdes		mac->key = buffer_get_string(&b, &len);
507248619Sdes		if (len > mac->key_len)
508248619Sdes			fatal("%s: bad mac key length: %u > %d", __func__, len,
509248619Sdes			    mac->key_len);
510248619Sdes		mac->key_len = len;
511248619Sdes	}
51298675Sdes
51398675Sdes	/* Comp structure */
51498675Sdes	comp->type = buffer_get_int(&b);
51598675Sdes	comp->enabled = buffer_get_int(&b);
51698675Sdes	comp->name = buffer_get_string(&b, NULL);
51798675Sdes
51898675Sdes	len = buffer_len(&b);
51998675Sdes	if (len != 0)
520106130Sdes		error("newkeys_from_blob: remaining bytes in blob %u", len);
52198675Sdes	buffer_free(&b);
52298675Sdes	return (newkey);
52398675Sdes}
52498675Sdes
52598675Sdesint
52698675Sdesmm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
52798675Sdes{
52898675Sdes	Buffer b;
52998675Sdes	int len;
53098675Sdes	Enc *enc;
53198675Sdes	Mac *mac;
53298675Sdes	Comp *comp;
533197679Sdes	Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
53498675Sdes
53598675Sdes	debug3("%s: converting %p", __func__, newkey);
53698675Sdes
53798675Sdes	if (newkey == NULL) {
53898675Sdes		error("%s: newkey == NULL", __func__);
53998675Sdes		return 0;
54098675Sdes	}
54198675Sdes	enc = &newkey->enc;
54298675Sdes	mac = &newkey->mac;
54398675Sdes	comp = &newkey->comp;
54498675Sdes
54598675Sdes	buffer_init(&b);
54698675Sdes	/* Enc structure */
54798675Sdes	buffer_put_cstring(&b, enc->name);
54898675Sdes	/* The cipher struct is constant and shared, you export pointer */
54998675Sdes	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
55098675Sdes	buffer_put_int(&b, enc->enabled);
55198675Sdes	buffer_put_int(&b, enc->block_size);
55298675Sdes	buffer_put_string(&b, enc->key, enc->key_len);
553248619Sdes	packet_get_keyiv(mode, enc->iv, enc->iv_len);
554248619Sdes	buffer_put_string(&b, enc->iv, enc->iv_len);
55598675Sdes
55698675Sdes	/* Mac structure */
557248619Sdes	if (cipher_authlen(enc->cipher) == 0) {
558248619Sdes		buffer_put_cstring(&b, mac->name);
559248619Sdes		buffer_put_int(&b, mac->enabled);
560248619Sdes		buffer_put_string(&b, mac->key, mac->key_len);
561248619Sdes	}
56298675Sdes
56398675Sdes	/* Comp structure */
56498675Sdes	buffer_put_int(&b, comp->type);
56598675Sdes	buffer_put_int(&b, comp->enabled);
56698675Sdes	buffer_put_cstring(&b, comp->name);
56798675Sdes
56898675Sdes	len = buffer_len(&b);
569106130Sdes	if (lenp != NULL)
570106130Sdes		*lenp = len;
571106130Sdes	if (blobp != NULL) {
572106130Sdes		*blobp = xmalloc(len);
573106130Sdes		memcpy(*blobp, buffer_ptr(&b), len);
574106130Sdes	}
575264377Sdes	explicit_bzero(buffer_ptr(&b), len);
57698675Sdes	buffer_free(&b);
57798675Sdes	return len;
57898675Sdes}
57998675Sdes
58098675Sdesstatic void
58198675Sdesmm_send_kex(Buffer *m, Kex *kex)
58298675Sdes{
58398675Sdes	buffer_put_string(m, kex->session_id, kex->session_id_len);
58498675Sdes	buffer_put_int(m, kex->we_need);
58598675Sdes	buffer_put_int(m, kex->hostkey_type);
58698675Sdes	buffer_put_int(m, kex->kex_type);
58798675Sdes	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
58898675Sdes	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
58998675Sdes	buffer_put_int(m, kex->flags);
59098675Sdes	buffer_put_cstring(m, kex->client_version_string);
59198675Sdes	buffer_put_cstring(m, kex->server_version_string);
59298675Sdes}
59398675Sdes
59498675Sdesvoid
595137019Sdesmm_send_keystate(struct monitor *monitor)
59698675Sdes{
597197679Sdes	Buffer m, *input, *output;
59898675Sdes	u_char *blob, *p;
59998675Sdes	u_int bloblen, plen;
600124211Sdes	u_int32_t seqnr, packets;
601181111Sdes	u_int64_t blocks, bytes;
60298675Sdes
60398675Sdes	buffer_init(&m);
60498675Sdes
60598675Sdes	if (!compat20) {
60698675Sdes		u_char iv[24];
60798675Sdes		u_char *key;
60898675Sdes		u_int ivlen, keylen;
60998675Sdes
61098675Sdes		buffer_put_int(&m, packet_get_protocol_flags());
61198675Sdes
61298675Sdes		buffer_put_int(&m, packet_get_ssh1_cipher());
61398675Sdes
61498675Sdes		debug3("%s: Sending ssh1 KEY+IV", __func__);
61598675Sdes		keylen = packet_get_encryption_key(NULL);
61698675Sdes		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
61798675Sdes		keylen = packet_get_encryption_key(key);
61898675Sdes		buffer_put_string(&m, key, keylen);
619264377Sdes		explicit_bzero(key, keylen);
620255767Sdes		free(key);
62198675Sdes
62298675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
62398675Sdes		packet_get_keyiv(MODE_OUT, iv, ivlen);
62498675Sdes		buffer_put_string(&m, iv, ivlen);
625248619Sdes		ivlen = packet_get_keyiv_len(MODE_IN);
62698675Sdes		packet_get_keyiv(MODE_IN, iv, ivlen);
62798675Sdes		buffer_put_string(&m, iv, ivlen);
62898675Sdes		goto skip;
62998675Sdes	} else {
63098675Sdes		/* Kex for rekeying */
631137019Sdes		mm_send_kex(&m, *monitor->m_pkex);
63298675Sdes	}
63398675Sdes
63498675Sdes	debug3("%s: Sending new keys: %p %p",
635197679Sdes	    __func__, packet_get_newkeys(MODE_OUT),
636197679Sdes	    packet_get_newkeys(MODE_IN));
63798675Sdes
63898675Sdes	/* Keys from Kex */
63998675Sdes	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
64098675Sdes		fatal("%s: conversion of newkeys failed", __func__);
64198675Sdes
64298675Sdes	buffer_put_string(&m, blob, bloblen);
643255767Sdes	free(blob);
64498675Sdes
64598675Sdes	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
64698675Sdes		fatal("%s: conversion of newkeys failed", __func__);
64798675Sdes
64898675Sdes	buffer_put_string(&m, blob, bloblen);
649255767Sdes	free(blob);
65098675Sdes
651181111Sdes	packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
652124211Sdes	buffer_put_int(&m, seqnr);
653124211Sdes	buffer_put_int64(&m, blocks);
654124211Sdes	buffer_put_int(&m, packets);
655181111Sdes	buffer_put_int64(&m, bytes);
656181111Sdes	packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
657124211Sdes	buffer_put_int(&m, seqnr);
658124211Sdes	buffer_put_int64(&m, blocks);
659124211Sdes	buffer_put_int(&m, packets);
660181111Sdes	buffer_put_int64(&m, bytes);
66198675Sdes
66298675Sdes	debug3("%s: New keys have been sent", __func__);
66398675Sdes skip:
66498675Sdes	/* More key context */
66598675Sdes	plen = packet_get_keycontext(MODE_OUT, NULL);
66698675Sdes	p = xmalloc(plen+1);
66798675Sdes	packet_get_keycontext(MODE_OUT, p);
66898675Sdes	buffer_put_string(&m, p, plen);
669255767Sdes	free(p);
67098675Sdes
67198675Sdes	plen = packet_get_keycontext(MODE_IN, NULL);
67298675Sdes	p = xmalloc(plen+1);
67398675Sdes	packet_get_keycontext(MODE_IN, p);
67498675Sdes	buffer_put_string(&m, p, plen);
675255767Sdes	free(p);
67698675Sdes
67798675Sdes	/* Compression state */
67898675Sdes	debug3("%s: Sending compression state", __func__);
67998675Sdes	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
68098675Sdes	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
68198675Sdes
68298675Sdes	/* Network I/O buffers */
683197679Sdes	input = (Buffer *)packet_get_input();
684197679Sdes	output = (Buffer *)packet_get_output();
685197679Sdes	buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
686197679Sdes	buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
68798675Sdes
688197679Sdes	/* Roaming */
689197679Sdes	if (compat20) {
690197679Sdes		buffer_put_int64(&m, get_sent_bytes());
691197679Sdes		buffer_put_int64(&m, get_recv_bytes());
692197679Sdes	}
693197679Sdes
694137019Sdes	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
69598675Sdes	debug3("%s: Finished sending state", __func__);
69698675Sdes
69798675Sdes	buffer_free(&m);
69898675Sdes}
69998675Sdes
70098675Sdesint
701162856Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
70298675Sdes{
70398675Sdes	Buffer m;
704137019Sdes	char *p, *msg;
705181111Sdes	int success = 0, tmp1 = -1, tmp2 = -1;
70698675Sdes
707181111Sdes	/* Kludge: ensure there are fds free to receive the pty/tty */
708181111Sdes	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
709181111Sdes	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
710181111Sdes		error("%s: cannot allocate fds for pty", __func__);
711181111Sdes		if (tmp1 > 0)
712181111Sdes			close(tmp1);
713181111Sdes		if (tmp2 > 0)
714181111Sdes			close(tmp2);
715181111Sdes		return 0;
716181111Sdes	}
717181111Sdes	close(tmp1);
718181111Sdes	close(tmp2);
719181111Sdes
72098675Sdes	buffer_init(&m);
72198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
72298675Sdes
72398675Sdes	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
72498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
72598675Sdes
72698675Sdes	success = buffer_get_int(&m);
72798675Sdes	if (success == 0) {
72898675Sdes		debug3("%s: pty alloc failed", __func__);
72998675Sdes		buffer_free(&m);
73098675Sdes		return (0);
73198675Sdes	}
73298675Sdes	p = buffer_get_string(&m, NULL);
733137019Sdes	msg = buffer_get_string(&m, NULL);
73498675Sdes	buffer_free(&m);
73598675Sdes
73698675Sdes	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
737255767Sdes	free(p);
73898675Sdes
739137019Sdes	buffer_append(&loginmsg, msg, strlen(msg));
740255767Sdes	free(msg);
741137019Sdes
742181111Sdes	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
743181111Sdes	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
744181111Sdes		fatal("%s: receive fds failed", __func__);
74598675Sdes
74698675Sdes	/* Success */
74798675Sdes	return (1);
74898675Sdes}
74998675Sdes
75098675Sdesvoid
751126277Sdesmm_session_pty_cleanup2(Session *s)
75298675Sdes{
75398675Sdes	Buffer m;
75498675Sdes
75598675Sdes	if (s->ttyfd == -1)
75698675Sdes		return;
75798675Sdes	buffer_init(&m);
75898675Sdes	buffer_put_cstring(&m, s->tty);
75998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
76098675Sdes	buffer_free(&m);
76198675Sdes
76298675Sdes	/* closed dup'ed master */
763181111Sdes	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
764181111Sdes		error("close(s->ptymaster/%d): %s",
765181111Sdes		    s->ptymaster, strerror(errno));
76698675Sdes
76798675Sdes	/* unlink pty from session */
76898675Sdes	s->ttyfd = -1;
76998675Sdes}
77098675Sdes
77198937Sdes#ifdef USE_PAM
77298937Sdesvoid
773128460Sdesmm_start_pam(Authctxt *authctxt)
77498937Sdes{
77598937Sdes	Buffer m;
77698937Sdes
77798937Sdes	debug3("%s entering", __func__);
778124211Sdes	if (!options.use_pam)
779124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
78098937Sdes
78198937Sdes	buffer_init(&m);
78298937Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
78398937Sdes
78498937Sdes	buffer_free(&m);
78598937Sdes}
78699052Sdes
787124211Sdesu_int
788124211Sdesmm_do_pam_account(void)
789124211Sdes{
790124211Sdes	Buffer m;
791124211Sdes	u_int ret;
792147005Sdes	char *msg;
793124211Sdes
794124211Sdes	debug3("%s entering", __func__);
795124211Sdes	if (!options.use_pam)
796124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
797124211Sdes
798124211Sdes	buffer_init(&m);
799124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
800124211Sdes
801126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
802124211Sdes	    MONITOR_ANS_PAM_ACCOUNT, &m);
803124211Sdes	ret = buffer_get_int(&m);
804147005Sdes	msg = buffer_get_string(&m, NULL);
805147005Sdes	buffer_append(&loginmsg, msg, strlen(msg));
806255767Sdes	free(msg);
807124211Sdes
808124211Sdes	buffer_free(&m);
809126277Sdes
810124211Sdes	debug3("%s returning %d", __func__, ret);
811124211Sdes
812124211Sdes	return (ret);
813124211Sdes}
814124211Sdes
81599052Sdesvoid *
816124211Sdesmm_sshpam_init_ctx(Authctxt *authctxt)
81799052Sdes{
81899052Sdes	Buffer m;
81999052Sdes	int success;
82099052Sdes
82199052Sdes	debug3("%s", __func__);
82299052Sdes	buffer_init(&m);
82399052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
82499052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
82599052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
82699052Sdes	success = buffer_get_int(&m);
82799052Sdes	if (success == 0) {
82899052Sdes		debug3("%s: pam_init_ctx failed", __func__);
82999052Sdes		buffer_free(&m);
83099052Sdes		return (NULL);
83199052Sdes	}
83299052Sdes	buffer_free(&m);
83399052Sdes	return (authctxt);
83499052Sdes}
83599052Sdes
83699052Sdesint
837124211Sdesmm_sshpam_query(void *ctx, char **name, char **info,
83899052Sdes    u_int *num, char ***prompts, u_int **echo_on)
83999052Sdes{
84099052Sdes	Buffer m;
841149753Sdes	u_int i;
842149753Sdes	int ret;
84399052Sdes
84499052Sdes	debug3("%s", __func__);
84599052Sdes	buffer_init(&m);
84699052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
84799052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
84899052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
84999052Sdes	ret = buffer_get_int(&m);
85099052Sdes	debug3("%s: pam_query returned %d", __func__, ret);
85199052Sdes	*name = buffer_get_string(&m, NULL);
85299052Sdes	*info = buffer_get_string(&m, NULL);
85399052Sdes	*num = buffer_get_int(&m);
854162856Sdes	if (*num > PAM_MAX_NUM_MSG)
855162856Sdes		fatal("%s: recieved %u PAM messages, expected <= %u",
856162856Sdes		    __func__, *num, PAM_MAX_NUM_MSG);
857162856Sdes	*prompts = xcalloc((*num + 1), sizeof(char *));
858162856Sdes	*echo_on = xcalloc((*num + 1), sizeof(u_int));
85999052Sdes	for (i = 0; i < *num; ++i) {
86099052Sdes		(*prompts)[i] = buffer_get_string(&m, NULL);
86199052Sdes		(*echo_on)[i] = buffer_get_int(&m);
86299052Sdes	}
86399052Sdes	buffer_free(&m);
86499052Sdes	return (ret);
86599052Sdes}
86699052Sdes
86799052Sdesint
868124211Sdesmm_sshpam_respond(void *ctx, u_int num, char **resp)
86999052Sdes{
87099052Sdes	Buffer m;
871149753Sdes	u_int i;
872149753Sdes	int ret;
87399052Sdes
87499052Sdes	debug3("%s", __func__);
87599052Sdes	buffer_init(&m);
87699052Sdes	buffer_put_int(&m, num);
87799052Sdes	for (i = 0; i < num; ++i)
87899052Sdes		buffer_put_cstring(&m, resp[i]);
87999052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
88099052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
88199052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
88299052Sdes	ret = buffer_get_int(&m);
88399052Sdes	debug3("%s: pam_respond returned %d", __func__, ret);
88499052Sdes	buffer_free(&m);
88599052Sdes	return (ret);
88699052Sdes}
88799052Sdes
88899052Sdesvoid
889124211Sdesmm_sshpam_free_ctx(void *ctxtp)
89099052Sdes{
89199052Sdes	Buffer m;
89299052Sdes
89399052Sdes	debug3("%s", __func__);
89499052Sdes	buffer_init(&m);
89599052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
89699052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
89799052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
89899052Sdes	buffer_free(&m);
89999052Sdes}
90098937Sdes#endif /* USE_PAM */
90198937Sdes
90298675Sdes/* Request process termination */
90398675Sdes
90498675Sdesvoid
90598675Sdesmm_terminate(void)
90698675Sdes{
90798675Sdes	Buffer m;
90898675Sdes
90998675Sdes	buffer_init(&m);
91098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
91198675Sdes	buffer_free(&m);
91298675Sdes}
91398675Sdes
91498675Sdesint
91598675Sdesmm_ssh1_session_key(BIGNUM *num)
91698675Sdes{
91798675Sdes	int rsafail;
91898675Sdes	Buffer m;
91998675Sdes
92098675Sdes	buffer_init(&m);
92198675Sdes	buffer_put_bignum2(&m, num);
92298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
92398675Sdes
92498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
92598675Sdes
92698675Sdes	rsafail = buffer_get_int(&m);
92798675Sdes	buffer_get_bignum2(&m, num);
92898675Sdes
92998675Sdes	buffer_free(&m);
93098675Sdes
93198675Sdes	return (rsafail);
93298675Sdes}
93398675Sdes
93498675Sdesstatic void
93598675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts,
93698675Sdes    char ***prompts, u_int **echo_on)
93798675Sdes{
93898675Sdes	*name = xstrdup("");
93998675Sdes	*infotxt = xstrdup("");
94098675Sdes	*numprompts = 1;
941162856Sdes	*prompts = xcalloc(*numprompts, sizeof(char *));
942162856Sdes	*echo_on = xcalloc(*numprompts, sizeof(u_int));
94398675Sdes	(*echo_on)[0] = 0;
94498675Sdes}
94598675Sdes
94698675Sdesint
94798675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt,
94898675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
94998675Sdes{
95098675Sdes	Buffer m;
951113911Sdes	u_int success;
95298675Sdes	char *challenge;
95398675Sdes
95498675Sdes	debug3("%s: entering", __func__);
95598675Sdes
95698675Sdes	buffer_init(&m);
95798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
95898675Sdes
95998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
96098675Sdes	    &m);
961113911Sdes	success = buffer_get_int(&m);
962113911Sdes	if (success == 0) {
96398675Sdes		debug3("%s: no challenge", __func__);
96498675Sdes		buffer_free(&m);
96598675Sdes		return (-1);
96698675Sdes	}
96798675Sdes
96898675Sdes	/* Get the challenge, and format the response */
96998675Sdes	challenge  = buffer_get_string(&m, NULL);
97098675Sdes	buffer_free(&m);
97198675Sdes
97298675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
97398675Sdes	(*prompts)[0] = challenge;
97498675Sdes
97598675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
97698675Sdes
97798675Sdes	return (0);
97898675Sdes}
97998675Sdes
98098675Sdesint
98198675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
98298675Sdes{
98398675Sdes	Buffer m;
98498675Sdes	int authok;
98598675Sdes
98698675Sdes	debug3("%s: entering", __func__);
98798675Sdes	if (numresponses != 1)
98898675Sdes		return (-1);
98998675Sdes
99098675Sdes	buffer_init(&m);
99198675Sdes	buffer_put_cstring(&m, responses[0]);
99298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
99398675Sdes
99498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
99598675Sdes	    MONITOR_ANS_BSDAUTHRESPOND, &m);
99698675Sdes
99798675Sdes	authok = buffer_get_int(&m);
99898675Sdes	buffer_free(&m);
99998675Sdes
100098675Sdes	return ((authok == 0) ? -1 : 0);
100198675Sdes}
100298675Sdes
100399046Sdes#ifdef SKEY
100498675Sdesint
100598675Sdesmm_skey_query(void *ctx, char **name, char **infotxt,
100698675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
100798675Sdes{
100898675Sdes	Buffer m;
1009113911Sdes	u_int success;
1010162856Sdes	char *challenge;
101198675Sdes
101298675Sdes	debug3("%s: entering", __func__);
101398675Sdes
101498675Sdes	buffer_init(&m);
101598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
101698675Sdes
101798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
101898675Sdes	    &m);
1019113911Sdes	success = buffer_get_int(&m);
1020113911Sdes	if (success == 0) {
102198675Sdes		debug3("%s: no challenge", __func__);
102298675Sdes		buffer_free(&m);
102398675Sdes		return (-1);
102498675Sdes	}
102598675Sdes
102698675Sdes	/* Get the challenge, and format the response */
102798675Sdes	challenge  = buffer_get_string(&m, NULL);
102898675Sdes	buffer_free(&m);
102998675Sdes
103098675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
103198675Sdes
103298675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
103398675Sdes
1034162856Sdes	xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
1035255767Sdes	free(challenge);
103698675Sdes
103798675Sdes	return (0);
103898675Sdes}
103998675Sdes
104098675Sdesint
104198675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses)
104298675Sdes{
104398675Sdes	Buffer m;
104498675Sdes	int authok;
104598675Sdes
104698675Sdes	debug3("%s: entering", __func__);
104798675Sdes	if (numresponses != 1)
104898675Sdes		return (-1);
104998675Sdes
105098675Sdes	buffer_init(&m);
105198675Sdes	buffer_put_cstring(&m, responses[0]);
105298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
105398675Sdes
105498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
105598675Sdes	    MONITOR_ANS_SKEYRESPOND, &m);
105698675Sdes
105798675Sdes	authok = buffer_get_int(&m);
105898675Sdes	buffer_free(&m);
105998675Sdes
106098675Sdes	return ((authok == 0) ? -1 : 0);
106198675Sdes}
1062137019Sdes#endif /* SKEY */
106398675Sdes
106498675Sdesvoid
106598675Sdesmm_ssh1_session_id(u_char session_id[16])
106698675Sdes{
106798675Sdes	Buffer m;
106898675Sdes	int i;
106998675Sdes
107098675Sdes	debug3("%s entering", __func__);
107198675Sdes
107298675Sdes	buffer_init(&m);
107398675Sdes	for (i = 0; i < 16; i++)
107498675Sdes		buffer_put_char(&m, session_id[i]);
107598675Sdes
107698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
107798675Sdes	buffer_free(&m);
107898675Sdes}
107998675Sdes
108098675Sdesint
108198675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
108298675Sdes{
108398675Sdes	Buffer m;
108498675Sdes	Key *key;
108598675Sdes	u_char *blob;
108698675Sdes	u_int blen;
1087113911Sdes	int allowed = 0, have_forced = 0;
108898675Sdes
108998675Sdes	debug3("%s entering", __func__);
109098675Sdes
109198675Sdes	buffer_init(&m);
109298675Sdes	buffer_put_bignum2(&m, client_n);
109398675Sdes
109498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
109598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
109698675Sdes
109798675Sdes	allowed = buffer_get_int(&m);
109898675Sdes
1099113911Sdes	/* fake forced command */
1100113911Sdes	auth_clear_options();
1101113911Sdes	have_forced = buffer_get_int(&m);
1102113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
1103113911Sdes
110498675Sdes	if (allowed && rkey != NULL) {
110598675Sdes		blob = buffer_get_string(&m, &blen);
110698675Sdes		if ((key = key_from_blob(blob, blen)) == NULL)
110798675Sdes			fatal("%s: key_from_blob failed", __func__);
110898675Sdes		*rkey = key;
1109255767Sdes		free(blob);
111098675Sdes	}
111198675Sdes	buffer_free(&m);
111298675Sdes
111398675Sdes	return (allowed);
111498675Sdes}
111598675Sdes
111698675SdesBIGNUM *
111798675Sdesmm_auth_rsa_generate_challenge(Key *key)
111898675Sdes{
111998675Sdes	Buffer m;
112098675Sdes	BIGNUM *challenge;
112198675Sdes	u_char *blob;
112298675Sdes	u_int blen;
112398675Sdes
112498675Sdes	debug3("%s entering", __func__);
112598675Sdes
112698675Sdes	if ((challenge = BN_new()) == NULL)
112798675Sdes		fatal("%s: BN_new failed", __func__);
112898675Sdes
112998675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
113098675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
113198675Sdes		fatal("%s: key_to_blob failed", __func__);
113298675Sdes	key->type = KEY_RSA1;
113398675Sdes
113498675Sdes	buffer_init(&m);
113598675Sdes	buffer_put_string(&m, blob, blen);
1136255767Sdes	free(blob);
113798675Sdes
113898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
113998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
114098675Sdes
114198675Sdes	buffer_get_bignum2(&m, challenge);
114298675Sdes	buffer_free(&m);
114398675Sdes
114498675Sdes	return (challenge);
114598675Sdes}
114698675Sdes
114798675Sdesint
114898675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
114998675Sdes{
115098675Sdes	Buffer m;
115198675Sdes	u_char *blob;
115298675Sdes	u_int blen;
115398675Sdes	int success = 0;
115498675Sdes
115598675Sdes	debug3("%s entering", __func__);
115698675Sdes
115798675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
115898675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
115998675Sdes		fatal("%s: key_to_blob failed", __func__);
116098675Sdes	key->type = KEY_RSA1;
116198675Sdes
116298675Sdes	buffer_init(&m);
116398675Sdes	buffer_put_string(&m, blob, blen);
116498675Sdes	buffer_put_string(&m, response, 16);
1165255767Sdes	free(blob);
116698675Sdes
116798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
116898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
116998675Sdes
117098675Sdes	success = buffer_get_int(&m);
117198675Sdes	buffer_free(&m);
117298675Sdes
117398675Sdes	return (success);
117498675Sdes}
1175106130Sdes
1176147005Sdes#ifdef SSH_AUDIT_EVENTS
1177147005Sdesvoid
1178147005Sdesmm_audit_event(ssh_audit_event_t event)
1179147005Sdes{
1180147005Sdes	Buffer m;
1181147005Sdes
1182147005Sdes	debug3("%s entering", __func__);
1183147005Sdes
1184147005Sdes	buffer_init(&m);
1185147005Sdes	buffer_put_int(&m, event);
1186147005Sdes
1187147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
1188147005Sdes	buffer_free(&m);
1189147005Sdes}
1190147005Sdes
1191147005Sdesvoid
1192147005Sdesmm_audit_run_command(const char *command)
1193147005Sdes{
1194147005Sdes	Buffer m;
1195147005Sdes
1196147005Sdes	debug3("%s entering command %s", __func__, command);
1197147005Sdes
1198147005Sdes	buffer_init(&m);
1199147005Sdes	buffer_put_cstring(&m, command);
1200147005Sdes
1201147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
1202147005Sdes	buffer_free(&m);
1203147005Sdes}
1204147005Sdes#endif /* SSH_AUDIT_EVENTS */
1205147005Sdes
1206124211Sdes#ifdef GSSAPI
1207124211SdesOM_uint32
1208137019Sdesmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
1209106130Sdes{
1210124211Sdes	Buffer m;
1211124211Sdes	OM_uint32 major;
1212106130Sdes
1213124211Sdes	/* Client doesn't get to see the context */
1214124211Sdes	*ctx = NULL;
1215106130Sdes
1216106130Sdes	buffer_init(&m);
1217137019Sdes	buffer_put_string(&m, goid->elements, goid->length);
1218106130Sdes
1219124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1220124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1221106130Sdes
1222124211Sdes	major = buffer_get_int(&m);
1223124211Sdes
1224106130Sdes	buffer_free(&m);
1225124211Sdes	return (major);
1226106130Sdes}
1227106130Sdes
1228124211SdesOM_uint32
1229124211Sdesmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1230124211Sdes    gss_buffer_desc *out, OM_uint32 *flags)
1231124211Sdes{
1232124211Sdes	Buffer m;
1233124211Sdes	OM_uint32 major;
1234124211Sdes	u_int len;
1235124211Sdes
1236124211Sdes	buffer_init(&m);
1237124211Sdes	buffer_put_string(&m, in->value, in->length);
1238124211Sdes
1239124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1240124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1241124211Sdes
1242124211Sdes	major = buffer_get_int(&m);
1243124211Sdes	out->value = buffer_get_string(&m, &len);
1244124211Sdes	out->length = len;
1245124211Sdes	if (flags)
1246124211Sdes		*flags = buffer_get_int(&m);
1247124211Sdes
1248124211Sdes	buffer_free(&m);
1249124211Sdes
1250124211Sdes	return (major);
1251124211Sdes}
1252124211Sdes
1253126277SdesOM_uint32
1254126277Sdesmm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
1255126277Sdes{
1256126277Sdes	Buffer m;
1257126277Sdes	OM_uint32 major;
1258126277Sdes
1259126277Sdes	buffer_init(&m);
1260126277Sdes	buffer_put_string(&m, gssbuf->value, gssbuf->length);
1261126277Sdes	buffer_put_string(&m, gssmic->value, gssmic->length);
1262126277Sdes
1263126277Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
1264126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
1265126277Sdes	    &m);
1266126277Sdes
1267126277Sdes	major = buffer_get_int(&m);
1268126277Sdes	buffer_free(&m);
1269126277Sdes	return(major);
1270126277Sdes}
1271126277Sdes
1272106130Sdesint
1273124211Sdesmm_ssh_gssapi_userok(char *user)
1274106130Sdes{
1275106130Sdes	Buffer m;
1276124211Sdes	int authenticated = 0;
1277106130Sdes
1278106130Sdes	buffer_init(&m);
1279106130Sdes
1280124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1281124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1282124211Sdes				  &m);
1283106130Sdes
1284124211Sdes	authenticated = buffer_get_int(&m);
1285106130Sdes
1286106130Sdes	buffer_free(&m);
1287124211Sdes	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1288124211Sdes	return (authenticated);
1289106130Sdes}
1290124211Sdes#endif /* GSSAPI */
1291192595Sdes
1292