monitor_wrap.c revision 124211
198675Sdes/*
298675Sdes * Copyright 2002 Niels Provos <provos@citi.umich.edu>
398675Sdes * Copyright 2002 Markus Friedl <markus@openbsd.org>
498675Sdes * All rights reserved.
598675Sdes *
698675Sdes * Redistribution and use in source and binary forms, with or without
798675Sdes * modification, are permitted provided that the following conditions
898675Sdes * are met:
998675Sdes * 1. Redistributions of source code must retain the above copyright
1098675Sdes *    notice, this list of conditions and the following disclaimer.
1198675Sdes * 2. Redistributions in binary form must reproduce the above copyright
1298675Sdes *    notice, this list of conditions and the following disclaimer in the
1398675Sdes *    documentation and/or other materials provided with the distribution.
1498675Sdes *
1598675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1698675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1798675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1898675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1998675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2098675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2198675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2298675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2398675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2498675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2598675Sdes */
2698675Sdes
2798675Sdes#include "includes.h"
28124211SdesRCSID("$OpenBSD: monitor_wrap.c,v 1.31 2003/08/28 12:54:34 markus Exp $");
2999052SdesRCSID("$FreeBSD: head/crypto/openssh/monitor_wrap.c 124211 2004-01-07 11:16:27Z des $");
3098675Sdes
3198675Sdes#include <openssl/bn.h>
3298675Sdes#include <openssl/dh.h>
3398675Sdes
3498675Sdes#include "ssh.h"
3598675Sdes#include "dh.h"
3698675Sdes#include "kex.h"
3798675Sdes#include "auth.h"
38113911Sdes#include "auth-options.h"
3998675Sdes#include "buffer.h"
4098675Sdes#include "bufaux.h"
4198675Sdes#include "packet.h"
4298675Sdes#include "mac.h"
4398675Sdes#include "log.h"
4498675Sdes#include "zlib.h"
4598675Sdes#include "monitor.h"
4698675Sdes#include "monitor_wrap.h"
4798675Sdes#include "xmalloc.h"
4898675Sdes#include "atomicio.h"
4998675Sdes#include "monitor_fdpass.h"
5098675Sdes#include "getput.h"
51124211Sdes#include "servconf.h"
5298675Sdes
5398675Sdes#include "auth.h"
5498675Sdes#include "channels.h"
5598675Sdes#include "session.h"
5698675Sdes
57124211Sdes#ifdef GSSAPI
58124211Sdes#include "ssh-gss.h"
59124211Sdes#endif
60124211Sdes
6198675Sdes/* Imports */
6298675Sdesextern int compat20;
6398675Sdesextern Newkeys *newkeys[];
6498675Sdesextern z_stream incoming_stream;
6598675Sdesextern z_stream outgoing_stream;
6698675Sdesextern struct monitor *pmonitor;
6798675Sdesextern Buffer input, output;
68124211Sdesextern ServerOptions options;
6998675Sdes
7098675Sdesvoid
7198675Sdesmm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
7298675Sdes{
73106130Sdes	u_int mlen = buffer_len(m);
7498675Sdes	u_char buf[5];
7598675Sdes
7698675Sdes	debug3("%s entering: type %d", __func__, type);
7798675Sdes
7898675Sdes	PUT_32BIT(buf, mlen + 1);
7998675Sdes	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
80124211Sdes	if (atomicio(vwrite, socket, buf, sizeof(buf)) != sizeof(buf))
8198675Sdes		fatal("%s: write", __func__);
82124211Sdes	if (atomicio(vwrite, socket, buffer_ptr(m), mlen) != mlen)
8398675Sdes		fatal("%s: write", __func__);
8498675Sdes}
8598675Sdes
8698675Sdesvoid
8798675Sdesmm_request_receive(int socket, Buffer *m)
8898675Sdes{
8998675Sdes	u_char buf[4];
90106130Sdes	u_int msg_len;
9198675Sdes	ssize_t res;
9298675Sdes
9398675Sdes	debug3("%s entering", __func__);
9498675Sdes
9598675Sdes	res = atomicio(read, socket, buf, sizeof(buf));
9698675Sdes	if (res != sizeof(buf)) {
9798675Sdes		if (res == 0)
9898675Sdes			fatal_cleanup();
9998675Sdes		fatal("%s: read: %ld", __func__, (long)res);
10098675Sdes	}
10198675Sdes	msg_len = GET_32BIT(buf);
10298675Sdes	if (msg_len > 256 * 1024)
10398675Sdes		fatal("%s: read: bad msg_len %d", __func__, msg_len);
10498675Sdes	buffer_clear(m);
10598675Sdes	buffer_append_space(m, msg_len);
10698675Sdes	res = atomicio(read, socket, buffer_ptr(m), msg_len);
10798675Sdes	if (res != msg_len)
10898675Sdes		fatal("%s: read: %ld != msg_len", __func__, (long)res);
10998675Sdes}
11098675Sdes
11198675Sdesvoid
11298675Sdesmm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
11398675Sdes{
11498675Sdes	u_char rtype;
11598675Sdes
11698675Sdes	debug3("%s entering: type %d", __func__, type);
11798675Sdes
11898675Sdes	mm_request_receive(socket, m);
11998675Sdes	rtype = buffer_get_char(m);
12098675Sdes	if (rtype != type)
12198675Sdes		fatal("%s: read: rtype %d != type %d", __func__,
12298675Sdes		    rtype, type);
12398675Sdes}
12498675Sdes
12598675SdesDH *
12698675Sdesmm_choose_dh(int min, int nbits, int max)
12798675Sdes{
12898675Sdes	BIGNUM *p, *g;
12998675Sdes	int success = 0;
13098675Sdes	Buffer m;
13198675Sdes
13298675Sdes	buffer_init(&m);
13398675Sdes	buffer_put_int(&m, min);
13498675Sdes	buffer_put_int(&m, nbits);
13598675Sdes	buffer_put_int(&m, max);
13698675Sdes
13798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
13898675Sdes
13998675Sdes	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
14098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
14198675Sdes
14298675Sdes	success = buffer_get_char(&m);
14398675Sdes	if (success == 0)
14498675Sdes		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
14598675Sdes
14698675Sdes	if ((p = BN_new()) == NULL)
14798675Sdes		fatal("%s: BN_new failed", __func__);
14898675Sdes	if ((g = BN_new()) == NULL)
14998675Sdes		fatal("%s: BN_new failed", __func__);
15098675Sdes	buffer_get_bignum2(&m, p);
15198675Sdes	buffer_get_bignum2(&m, g);
15298675Sdes
15398675Sdes	debug3("%s: remaining %d", __func__, buffer_len(&m));
15498675Sdes	buffer_free(&m);
15598675Sdes
15698675Sdes	return (dh_new_group(g, p));
15798675Sdes}
15898675Sdes
15998675Sdesint
16098675Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
16198675Sdes{
16298675Sdes	Kex *kex = *pmonitor->m_pkex;
16398675Sdes	Buffer m;
16498675Sdes
16598675Sdes	debug3("%s entering", __func__);
16698675Sdes
16798675Sdes	buffer_init(&m);
16898675Sdes	buffer_put_int(&m, kex->host_key_index(key));
16998675Sdes	buffer_put_string(&m, data, datalen);
17098675Sdes
17198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
17298675Sdes
17398675Sdes	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
17498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
17598675Sdes	*sigp  = buffer_get_string(&m, lenp);
17698675Sdes	buffer_free(&m);
17798675Sdes
17898675Sdes	return (0);
17998675Sdes}
18098675Sdes
18198675Sdesstruct passwd *
18298675Sdesmm_getpwnamallow(const char *login)
18398675Sdes{
18498675Sdes	Buffer m;
18598675Sdes	struct passwd *pw;
18698675Sdes	u_int pwlen;
18798675Sdes
18898675Sdes	debug3("%s entering", __func__);
18998675Sdes
19098675Sdes	buffer_init(&m);
19198675Sdes	buffer_put_cstring(&m, login);
19298675Sdes
19398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
19498675Sdes
19598675Sdes	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
19698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
19798675Sdes
19898675Sdes	if (buffer_get_char(&m) == 0) {
19998675Sdes		buffer_free(&m);
20098675Sdes		return (NULL);
20198675Sdes	}
20298675Sdes	pw = buffer_get_string(&m, &pwlen);
20398675Sdes	if (pwlen != sizeof(struct passwd))
20498675Sdes		fatal("%s: struct passwd size mismatch", __func__);
20598675Sdes	pw->pw_name = buffer_get_string(&m, NULL);
20698675Sdes	pw->pw_passwd = buffer_get_string(&m, NULL);
20798675Sdes	pw->pw_gecos = buffer_get_string(&m, NULL);
20898937Sdes#ifdef HAVE_PW_CLASS_IN_PASSWD
20998675Sdes	pw->pw_class = buffer_get_string(&m, NULL);
21098937Sdes#endif
21198675Sdes	pw->pw_dir = buffer_get_string(&m, NULL);
21298675Sdes	pw->pw_shell = buffer_get_string(&m, NULL);
21398675Sdes	buffer_free(&m);
21498675Sdes
21598675Sdes	return (pw);
21698675Sdes}
21798675Sdes
218106130Sdeschar *mm_auth2_read_banner(void)
21998675Sdes{
22098675Sdes	Buffer m;
22198675Sdes	char *banner;
22298675Sdes
22398675Sdes	debug3("%s entering", __func__);
22498675Sdes
22598675Sdes	buffer_init(&m);
22698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
22798675Sdes	buffer_clear(&m);
22898675Sdes
22998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
23098675Sdes	banner = buffer_get_string(&m, NULL);
23198675Sdes	buffer_free(&m);
23298675Sdes
23398675Sdes	return (banner);
23498675Sdes}
23598675Sdes
23698675Sdes/* Inform the privileged process about service and style */
23798675Sdes
23898675Sdesvoid
23998675Sdesmm_inform_authserv(char *service, char *style)
24098675Sdes{
24198675Sdes	Buffer m;
24298675Sdes
24398675Sdes	debug3("%s entering", __func__);
24498675Sdes
24598675Sdes	buffer_init(&m);
24698675Sdes	buffer_put_cstring(&m, service);
24798675Sdes	buffer_put_cstring(&m, style ? style : "");
24898675Sdes
24998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
25098675Sdes
25198675Sdes	buffer_free(&m);
25298675Sdes}
25398675Sdes
25498675Sdes/* Do the password authentication */
25598675Sdesint
25698675Sdesmm_auth_password(Authctxt *authctxt, char *password)
25798675Sdes{
25898675Sdes	Buffer m;
25998675Sdes	int authenticated = 0;
26098675Sdes
26198675Sdes	debug3("%s entering", __func__);
26298675Sdes
26398675Sdes	buffer_init(&m);
26498675Sdes	buffer_put_cstring(&m, password);
26598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
26698675Sdes
26798675Sdes	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
26898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
26998675Sdes
27098675Sdes	authenticated = buffer_get_int(&m);
27198675Sdes
27298675Sdes	buffer_free(&m);
27398675Sdes
27498675Sdes	debug3("%s: user %sauthenticated",
27598675Sdes	    __func__, authenticated ? "" : "not ");
27698675Sdes	return (authenticated);
27798675Sdes}
27898675Sdes
27998675Sdesint
28098675Sdesmm_user_key_allowed(struct passwd *pw, Key *key)
28198675Sdes{
28298675Sdes	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
28398675Sdes}
28498675Sdes
28598675Sdesint
28698675Sdesmm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
28798675Sdes    Key *key)
28898675Sdes{
28998675Sdes	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
29098675Sdes}
29198675Sdes
29298675Sdesint
29398675Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
29498675Sdes    char *host, Key *key)
29598675Sdes{
29698675Sdes	int ret;
29798675Sdes
29898675Sdes	key->type = KEY_RSA; /* XXX hack for key_to_blob */
29998675Sdes	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
30098675Sdes	key->type = KEY_RSA1;
30198675Sdes	return (ret);
30298675Sdes}
30398675Sdes
30498675Sdesstatic void
30598675Sdesmm_send_debug(Buffer *m)
30698675Sdes{
30798675Sdes	char *msg;
30898675Sdes
30998675Sdes	while (buffer_len(m)) {
31098675Sdes		msg = buffer_get_string(m, NULL);
31198675Sdes		debug3("%s: Sending debug: %s", __func__, msg);
31298675Sdes		packet_send_debug("%s", msg);
31398675Sdes		xfree(msg);
31498675Sdes	}
31598675Sdes}
31698675Sdes
31798675Sdesint
31898675Sdesmm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
31998675Sdes{
32098675Sdes	Buffer m;
32198675Sdes	u_char *blob;
32298675Sdes	u_int len;
323113911Sdes	int allowed = 0, have_forced = 0;
32498675Sdes
32598675Sdes	debug3("%s entering", __func__);
32698675Sdes
32798675Sdes	/* Convert the key to a blob and the pass it over */
32898675Sdes	if (!key_to_blob(key, &blob, &len))
32998675Sdes		return (0);
33098675Sdes
33198675Sdes	buffer_init(&m);
33298675Sdes	buffer_put_int(&m, type);
33398675Sdes	buffer_put_cstring(&m, user ? user : "");
33498675Sdes	buffer_put_cstring(&m, host ? host : "");
33598675Sdes	buffer_put_string(&m, blob, len);
33698675Sdes	xfree(blob);
33798675Sdes
33898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
33998675Sdes
34098675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
34198675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
34298675Sdes
34398675Sdes	allowed = buffer_get_int(&m);
34498675Sdes
345113911Sdes	/* fake forced command */
346113911Sdes	auth_clear_options();
347113911Sdes	have_forced = buffer_get_int(&m);
348113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
349113911Sdes
35098675Sdes	/* Send potential debug messages */
35198675Sdes	mm_send_debug(&m);
35298675Sdes
35398675Sdes	buffer_free(&m);
35498675Sdes
35598675Sdes	return (allowed);
35698675Sdes}
35798675Sdes
35898675Sdes/*
35998675Sdes * This key verify needs to send the key type along, because the
36098675Sdes * privileged parent makes the decision if the key is allowed
36198675Sdes * for authentication.
36298675Sdes */
36398675Sdes
36498675Sdesint
36598675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
36698675Sdes{
36798675Sdes	Buffer m;
36898675Sdes	u_char *blob;
36998675Sdes	u_int len;
37098675Sdes	int verified = 0;
37198675Sdes
37298675Sdes	debug3("%s entering", __func__);
37398675Sdes
37498675Sdes	/* Convert the key to a blob and the pass it over */
37598675Sdes	if (!key_to_blob(key, &blob, &len))
37698675Sdes		return (0);
37798675Sdes
37898675Sdes	buffer_init(&m);
37998675Sdes	buffer_put_string(&m, blob, len);
38098675Sdes	buffer_put_string(&m, sig, siglen);
38198675Sdes	buffer_put_string(&m, data, datalen);
38298675Sdes	xfree(blob);
38398675Sdes
38498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
38598675Sdes
38698675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
38798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
38898675Sdes
38998675Sdes	verified = buffer_get_int(&m);
39098675Sdes
39198675Sdes	buffer_free(&m);
39298675Sdes
39398675Sdes	return (verified);
39498675Sdes}
39598675Sdes
39698675Sdes/* Export key state after authentication */
39798675SdesNewkeys *
39898675Sdesmm_newkeys_from_blob(u_char *blob, int blen)
39998675Sdes{
40098675Sdes	Buffer b;
40198675Sdes	u_int len;
40298675Sdes	Newkeys *newkey = NULL;
40398675Sdes	Enc *enc;
40498675Sdes	Mac *mac;
40598675Sdes	Comp *comp;
40698675Sdes
40798675Sdes	debug3("%s: %p(%d)", __func__, blob, blen);
40898675Sdes#ifdef DEBUG_PK
40998675Sdes	dump_base64(stderr, blob, blen);
41098675Sdes#endif
41198675Sdes	buffer_init(&b);
41298675Sdes	buffer_append(&b, blob, blen);
41398675Sdes
41498675Sdes	newkey = xmalloc(sizeof(*newkey));
41598675Sdes	enc = &newkey->enc;
41698675Sdes	mac = &newkey->mac;
41798675Sdes	comp = &newkey->comp;
41898675Sdes
41998675Sdes	/* Enc structure */
42098675Sdes	enc->name = buffer_get_string(&b, NULL);
42198675Sdes	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
42298675Sdes	enc->enabled = buffer_get_int(&b);
42398675Sdes	enc->block_size = buffer_get_int(&b);
42498675Sdes	enc->key = buffer_get_string(&b, &enc->key_len);
42598675Sdes	enc->iv = buffer_get_string(&b, &len);
42698675Sdes	if (len != enc->block_size)
427106130Sdes		fatal("%s: bad ivlen: expected %u != %u", __func__,
42898675Sdes		    enc->block_size, len);
42998675Sdes
43098675Sdes	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
43198675Sdes		fatal("%s: bad cipher name %s or pointer %p", __func__,
43298675Sdes		    enc->name, enc->cipher);
43398675Sdes
43498675Sdes	/* Mac structure */
43598675Sdes	mac->name = buffer_get_string(&b, NULL);
43698675Sdes	if (mac->name == NULL || mac_init(mac, mac->name) == -1)
43798675Sdes		fatal("%s: can not init mac %s", __func__, mac->name);
43898675Sdes	mac->enabled = buffer_get_int(&b);
43998675Sdes	mac->key = buffer_get_string(&b, &len);
44098675Sdes	if (len > mac->key_len)
441106130Sdes		fatal("%s: bad mac key length: %u > %d", __func__, len,
44298675Sdes		    mac->key_len);
44398675Sdes	mac->key_len = len;
44498675Sdes
44598675Sdes	/* Comp structure */
44698675Sdes	comp->type = buffer_get_int(&b);
44798675Sdes	comp->enabled = buffer_get_int(&b);
44898675Sdes	comp->name = buffer_get_string(&b, NULL);
44998675Sdes
45098675Sdes	len = buffer_len(&b);
45198675Sdes	if (len != 0)
452106130Sdes		error("newkeys_from_blob: remaining bytes in blob %u", len);
45398675Sdes	buffer_free(&b);
45498675Sdes	return (newkey);
45598675Sdes}
45698675Sdes
45798675Sdesint
45898675Sdesmm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
45998675Sdes{
46098675Sdes	Buffer b;
46198675Sdes	int len;
46298675Sdes	Enc *enc;
46398675Sdes	Mac *mac;
46498675Sdes	Comp *comp;
46598675Sdes	Newkeys *newkey = newkeys[mode];
46698675Sdes
46798675Sdes	debug3("%s: converting %p", __func__, newkey);
46898675Sdes
46998675Sdes	if (newkey == NULL) {
47098675Sdes		error("%s: newkey == NULL", __func__);
47198675Sdes		return 0;
47298675Sdes	}
47398675Sdes	enc = &newkey->enc;
47498675Sdes	mac = &newkey->mac;
47598675Sdes	comp = &newkey->comp;
47698675Sdes
47798675Sdes	buffer_init(&b);
47898675Sdes	/* Enc structure */
47998675Sdes	buffer_put_cstring(&b, enc->name);
48098675Sdes	/* The cipher struct is constant and shared, you export pointer */
48198675Sdes	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
48298675Sdes	buffer_put_int(&b, enc->enabled);
48398675Sdes	buffer_put_int(&b, enc->block_size);
48498675Sdes	buffer_put_string(&b, enc->key, enc->key_len);
48598675Sdes	packet_get_keyiv(mode, enc->iv, enc->block_size);
48698675Sdes	buffer_put_string(&b, enc->iv, enc->block_size);
48798675Sdes
48898675Sdes	/* Mac structure */
48998675Sdes	buffer_put_cstring(&b, mac->name);
49098675Sdes	buffer_put_int(&b, mac->enabled);
49198675Sdes	buffer_put_string(&b, mac->key, mac->key_len);
49298675Sdes
49398675Sdes	/* Comp structure */
49498675Sdes	buffer_put_int(&b, comp->type);
49598675Sdes	buffer_put_int(&b, comp->enabled);
49698675Sdes	buffer_put_cstring(&b, comp->name);
49798675Sdes
49898675Sdes	len = buffer_len(&b);
499106130Sdes	if (lenp != NULL)
500106130Sdes		*lenp = len;
501106130Sdes	if (blobp != NULL) {
502106130Sdes		*blobp = xmalloc(len);
503106130Sdes		memcpy(*blobp, buffer_ptr(&b), len);
504106130Sdes	}
50598675Sdes	memset(buffer_ptr(&b), 0, len);
50698675Sdes	buffer_free(&b);
50798675Sdes	return len;
50898675Sdes}
50998675Sdes
51098675Sdesstatic void
51198675Sdesmm_send_kex(Buffer *m, Kex *kex)
51298675Sdes{
51398675Sdes	buffer_put_string(m, kex->session_id, kex->session_id_len);
51498675Sdes	buffer_put_int(m, kex->we_need);
51598675Sdes	buffer_put_int(m, kex->hostkey_type);
51698675Sdes	buffer_put_int(m, kex->kex_type);
51798675Sdes	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
51898675Sdes	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
51998675Sdes	buffer_put_int(m, kex->flags);
52098675Sdes	buffer_put_cstring(m, kex->client_version_string);
52198675Sdes	buffer_put_cstring(m, kex->server_version_string);
52298675Sdes}
52398675Sdes
52498675Sdesvoid
52598675Sdesmm_send_keystate(struct monitor *pmonitor)
52698675Sdes{
52798675Sdes	Buffer m;
52898675Sdes	u_char *blob, *p;
52998675Sdes	u_int bloblen, plen;
530124211Sdes	u_int32_t seqnr, packets;
531124211Sdes	u_int64_t blocks;
53298675Sdes
53398675Sdes	buffer_init(&m);
53498675Sdes
53598675Sdes	if (!compat20) {
53698675Sdes		u_char iv[24];
53798675Sdes		u_char *key;
53898675Sdes		u_int ivlen, keylen;
53998675Sdes
54098675Sdes		buffer_put_int(&m, packet_get_protocol_flags());
54198675Sdes
54298675Sdes		buffer_put_int(&m, packet_get_ssh1_cipher());
54398675Sdes
54498675Sdes		debug3("%s: Sending ssh1 KEY+IV", __func__);
54598675Sdes		keylen = packet_get_encryption_key(NULL);
54698675Sdes		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
54798675Sdes		keylen = packet_get_encryption_key(key);
54898675Sdes		buffer_put_string(&m, key, keylen);
54998675Sdes		memset(key, 0, keylen);
55098675Sdes		xfree(key);
55198675Sdes
55298675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
55398675Sdes		packet_get_keyiv(MODE_OUT, iv, ivlen);
55498675Sdes		buffer_put_string(&m, iv, ivlen);
55598675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
55698675Sdes		packet_get_keyiv(MODE_IN, iv, ivlen);
55798675Sdes		buffer_put_string(&m, iv, ivlen);
55898675Sdes		goto skip;
55998675Sdes	} else {
56098675Sdes		/* Kex for rekeying */
56198675Sdes		mm_send_kex(&m, *pmonitor->m_pkex);
56298675Sdes	}
56398675Sdes
56498675Sdes	debug3("%s: Sending new keys: %p %p",
56598675Sdes	    __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
56698675Sdes
56798675Sdes	/* Keys from Kex */
56898675Sdes	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
56998675Sdes		fatal("%s: conversion of newkeys failed", __func__);
57098675Sdes
57198675Sdes	buffer_put_string(&m, blob, bloblen);
57298675Sdes	xfree(blob);
57398675Sdes
57498675Sdes	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
57598675Sdes		fatal("%s: conversion of newkeys failed", __func__);
57698675Sdes
57798675Sdes	buffer_put_string(&m, blob, bloblen);
57898675Sdes	xfree(blob);
57998675Sdes
580124211Sdes	packet_get_state(MODE_OUT, &seqnr, &blocks, &packets);
581124211Sdes	buffer_put_int(&m, seqnr);
582124211Sdes	buffer_put_int64(&m, blocks);
583124211Sdes	buffer_put_int(&m, packets);
584124211Sdes	packet_get_state(MODE_IN, &seqnr, &blocks, &packets);
585124211Sdes	buffer_put_int(&m, seqnr);
586124211Sdes	buffer_put_int64(&m, blocks);
587124211Sdes	buffer_put_int(&m, packets);
58898675Sdes
58998675Sdes	debug3("%s: New keys have been sent", __func__);
59098675Sdes skip:
59198675Sdes	/* More key context */
59298675Sdes	plen = packet_get_keycontext(MODE_OUT, NULL);
59398675Sdes	p = xmalloc(plen+1);
59498675Sdes	packet_get_keycontext(MODE_OUT, p);
59598675Sdes	buffer_put_string(&m, p, plen);
59698675Sdes	xfree(p);
59798675Sdes
59898675Sdes	plen = packet_get_keycontext(MODE_IN, NULL);
59998675Sdes	p = xmalloc(plen+1);
60098675Sdes	packet_get_keycontext(MODE_IN, p);
60198675Sdes	buffer_put_string(&m, p, plen);
60298675Sdes	xfree(p);
60398675Sdes
60498675Sdes	/* Compression state */
60598675Sdes	debug3("%s: Sending compression state", __func__);
60698675Sdes	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
60798675Sdes	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
60898675Sdes
60998675Sdes	/* Network I/O buffers */
61098675Sdes	buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
61198675Sdes	buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
61298675Sdes
61398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
61498675Sdes	debug3("%s: Finished sending state", __func__);
61598675Sdes
61698675Sdes	buffer_free(&m);
61798675Sdes}
61898675Sdes
61998675Sdesint
62098675Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
62198675Sdes{
62298675Sdes	Buffer m;
623106130Sdes	char *p;
62498675Sdes	int success = 0;
62598675Sdes
62698675Sdes	buffer_init(&m);
62798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
62898675Sdes
62998675Sdes	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
63098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
63198675Sdes
63298675Sdes	success = buffer_get_int(&m);
63398675Sdes	if (success == 0) {
63498675Sdes		debug3("%s: pty alloc failed", __func__);
63598675Sdes		buffer_free(&m);
63698675Sdes		return (0);
63798675Sdes	}
63898675Sdes	p = buffer_get_string(&m, NULL);
63998675Sdes	buffer_free(&m);
64098675Sdes
64198675Sdes	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
64298675Sdes	xfree(p);
64398675Sdes
64498675Sdes	*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
64598675Sdes	*ttyfd = mm_receive_fd(pmonitor->m_recvfd);
64698675Sdes
64798675Sdes	/* Success */
64898675Sdes	return (1);
64998675Sdes}
65098675Sdes
65198675Sdesvoid
65298675Sdesmm_session_pty_cleanup2(void *session)
65398675Sdes{
65498675Sdes	Session *s = session;
65598675Sdes	Buffer m;
65698675Sdes
65798675Sdes	if (s->ttyfd == -1)
65898675Sdes		return;
65998675Sdes	buffer_init(&m);
66098675Sdes	buffer_put_cstring(&m, s->tty);
66198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
66298675Sdes	buffer_free(&m);
66398675Sdes
66498675Sdes	/* closed dup'ed master */
66598675Sdes	if (close(s->ptymaster) < 0)
66698675Sdes		error("close(s->ptymaster): %s", strerror(errno));
66798675Sdes
66898675Sdes	/* unlink pty from session */
66998675Sdes	s->ttyfd = -1;
67098675Sdes}
67198675Sdes
67298937Sdes#ifdef USE_PAM
67398937Sdesvoid
67498937Sdesmm_start_pam(char *user)
67598937Sdes{
67698937Sdes	Buffer m;
67798937Sdes
67898937Sdes	debug3("%s entering", __func__);
679124211Sdes	if (!options.use_pam)
680124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
68198937Sdes
68298937Sdes	buffer_init(&m);
68398937Sdes	buffer_put_cstring(&m, user);
68498937Sdes
68598937Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
68698937Sdes
68798937Sdes	buffer_free(&m);
68898937Sdes}
68999052Sdes
690124211Sdesu_int
691124211Sdesmm_do_pam_account(void)
692124211Sdes{
693124211Sdes	Buffer m;
694124211Sdes	u_int ret;
695124211Sdes
696124211Sdes	debug3("%s entering", __func__);
697124211Sdes	if (!options.use_pam)
698124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
699124211Sdes
700124211Sdes	buffer_init(&m);
701124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
702124211Sdes
703124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
704124211Sdes	    MONITOR_ANS_PAM_ACCOUNT, &m);
705124211Sdes	ret = buffer_get_int(&m);
706124211Sdes
707124211Sdes	buffer_free(&m);
708124211Sdes
709124211Sdes	debug3("%s returning %d", __func__, ret);
710124211Sdes
711124211Sdes	return (ret);
712124211Sdes}
713124211Sdes
71499052Sdesvoid *
715124211Sdesmm_sshpam_init_ctx(Authctxt *authctxt)
71699052Sdes{
71799052Sdes	Buffer m;
71899052Sdes	int success;
71999052Sdes
72099052Sdes	debug3("%s", __func__);
72199052Sdes	buffer_init(&m);
72299052Sdes	buffer_put_cstring(&m, authctxt->user);
72399052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
72499052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
72599052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
72699052Sdes	success = buffer_get_int(&m);
72799052Sdes	if (success == 0) {
72899052Sdes		debug3("%s: pam_init_ctx failed", __func__);
72999052Sdes		buffer_free(&m);
73099052Sdes		return (NULL);
73199052Sdes	}
73299052Sdes	buffer_free(&m);
73399052Sdes	return (authctxt);
73499052Sdes}
73599052Sdes
73699052Sdesint
737124211Sdesmm_sshpam_query(void *ctx, char **name, char **info,
73899052Sdes    u_int *num, char ***prompts, u_int **echo_on)
73999052Sdes{
74099052Sdes	Buffer m;
74199052Sdes	int i, ret;
74299052Sdes
74399052Sdes	debug3("%s", __func__);
74499052Sdes	buffer_init(&m);
74599052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
74699052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
74799052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
74899052Sdes	ret = buffer_get_int(&m);
74999052Sdes	debug3("%s: pam_query returned %d", __func__, ret);
75099052Sdes	*name = buffer_get_string(&m, NULL);
75199052Sdes	*info = buffer_get_string(&m, NULL);
75299052Sdes	*num = buffer_get_int(&m);
75399052Sdes	*prompts = xmalloc((*num + 1) * sizeof(char *));
75499052Sdes	*echo_on = xmalloc((*num + 1) * sizeof(u_int));
75599052Sdes	for (i = 0; i < *num; ++i) {
75699052Sdes		(*prompts)[i] = buffer_get_string(&m, NULL);
75799052Sdes		(*echo_on)[i] = buffer_get_int(&m);
75899052Sdes	}
75999052Sdes	buffer_free(&m);
76099052Sdes	return (ret);
76199052Sdes}
76299052Sdes
76399052Sdesint
764124211Sdesmm_sshpam_respond(void *ctx, u_int num, char **resp)
76599052Sdes{
76699052Sdes	Buffer m;
76799052Sdes	int i, ret;
76899052Sdes
76999052Sdes	debug3("%s", __func__);
77099052Sdes	buffer_init(&m);
77199052Sdes	buffer_put_int(&m, num);
77299052Sdes	for (i = 0; i < num; ++i)
77399052Sdes		buffer_put_cstring(&m, resp[i]);
77499052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
77599052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
77699052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
77799052Sdes	ret = buffer_get_int(&m);
77899052Sdes	debug3("%s: pam_respond returned %d", __func__, ret);
77999052Sdes	buffer_free(&m);
78099052Sdes	return (ret);
78199052Sdes}
78299052Sdes
78399052Sdesvoid
784124211Sdesmm_sshpam_free_ctx(void *ctxtp)
78599052Sdes{
78699052Sdes	Buffer m;
78799052Sdes
78899052Sdes	debug3("%s", __func__);
78999052Sdes	buffer_init(&m);
79099052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
79199052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
79299052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
79399052Sdes	buffer_free(&m);
79499052Sdes}
79598937Sdes#endif /* USE_PAM */
79698937Sdes
79798675Sdes/* Request process termination */
79898675Sdes
79998675Sdesvoid
80098675Sdesmm_terminate(void)
80198675Sdes{
80298675Sdes	Buffer m;
80398675Sdes
80498675Sdes	buffer_init(&m);
80598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
80698675Sdes	buffer_free(&m);
80798675Sdes}
80898675Sdes
80998675Sdesint
81098675Sdesmm_ssh1_session_key(BIGNUM *num)
81198675Sdes{
81298675Sdes	int rsafail;
81398675Sdes	Buffer m;
81498675Sdes
81598675Sdes	buffer_init(&m);
81698675Sdes	buffer_put_bignum2(&m, num);
81798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
81898675Sdes
81998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
82098675Sdes
82198675Sdes	rsafail = buffer_get_int(&m);
82298675Sdes	buffer_get_bignum2(&m, num);
82398675Sdes
82498675Sdes	buffer_free(&m);
82598675Sdes
82698675Sdes	return (rsafail);
82798675Sdes}
82898675Sdes
82998675Sdesstatic void
83098675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts,
83198675Sdes    char ***prompts, u_int **echo_on)
83298675Sdes{
83398675Sdes	*name = xstrdup("");
83498675Sdes	*infotxt = xstrdup("");
83598675Sdes	*numprompts = 1;
836106130Sdes	*prompts = xmalloc(*numprompts * sizeof(char *));
83798675Sdes	*echo_on = xmalloc(*numprompts * sizeof(u_int));
83898675Sdes	(*echo_on)[0] = 0;
83998675Sdes}
84098675Sdes
84198675Sdesint
84298675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt,
84398675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
84498675Sdes{
84598675Sdes	Buffer m;
846113911Sdes	u_int success;
84798675Sdes	char *challenge;
84898675Sdes
84998675Sdes	debug3("%s: entering", __func__);
85098675Sdes
85198675Sdes	buffer_init(&m);
85298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
85398675Sdes
85498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
85598675Sdes	    &m);
856113911Sdes	success = buffer_get_int(&m);
857113911Sdes	if (success == 0) {
85898675Sdes		debug3("%s: no challenge", __func__);
85998675Sdes		buffer_free(&m);
86098675Sdes		return (-1);
86198675Sdes	}
86298675Sdes
86398675Sdes	/* Get the challenge, and format the response */
86498675Sdes	challenge  = buffer_get_string(&m, NULL);
86598675Sdes	buffer_free(&m);
86698675Sdes
86798675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
86898675Sdes	(*prompts)[0] = challenge;
86998675Sdes
87098675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
87198675Sdes
87298675Sdes	return (0);
87398675Sdes}
87498675Sdes
87598675Sdesint
87698675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
87798675Sdes{
87898675Sdes	Buffer m;
87998675Sdes	int authok;
88098675Sdes
88198675Sdes	debug3("%s: entering", __func__);
88298675Sdes	if (numresponses != 1)
88398675Sdes		return (-1);
88498675Sdes
88598675Sdes	buffer_init(&m);
88698675Sdes	buffer_put_cstring(&m, responses[0]);
88798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
88898675Sdes
88998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
89098675Sdes	    MONITOR_ANS_BSDAUTHRESPOND, &m);
89198675Sdes
89298675Sdes	authok = buffer_get_int(&m);
89398675Sdes	buffer_free(&m);
89498675Sdes
89598675Sdes	return ((authok == 0) ? -1 : 0);
89698675Sdes}
89798675Sdes
89899046Sdes#ifdef SKEY
89998675Sdesint
90098675Sdesmm_skey_query(void *ctx, char **name, char **infotxt,
90198675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
90298675Sdes{
90398675Sdes	Buffer m;
904113911Sdes	int len;
905113911Sdes	u_int success;
90698675Sdes	char *p, *challenge;
90798675Sdes
90898675Sdes	debug3("%s: entering", __func__);
90998675Sdes
91098675Sdes	buffer_init(&m);
91198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
91298675Sdes
91398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
91498675Sdes	    &m);
915113911Sdes	success = buffer_get_int(&m);
916113911Sdes	if (success == 0) {
91798675Sdes		debug3("%s: no challenge", __func__);
91898675Sdes		buffer_free(&m);
91998675Sdes		return (-1);
92098675Sdes	}
92198675Sdes
92298675Sdes	/* Get the challenge, and format the response */
92398675Sdes	challenge  = buffer_get_string(&m, NULL);
92498675Sdes	buffer_free(&m);
92598675Sdes
92698675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
92798675Sdes
92898675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
92998675Sdes
93098675Sdes	len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
93198675Sdes	p = xmalloc(len);
93298675Sdes	strlcpy(p, challenge, len);
93398675Sdes	strlcat(p, SKEY_PROMPT, len);
93498675Sdes	(*prompts)[0] = p;
93598675Sdes	xfree(challenge);
93698675Sdes
93798675Sdes	return (0);
93898675Sdes}
93998675Sdes
94098675Sdesint
94198675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses)
94298675Sdes{
94398675Sdes	Buffer m;
94498675Sdes	int authok;
94598675Sdes
94698675Sdes	debug3("%s: entering", __func__);
94798675Sdes	if (numresponses != 1)
94898675Sdes		return (-1);
94998675Sdes
95098675Sdes	buffer_init(&m);
95198675Sdes	buffer_put_cstring(&m, responses[0]);
95298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
95398675Sdes
95498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
95598675Sdes	    MONITOR_ANS_SKEYRESPOND, &m);
95698675Sdes
95798675Sdes	authok = buffer_get_int(&m);
95898675Sdes	buffer_free(&m);
95998675Sdes
96098675Sdes	return ((authok == 0) ? -1 : 0);
96198675Sdes}
96299046Sdes#endif
96398675Sdes
96498675Sdesvoid
96598675Sdesmm_ssh1_session_id(u_char session_id[16])
96698675Sdes{
96798675Sdes	Buffer m;
96898675Sdes	int i;
96998675Sdes
97098675Sdes	debug3("%s entering", __func__);
97198675Sdes
97298675Sdes	buffer_init(&m);
97398675Sdes	for (i = 0; i < 16; i++)
97498675Sdes		buffer_put_char(&m, session_id[i]);
97598675Sdes
97698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
97798675Sdes	buffer_free(&m);
97898675Sdes}
97998675Sdes
98098675Sdesint
98198675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
98298675Sdes{
98398675Sdes	Buffer m;
98498675Sdes	Key *key;
98598675Sdes	u_char *blob;
98698675Sdes	u_int blen;
987113911Sdes	int allowed = 0, have_forced = 0;
98898675Sdes
98998675Sdes	debug3("%s entering", __func__);
99098675Sdes
99198675Sdes	buffer_init(&m);
99298675Sdes	buffer_put_bignum2(&m, client_n);
99398675Sdes
99498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
99598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
99698675Sdes
99798675Sdes	allowed = buffer_get_int(&m);
99898675Sdes
999113911Sdes	/* fake forced command */
1000113911Sdes	auth_clear_options();
1001113911Sdes	have_forced = buffer_get_int(&m);
1002113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
1003113911Sdes
100498675Sdes	if (allowed && rkey != NULL) {
100598675Sdes		blob = buffer_get_string(&m, &blen);
100698675Sdes		if ((key = key_from_blob(blob, blen)) == NULL)
100798675Sdes			fatal("%s: key_from_blob failed", __func__);
100898675Sdes		*rkey = key;
100998675Sdes		xfree(blob);
101098675Sdes	}
101198675Sdes	mm_send_debug(&m);
101298675Sdes	buffer_free(&m);
101398675Sdes
101498675Sdes	return (allowed);
101598675Sdes}
101698675Sdes
101798675SdesBIGNUM *
101898675Sdesmm_auth_rsa_generate_challenge(Key *key)
101998675Sdes{
102098675Sdes	Buffer m;
102198675Sdes	BIGNUM *challenge;
102298675Sdes	u_char *blob;
102398675Sdes	u_int blen;
102498675Sdes
102598675Sdes	debug3("%s entering", __func__);
102698675Sdes
102798675Sdes	if ((challenge = BN_new()) == NULL)
102898675Sdes		fatal("%s: BN_new failed", __func__);
102998675Sdes
103098675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
103198675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
103298675Sdes		fatal("%s: key_to_blob failed", __func__);
103398675Sdes	key->type = KEY_RSA1;
103498675Sdes
103598675Sdes	buffer_init(&m);
103698675Sdes	buffer_put_string(&m, blob, blen);
103798675Sdes	xfree(blob);
103898675Sdes
103998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
104098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
104198675Sdes
104298675Sdes	buffer_get_bignum2(&m, challenge);
104398675Sdes	buffer_free(&m);
104498675Sdes
104598675Sdes	return (challenge);
104698675Sdes}
104798675Sdes
104898675Sdesint
104998675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
105098675Sdes{
105198675Sdes	Buffer m;
105298675Sdes	u_char *blob;
105398675Sdes	u_int blen;
105498675Sdes	int success = 0;
105598675Sdes
105698675Sdes	debug3("%s entering", __func__);
105798675Sdes
105898675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
105998675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
106098675Sdes		fatal("%s: key_to_blob failed", __func__);
106198675Sdes	key->type = KEY_RSA1;
106298675Sdes
106398675Sdes	buffer_init(&m);
106498675Sdes	buffer_put_string(&m, blob, blen);
106598675Sdes	buffer_put_string(&m, response, 16);
106698675Sdes	xfree(blob);
106798675Sdes
106898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
106998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
107098675Sdes
107198675Sdes	success = buffer_get_int(&m);
107298675Sdes	buffer_free(&m);
107398675Sdes
107498675Sdes	return (success);
107598675Sdes}
1076106130Sdes
1077124211Sdes#ifdef GSSAPI
1078124211SdesOM_uint32
1079124211Sdesmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
1080106130Sdes{
1081124211Sdes	Buffer m;
1082124211Sdes	OM_uint32 major;
1083106130Sdes
1084124211Sdes	/* Client doesn't get to see the context */
1085124211Sdes	*ctx = NULL;
1086106130Sdes
1087106130Sdes	buffer_init(&m);
1088124211Sdes	buffer_put_string(&m, oid->elements, oid->length);
1089106130Sdes
1090124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1091124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1092106130Sdes
1093124211Sdes	major = buffer_get_int(&m);
1094124211Sdes
1095106130Sdes	buffer_free(&m);
1096124211Sdes	return (major);
1097106130Sdes}
1098106130Sdes
1099124211SdesOM_uint32
1100124211Sdesmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1101124211Sdes    gss_buffer_desc *out, OM_uint32 *flags)
1102124211Sdes{
1103124211Sdes	Buffer m;
1104124211Sdes	OM_uint32 major;
1105124211Sdes	u_int len;
1106124211Sdes
1107124211Sdes	buffer_init(&m);
1108124211Sdes	buffer_put_string(&m, in->value, in->length);
1109124211Sdes
1110124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1111124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1112124211Sdes
1113124211Sdes	major = buffer_get_int(&m);
1114124211Sdes	out->value = buffer_get_string(&m, &len);
1115124211Sdes	out->length = len;
1116124211Sdes	if (flags)
1117124211Sdes		*flags = buffer_get_int(&m);
1118124211Sdes
1119124211Sdes	buffer_free(&m);
1120124211Sdes
1121124211Sdes	return (major);
1122124211Sdes}
1123124211Sdes
1124106130Sdesint
1125124211Sdesmm_ssh_gssapi_userok(char *user)
1126106130Sdes{
1127106130Sdes	Buffer m;
1128124211Sdes	int authenticated = 0;
1129106130Sdes
1130106130Sdes	buffer_init(&m);
1131106130Sdes
1132124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1133124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1134124211Sdes				  &m);
1135106130Sdes
1136124211Sdes	authenticated = buffer_get_int(&m);
1137106130Sdes
1138106130Sdes	buffer_free(&m);
1139124211Sdes	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1140124211Sdes	return (authenticated);
1141106130Sdes}
1142124211Sdes#endif /* GSSAPI */
1143