monitor_wrap.c revision 113911
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"
28113911SdesRCSID("$OpenBSD: monitor_wrap.c,v 1.24 2003/04/01 10:22:21 markus Exp $");
2999052SdesRCSID("$FreeBSD: head/crypto/openssh/monitor_wrap.c 113911 2003-04-23 17:13:13Z 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"
5198675Sdes
5298675Sdes#include "auth.h"
5398675Sdes#include "channels.h"
5498675Sdes#include "session.h"
5598675Sdes
5698675Sdes/* Imports */
5798675Sdesextern int compat20;
5898675Sdesextern Newkeys *newkeys[];
5998675Sdesextern z_stream incoming_stream;
6098675Sdesextern z_stream outgoing_stream;
6198675Sdesextern struct monitor *pmonitor;
6298675Sdesextern Buffer input, output;
6398675Sdes
6498675Sdesvoid
6598675Sdesmm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
6698675Sdes{
67106130Sdes	u_int mlen = buffer_len(m);
6898675Sdes	u_char buf[5];
6998675Sdes
7098675Sdes	debug3("%s entering: type %d", __func__, type);
7198675Sdes
7298675Sdes	PUT_32BIT(buf, mlen + 1);
7398675Sdes	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
7498675Sdes	if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
7598675Sdes		fatal("%s: write", __func__);
7698675Sdes	if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
7798675Sdes		fatal("%s: write", __func__);
7898675Sdes}
7998675Sdes
8098675Sdesvoid
8198675Sdesmm_request_receive(int socket, Buffer *m)
8298675Sdes{
8398675Sdes	u_char buf[4];
84106130Sdes	u_int msg_len;
8598675Sdes	ssize_t res;
8698675Sdes
8798675Sdes	debug3("%s entering", __func__);
8898675Sdes
8998675Sdes	res = atomicio(read, socket, buf, sizeof(buf));
9098675Sdes	if (res != sizeof(buf)) {
9198675Sdes		if (res == 0)
9298675Sdes			fatal_cleanup();
9398675Sdes		fatal("%s: read: %ld", __func__, (long)res);
9498675Sdes	}
9598675Sdes	msg_len = GET_32BIT(buf);
9698675Sdes	if (msg_len > 256 * 1024)
9798675Sdes		fatal("%s: read: bad msg_len %d", __func__, msg_len);
9898675Sdes	buffer_clear(m);
9998675Sdes	buffer_append_space(m, msg_len);
10098675Sdes	res = atomicio(read, socket, buffer_ptr(m), msg_len);
10198675Sdes	if (res != msg_len)
10298675Sdes		fatal("%s: read: %ld != msg_len", __func__, (long)res);
10398675Sdes}
10498675Sdes
10598675Sdesvoid
10698675Sdesmm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
10798675Sdes{
10898675Sdes	u_char rtype;
10998675Sdes
11098675Sdes	debug3("%s entering: type %d", __func__, type);
11198675Sdes
11298675Sdes	mm_request_receive(socket, m);
11398675Sdes	rtype = buffer_get_char(m);
11498675Sdes	if (rtype != type)
11598675Sdes		fatal("%s: read: rtype %d != type %d", __func__,
11698675Sdes		    rtype, type);
11798675Sdes}
11898675Sdes
11998675SdesDH *
12098675Sdesmm_choose_dh(int min, int nbits, int max)
12198675Sdes{
12298675Sdes	BIGNUM *p, *g;
12398675Sdes	int success = 0;
12498675Sdes	Buffer m;
12598675Sdes
12698675Sdes	buffer_init(&m);
12798675Sdes	buffer_put_int(&m, min);
12898675Sdes	buffer_put_int(&m, nbits);
12998675Sdes	buffer_put_int(&m, max);
13098675Sdes
13198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
13298675Sdes
13398675Sdes	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
13498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
13598675Sdes
13698675Sdes	success = buffer_get_char(&m);
13798675Sdes	if (success == 0)
13898675Sdes		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
13998675Sdes
14098675Sdes	if ((p = BN_new()) == NULL)
14198675Sdes		fatal("%s: BN_new failed", __func__);
14298675Sdes	if ((g = BN_new()) == NULL)
14398675Sdes		fatal("%s: BN_new failed", __func__);
14498675Sdes	buffer_get_bignum2(&m, p);
14598675Sdes	buffer_get_bignum2(&m, g);
14698675Sdes
14798675Sdes	debug3("%s: remaining %d", __func__, buffer_len(&m));
14898675Sdes	buffer_free(&m);
14998675Sdes
15098675Sdes	return (dh_new_group(g, p));
15198675Sdes}
15298675Sdes
15398675Sdesint
15498675Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
15598675Sdes{
15698675Sdes	Kex *kex = *pmonitor->m_pkex;
15798675Sdes	Buffer m;
15898675Sdes
15998675Sdes	debug3("%s entering", __func__);
16098675Sdes
16198675Sdes	buffer_init(&m);
16298675Sdes	buffer_put_int(&m, kex->host_key_index(key));
16398675Sdes	buffer_put_string(&m, data, datalen);
16498675Sdes
16598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
16698675Sdes
16798675Sdes	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
16898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
16998675Sdes	*sigp  = buffer_get_string(&m, lenp);
17098675Sdes	buffer_free(&m);
17198675Sdes
17298675Sdes	return (0);
17398675Sdes}
17498675Sdes
17598675Sdesstruct passwd *
17698675Sdesmm_getpwnamallow(const char *login)
17798675Sdes{
17898675Sdes	Buffer m;
17998675Sdes	struct passwd *pw;
18098675Sdes	u_int pwlen;
18198675Sdes
18298675Sdes	debug3("%s entering", __func__);
18398675Sdes
18498675Sdes	buffer_init(&m);
18598675Sdes	buffer_put_cstring(&m, login);
18698675Sdes
18798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
18898675Sdes
18998675Sdes	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
19098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
19198675Sdes
19298675Sdes	if (buffer_get_char(&m) == 0) {
19398675Sdes		buffer_free(&m);
19498675Sdes		return (NULL);
19598675Sdes	}
19698675Sdes	pw = buffer_get_string(&m, &pwlen);
19798675Sdes	if (pwlen != sizeof(struct passwd))
19898675Sdes		fatal("%s: struct passwd size mismatch", __func__);
19998675Sdes	pw->pw_name = buffer_get_string(&m, NULL);
20098675Sdes	pw->pw_passwd = buffer_get_string(&m, NULL);
20198675Sdes	pw->pw_gecos = buffer_get_string(&m, NULL);
20298937Sdes#ifdef HAVE_PW_CLASS_IN_PASSWD
20398675Sdes	pw->pw_class = buffer_get_string(&m, NULL);
20498937Sdes#endif
20598675Sdes	pw->pw_dir = buffer_get_string(&m, NULL);
20698675Sdes	pw->pw_shell = buffer_get_string(&m, NULL);
20798675Sdes	buffer_free(&m);
20898675Sdes
20998675Sdes	return (pw);
21098675Sdes}
21198675Sdes
212106130Sdeschar *mm_auth2_read_banner(void)
21398675Sdes{
21498675Sdes	Buffer m;
21598675Sdes	char *banner;
21698675Sdes
21798675Sdes	debug3("%s entering", __func__);
21898675Sdes
21998675Sdes	buffer_init(&m);
22098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
22198675Sdes	buffer_clear(&m);
22298675Sdes
22398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
22498675Sdes	banner = buffer_get_string(&m, NULL);
22598675Sdes	buffer_free(&m);
22698675Sdes
22798675Sdes	return (banner);
22898675Sdes}
22998675Sdes
23098675Sdes/* Inform the privileged process about service and style */
23198675Sdes
23298675Sdesvoid
23398675Sdesmm_inform_authserv(char *service, char *style)
23498675Sdes{
23598675Sdes	Buffer m;
23698675Sdes
23798675Sdes	debug3("%s entering", __func__);
23898675Sdes
23998675Sdes	buffer_init(&m);
24098675Sdes	buffer_put_cstring(&m, service);
24198675Sdes	buffer_put_cstring(&m, style ? style : "");
24298675Sdes
24398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
24498675Sdes
24598675Sdes	buffer_free(&m);
24698675Sdes}
24798675Sdes
24898675Sdes/* Do the password authentication */
24998675Sdesint
25098675Sdesmm_auth_password(Authctxt *authctxt, char *password)
25198675Sdes{
25298675Sdes	Buffer m;
25398675Sdes	int authenticated = 0;
25498675Sdes
25598675Sdes	debug3("%s entering", __func__);
25698675Sdes
25798675Sdes	buffer_init(&m);
25898675Sdes	buffer_put_cstring(&m, password);
25998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
26098675Sdes
26198675Sdes	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
26298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
26398675Sdes
26498675Sdes	authenticated = buffer_get_int(&m);
26598675Sdes
26698675Sdes	buffer_free(&m);
26798675Sdes
26898675Sdes	debug3("%s: user %sauthenticated",
26998675Sdes	    __func__, authenticated ? "" : "not ");
27098675Sdes	return (authenticated);
27198675Sdes}
27298675Sdes
27398675Sdesint
27498675Sdesmm_user_key_allowed(struct passwd *pw, Key *key)
27598675Sdes{
27698675Sdes	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
27798675Sdes}
27898675Sdes
27998675Sdesint
28098675Sdesmm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
28198675Sdes    Key *key)
28298675Sdes{
28398675Sdes	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
28498675Sdes}
28598675Sdes
28698675Sdesint
28798675Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
28898675Sdes    char *host, Key *key)
28998675Sdes{
29098675Sdes	int ret;
29198675Sdes
29298675Sdes	key->type = KEY_RSA; /* XXX hack for key_to_blob */
29398675Sdes	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
29498675Sdes	key->type = KEY_RSA1;
29598675Sdes	return (ret);
29698675Sdes}
29798675Sdes
29898675Sdesstatic void
29998675Sdesmm_send_debug(Buffer *m)
30098675Sdes{
30198675Sdes	char *msg;
30298675Sdes
30398675Sdes	while (buffer_len(m)) {
30498675Sdes		msg = buffer_get_string(m, NULL);
30598675Sdes		debug3("%s: Sending debug: %s", __func__, msg);
30698675Sdes		packet_send_debug("%s", msg);
30798675Sdes		xfree(msg);
30898675Sdes	}
30998675Sdes}
31098675Sdes
31198675Sdesint
31298675Sdesmm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
31398675Sdes{
31498675Sdes	Buffer m;
31598675Sdes	u_char *blob;
31698675Sdes	u_int len;
317113911Sdes	int allowed = 0, have_forced = 0;
31898675Sdes
31998675Sdes	debug3("%s entering", __func__);
32098675Sdes
32198675Sdes	/* Convert the key to a blob and the pass it over */
32298675Sdes	if (!key_to_blob(key, &blob, &len))
32398675Sdes		return (0);
32498675Sdes
32598675Sdes	buffer_init(&m);
32698675Sdes	buffer_put_int(&m, type);
32798675Sdes	buffer_put_cstring(&m, user ? user : "");
32898675Sdes	buffer_put_cstring(&m, host ? host : "");
32998675Sdes	buffer_put_string(&m, blob, len);
33098675Sdes	xfree(blob);
33198675Sdes
33298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
33398675Sdes
33498675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
33598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
33698675Sdes
33798675Sdes	allowed = buffer_get_int(&m);
33898675Sdes
339113911Sdes	/* fake forced command */
340113911Sdes	auth_clear_options();
341113911Sdes	have_forced = buffer_get_int(&m);
342113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
343113911Sdes
34498675Sdes	/* Send potential debug messages */
34598675Sdes	mm_send_debug(&m);
34698675Sdes
34798675Sdes	buffer_free(&m);
34898675Sdes
34998675Sdes	return (allowed);
35098675Sdes}
35198675Sdes
35298675Sdes/*
35398675Sdes * This key verify needs to send the key type along, because the
35498675Sdes * privileged parent makes the decision if the key is allowed
35598675Sdes * for authentication.
35698675Sdes */
35798675Sdes
35898675Sdesint
35998675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
36098675Sdes{
36198675Sdes	Buffer m;
36298675Sdes	u_char *blob;
36398675Sdes	u_int len;
36498675Sdes	int verified = 0;
36598675Sdes
36698675Sdes	debug3("%s entering", __func__);
36798675Sdes
36898675Sdes	/* Convert the key to a blob and the pass it over */
36998675Sdes	if (!key_to_blob(key, &blob, &len))
37098675Sdes		return (0);
37198675Sdes
37298675Sdes	buffer_init(&m);
37398675Sdes	buffer_put_string(&m, blob, len);
37498675Sdes	buffer_put_string(&m, sig, siglen);
37598675Sdes	buffer_put_string(&m, data, datalen);
37698675Sdes	xfree(blob);
37798675Sdes
37898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
37998675Sdes
38098675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
38198675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
38298675Sdes
38398675Sdes	verified = buffer_get_int(&m);
38498675Sdes
38598675Sdes	buffer_free(&m);
38698675Sdes
38798675Sdes	return (verified);
38898675Sdes}
38998675Sdes
39098675Sdes/* Export key state after authentication */
39198675SdesNewkeys *
39298675Sdesmm_newkeys_from_blob(u_char *blob, int blen)
39398675Sdes{
39498675Sdes	Buffer b;
39598675Sdes	u_int len;
39698675Sdes	Newkeys *newkey = NULL;
39798675Sdes	Enc *enc;
39898675Sdes	Mac *mac;
39998675Sdes	Comp *comp;
40098675Sdes
40198675Sdes	debug3("%s: %p(%d)", __func__, blob, blen);
40298675Sdes#ifdef DEBUG_PK
40398675Sdes	dump_base64(stderr, blob, blen);
40498675Sdes#endif
40598675Sdes	buffer_init(&b);
40698675Sdes	buffer_append(&b, blob, blen);
40798675Sdes
40898675Sdes	newkey = xmalloc(sizeof(*newkey));
40998675Sdes	enc = &newkey->enc;
41098675Sdes	mac = &newkey->mac;
41198675Sdes	comp = &newkey->comp;
41298675Sdes
41398675Sdes	/* Enc structure */
41498675Sdes	enc->name = buffer_get_string(&b, NULL);
41598675Sdes	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
41698675Sdes	enc->enabled = buffer_get_int(&b);
41798675Sdes	enc->block_size = buffer_get_int(&b);
41898675Sdes	enc->key = buffer_get_string(&b, &enc->key_len);
41998675Sdes	enc->iv = buffer_get_string(&b, &len);
42098675Sdes	if (len != enc->block_size)
421106130Sdes		fatal("%s: bad ivlen: expected %u != %u", __func__,
42298675Sdes		    enc->block_size, len);
42398675Sdes
42498675Sdes	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
42598675Sdes		fatal("%s: bad cipher name %s or pointer %p", __func__,
42698675Sdes		    enc->name, enc->cipher);
42798675Sdes
42898675Sdes	/* Mac structure */
42998675Sdes	mac->name = buffer_get_string(&b, NULL);
43098675Sdes	if (mac->name == NULL || mac_init(mac, mac->name) == -1)
43198675Sdes		fatal("%s: can not init mac %s", __func__, mac->name);
43298675Sdes	mac->enabled = buffer_get_int(&b);
43398675Sdes	mac->key = buffer_get_string(&b, &len);
43498675Sdes	if (len > mac->key_len)
435106130Sdes		fatal("%s: bad mac key length: %u > %d", __func__, len,
43698675Sdes		    mac->key_len);
43798675Sdes	mac->key_len = len;
43898675Sdes
43998675Sdes	/* Comp structure */
44098675Sdes	comp->type = buffer_get_int(&b);
44198675Sdes	comp->enabled = buffer_get_int(&b);
44298675Sdes	comp->name = buffer_get_string(&b, NULL);
44398675Sdes
44498675Sdes	len = buffer_len(&b);
44598675Sdes	if (len != 0)
446106130Sdes		error("newkeys_from_blob: remaining bytes in blob %u", len);
44798675Sdes	buffer_free(&b);
44898675Sdes	return (newkey);
44998675Sdes}
45098675Sdes
45198675Sdesint
45298675Sdesmm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
45398675Sdes{
45498675Sdes	Buffer b;
45598675Sdes	int len;
45698675Sdes	Enc *enc;
45798675Sdes	Mac *mac;
45898675Sdes	Comp *comp;
45998675Sdes	Newkeys *newkey = newkeys[mode];
46098675Sdes
46198675Sdes	debug3("%s: converting %p", __func__, newkey);
46298675Sdes
46398675Sdes	if (newkey == NULL) {
46498675Sdes		error("%s: newkey == NULL", __func__);
46598675Sdes		return 0;
46698675Sdes	}
46798675Sdes	enc = &newkey->enc;
46898675Sdes	mac = &newkey->mac;
46998675Sdes	comp = &newkey->comp;
47098675Sdes
47198675Sdes	buffer_init(&b);
47298675Sdes	/* Enc structure */
47398675Sdes	buffer_put_cstring(&b, enc->name);
47498675Sdes	/* The cipher struct is constant and shared, you export pointer */
47598675Sdes	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
47698675Sdes	buffer_put_int(&b, enc->enabled);
47798675Sdes	buffer_put_int(&b, enc->block_size);
47898675Sdes	buffer_put_string(&b, enc->key, enc->key_len);
47998675Sdes	packet_get_keyiv(mode, enc->iv, enc->block_size);
48098675Sdes	buffer_put_string(&b, enc->iv, enc->block_size);
48198675Sdes
48298675Sdes	/* Mac structure */
48398675Sdes	buffer_put_cstring(&b, mac->name);
48498675Sdes	buffer_put_int(&b, mac->enabled);
48598675Sdes	buffer_put_string(&b, mac->key, mac->key_len);
48698675Sdes
48798675Sdes	/* Comp structure */
48898675Sdes	buffer_put_int(&b, comp->type);
48998675Sdes	buffer_put_int(&b, comp->enabled);
49098675Sdes	buffer_put_cstring(&b, comp->name);
49198675Sdes
49298675Sdes	len = buffer_len(&b);
493106130Sdes	if (lenp != NULL)
494106130Sdes		*lenp = len;
495106130Sdes	if (blobp != NULL) {
496106130Sdes		*blobp = xmalloc(len);
497106130Sdes		memcpy(*blobp, buffer_ptr(&b), len);
498106130Sdes	}
49998675Sdes	memset(buffer_ptr(&b), 0, len);
50098675Sdes	buffer_free(&b);
50198675Sdes	return len;
50298675Sdes}
50398675Sdes
50498675Sdesstatic void
50598675Sdesmm_send_kex(Buffer *m, Kex *kex)
50698675Sdes{
50798675Sdes	buffer_put_string(m, kex->session_id, kex->session_id_len);
50898675Sdes	buffer_put_int(m, kex->we_need);
50998675Sdes	buffer_put_int(m, kex->hostkey_type);
51098675Sdes	buffer_put_int(m, kex->kex_type);
51198675Sdes	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
51298675Sdes	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
51398675Sdes	buffer_put_int(m, kex->flags);
51498675Sdes	buffer_put_cstring(m, kex->client_version_string);
51598675Sdes	buffer_put_cstring(m, kex->server_version_string);
51698675Sdes}
51798675Sdes
51898675Sdesvoid
51998675Sdesmm_send_keystate(struct monitor *pmonitor)
52098675Sdes{
52198675Sdes	Buffer m;
52298675Sdes	u_char *blob, *p;
52398675Sdes	u_int bloblen, plen;
52498675Sdes
52598675Sdes	buffer_init(&m);
52698675Sdes
52798675Sdes	if (!compat20) {
52898675Sdes		u_char iv[24];
52998675Sdes		u_char *key;
53098675Sdes		u_int ivlen, keylen;
53198675Sdes
53298675Sdes		buffer_put_int(&m, packet_get_protocol_flags());
53398675Sdes
53498675Sdes		buffer_put_int(&m, packet_get_ssh1_cipher());
53598675Sdes
53698675Sdes		debug3("%s: Sending ssh1 KEY+IV", __func__);
53798675Sdes		keylen = packet_get_encryption_key(NULL);
53898675Sdes		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
53998675Sdes		keylen = packet_get_encryption_key(key);
54098675Sdes		buffer_put_string(&m, key, keylen);
54198675Sdes		memset(key, 0, keylen);
54298675Sdes		xfree(key);
54398675Sdes
54498675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
54598675Sdes		packet_get_keyiv(MODE_OUT, iv, ivlen);
54698675Sdes		buffer_put_string(&m, iv, ivlen);
54798675Sdes		ivlen = packet_get_keyiv_len(MODE_OUT);
54898675Sdes		packet_get_keyiv(MODE_IN, iv, ivlen);
54998675Sdes		buffer_put_string(&m, iv, ivlen);
55098675Sdes		goto skip;
55198675Sdes	} else {
55298675Sdes		/* Kex for rekeying */
55398675Sdes		mm_send_kex(&m, *pmonitor->m_pkex);
55498675Sdes	}
55598675Sdes
55698675Sdes	debug3("%s: Sending new keys: %p %p",
55798675Sdes	    __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
55898675Sdes
55998675Sdes	/* Keys from Kex */
56098675Sdes	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
56198675Sdes		fatal("%s: conversion of newkeys failed", __func__);
56298675Sdes
56398675Sdes	buffer_put_string(&m, blob, bloblen);
56498675Sdes	xfree(blob);
56598675Sdes
56698675Sdes	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
56798675Sdes		fatal("%s: conversion of newkeys failed", __func__);
56898675Sdes
56998675Sdes	buffer_put_string(&m, blob, bloblen);
57098675Sdes	xfree(blob);
57198675Sdes
57298675Sdes	buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
57398675Sdes	buffer_put_int(&m, packet_get_seqnr(MODE_IN));
57498675Sdes
57598675Sdes	debug3("%s: New keys have been sent", __func__);
57698675Sdes skip:
57798675Sdes	/* More key context */
57898675Sdes	plen = packet_get_keycontext(MODE_OUT, NULL);
57998675Sdes	p = xmalloc(plen+1);
58098675Sdes	packet_get_keycontext(MODE_OUT, p);
58198675Sdes	buffer_put_string(&m, p, plen);
58298675Sdes	xfree(p);
58398675Sdes
58498675Sdes	plen = packet_get_keycontext(MODE_IN, NULL);
58598675Sdes	p = xmalloc(plen+1);
58698675Sdes	packet_get_keycontext(MODE_IN, p);
58798675Sdes	buffer_put_string(&m, p, plen);
58898675Sdes	xfree(p);
58998675Sdes
59098675Sdes	/* Compression state */
59198675Sdes	debug3("%s: Sending compression state", __func__);
59298675Sdes	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
59398675Sdes	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
59498675Sdes
59598675Sdes	/* Network I/O buffers */
59698675Sdes	buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
59798675Sdes	buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
59898675Sdes
59998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
60098675Sdes	debug3("%s: Finished sending state", __func__);
60198675Sdes
60298675Sdes	buffer_free(&m);
60398675Sdes}
60498675Sdes
60598675Sdesint
60698675Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
60798675Sdes{
60898675Sdes	Buffer m;
609106130Sdes	char *p;
61098675Sdes	int success = 0;
61198675Sdes
61298675Sdes	buffer_init(&m);
61398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
61498675Sdes
61598675Sdes	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
61698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
61798675Sdes
61898675Sdes	success = buffer_get_int(&m);
61998675Sdes	if (success == 0) {
62098675Sdes		debug3("%s: pty alloc failed", __func__);
62198675Sdes		buffer_free(&m);
62298675Sdes		return (0);
62398675Sdes	}
62498675Sdes	p = buffer_get_string(&m, NULL);
62598675Sdes	buffer_free(&m);
62698675Sdes
62798675Sdes	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
62898675Sdes	xfree(p);
62998675Sdes
63098675Sdes	*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
63198675Sdes	*ttyfd = mm_receive_fd(pmonitor->m_recvfd);
63298675Sdes
63398675Sdes	/* Success */
63498675Sdes	return (1);
63598675Sdes}
63698675Sdes
63798675Sdesvoid
63898675Sdesmm_session_pty_cleanup2(void *session)
63998675Sdes{
64098675Sdes	Session *s = session;
64198675Sdes	Buffer m;
64298675Sdes
64398675Sdes	if (s->ttyfd == -1)
64498675Sdes		return;
64598675Sdes	buffer_init(&m);
64698675Sdes	buffer_put_cstring(&m, s->tty);
64798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
64898675Sdes	buffer_free(&m);
64998675Sdes
65098675Sdes	/* closed dup'ed master */
65198675Sdes	if (close(s->ptymaster) < 0)
65298675Sdes		error("close(s->ptymaster): %s", strerror(errno));
65398675Sdes
65498675Sdes	/* unlink pty from session */
65598675Sdes	s->ttyfd = -1;
65698675Sdes}
65798675Sdes
65898937Sdes#ifdef USE_PAM
65998937Sdesvoid
66098937Sdesmm_start_pam(char *user)
66198937Sdes{
66298937Sdes	Buffer m;
66398937Sdes
66498937Sdes	debug3("%s entering", __func__);
66598937Sdes
66698937Sdes	buffer_init(&m);
66798937Sdes	buffer_put_cstring(&m, user);
66898937Sdes
66998937Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
67098937Sdes
67198937Sdes	buffer_free(&m);
67298937Sdes}
67399052Sdes
67499052Sdesvoid *
67599052Sdesmm_pam_init_ctx(Authctxt *authctxt)
67699052Sdes{
67799052Sdes	Buffer m;
67899052Sdes	int success;
67999052Sdes
68099052Sdes	debug3("%s", __func__);
68199052Sdes	buffer_init(&m);
68299052Sdes	buffer_put_cstring(&m, authctxt->user);
68399052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
68499052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
68599052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
68699052Sdes	success = buffer_get_int(&m);
68799052Sdes	if (success == 0) {
68899052Sdes		debug3("%s: pam_init_ctx failed", __func__);
68999052Sdes		buffer_free(&m);
69099052Sdes		return (NULL);
69199052Sdes	}
69299052Sdes	buffer_free(&m);
69399052Sdes	return (authctxt);
69499052Sdes}
69599052Sdes
69699052Sdesint
69799052Sdesmm_pam_query(void *ctx, char **name, char **info,
69899052Sdes    u_int *num, char ***prompts, u_int **echo_on)
69999052Sdes{
70099052Sdes	Buffer m;
70199052Sdes	int i, ret;
70299052Sdes
70399052Sdes	debug3("%s", __func__);
70499052Sdes	buffer_init(&m);
70599052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
70699052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
70799052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
70899052Sdes	ret = buffer_get_int(&m);
70999052Sdes	debug3("%s: pam_query returned %d", __func__, ret);
71099052Sdes	*name = buffer_get_string(&m, NULL);
71199052Sdes	*info = buffer_get_string(&m, NULL);
71299052Sdes	*num = buffer_get_int(&m);
71399052Sdes	*prompts = xmalloc((*num + 1) * sizeof(char *));
71499052Sdes	*echo_on = xmalloc((*num + 1) * sizeof(u_int));
71599052Sdes	for (i = 0; i < *num; ++i) {
71699052Sdes		(*prompts)[i] = buffer_get_string(&m, NULL);
71799052Sdes		(*echo_on)[i] = buffer_get_int(&m);
71899052Sdes	}
71999052Sdes	buffer_free(&m);
72099052Sdes	return (ret);
72199052Sdes}
72299052Sdes
72399052Sdesint
72499052Sdesmm_pam_respond(void *ctx, u_int num, char **resp)
72599052Sdes{
72699052Sdes	Buffer m;
72799052Sdes	int i, ret;
72899052Sdes
72999052Sdes	debug3("%s", __func__);
73099052Sdes	buffer_init(&m);
73199052Sdes	buffer_put_int(&m, num);
73299052Sdes	for (i = 0; i < num; ++i)
73399052Sdes		buffer_put_cstring(&m, resp[i]);
73499052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
73599052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
73699052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
73799052Sdes	ret = buffer_get_int(&m);
73899052Sdes	debug3("%s: pam_respond returned %d", __func__, ret);
73999052Sdes	buffer_free(&m);
74099052Sdes	return (ret);
74199052Sdes}
74299052Sdes
74399052Sdesvoid
74499052Sdesmm_pam_free_ctx(void *ctxtp)
74599052Sdes{
74699052Sdes	Buffer m;
74799052Sdes
74899052Sdes	debug3("%s", __func__);
74999052Sdes	buffer_init(&m);
75099052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
75199052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
75299052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
75399052Sdes	buffer_free(&m);
75499052Sdes}
75598937Sdes#endif /* USE_PAM */
75698937Sdes
75798675Sdes/* Request process termination */
75898675Sdes
75998675Sdesvoid
76098675Sdesmm_terminate(void)
76198675Sdes{
76298675Sdes	Buffer m;
76398675Sdes
76498675Sdes	buffer_init(&m);
76598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
76698675Sdes	buffer_free(&m);
76798675Sdes}
76898675Sdes
76998675Sdesint
77098675Sdesmm_ssh1_session_key(BIGNUM *num)
77198675Sdes{
77298675Sdes	int rsafail;
77398675Sdes	Buffer m;
77498675Sdes
77598675Sdes	buffer_init(&m);
77698675Sdes	buffer_put_bignum2(&m, num);
77798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
77898675Sdes
77998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
78098675Sdes
78198675Sdes	rsafail = buffer_get_int(&m);
78298675Sdes	buffer_get_bignum2(&m, num);
78398675Sdes
78498675Sdes	buffer_free(&m);
78598675Sdes
78698675Sdes	return (rsafail);
78798675Sdes}
78898675Sdes
78998675Sdesstatic void
79098675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts,
79198675Sdes    char ***prompts, u_int **echo_on)
79298675Sdes{
79398675Sdes	*name = xstrdup("");
79498675Sdes	*infotxt = xstrdup("");
79598675Sdes	*numprompts = 1;
796106130Sdes	*prompts = xmalloc(*numprompts * sizeof(char *));
79798675Sdes	*echo_on = xmalloc(*numprompts * sizeof(u_int));
79898675Sdes	(*echo_on)[0] = 0;
79998675Sdes}
80098675Sdes
80198675Sdesint
80298675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt,
80398675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
80498675Sdes{
80598675Sdes	Buffer m;
806113911Sdes	u_int success;
80798675Sdes	char *challenge;
80898675Sdes
80998675Sdes	debug3("%s: entering", __func__);
81098675Sdes
81198675Sdes	buffer_init(&m);
81298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
81398675Sdes
81498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
81598675Sdes	    &m);
816113911Sdes	success = buffer_get_int(&m);
817113911Sdes	if (success == 0) {
81898675Sdes		debug3("%s: no challenge", __func__);
81998675Sdes		buffer_free(&m);
82098675Sdes		return (-1);
82198675Sdes	}
82298675Sdes
82398675Sdes	/* Get the challenge, and format the response */
82498675Sdes	challenge  = buffer_get_string(&m, NULL);
82598675Sdes	buffer_free(&m);
82698675Sdes
82798675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
82898675Sdes	(*prompts)[0] = challenge;
82998675Sdes
83098675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
83198675Sdes
83298675Sdes	return (0);
83398675Sdes}
83498675Sdes
83598675Sdesint
83698675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
83798675Sdes{
83898675Sdes	Buffer m;
83998675Sdes	int authok;
84098675Sdes
84198675Sdes	debug3("%s: entering", __func__);
84298675Sdes	if (numresponses != 1)
84398675Sdes		return (-1);
84498675Sdes
84598675Sdes	buffer_init(&m);
84698675Sdes	buffer_put_cstring(&m, responses[0]);
84798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
84898675Sdes
84998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
85098675Sdes	    MONITOR_ANS_BSDAUTHRESPOND, &m);
85198675Sdes
85298675Sdes	authok = buffer_get_int(&m);
85398675Sdes	buffer_free(&m);
85498675Sdes
85598675Sdes	return ((authok == 0) ? -1 : 0);
85698675Sdes}
85798675Sdes
85899046Sdes#ifdef SKEY
85998675Sdesint
86098675Sdesmm_skey_query(void *ctx, char **name, char **infotxt,
86198675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
86298675Sdes{
86398675Sdes	Buffer m;
864113911Sdes	int len;
865113911Sdes	u_int success;
86698675Sdes	char *p, *challenge;
86798675Sdes
86898675Sdes	debug3("%s: entering", __func__);
86998675Sdes
87098675Sdes	buffer_init(&m);
87198675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
87298675Sdes
87398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
87498675Sdes	    &m);
875113911Sdes	success = buffer_get_int(&m);
876113911Sdes	if (success == 0) {
87798675Sdes		debug3("%s: no challenge", __func__);
87898675Sdes		buffer_free(&m);
87998675Sdes		return (-1);
88098675Sdes	}
88198675Sdes
88298675Sdes	/* Get the challenge, and format the response */
88398675Sdes	challenge  = buffer_get_string(&m, NULL);
88498675Sdes	buffer_free(&m);
88598675Sdes
88698675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
88798675Sdes
88898675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
88998675Sdes
89098675Sdes	len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
89198675Sdes	p = xmalloc(len);
89298675Sdes	strlcpy(p, challenge, len);
89398675Sdes	strlcat(p, SKEY_PROMPT, len);
89498675Sdes	(*prompts)[0] = p;
89598675Sdes	xfree(challenge);
89698675Sdes
89798675Sdes	return (0);
89898675Sdes}
89998675Sdes
90098675Sdesint
90198675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses)
90298675Sdes{
90398675Sdes	Buffer m;
90498675Sdes	int authok;
90598675Sdes
90698675Sdes	debug3("%s: entering", __func__);
90798675Sdes	if (numresponses != 1)
90898675Sdes		return (-1);
90998675Sdes
91098675Sdes	buffer_init(&m);
91198675Sdes	buffer_put_cstring(&m, responses[0]);
91298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
91398675Sdes
91498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
91598675Sdes	    MONITOR_ANS_SKEYRESPOND, &m);
91698675Sdes
91798675Sdes	authok = buffer_get_int(&m);
91898675Sdes	buffer_free(&m);
91998675Sdes
92098675Sdes	return ((authok == 0) ? -1 : 0);
92198675Sdes}
92299046Sdes#endif
92398675Sdes
92498675Sdesvoid
92598675Sdesmm_ssh1_session_id(u_char session_id[16])
92698675Sdes{
92798675Sdes	Buffer m;
92898675Sdes	int i;
92998675Sdes
93098675Sdes	debug3("%s entering", __func__);
93198675Sdes
93298675Sdes	buffer_init(&m);
93398675Sdes	for (i = 0; i < 16; i++)
93498675Sdes		buffer_put_char(&m, session_id[i]);
93598675Sdes
93698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
93798675Sdes	buffer_free(&m);
93898675Sdes}
93998675Sdes
94098675Sdesint
94198675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
94298675Sdes{
94398675Sdes	Buffer m;
94498675Sdes	Key *key;
94598675Sdes	u_char *blob;
94698675Sdes	u_int blen;
947113911Sdes	int allowed = 0, have_forced = 0;
94898675Sdes
94998675Sdes	debug3("%s entering", __func__);
95098675Sdes
95198675Sdes	buffer_init(&m);
95298675Sdes	buffer_put_bignum2(&m, client_n);
95398675Sdes
95498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
95598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
95698675Sdes
95798675Sdes	allowed = buffer_get_int(&m);
95898675Sdes
959113911Sdes	/* fake forced command */
960113911Sdes	auth_clear_options();
961113911Sdes	have_forced = buffer_get_int(&m);
962113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
963113911Sdes
96498675Sdes	if (allowed && rkey != NULL) {
96598675Sdes		blob = buffer_get_string(&m, &blen);
96698675Sdes		if ((key = key_from_blob(blob, blen)) == NULL)
96798675Sdes			fatal("%s: key_from_blob failed", __func__);
96898675Sdes		*rkey = key;
96998675Sdes		xfree(blob);
97098675Sdes	}
97198675Sdes	mm_send_debug(&m);
97298675Sdes	buffer_free(&m);
97398675Sdes
97498675Sdes	return (allowed);
97598675Sdes}
97698675Sdes
97798675SdesBIGNUM *
97898675Sdesmm_auth_rsa_generate_challenge(Key *key)
97998675Sdes{
98098675Sdes	Buffer m;
98198675Sdes	BIGNUM *challenge;
98298675Sdes	u_char *blob;
98398675Sdes	u_int blen;
98498675Sdes
98598675Sdes	debug3("%s entering", __func__);
98698675Sdes
98798675Sdes	if ((challenge = BN_new()) == NULL)
98898675Sdes		fatal("%s: BN_new failed", __func__);
98998675Sdes
99098675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
99198675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
99298675Sdes		fatal("%s: key_to_blob failed", __func__);
99398675Sdes	key->type = KEY_RSA1;
99498675Sdes
99598675Sdes	buffer_init(&m);
99698675Sdes	buffer_put_string(&m, blob, blen);
99798675Sdes	xfree(blob);
99898675Sdes
99998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
100098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
100198675Sdes
100298675Sdes	buffer_get_bignum2(&m, challenge);
100398675Sdes	buffer_free(&m);
100498675Sdes
100598675Sdes	return (challenge);
100698675Sdes}
100798675Sdes
100898675Sdesint
100998675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
101098675Sdes{
101198675Sdes	Buffer m;
101298675Sdes	u_char *blob;
101398675Sdes	u_int blen;
101498675Sdes	int success = 0;
101598675Sdes
101698675Sdes	debug3("%s entering", __func__);
101798675Sdes
101898675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
101998675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
102098675Sdes		fatal("%s: key_to_blob failed", __func__);
102198675Sdes	key->type = KEY_RSA1;
102298675Sdes
102398675Sdes	buffer_init(&m);
102498675Sdes	buffer_put_string(&m, blob, blen);
102598675Sdes	buffer_put_string(&m, response, 16);
102698675Sdes	xfree(blob);
102798675Sdes
102898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
102998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
103098675Sdes
103198675Sdes	success = buffer_get_int(&m);
103298675Sdes	buffer_free(&m);
103398675Sdes
103498675Sdes	return (success);
103598675Sdes}
1036106130Sdes
1037106130Sdes#ifdef KRB4
1038106130Sdesint
1039106130Sdesmm_auth_krb4(Authctxt *authctxt, void *_auth, char **client, void *_reply)
1040106130Sdes{
1041106130Sdes	KTEXT auth, reply;
1042106130Sdes 	Buffer m;
1043106130Sdes	u_int rlen;
1044106130Sdes	int success = 0;
1045106130Sdes	char *p;
1046106130Sdes
1047106130Sdes	debug3("%s entering", __func__);
1048106130Sdes	auth = _auth;
1049106130Sdes	reply = _reply;
1050106130Sdes
1051106130Sdes	buffer_init(&m);
1052106130Sdes	buffer_put_string(&m, auth->dat, auth->length);
1053106130Sdes
1054106130Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB4, &m);
1055106130Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB4, &m);
1056106130Sdes
1057106130Sdes	success = buffer_get_int(&m);
1058106130Sdes	if (success) {
1059106130Sdes		*client = buffer_get_string(&m, NULL);
1060106130Sdes		p = buffer_get_string(&m, &rlen);
1061106130Sdes		if (rlen >= MAX_KTXT_LEN)
1062106130Sdes			fatal("%s: reply from monitor too large", __func__);
1063106130Sdes		reply->length = rlen;
1064106130Sdes		memcpy(reply->dat, p, rlen);
1065106130Sdes		memset(p, 0, rlen);
1066106130Sdes		xfree(p);
1067106130Sdes	}
1068106130Sdes	buffer_free(&m);
1069113911Sdes	return (success);
1070106130Sdes}
1071106130Sdes#endif
1072106130Sdes
1073106130Sdes#ifdef KRB5
1074106130Sdesint
1075106130Sdesmm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
1076106130Sdes{
1077106130Sdes	krb5_data *tkt, *reply;
1078106130Sdes	Buffer m;
1079106130Sdes	int success;
1080106130Sdes
1081106130Sdes	debug3("%s entering", __func__);
1082106130Sdes	tkt = (krb5_data *) argp;
1083106130Sdes	reply = (krb5_data *) resp;
1084106130Sdes
1085106130Sdes	buffer_init(&m);
1086106130Sdes	buffer_put_string(&m, tkt->data, tkt->length);
1087106130Sdes
1088106130Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, &m);
1089106130Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, &m);
1090106130Sdes
1091106130Sdes	success = buffer_get_int(&m);
1092106130Sdes	if (success) {
1093106130Sdes		u_int len;
1094106130Sdes
1095106130Sdes		*userp = buffer_get_string(&m, NULL);
1096106130Sdes		reply->data = buffer_get_string(&m, &len);
1097106130Sdes		reply->length = len;
1098106130Sdes	} else {
1099106130Sdes		memset(reply, 0, sizeof(*reply));
1100106130Sdes		*userp = NULL;
1101106130Sdes	}
1102106130Sdes
1103106130Sdes	buffer_free(&m);
1104106130Sdes	return (success);
1105106130Sdes}
1106106130Sdes#endif
1107