xref: /freebsd/crypto/openssh/monitor_wrap.c (revision 545d5eca429a5967b3300cb527d49cae8184e79f)
1545d5ecaSDag-Erling Smørgrav /*
2545d5ecaSDag-Erling Smørgrav  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3545d5ecaSDag-Erling Smørgrav  * Copyright 2002 Markus Friedl <markus@openbsd.org>
4545d5ecaSDag-Erling Smørgrav  * All rights reserved.
5545d5ecaSDag-Erling Smørgrav  *
6545d5ecaSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
7545d5ecaSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
8545d5ecaSDag-Erling Smørgrav  * are met:
9545d5ecaSDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
10545d5ecaSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
11545d5ecaSDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
12545d5ecaSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
13545d5ecaSDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
14545d5ecaSDag-Erling Smørgrav  *
15545d5ecaSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16545d5ecaSDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17545d5ecaSDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18545d5ecaSDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19545d5ecaSDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20545d5ecaSDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21545d5ecaSDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22545d5ecaSDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23545d5ecaSDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24545d5ecaSDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25545d5ecaSDag-Erling Smørgrav  */
26545d5ecaSDag-Erling Smørgrav 
27545d5ecaSDag-Erling Smørgrav #include "includes.h"
28545d5ecaSDag-Erling Smørgrav RCSID("$OpenBSD: monitor_wrap.c,v 1.11 2002/06/19 18:01:00 markus Exp $");
29545d5ecaSDag-Erling Smørgrav 
30545d5ecaSDag-Erling Smørgrav #include <openssl/bn.h>
31545d5ecaSDag-Erling Smørgrav #include <openssl/dh.h>
32545d5ecaSDag-Erling Smørgrav 
33545d5ecaSDag-Erling Smørgrav #include "ssh.h"
34545d5ecaSDag-Erling Smørgrav #include "dh.h"
35545d5ecaSDag-Erling Smørgrav #include "kex.h"
36545d5ecaSDag-Erling Smørgrav #include "auth.h"
37545d5ecaSDag-Erling Smørgrav #include "buffer.h"
38545d5ecaSDag-Erling Smørgrav #include "bufaux.h"
39545d5ecaSDag-Erling Smørgrav #include "packet.h"
40545d5ecaSDag-Erling Smørgrav #include "mac.h"
41545d5ecaSDag-Erling Smørgrav #include "log.h"
42545d5ecaSDag-Erling Smørgrav #include "zlib.h"
43545d5ecaSDag-Erling Smørgrav #include "monitor.h"
44545d5ecaSDag-Erling Smørgrav #include "monitor_wrap.h"
45545d5ecaSDag-Erling Smørgrav #include "xmalloc.h"
46545d5ecaSDag-Erling Smørgrav #include "atomicio.h"
47545d5ecaSDag-Erling Smørgrav #include "monitor_fdpass.h"
48545d5ecaSDag-Erling Smørgrav #include "getput.h"
49545d5ecaSDag-Erling Smørgrav 
50545d5ecaSDag-Erling Smørgrav #include "auth.h"
51545d5ecaSDag-Erling Smørgrav #include "channels.h"
52545d5ecaSDag-Erling Smørgrav #include "session.h"
53545d5ecaSDag-Erling Smørgrav 
54545d5ecaSDag-Erling Smørgrav /* Imports */
55545d5ecaSDag-Erling Smørgrav extern int compat20;
56545d5ecaSDag-Erling Smørgrav extern Newkeys *newkeys[];
57545d5ecaSDag-Erling Smørgrav extern z_stream incoming_stream;
58545d5ecaSDag-Erling Smørgrav extern z_stream outgoing_stream;
59545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor;
60545d5ecaSDag-Erling Smørgrav extern Buffer input, output;
61545d5ecaSDag-Erling Smørgrav 
62545d5ecaSDag-Erling Smørgrav void
63545d5ecaSDag-Erling Smørgrav mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
64545d5ecaSDag-Erling Smørgrav {
65545d5ecaSDag-Erling Smørgrav 	u_char buf[5];
66545d5ecaSDag-Erling Smørgrav 	u_int mlen = buffer_len(m);
67545d5ecaSDag-Erling Smørgrav 
68545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
69545d5ecaSDag-Erling Smørgrav 
70545d5ecaSDag-Erling Smørgrav 	PUT_32BIT(buf, mlen + 1);
71545d5ecaSDag-Erling Smørgrav 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
72545d5ecaSDag-Erling Smørgrav 	if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
73545d5ecaSDag-Erling Smørgrav 		fatal("%s: write", __func__);
74545d5ecaSDag-Erling Smørgrav 	if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
75545d5ecaSDag-Erling Smørgrav 		fatal("%s: write", __func__);
76545d5ecaSDag-Erling Smørgrav }
77545d5ecaSDag-Erling Smørgrav 
78545d5ecaSDag-Erling Smørgrav void
79545d5ecaSDag-Erling Smørgrav mm_request_receive(int socket, Buffer *m)
80545d5ecaSDag-Erling Smørgrav {
81545d5ecaSDag-Erling Smørgrav 	u_char buf[4];
82545d5ecaSDag-Erling Smørgrav 	ssize_t res;
83545d5ecaSDag-Erling Smørgrav 	u_int msg_len;
84545d5ecaSDag-Erling Smørgrav 
85545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
86545d5ecaSDag-Erling Smørgrav 
87545d5ecaSDag-Erling Smørgrav 	res = atomicio(read, socket, buf, sizeof(buf));
88545d5ecaSDag-Erling Smørgrav 	if (res != sizeof(buf)) {
89545d5ecaSDag-Erling Smørgrav 		if (res == 0)
90545d5ecaSDag-Erling Smørgrav 			fatal_cleanup();
91545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: %ld", __func__, (long)res);
92545d5ecaSDag-Erling Smørgrav 	}
93545d5ecaSDag-Erling Smørgrav 	msg_len = GET_32BIT(buf);
94545d5ecaSDag-Erling Smørgrav 	if (msg_len > 256 * 1024)
95545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: bad msg_len %d", __func__, msg_len);
96545d5ecaSDag-Erling Smørgrav 	buffer_clear(m);
97545d5ecaSDag-Erling Smørgrav 	buffer_append_space(m, msg_len);
98545d5ecaSDag-Erling Smørgrav 	res = atomicio(read, socket, buffer_ptr(m), msg_len);
99545d5ecaSDag-Erling Smørgrav 	if (res != msg_len)
100545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: %ld != msg_len", __func__, (long)res);
101545d5ecaSDag-Erling Smørgrav }
102545d5ecaSDag-Erling Smørgrav 
103545d5ecaSDag-Erling Smørgrav void
104545d5ecaSDag-Erling Smørgrav mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
105545d5ecaSDag-Erling Smørgrav {
106545d5ecaSDag-Erling Smørgrav 	u_char rtype;
107545d5ecaSDag-Erling Smørgrav 
108545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
109545d5ecaSDag-Erling Smørgrav 
110545d5ecaSDag-Erling Smørgrav 	mm_request_receive(socket, m);
111545d5ecaSDag-Erling Smørgrav 	rtype = buffer_get_char(m);
112545d5ecaSDag-Erling Smørgrav 	if (rtype != type)
113545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: rtype %d != type %d", __func__,
114545d5ecaSDag-Erling Smørgrav 		    rtype, type);
115545d5ecaSDag-Erling Smørgrav }
116545d5ecaSDag-Erling Smørgrav 
117545d5ecaSDag-Erling Smørgrav DH *
118545d5ecaSDag-Erling Smørgrav mm_choose_dh(int min, int nbits, int max)
119545d5ecaSDag-Erling Smørgrav {
120545d5ecaSDag-Erling Smørgrav 	BIGNUM *p, *g;
121545d5ecaSDag-Erling Smørgrav 	int success = 0;
122545d5ecaSDag-Erling Smørgrav 	Buffer m;
123545d5ecaSDag-Erling Smørgrav 
124545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
125545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, min);
126545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, nbits);
127545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, max);
128545d5ecaSDag-Erling Smørgrav 
129545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
130545d5ecaSDag-Erling Smørgrav 
131545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
132545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
133545d5ecaSDag-Erling Smørgrav 
134545d5ecaSDag-Erling Smørgrav 	success = buffer_get_char(&m);
135545d5ecaSDag-Erling Smørgrav 	if (success == 0)
136545d5ecaSDag-Erling Smørgrav 		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
137545d5ecaSDag-Erling Smørgrav 
138545d5ecaSDag-Erling Smørgrav 	if ((p = BN_new()) == NULL)
139545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
140545d5ecaSDag-Erling Smørgrav 	if ((g = BN_new()) == NULL)
141545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
142545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, p);
143545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, g);
144545d5ecaSDag-Erling Smørgrav 
145545d5ecaSDag-Erling Smørgrav 	debug3("%s: remaining %d", __func__, buffer_len(&m));
146545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
147545d5ecaSDag-Erling Smørgrav 
148545d5ecaSDag-Erling Smørgrav 	return (dh_new_group(g, p));
149545d5ecaSDag-Erling Smørgrav }
150545d5ecaSDag-Erling Smørgrav 
151545d5ecaSDag-Erling Smørgrav int
152545d5ecaSDag-Erling Smørgrav mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
153545d5ecaSDag-Erling Smørgrav {
154545d5ecaSDag-Erling Smørgrav 	Kex *kex = *pmonitor->m_pkex;
155545d5ecaSDag-Erling Smørgrav 	Buffer m;
156545d5ecaSDag-Erling Smørgrav 
157545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
158545d5ecaSDag-Erling Smørgrav 
159545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
160545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, kex->host_key_index(key));
161545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, data, datalen);
162545d5ecaSDag-Erling Smørgrav 
163545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
164545d5ecaSDag-Erling Smørgrav 
165545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
166545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
167545d5ecaSDag-Erling Smørgrav 	*sigp  = buffer_get_string(&m, lenp);
168545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
169545d5ecaSDag-Erling Smørgrav 
170545d5ecaSDag-Erling Smørgrav 	return (0);
171545d5ecaSDag-Erling Smørgrav }
172545d5ecaSDag-Erling Smørgrav 
173545d5ecaSDag-Erling Smørgrav struct passwd *
174545d5ecaSDag-Erling Smørgrav mm_getpwnamallow(const char *login)
175545d5ecaSDag-Erling Smørgrav {
176545d5ecaSDag-Erling Smørgrav 	Buffer m;
177545d5ecaSDag-Erling Smørgrav 	struct passwd *pw;
178545d5ecaSDag-Erling Smørgrav 	u_int pwlen;
179545d5ecaSDag-Erling Smørgrav 
180545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
181545d5ecaSDag-Erling Smørgrav 
182545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
183545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, login);
184545d5ecaSDag-Erling Smørgrav 
185545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
186545d5ecaSDag-Erling Smørgrav 
187545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
188545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
189545d5ecaSDag-Erling Smørgrav 
190545d5ecaSDag-Erling Smørgrav 	if (buffer_get_char(&m) == 0) {
191545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
192545d5ecaSDag-Erling Smørgrav 		return (NULL);
193545d5ecaSDag-Erling Smørgrav 	}
194545d5ecaSDag-Erling Smørgrav 	pw = buffer_get_string(&m, &pwlen);
195545d5ecaSDag-Erling Smørgrav 	if (pwlen != sizeof(struct passwd))
196545d5ecaSDag-Erling Smørgrav 		fatal("%s: struct passwd size mismatch", __func__);
197545d5ecaSDag-Erling Smørgrav 	pw->pw_name = buffer_get_string(&m, NULL);
198545d5ecaSDag-Erling Smørgrav 	pw->pw_passwd = buffer_get_string(&m, NULL);
199545d5ecaSDag-Erling Smørgrav 	pw->pw_gecos = buffer_get_string(&m, NULL);
200545d5ecaSDag-Erling Smørgrav 	pw->pw_class = buffer_get_string(&m, NULL);
201545d5ecaSDag-Erling Smørgrav 	pw->pw_dir = buffer_get_string(&m, NULL);
202545d5ecaSDag-Erling Smørgrav 	pw->pw_shell = buffer_get_string(&m, NULL);
203545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
204545d5ecaSDag-Erling Smørgrav 
205545d5ecaSDag-Erling Smørgrav 	return (pw);
206545d5ecaSDag-Erling Smørgrav }
207545d5ecaSDag-Erling Smørgrav 
208545d5ecaSDag-Erling Smørgrav char* mm_auth2_read_banner(void)
209545d5ecaSDag-Erling Smørgrav {
210545d5ecaSDag-Erling Smørgrav 	Buffer m;
211545d5ecaSDag-Erling Smørgrav 	char *banner;
212545d5ecaSDag-Erling Smørgrav 
213545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
214545d5ecaSDag-Erling Smørgrav 
215545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
216545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
217545d5ecaSDag-Erling Smørgrav 	buffer_clear(&m);
218545d5ecaSDag-Erling Smørgrav 
219545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
220545d5ecaSDag-Erling Smørgrav 	banner = buffer_get_string(&m, NULL);
221545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
222545d5ecaSDag-Erling Smørgrav 
223545d5ecaSDag-Erling Smørgrav 	return (banner);
224545d5ecaSDag-Erling Smørgrav }
225545d5ecaSDag-Erling Smørgrav 
226545d5ecaSDag-Erling Smørgrav /* Inform the privileged process about service and style */
227545d5ecaSDag-Erling Smørgrav 
228545d5ecaSDag-Erling Smørgrav void
229545d5ecaSDag-Erling Smørgrav mm_inform_authserv(char *service, char *style)
230545d5ecaSDag-Erling Smørgrav {
231545d5ecaSDag-Erling Smørgrav 	Buffer m;
232545d5ecaSDag-Erling Smørgrav 
233545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
234545d5ecaSDag-Erling Smørgrav 
235545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
236545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, service);
237545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, style ? style : "");
238545d5ecaSDag-Erling Smørgrav 
239545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
240545d5ecaSDag-Erling Smørgrav 
241545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
242545d5ecaSDag-Erling Smørgrav }
243545d5ecaSDag-Erling Smørgrav 
244545d5ecaSDag-Erling Smørgrav /* Do the password authentication */
245545d5ecaSDag-Erling Smørgrav int
246545d5ecaSDag-Erling Smørgrav mm_auth_password(Authctxt *authctxt, char *password)
247545d5ecaSDag-Erling Smørgrav {
248545d5ecaSDag-Erling Smørgrav 	Buffer m;
249545d5ecaSDag-Erling Smørgrav 	int authenticated = 0;
250545d5ecaSDag-Erling Smørgrav 
251545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
252545d5ecaSDag-Erling Smørgrav 
253545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
254545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, password);
255545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
256545d5ecaSDag-Erling Smørgrav 
257545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
258545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
259545d5ecaSDag-Erling Smørgrav 
260545d5ecaSDag-Erling Smørgrav 	authenticated = buffer_get_int(&m);
261545d5ecaSDag-Erling Smørgrav 
262545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
263545d5ecaSDag-Erling Smørgrav 
264545d5ecaSDag-Erling Smørgrav 	debug3("%s: user %sauthenticated",
265545d5ecaSDag-Erling Smørgrav 	    __func__, authenticated ? "" : "not ");
266545d5ecaSDag-Erling Smørgrav 	return (authenticated);
267545d5ecaSDag-Erling Smørgrav }
268545d5ecaSDag-Erling Smørgrav 
269545d5ecaSDag-Erling Smørgrav int
270545d5ecaSDag-Erling Smørgrav mm_user_key_allowed(struct passwd *pw, Key *key)
271545d5ecaSDag-Erling Smørgrav {
272545d5ecaSDag-Erling Smørgrav 	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
273545d5ecaSDag-Erling Smørgrav }
274545d5ecaSDag-Erling Smørgrav 
275545d5ecaSDag-Erling Smørgrav int
276545d5ecaSDag-Erling Smørgrav mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
277545d5ecaSDag-Erling Smørgrav     Key *key)
278545d5ecaSDag-Erling Smørgrav {
279545d5ecaSDag-Erling Smørgrav 	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
280545d5ecaSDag-Erling Smørgrav }
281545d5ecaSDag-Erling Smørgrav 
282545d5ecaSDag-Erling Smørgrav int
283545d5ecaSDag-Erling Smørgrav mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
284545d5ecaSDag-Erling Smørgrav     char *host, Key *key)
285545d5ecaSDag-Erling Smørgrav {
286545d5ecaSDag-Erling Smørgrav 	int ret;
287545d5ecaSDag-Erling Smørgrav 
288545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA; /* XXX hack for key_to_blob */
289545d5ecaSDag-Erling Smørgrav 	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
290545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
291545d5ecaSDag-Erling Smørgrav 	return (ret);
292545d5ecaSDag-Erling Smørgrav }
293545d5ecaSDag-Erling Smørgrav 
294545d5ecaSDag-Erling Smørgrav static void
295545d5ecaSDag-Erling Smørgrav mm_send_debug(Buffer *m)
296545d5ecaSDag-Erling Smørgrav {
297545d5ecaSDag-Erling Smørgrav 	char *msg;
298545d5ecaSDag-Erling Smørgrav 
299545d5ecaSDag-Erling Smørgrav 	while (buffer_len(m)) {
300545d5ecaSDag-Erling Smørgrav 		msg = buffer_get_string(m, NULL);
301545d5ecaSDag-Erling Smørgrav 		debug3("%s: Sending debug: %s", __func__, msg);
302545d5ecaSDag-Erling Smørgrav 		packet_send_debug("%s", msg);
303545d5ecaSDag-Erling Smørgrav 		xfree(msg);
304545d5ecaSDag-Erling Smørgrav 	}
305545d5ecaSDag-Erling Smørgrav }
306545d5ecaSDag-Erling Smørgrav 
307545d5ecaSDag-Erling Smørgrav int
308545d5ecaSDag-Erling Smørgrav mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
309545d5ecaSDag-Erling Smørgrav {
310545d5ecaSDag-Erling Smørgrav 	Buffer m;
311545d5ecaSDag-Erling Smørgrav 	u_char *blob;
312545d5ecaSDag-Erling Smørgrav 	u_int len;
313545d5ecaSDag-Erling Smørgrav 	int allowed = 0;
314545d5ecaSDag-Erling Smørgrav 
315545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
316545d5ecaSDag-Erling Smørgrav 
317545d5ecaSDag-Erling Smørgrav 	/* Convert the key to a blob and the pass it over */
318545d5ecaSDag-Erling Smørgrav 	if (!key_to_blob(key, &blob, &len))
319545d5ecaSDag-Erling Smørgrav 		return (0);
320545d5ecaSDag-Erling Smørgrav 
321545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
322545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, type);
323545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, user ? user : "");
324545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, host ? host : "");
325545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, len);
326545d5ecaSDag-Erling Smørgrav 	xfree(blob);
327545d5ecaSDag-Erling Smørgrav 
328545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
329545d5ecaSDag-Erling Smørgrav 
330545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
331545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
332545d5ecaSDag-Erling Smørgrav 
333545d5ecaSDag-Erling Smørgrav 	allowed = buffer_get_int(&m);
334545d5ecaSDag-Erling Smørgrav 
335545d5ecaSDag-Erling Smørgrav 	/* Send potential debug messages */
336545d5ecaSDag-Erling Smørgrav 	mm_send_debug(&m);
337545d5ecaSDag-Erling Smørgrav 
338545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
339545d5ecaSDag-Erling Smørgrav 
340545d5ecaSDag-Erling Smørgrav 	return (allowed);
341545d5ecaSDag-Erling Smørgrav }
342545d5ecaSDag-Erling Smørgrav 
343545d5ecaSDag-Erling Smørgrav /*
344545d5ecaSDag-Erling Smørgrav  * This key verify needs to send the key type along, because the
345545d5ecaSDag-Erling Smørgrav  * privileged parent makes the decision if the key is allowed
346545d5ecaSDag-Erling Smørgrav  * for authentication.
347545d5ecaSDag-Erling Smørgrav  */
348545d5ecaSDag-Erling Smørgrav 
349545d5ecaSDag-Erling Smørgrav int
350545d5ecaSDag-Erling Smørgrav mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
351545d5ecaSDag-Erling Smørgrav {
352545d5ecaSDag-Erling Smørgrav 	Buffer m;
353545d5ecaSDag-Erling Smørgrav 	u_char *blob;
354545d5ecaSDag-Erling Smørgrav 	u_int len;
355545d5ecaSDag-Erling Smørgrav 	int verified = 0;
356545d5ecaSDag-Erling Smørgrav 
357545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
358545d5ecaSDag-Erling Smørgrav 
359545d5ecaSDag-Erling Smørgrav 	/* Convert the key to a blob and the pass it over */
360545d5ecaSDag-Erling Smørgrav 	if (!key_to_blob(key, &blob, &len))
361545d5ecaSDag-Erling Smørgrav 		return (0);
362545d5ecaSDag-Erling Smørgrav 
363545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
364545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, len);
365545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, sig, siglen);
366545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, data, datalen);
367545d5ecaSDag-Erling Smørgrav 	xfree(blob);
368545d5ecaSDag-Erling Smørgrav 
369545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
370545d5ecaSDag-Erling Smørgrav 
371545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
372545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
373545d5ecaSDag-Erling Smørgrav 
374545d5ecaSDag-Erling Smørgrav 	verified = buffer_get_int(&m);
375545d5ecaSDag-Erling Smørgrav 
376545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
377545d5ecaSDag-Erling Smørgrav 
378545d5ecaSDag-Erling Smørgrav 	return (verified);
379545d5ecaSDag-Erling Smørgrav }
380545d5ecaSDag-Erling Smørgrav 
381545d5ecaSDag-Erling Smørgrav /* Export key state after authentication */
382545d5ecaSDag-Erling Smørgrav Newkeys *
383545d5ecaSDag-Erling Smørgrav mm_newkeys_from_blob(u_char *blob, int blen)
384545d5ecaSDag-Erling Smørgrav {
385545d5ecaSDag-Erling Smørgrav 	Buffer b;
386545d5ecaSDag-Erling Smørgrav 	u_int len;
387545d5ecaSDag-Erling Smørgrav 	Newkeys *newkey = NULL;
388545d5ecaSDag-Erling Smørgrav 	Enc *enc;
389545d5ecaSDag-Erling Smørgrav 	Mac *mac;
390545d5ecaSDag-Erling Smørgrav 	Comp *comp;
391545d5ecaSDag-Erling Smørgrav 
392545d5ecaSDag-Erling Smørgrav 	debug3("%s: %p(%d)", __func__, blob, blen);
393545d5ecaSDag-Erling Smørgrav #ifdef DEBUG_PK
394545d5ecaSDag-Erling Smørgrav 	dump_base64(stderr, blob, blen);
395545d5ecaSDag-Erling Smørgrav #endif
396545d5ecaSDag-Erling Smørgrav 	buffer_init(&b);
397545d5ecaSDag-Erling Smørgrav 	buffer_append(&b, blob, blen);
398545d5ecaSDag-Erling Smørgrav 
399545d5ecaSDag-Erling Smørgrav 	newkey = xmalloc(sizeof(*newkey));
400545d5ecaSDag-Erling Smørgrav 	enc = &newkey->enc;
401545d5ecaSDag-Erling Smørgrav 	mac = &newkey->mac;
402545d5ecaSDag-Erling Smørgrav 	comp = &newkey->comp;
403545d5ecaSDag-Erling Smørgrav 
404545d5ecaSDag-Erling Smørgrav 	/* Enc structure */
405545d5ecaSDag-Erling Smørgrav 	enc->name = buffer_get_string(&b, NULL);
406545d5ecaSDag-Erling Smørgrav 	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
407545d5ecaSDag-Erling Smørgrav 	enc->enabled = buffer_get_int(&b);
408545d5ecaSDag-Erling Smørgrav 	enc->block_size = buffer_get_int(&b);
409545d5ecaSDag-Erling Smørgrav 	enc->key = buffer_get_string(&b, &enc->key_len);
410545d5ecaSDag-Erling Smørgrav 	enc->iv = buffer_get_string(&b, &len);
411545d5ecaSDag-Erling Smørgrav 	if (len != enc->block_size)
412545d5ecaSDag-Erling Smørgrav 		fatal("%s: bad ivlen: expected %d != %d", __func__,
413545d5ecaSDag-Erling Smørgrav 		    enc->block_size, len);
414545d5ecaSDag-Erling Smørgrav 
415545d5ecaSDag-Erling Smørgrav 	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
416545d5ecaSDag-Erling Smørgrav 		fatal("%s: bad cipher name %s or pointer %p", __func__,
417545d5ecaSDag-Erling Smørgrav 		    enc->name, enc->cipher);
418545d5ecaSDag-Erling Smørgrav 
419545d5ecaSDag-Erling Smørgrav 	/* Mac structure */
420545d5ecaSDag-Erling Smørgrav 	mac->name = buffer_get_string(&b, NULL);
421545d5ecaSDag-Erling Smørgrav 	if (mac->name == NULL || mac_init(mac, mac->name) == -1)
422545d5ecaSDag-Erling Smørgrav 		fatal("%s: can not init mac %s", __func__, mac->name);
423545d5ecaSDag-Erling Smørgrav 	mac->enabled = buffer_get_int(&b);
424545d5ecaSDag-Erling Smørgrav 	mac->key = buffer_get_string(&b, &len);
425545d5ecaSDag-Erling Smørgrav 	if (len > mac->key_len)
426545d5ecaSDag-Erling Smørgrav 		fatal("%s: bad mac key length: %d > %d", __func__, len,
427545d5ecaSDag-Erling Smørgrav 		    mac->key_len);
428545d5ecaSDag-Erling Smørgrav 	mac->key_len = len;
429545d5ecaSDag-Erling Smørgrav 
430545d5ecaSDag-Erling Smørgrav 	/* Comp structure */
431545d5ecaSDag-Erling Smørgrav 	comp->type = buffer_get_int(&b);
432545d5ecaSDag-Erling Smørgrav 	comp->enabled = buffer_get_int(&b);
433545d5ecaSDag-Erling Smørgrav 	comp->name = buffer_get_string(&b, NULL);
434545d5ecaSDag-Erling Smørgrav 
435545d5ecaSDag-Erling Smørgrav 	len = buffer_len(&b);
436545d5ecaSDag-Erling Smørgrav 	if (len != 0)
437545d5ecaSDag-Erling Smørgrav 		error("newkeys_from_blob: remaining bytes in blob %d", len);
438545d5ecaSDag-Erling Smørgrav 	buffer_free(&b);
439545d5ecaSDag-Erling Smørgrav 	return (newkey);
440545d5ecaSDag-Erling Smørgrav }
441545d5ecaSDag-Erling Smørgrav 
442545d5ecaSDag-Erling Smørgrav int
443545d5ecaSDag-Erling Smørgrav mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
444545d5ecaSDag-Erling Smørgrav {
445545d5ecaSDag-Erling Smørgrav 	Buffer b;
446545d5ecaSDag-Erling Smørgrav 	int len;
447545d5ecaSDag-Erling Smørgrav 	u_char *buf;
448545d5ecaSDag-Erling Smørgrav 	Enc *enc;
449545d5ecaSDag-Erling Smørgrav 	Mac *mac;
450545d5ecaSDag-Erling Smørgrav 	Comp *comp;
451545d5ecaSDag-Erling Smørgrav 	Newkeys *newkey = newkeys[mode];
452545d5ecaSDag-Erling Smørgrav 
453545d5ecaSDag-Erling Smørgrav 	debug3("%s: converting %p", __func__, newkey);
454545d5ecaSDag-Erling Smørgrav 
455545d5ecaSDag-Erling Smørgrav 	if (newkey == NULL) {
456545d5ecaSDag-Erling Smørgrav 		error("%s: newkey == NULL", __func__);
457545d5ecaSDag-Erling Smørgrav 		return 0;
458545d5ecaSDag-Erling Smørgrav 	}
459545d5ecaSDag-Erling Smørgrav 	enc = &newkey->enc;
460545d5ecaSDag-Erling Smørgrav 	mac = &newkey->mac;
461545d5ecaSDag-Erling Smørgrav 	comp = &newkey->comp;
462545d5ecaSDag-Erling Smørgrav 
463545d5ecaSDag-Erling Smørgrav 	buffer_init(&b);
464545d5ecaSDag-Erling Smørgrav 	/* Enc structure */
465545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&b, enc->name);
466545d5ecaSDag-Erling Smørgrav 	/* The cipher struct is constant and shared, you export pointer */
467545d5ecaSDag-Erling Smørgrav 	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
468545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, enc->enabled);
469545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, enc->block_size);
470545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&b, enc->key, enc->key_len);
471545d5ecaSDag-Erling Smørgrav 	packet_get_keyiv(mode, enc->iv, enc->block_size);
472545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&b, enc->iv, enc->block_size);
473545d5ecaSDag-Erling Smørgrav 
474545d5ecaSDag-Erling Smørgrav 	/* Mac structure */
475545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&b, mac->name);
476545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, mac->enabled);
477545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&b, mac->key, mac->key_len);
478545d5ecaSDag-Erling Smørgrav 
479545d5ecaSDag-Erling Smørgrav 	/* Comp structure */
480545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, comp->type);
481545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, comp->enabled);
482545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&b, comp->name);
483545d5ecaSDag-Erling Smørgrav 
484545d5ecaSDag-Erling Smørgrav 	len = buffer_len(&b);
485545d5ecaSDag-Erling Smørgrav 	buf = xmalloc(len);
486545d5ecaSDag-Erling Smørgrav 	memcpy(buf, buffer_ptr(&b), len);
487545d5ecaSDag-Erling Smørgrav 	memset(buffer_ptr(&b), 0, len);
488545d5ecaSDag-Erling Smørgrav 	buffer_free(&b);
489545d5ecaSDag-Erling Smørgrav 	if (lenp != NULL)
490545d5ecaSDag-Erling Smørgrav 		*lenp = len;
491545d5ecaSDag-Erling Smørgrav 	if (blobp != NULL)
492545d5ecaSDag-Erling Smørgrav 		*blobp = buf;
493545d5ecaSDag-Erling Smørgrav 	return len;
494545d5ecaSDag-Erling Smørgrav }
495545d5ecaSDag-Erling Smørgrav 
496545d5ecaSDag-Erling Smørgrav static void
497545d5ecaSDag-Erling Smørgrav mm_send_kex(Buffer *m, Kex *kex)
498545d5ecaSDag-Erling Smørgrav {
499545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, kex->session_id, kex->session_id_len);
500545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->we_need);
501545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->hostkey_type);
502545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->kex_type);
503545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
504545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
505545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->flags);
506545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(m, kex->client_version_string);
507545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(m, kex->server_version_string);
508545d5ecaSDag-Erling Smørgrav }
509545d5ecaSDag-Erling Smørgrav 
510545d5ecaSDag-Erling Smørgrav void
511545d5ecaSDag-Erling Smørgrav mm_send_keystate(struct monitor *pmonitor)
512545d5ecaSDag-Erling Smørgrav {
513545d5ecaSDag-Erling Smørgrav 	Buffer m;
514545d5ecaSDag-Erling Smørgrav 	u_char *blob, *p;
515545d5ecaSDag-Erling Smørgrav 	u_int bloblen, plen;
516545d5ecaSDag-Erling Smørgrav 
517545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
518545d5ecaSDag-Erling Smørgrav 
519545d5ecaSDag-Erling Smørgrav 	if (!compat20) {
520545d5ecaSDag-Erling Smørgrav 		u_char iv[24];
521545d5ecaSDag-Erling Smørgrav 		u_char *key;
522545d5ecaSDag-Erling Smørgrav 		u_int ivlen, keylen;
523545d5ecaSDag-Erling Smørgrav 
524545d5ecaSDag-Erling Smørgrav 		buffer_put_int(&m, packet_get_protocol_flags());
525545d5ecaSDag-Erling Smørgrav 
526545d5ecaSDag-Erling Smørgrav 		buffer_put_int(&m, packet_get_ssh1_cipher());
527545d5ecaSDag-Erling Smørgrav 
528545d5ecaSDag-Erling Smørgrav 		debug3("%s: Sending ssh1 KEY+IV", __func__);
529545d5ecaSDag-Erling Smørgrav 		keylen = packet_get_encryption_key(NULL);
530545d5ecaSDag-Erling Smørgrav 		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
531545d5ecaSDag-Erling Smørgrav 		keylen = packet_get_encryption_key(key);
532545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, key, keylen);
533545d5ecaSDag-Erling Smørgrav 		memset(key, 0, keylen);
534545d5ecaSDag-Erling Smørgrav 		xfree(key);
535545d5ecaSDag-Erling Smørgrav 
536545d5ecaSDag-Erling Smørgrav 		ivlen = packet_get_keyiv_len(MODE_OUT);
537545d5ecaSDag-Erling Smørgrav 		packet_get_keyiv(MODE_OUT, iv, ivlen);
538545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, iv, ivlen);
539545d5ecaSDag-Erling Smørgrav 		ivlen = packet_get_keyiv_len(MODE_OUT);
540545d5ecaSDag-Erling Smørgrav 		packet_get_keyiv(MODE_IN, iv, ivlen);
541545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, iv, ivlen);
542545d5ecaSDag-Erling Smørgrav 		goto skip;
543545d5ecaSDag-Erling Smørgrav 	} else {
544545d5ecaSDag-Erling Smørgrav 		/* Kex for rekeying */
545545d5ecaSDag-Erling Smørgrav 		mm_send_kex(&m, *pmonitor->m_pkex);
546545d5ecaSDag-Erling Smørgrav 	}
547545d5ecaSDag-Erling Smørgrav 
548545d5ecaSDag-Erling Smørgrav 	debug3("%s: Sending new keys: %p %p",
549545d5ecaSDag-Erling Smørgrav 	    __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
550545d5ecaSDag-Erling Smørgrav 
551545d5ecaSDag-Erling Smørgrav 	/* Keys from Kex */
552545d5ecaSDag-Erling Smørgrav 	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
553545d5ecaSDag-Erling Smørgrav 		fatal("%s: conversion of newkeys failed", __func__);
554545d5ecaSDag-Erling Smørgrav 
555545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, bloblen);
556545d5ecaSDag-Erling Smørgrav 	xfree(blob);
557545d5ecaSDag-Erling Smørgrav 
558545d5ecaSDag-Erling Smørgrav 	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
559545d5ecaSDag-Erling Smørgrav 		fatal("%s: conversion of newkeys failed", __func__);
560545d5ecaSDag-Erling Smørgrav 
561545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, bloblen);
562545d5ecaSDag-Erling Smørgrav 	xfree(blob);
563545d5ecaSDag-Erling Smørgrav 
564545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
565545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, packet_get_seqnr(MODE_IN));
566545d5ecaSDag-Erling Smørgrav 
567545d5ecaSDag-Erling Smørgrav 	debug3("%s: New keys have been sent", __func__);
568545d5ecaSDag-Erling Smørgrav  skip:
569545d5ecaSDag-Erling Smørgrav 	/* More key context */
570545d5ecaSDag-Erling Smørgrav 	plen = packet_get_keycontext(MODE_OUT, NULL);
571545d5ecaSDag-Erling Smørgrav 	p = xmalloc(plen+1);
572545d5ecaSDag-Erling Smørgrav 	packet_get_keycontext(MODE_OUT, p);
573545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, p, plen);
574545d5ecaSDag-Erling Smørgrav 	xfree(p);
575545d5ecaSDag-Erling Smørgrav 
576545d5ecaSDag-Erling Smørgrav 	plen = packet_get_keycontext(MODE_IN, NULL);
577545d5ecaSDag-Erling Smørgrav 	p = xmalloc(plen+1);
578545d5ecaSDag-Erling Smørgrav 	packet_get_keycontext(MODE_IN, p);
579545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, p, plen);
580545d5ecaSDag-Erling Smørgrav 	xfree(p);
581545d5ecaSDag-Erling Smørgrav 
582545d5ecaSDag-Erling Smørgrav 	/* Compression state */
583545d5ecaSDag-Erling Smørgrav 	debug3("%s: Sending compression state", __func__);
584545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
585545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
586545d5ecaSDag-Erling Smørgrav 
587545d5ecaSDag-Erling Smørgrav 	/* Network I/O buffers */
588545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
589545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
590545d5ecaSDag-Erling Smørgrav 
591545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
592545d5ecaSDag-Erling Smørgrav 	debug3("%s: Finished sending state", __func__);
593545d5ecaSDag-Erling Smørgrav 
594545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
595545d5ecaSDag-Erling Smørgrav }
596545d5ecaSDag-Erling Smørgrav 
597545d5ecaSDag-Erling Smørgrav int
598545d5ecaSDag-Erling Smørgrav mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
599545d5ecaSDag-Erling Smørgrav {
600545d5ecaSDag-Erling Smørgrav 	Buffer m;
601545d5ecaSDag-Erling Smørgrav 	u_char *p;
602545d5ecaSDag-Erling Smørgrav 	int success = 0;
603545d5ecaSDag-Erling Smørgrav 
604545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
605545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
606545d5ecaSDag-Erling Smørgrav 
607545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
608545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
609545d5ecaSDag-Erling Smørgrav 
610545d5ecaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
611545d5ecaSDag-Erling Smørgrav 	if (success == 0) {
612545d5ecaSDag-Erling Smørgrav 		debug3("%s: pty alloc failed", __func__);
613545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
614545d5ecaSDag-Erling Smørgrav 		return (0);
615545d5ecaSDag-Erling Smørgrav 	}
616545d5ecaSDag-Erling Smørgrav 	p = buffer_get_string(&m, NULL);
617545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
618545d5ecaSDag-Erling Smørgrav 
619545d5ecaSDag-Erling Smørgrav 	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
620545d5ecaSDag-Erling Smørgrav 	xfree(p);
621545d5ecaSDag-Erling Smørgrav 
622545d5ecaSDag-Erling Smørgrav 	*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
623545d5ecaSDag-Erling Smørgrav 	*ttyfd = mm_receive_fd(pmonitor->m_recvfd);
624545d5ecaSDag-Erling Smørgrav 
625545d5ecaSDag-Erling Smørgrav 	/* Success */
626545d5ecaSDag-Erling Smørgrav 	return (1);
627545d5ecaSDag-Erling Smørgrav }
628545d5ecaSDag-Erling Smørgrav 
629545d5ecaSDag-Erling Smørgrav void
630545d5ecaSDag-Erling Smørgrav mm_session_pty_cleanup2(void *session)
631545d5ecaSDag-Erling Smørgrav {
632545d5ecaSDag-Erling Smørgrav 	Session *s = session;
633545d5ecaSDag-Erling Smørgrav 	Buffer m;
634545d5ecaSDag-Erling Smørgrav 
635545d5ecaSDag-Erling Smørgrav 	if (s->ttyfd == -1)
636545d5ecaSDag-Erling Smørgrav 		return;
637545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
638545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, s->tty);
639545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
640545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
641545d5ecaSDag-Erling Smørgrav 
642545d5ecaSDag-Erling Smørgrav 	/* closed dup'ed master */
643545d5ecaSDag-Erling Smørgrav 	if (close(s->ptymaster) < 0)
644545d5ecaSDag-Erling Smørgrav 		error("close(s->ptymaster): %s", strerror(errno));
645545d5ecaSDag-Erling Smørgrav 
646545d5ecaSDag-Erling Smørgrav 	/* unlink pty from session */
647545d5ecaSDag-Erling Smørgrav 	s->ttyfd = -1;
648545d5ecaSDag-Erling Smørgrav }
649545d5ecaSDag-Erling Smørgrav 
650545d5ecaSDag-Erling Smørgrav /* Request process termination */
651545d5ecaSDag-Erling Smørgrav 
652545d5ecaSDag-Erling Smørgrav void
653545d5ecaSDag-Erling Smørgrav mm_terminate(void)
654545d5ecaSDag-Erling Smørgrav {
655545d5ecaSDag-Erling Smørgrav 	Buffer m;
656545d5ecaSDag-Erling Smørgrav 
657545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
658545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
659545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
660545d5ecaSDag-Erling Smørgrav }
661545d5ecaSDag-Erling Smørgrav 
662545d5ecaSDag-Erling Smørgrav int
663545d5ecaSDag-Erling Smørgrav mm_ssh1_session_key(BIGNUM *num)
664545d5ecaSDag-Erling Smørgrav {
665545d5ecaSDag-Erling Smørgrav 	int rsafail;
666545d5ecaSDag-Erling Smørgrav 	Buffer m;
667545d5ecaSDag-Erling Smørgrav 
668545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
669545d5ecaSDag-Erling Smørgrav 	buffer_put_bignum2(&m, num);
670545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
671545d5ecaSDag-Erling Smørgrav 
672545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
673545d5ecaSDag-Erling Smørgrav 
674545d5ecaSDag-Erling Smørgrav 	rsafail = buffer_get_int(&m);
675545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, num);
676545d5ecaSDag-Erling Smørgrav 
677545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
678545d5ecaSDag-Erling Smørgrav 
679545d5ecaSDag-Erling Smørgrav 	return (rsafail);
680545d5ecaSDag-Erling Smørgrav }
681545d5ecaSDag-Erling Smørgrav 
682545d5ecaSDag-Erling Smørgrav static void
683545d5ecaSDag-Erling Smørgrav mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
684545d5ecaSDag-Erling Smørgrav     char ***prompts, u_int **echo_on)
685545d5ecaSDag-Erling Smørgrav {
686545d5ecaSDag-Erling Smørgrav 	*name = xstrdup("");
687545d5ecaSDag-Erling Smørgrav 	*infotxt = xstrdup("");
688545d5ecaSDag-Erling Smørgrav 	*numprompts = 1;
689545d5ecaSDag-Erling Smørgrav 	*prompts = xmalloc(*numprompts * sizeof(char*));
690545d5ecaSDag-Erling Smørgrav 	*echo_on = xmalloc(*numprompts * sizeof(u_int));
691545d5ecaSDag-Erling Smørgrav 	(*echo_on)[0] = 0;
692545d5ecaSDag-Erling Smørgrav }
693545d5ecaSDag-Erling Smørgrav 
694545d5ecaSDag-Erling Smørgrav int
695545d5ecaSDag-Erling Smørgrav mm_bsdauth_query(void *ctx, char **name, char **infotxt,
696545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
697545d5ecaSDag-Erling Smørgrav {
698545d5ecaSDag-Erling Smørgrav 	Buffer m;
699545d5ecaSDag-Erling Smørgrav 	int res;
700545d5ecaSDag-Erling Smørgrav 	char *challenge;
701545d5ecaSDag-Erling Smørgrav 
702545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
703545d5ecaSDag-Erling Smørgrav 
704545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
705545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
706545d5ecaSDag-Erling Smørgrav 
707545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
708545d5ecaSDag-Erling Smørgrav 	    &m);
709545d5ecaSDag-Erling Smørgrav 	res = buffer_get_int(&m);
710545d5ecaSDag-Erling Smørgrav 	if (res == -1) {
711545d5ecaSDag-Erling Smørgrav 		debug3("%s: no challenge", __func__);
712545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
713545d5ecaSDag-Erling Smørgrav 		return (-1);
714545d5ecaSDag-Erling Smørgrav 	}
715545d5ecaSDag-Erling Smørgrav 
716545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
717545d5ecaSDag-Erling Smørgrav 	challenge  = buffer_get_string(&m, NULL);
718545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
719545d5ecaSDag-Erling Smørgrav 
720545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
721545d5ecaSDag-Erling Smørgrav 	(*prompts)[0] = challenge;
722545d5ecaSDag-Erling Smørgrav 
723545d5ecaSDag-Erling Smørgrav 	debug3("%s: received challenge: %s", __func__, challenge);
724545d5ecaSDag-Erling Smørgrav 
725545d5ecaSDag-Erling Smørgrav 	return (0);
726545d5ecaSDag-Erling Smørgrav }
727545d5ecaSDag-Erling Smørgrav 
728545d5ecaSDag-Erling Smørgrav int
729545d5ecaSDag-Erling Smørgrav mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
730545d5ecaSDag-Erling Smørgrav {
731545d5ecaSDag-Erling Smørgrav 	Buffer m;
732545d5ecaSDag-Erling Smørgrav 	int authok;
733545d5ecaSDag-Erling Smørgrav 
734545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
735545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
736545d5ecaSDag-Erling Smørgrav 		return (-1);
737545d5ecaSDag-Erling Smørgrav 
738545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
739545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, responses[0]);
740545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
741545d5ecaSDag-Erling Smørgrav 
742545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
743545d5ecaSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHRESPOND, &m);
744545d5ecaSDag-Erling Smørgrav 
745545d5ecaSDag-Erling Smørgrav 	authok = buffer_get_int(&m);
746545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
747545d5ecaSDag-Erling Smørgrav 
748545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
749545d5ecaSDag-Erling Smørgrav }
750545d5ecaSDag-Erling Smørgrav 
751545d5ecaSDag-Erling Smørgrav int
752545d5ecaSDag-Erling Smørgrav mm_skey_query(void *ctx, char **name, char **infotxt,
753545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
754545d5ecaSDag-Erling Smørgrav {
755545d5ecaSDag-Erling Smørgrav 	Buffer m;
756545d5ecaSDag-Erling Smørgrav 	int len, res;
757545d5ecaSDag-Erling Smørgrav 	char *p, *challenge;
758545d5ecaSDag-Erling Smørgrav 
759545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
760545d5ecaSDag-Erling Smørgrav 
761545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
762545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
763545d5ecaSDag-Erling Smørgrav 
764545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
765545d5ecaSDag-Erling Smørgrav 	    &m);
766545d5ecaSDag-Erling Smørgrav 	res = buffer_get_int(&m);
767545d5ecaSDag-Erling Smørgrav 	if (res == -1) {
768545d5ecaSDag-Erling Smørgrav 		debug3("%s: no challenge", __func__);
769545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
770545d5ecaSDag-Erling Smørgrav 		return (-1);
771545d5ecaSDag-Erling Smørgrav 	}
772545d5ecaSDag-Erling Smørgrav 
773545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
774545d5ecaSDag-Erling Smørgrav 	challenge  = buffer_get_string(&m, NULL);
775545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
776545d5ecaSDag-Erling Smørgrav 
777545d5ecaSDag-Erling Smørgrav 	debug3("%s: received challenge: %s", __func__, challenge);
778545d5ecaSDag-Erling Smørgrav 
779545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
780545d5ecaSDag-Erling Smørgrav 
781545d5ecaSDag-Erling Smørgrav 	len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
782545d5ecaSDag-Erling Smørgrav 	p = xmalloc(len);
783545d5ecaSDag-Erling Smørgrav 	strlcpy(p, challenge, len);
784545d5ecaSDag-Erling Smørgrav 	strlcat(p, SKEY_PROMPT, len);
785545d5ecaSDag-Erling Smørgrav 	(*prompts)[0] = p;
786545d5ecaSDag-Erling Smørgrav 	xfree(challenge);
787545d5ecaSDag-Erling Smørgrav 
788545d5ecaSDag-Erling Smørgrav 	return (0);
789545d5ecaSDag-Erling Smørgrav }
790545d5ecaSDag-Erling Smørgrav 
791545d5ecaSDag-Erling Smørgrav int
792545d5ecaSDag-Erling Smørgrav mm_skey_respond(void *ctx, u_int numresponses, char **responses)
793545d5ecaSDag-Erling Smørgrav {
794545d5ecaSDag-Erling Smørgrav 	Buffer m;
795545d5ecaSDag-Erling Smørgrav 	int authok;
796545d5ecaSDag-Erling Smørgrav 
797545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
798545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
799545d5ecaSDag-Erling Smørgrav 		return (-1);
800545d5ecaSDag-Erling Smørgrav 
801545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
802545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, responses[0]);
803545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
804545d5ecaSDag-Erling Smørgrav 
805545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
806545d5ecaSDag-Erling Smørgrav 	    MONITOR_ANS_SKEYRESPOND, &m);
807545d5ecaSDag-Erling Smørgrav 
808545d5ecaSDag-Erling Smørgrav 	authok = buffer_get_int(&m);
809545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
810545d5ecaSDag-Erling Smørgrav 
811545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
812545d5ecaSDag-Erling Smørgrav }
813545d5ecaSDag-Erling Smørgrav 
814545d5ecaSDag-Erling Smørgrav void
815545d5ecaSDag-Erling Smørgrav mm_ssh1_session_id(u_char session_id[16])
816545d5ecaSDag-Erling Smørgrav {
817545d5ecaSDag-Erling Smørgrav 	Buffer m;
818545d5ecaSDag-Erling Smørgrav 	int i;
819545d5ecaSDag-Erling Smørgrav 
820545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
821545d5ecaSDag-Erling Smørgrav 
822545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
823545d5ecaSDag-Erling Smørgrav 	for (i = 0; i < 16; i++)
824545d5ecaSDag-Erling Smørgrav 		buffer_put_char(&m, session_id[i]);
825545d5ecaSDag-Erling Smørgrav 
826545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
827545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
828545d5ecaSDag-Erling Smørgrav }
829545d5ecaSDag-Erling Smørgrav 
830545d5ecaSDag-Erling Smørgrav int
831545d5ecaSDag-Erling Smørgrav mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
832545d5ecaSDag-Erling Smørgrav {
833545d5ecaSDag-Erling Smørgrav 	Buffer m;
834545d5ecaSDag-Erling Smørgrav 	Key *key;
835545d5ecaSDag-Erling Smørgrav 	u_char *blob;
836545d5ecaSDag-Erling Smørgrav 	u_int blen;
837545d5ecaSDag-Erling Smørgrav 	int allowed = 0;
838545d5ecaSDag-Erling Smørgrav 
839545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
840545d5ecaSDag-Erling Smørgrav 
841545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
842545d5ecaSDag-Erling Smørgrav 	buffer_put_bignum2(&m, client_n);
843545d5ecaSDag-Erling Smørgrav 
844545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
845545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
846545d5ecaSDag-Erling Smørgrav 
847545d5ecaSDag-Erling Smørgrav 	allowed = buffer_get_int(&m);
848545d5ecaSDag-Erling Smørgrav 
849545d5ecaSDag-Erling Smørgrav 	if (allowed && rkey != NULL) {
850545d5ecaSDag-Erling Smørgrav 		blob = buffer_get_string(&m, &blen);
851545d5ecaSDag-Erling Smørgrav 		if ((key = key_from_blob(blob, blen)) == NULL)
852545d5ecaSDag-Erling Smørgrav 			fatal("%s: key_from_blob failed", __func__);
853545d5ecaSDag-Erling Smørgrav 		*rkey = key;
854545d5ecaSDag-Erling Smørgrav 		xfree(blob);
855545d5ecaSDag-Erling Smørgrav 	}
856545d5ecaSDag-Erling Smørgrav 	mm_send_debug(&m);
857545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
858545d5ecaSDag-Erling Smørgrav 
859545d5ecaSDag-Erling Smørgrav 	return (allowed);
860545d5ecaSDag-Erling Smørgrav }
861545d5ecaSDag-Erling Smørgrav 
862545d5ecaSDag-Erling Smørgrav BIGNUM *
863545d5ecaSDag-Erling Smørgrav mm_auth_rsa_generate_challenge(Key *key)
864545d5ecaSDag-Erling Smørgrav {
865545d5ecaSDag-Erling Smørgrav 	Buffer m;
866545d5ecaSDag-Erling Smørgrav 	BIGNUM *challenge;
867545d5ecaSDag-Erling Smørgrav 	u_char *blob;
868545d5ecaSDag-Erling Smørgrav 	u_int blen;
869545d5ecaSDag-Erling Smørgrav 
870545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
871545d5ecaSDag-Erling Smørgrav 
872545d5ecaSDag-Erling Smørgrav 	if ((challenge = BN_new()) == NULL)
873545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
874545d5ecaSDag-Erling Smørgrav 
875545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
876545d5ecaSDag-Erling Smørgrav 	if (key_to_blob(key, &blob, &blen) == 0)
877545d5ecaSDag-Erling Smørgrav 		fatal("%s: key_to_blob failed", __func__);
878545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
879545d5ecaSDag-Erling Smørgrav 
880545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
881545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, blen);
882545d5ecaSDag-Erling Smørgrav 	xfree(blob);
883545d5ecaSDag-Erling Smørgrav 
884545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
885545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
886545d5ecaSDag-Erling Smørgrav 
887545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, challenge);
888545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
889545d5ecaSDag-Erling Smørgrav 
890545d5ecaSDag-Erling Smørgrav 	return (challenge);
891545d5ecaSDag-Erling Smørgrav }
892545d5ecaSDag-Erling Smørgrav 
893545d5ecaSDag-Erling Smørgrav int
894545d5ecaSDag-Erling Smørgrav mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
895545d5ecaSDag-Erling Smørgrav {
896545d5ecaSDag-Erling Smørgrav 	Buffer m;
897545d5ecaSDag-Erling Smørgrav 	u_char *blob;
898545d5ecaSDag-Erling Smørgrav 	u_int blen;
899545d5ecaSDag-Erling Smørgrav 	int success = 0;
900545d5ecaSDag-Erling Smørgrav 
901545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
902545d5ecaSDag-Erling Smørgrav 
903545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
904545d5ecaSDag-Erling Smørgrav 	if (key_to_blob(key, &blob, &blen) == 0)
905545d5ecaSDag-Erling Smørgrav 		fatal("%s: key_to_blob failed", __func__);
906545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
907545d5ecaSDag-Erling Smørgrav 
908545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
909545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, blen);
910545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, response, 16);
911545d5ecaSDag-Erling Smørgrav 	xfree(blob);
912545d5ecaSDag-Erling Smørgrav 
913545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
914545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
915545d5ecaSDag-Erling Smørgrav 
916545d5ecaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
917545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
918545d5ecaSDag-Erling Smørgrav 
919545d5ecaSDag-Erling Smørgrav 	return (success);
920545d5ecaSDag-Erling Smørgrav }
921