xref: /freebsd/crypto/openssh/monitor_wrap.c (revision e4a9863fb76a1f6b16ecbcbd31e88f4ad9a9565e)
1*e4a9863fSDag-Erling Smørgrav /* $OpenBSD: monitor_wrap.c,v 1.76 2013/05/17 00:13:13 djm Exp $ */
2545d5ecaSDag-Erling Smørgrav /*
3545d5ecaSDag-Erling Smørgrav  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4545d5ecaSDag-Erling Smørgrav  * Copyright 2002 Markus Friedl <markus@openbsd.org>
5545d5ecaSDag-Erling Smørgrav  * All rights reserved.
6545d5ecaSDag-Erling Smørgrav  *
7545d5ecaSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
8545d5ecaSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
9545d5ecaSDag-Erling Smørgrav  * are met:
10545d5ecaSDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
11545d5ecaSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
12545d5ecaSDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
13545d5ecaSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
14545d5ecaSDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
15545d5ecaSDag-Erling Smørgrav  *
16545d5ecaSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17545d5ecaSDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18545d5ecaSDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19545d5ecaSDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20545d5ecaSDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21545d5ecaSDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22545d5ecaSDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23545d5ecaSDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24545d5ecaSDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25545d5ecaSDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26545d5ecaSDag-Erling Smørgrav  */
27545d5ecaSDag-Erling Smørgrav 
28545d5ecaSDag-Erling Smørgrav #include "includes.h"
29333ee039SDag-Erling Smørgrav 
30333ee039SDag-Erling Smørgrav #include <sys/types.h>
31333ee039SDag-Erling Smørgrav #include <sys/uio.h>
32333ee039SDag-Erling Smørgrav 
33333ee039SDag-Erling Smørgrav #include <errno.h>
34333ee039SDag-Erling Smørgrav #include <pwd.h>
35333ee039SDag-Erling Smørgrav #include <signal.h>
36333ee039SDag-Erling Smørgrav #include <stdarg.h>
37333ee039SDag-Erling Smørgrav #include <stdio.h>
38333ee039SDag-Erling Smørgrav #include <string.h>
39333ee039SDag-Erling Smørgrav #include <unistd.h>
40545d5ecaSDag-Erling Smørgrav 
41545d5ecaSDag-Erling Smørgrav #include <openssl/bn.h>
42545d5ecaSDag-Erling Smørgrav #include <openssl/dh.h>
43cce7d346SDag-Erling Smørgrav #include <openssl/evp.h>
44545d5ecaSDag-Erling Smørgrav 
45d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h"
46333ee039SDag-Erling Smørgrav #include "xmalloc.h"
47545d5ecaSDag-Erling Smørgrav #include "ssh.h"
48545d5ecaSDag-Erling Smørgrav #include "dh.h"
49333ee039SDag-Erling Smørgrav #include "buffer.h"
50333ee039SDag-Erling Smørgrav #include "key.h"
51333ee039SDag-Erling Smørgrav #include "cipher.h"
52545d5ecaSDag-Erling Smørgrav #include "kex.h"
53333ee039SDag-Erling Smørgrav #include "hostfile.h"
54545d5ecaSDag-Erling Smørgrav #include "auth.h"
55e73e9afaSDag-Erling Smørgrav #include "auth-options.h"
56545d5ecaSDag-Erling Smørgrav #include "packet.h"
57545d5ecaSDag-Erling Smørgrav #include "mac.h"
58545d5ecaSDag-Erling Smørgrav #include "log.h"
595962c0e9SDag-Erling Smørgrav #ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
605962c0e9SDag-Erling Smørgrav #undef TARGET_OS_MAC
61545d5ecaSDag-Erling Smørgrav #include "zlib.h"
625962c0e9SDag-Erling Smørgrav #define TARGET_OS_MAC 1
635962c0e9SDag-Erling Smørgrav #else
645962c0e9SDag-Erling Smørgrav #include "zlib.h"
655962c0e9SDag-Erling Smørgrav #endif
66545d5ecaSDag-Erling Smørgrav #include "monitor.h"
67cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
68cf2b5f3bSDag-Erling Smørgrav #include "ssh-gss.h"
69cf2b5f3bSDag-Erling Smørgrav #endif
70333ee039SDag-Erling Smørgrav #include "monitor_wrap.h"
71333ee039SDag-Erling Smørgrav #include "atomicio.h"
72333ee039SDag-Erling Smørgrav #include "monitor_fdpass.h"
73333ee039SDag-Erling Smørgrav #include "misc.h"
747aee6ffeSDag-Erling Smørgrav #include "schnorr.h"
75cce7d346SDag-Erling Smørgrav #include "jpake.h"
764a421b63SDag-Erling Smørgrav #include "uuencode.h"
77333ee039SDag-Erling Smørgrav 
78333ee039SDag-Erling Smørgrav #include "channels.h"
79333ee039SDag-Erling Smørgrav #include "session.h"
80d4af9e69SDag-Erling Smørgrav #include "servconf.h"
817aee6ffeSDag-Erling Smørgrav #include "roaming.h"
82cf2b5f3bSDag-Erling Smørgrav 
83545d5ecaSDag-Erling Smørgrav /* Imports */
84545d5ecaSDag-Erling Smørgrav extern int compat20;
85545d5ecaSDag-Erling Smørgrav extern z_stream incoming_stream;
86545d5ecaSDag-Erling Smørgrav extern z_stream outgoing_stream;
87545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor;
8821e764dfSDag-Erling Smørgrav extern Buffer loginmsg;
89cf2b5f3bSDag-Erling Smørgrav extern ServerOptions options;
90545d5ecaSDag-Erling Smørgrav 
91e146993eSDag-Erling Smørgrav void
92e146993eSDag-Erling Smørgrav mm_log_handler(LogLevel level, const char *msg, void *ctx)
93e146993eSDag-Erling Smørgrav {
94e146993eSDag-Erling Smørgrav 	Buffer log_msg;
95e146993eSDag-Erling Smørgrav 	struct monitor *mon = (struct monitor *)ctx;
96e146993eSDag-Erling Smørgrav 
97e146993eSDag-Erling Smørgrav 	if (mon->m_log_sendfd == -1)
98e146993eSDag-Erling Smørgrav 		fatal("%s: no log channel", __func__);
99e146993eSDag-Erling Smørgrav 
100e146993eSDag-Erling Smørgrav 	buffer_init(&log_msg);
101e146993eSDag-Erling Smørgrav 	/*
102e146993eSDag-Erling Smørgrav 	 * Placeholder for packet length. Will be filled in with the actual
103e146993eSDag-Erling Smørgrav 	 * packet length once the packet has been constucted. This saves
104e146993eSDag-Erling Smørgrav 	 * fragile math.
105e146993eSDag-Erling Smørgrav 	 */
106e146993eSDag-Erling Smørgrav 	buffer_put_int(&log_msg, 0);
107e146993eSDag-Erling Smørgrav 
108e146993eSDag-Erling Smørgrav 	buffer_put_int(&log_msg, level);
109e146993eSDag-Erling Smørgrav 	buffer_put_cstring(&log_msg, msg);
110e146993eSDag-Erling Smørgrav 	put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
111e146993eSDag-Erling Smørgrav 	if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
112e146993eSDag-Erling Smørgrav 	    buffer_len(&log_msg)) != buffer_len(&log_msg))
113e146993eSDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
114e146993eSDag-Erling Smørgrav 	buffer_free(&log_msg);
115e146993eSDag-Erling Smørgrav }
116e146993eSDag-Erling Smørgrav 
1171ec0d754SDag-Erling Smørgrav int
1181ec0d754SDag-Erling Smørgrav mm_is_monitor(void)
1191ec0d754SDag-Erling Smørgrav {
1201ec0d754SDag-Erling Smørgrav 	/*
1211ec0d754SDag-Erling Smørgrav 	 * m_pid is only set in the privileged part, and
1221ec0d754SDag-Erling Smørgrav 	 * points to the unprivileged child.
1231ec0d754SDag-Erling Smørgrav 	 */
1241ec0d754SDag-Erling Smørgrav 	return (pmonitor && pmonitor->m_pid > 0);
1251ec0d754SDag-Erling Smørgrav }
1261ec0d754SDag-Erling Smørgrav 
127545d5ecaSDag-Erling Smørgrav void
12821e764dfSDag-Erling Smørgrav mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
129545d5ecaSDag-Erling Smørgrav {
130545d5ecaSDag-Erling Smørgrav 	u_int mlen = buffer_len(m);
131f388f5efSDag-Erling Smørgrav 	u_char buf[5];
132545d5ecaSDag-Erling Smørgrav 
133545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
134545d5ecaSDag-Erling Smørgrav 
135333ee039SDag-Erling Smørgrav 	put_u32(buf, mlen + 1);
136545d5ecaSDag-Erling Smørgrav 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
13721e764dfSDag-Erling Smørgrav 	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
138d4ecd108SDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
13921e764dfSDag-Erling Smørgrav 	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
140d4ecd108SDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
141545d5ecaSDag-Erling Smørgrav }
142545d5ecaSDag-Erling Smørgrav 
143545d5ecaSDag-Erling Smørgrav void
14421e764dfSDag-Erling Smørgrav mm_request_receive(int sock, Buffer *m)
145545d5ecaSDag-Erling Smørgrav {
146545d5ecaSDag-Erling Smørgrav 	u_char buf[4];
147545d5ecaSDag-Erling Smørgrav 	u_int msg_len;
148545d5ecaSDag-Erling Smørgrav 
149545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
150545d5ecaSDag-Erling Smørgrav 
151d4ecd108SDag-Erling Smørgrav 	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
152d4ecd108SDag-Erling Smørgrav 		if (errno == EPIPE)
1531ec0d754SDag-Erling Smørgrav 			cleanup_exit(255);
154d4ecd108SDag-Erling Smørgrav 		fatal("%s: read: %s", __func__, strerror(errno));
155545d5ecaSDag-Erling Smørgrav 	}
156333ee039SDag-Erling Smørgrav 	msg_len = get_u32(buf);
157545d5ecaSDag-Erling Smørgrav 	if (msg_len > 256 * 1024)
158545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: bad msg_len %d", __func__, msg_len);
159545d5ecaSDag-Erling Smørgrav 	buffer_clear(m);
160545d5ecaSDag-Erling Smørgrav 	buffer_append_space(m, msg_len);
161d4ecd108SDag-Erling Smørgrav 	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
162d4ecd108SDag-Erling Smørgrav 		fatal("%s: read: %s", __func__, strerror(errno));
163545d5ecaSDag-Erling Smørgrav }
164545d5ecaSDag-Erling Smørgrav 
165545d5ecaSDag-Erling Smørgrav void
16621e764dfSDag-Erling Smørgrav mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
167545d5ecaSDag-Erling Smørgrav {
168545d5ecaSDag-Erling Smørgrav 	u_char rtype;
169545d5ecaSDag-Erling Smørgrav 
170545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
171545d5ecaSDag-Erling Smørgrav 
17221e764dfSDag-Erling Smørgrav 	mm_request_receive(sock, m);
173545d5ecaSDag-Erling Smørgrav 	rtype = buffer_get_char(m);
174545d5ecaSDag-Erling Smørgrav 	if (rtype != type)
175545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: rtype %d != type %d", __func__,
176545d5ecaSDag-Erling Smørgrav 		    rtype, type);
177545d5ecaSDag-Erling Smørgrav }
178545d5ecaSDag-Erling Smørgrav 
179545d5ecaSDag-Erling Smørgrav DH *
180545d5ecaSDag-Erling Smørgrav mm_choose_dh(int min, int nbits, int max)
181545d5ecaSDag-Erling Smørgrav {
182545d5ecaSDag-Erling Smørgrav 	BIGNUM *p, *g;
183545d5ecaSDag-Erling Smørgrav 	int success = 0;
184545d5ecaSDag-Erling Smørgrav 	Buffer m;
185545d5ecaSDag-Erling Smørgrav 
186545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
187545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, min);
188545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, nbits);
189545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, max);
190545d5ecaSDag-Erling Smørgrav 
191545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
192545d5ecaSDag-Erling Smørgrav 
193545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
194545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
195545d5ecaSDag-Erling Smørgrav 
196545d5ecaSDag-Erling Smørgrav 	success = buffer_get_char(&m);
197545d5ecaSDag-Erling Smørgrav 	if (success == 0)
198545d5ecaSDag-Erling Smørgrav 		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
199545d5ecaSDag-Erling Smørgrav 
200545d5ecaSDag-Erling Smørgrav 	if ((p = BN_new()) == NULL)
201545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
202545d5ecaSDag-Erling Smørgrav 	if ((g = BN_new()) == NULL)
203545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
204545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, p);
205545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, g);
206545d5ecaSDag-Erling Smørgrav 
207545d5ecaSDag-Erling Smørgrav 	debug3("%s: remaining %d", __func__, buffer_len(&m));
208545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
209545d5ecaSDag-Erling Smørgrav 
210545d5ecaSDag-Erling Smørgrav 	return (dh_new_group(g, p));
211545d5ecaSDag-Erling Smørgrav }
212545d5ecaSDag-Erling Smørgrav 
213545d5ecaSDag-Erling Smørgrav int
214545d5ecaSDag-Erling Smørgrav mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
215545d5ecaSDag-Erling Smørgrav {
216545d5ecaSDag-Erling Smørgrav 	Kex *kex = *pmonitor->m_pkex;
217545d5ecaSDag-Erling Smørgrav 	Buffer m;
218545d5ecaSDag-Erling Smørgrav 
219545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
220545d5ecaSDag-Erling Smørgrav 
221545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
222545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, kex->host_key_index(key));
223545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, data, datalen);
224545d5ecaSDag-Erling Smørgrav 
225545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
226545d5ecaSDag-Erling Smørgrav 
227545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
228545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
229545d5ecaSDag-Erling Smørgrav 	*sigp  = buffer_get_string(&m, lenp);
230545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
231545d5ecaSDag-Erling Smørgrav 
232545d5ecaSDag-Erling Smørgrav 	return (0);
233545d5ecaSDag-Erling Smørgrav }
234545d5ecaSDag-Erling Smørgrav 
235545d5ecaSDag-Erling Smørgrav struct passwd *
23621e764dfSDag-Erling Smørgrav mm_getpwnamallow(const char *username)
237545d5ecaSDag-Erling Smørgrav {
238545d5ecaSDag-Erling Smørgrav 	Buffer m;
239545d5ecaSDag-Erling Smørgrav 	struct passwd *pw;
240e146993eSDag-Erling Smørgrav 	u_int len, i;
241d4af9e69SDag-Erling Smørgrav 	ServerOptions *newopts;
242545d5ecaSDag-Erling Smørgrav 
243545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
244545d5ecaSDag-Erling Smørgrav 
245545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
24621e764dfSDag-Erling Smørgrav 	buffer_put_cstring(&m, username);
247545d5ecaSDag-Erling Smørgrav 
248545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
249545d5ecaSDag-Erling Smørgrav 
250545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
251545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
252545d5ecaSDag-Erling Smørgrav 
253545d5ecaSDag-Erling Smørgrav 	if (buffer_get_char(&m) == 0) {
254d4af9e69SDag-Erling Smørgrav 		pw = NULL;
255d4af9e69SDag-Erling Smørgrav 		goto out;
256545d5ecaSDag-Erling Smørgrav 	}
257d4af9e69SDag-Erling Smørgrav 	pw = buffer_get_string(&m, &len);
258d4af9e69SDag-Erling Smørgrav 	if (len != sizeof(struct passwd))
259545d5ecaSDag-Erling Smørgrav 		fatal("%s: struct passwd size mismatch", __func__);
260545d5ecaSDag-Erling Smørgrav 	pw->pw_name = buffer_get_string(&m, NULL);
261545d5ecaSDag-Erling Smørgrav 	pw->pw_passwd = buffer_get_string(&m, NULL);
262*e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
263545d5ecaSDag-Erling Smørgrav 	pw->pw_gecos = buffer_get_string(&m, NULL);
264*e4a9863fSDag-Erling Smørgrav #endif
265*e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
266545d5ecaSDag-Erling Smørgrav 	pw->pw_class = buffer_get_string(&m, NULL);
26783d2307dSDag-Erling Smørgrav #endif
268545d5ecaSDag-Erling Smørgrav 	pw->pw_dir = buffer_get_string(&m, NULL);
269545d5ecaSDag-Erling Smørgrav 	pw->pw_shell = buffer_get_string(&m, NULL);
270d4af9e69SDag-Erling Smørgrav 
271d4af9e69SDag-Erling Smørgrav out:
272d4af9e69SDag-Erling Smørgrav 	/* copy options block as a Match directive may have changed some */
273d4af9e69SDag-Erling Smørgrav 	newopts = buffer_get_string(&m, &len);
274d4af9e69SDag-Erling Smørgrav 	if (len != sizeof(*newopts))
275d4af9e69SDag-Erling Smørgrav 		fatal("%s: option block size mismatch", __func__);
276e146993eSDag-Erling Smørgrav 
277e146993eSDag-Erling Smørgrav #define M_CP_STROPT(x) do { \
278e146993eSDag-Erling Smørgrav 		if (newopts->x != NULL) \
279e146993eSDag-Erling Smørgrav 			newopts->x = buffer_get_string(&m, NULL); \
280e146993eSDag-Erling Smørgrav 	} while (0)
281e146993eSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(x, nx) do { \
282e146993eSDag-Erling Smørgrav 		for (i = 0; i < newopts->nx; i++) \
283e146993eSDag-Erling Smørgrav 			newopts->x[i] = buffer_get_string(&m, NULL); \
284e146993eSDag-Erling Smørgrav 	} while (0)
285e146993eSDag-Erling Smørgrav 	/* See comment in servconf.h */
286e146993eSDag-Erling Smørgrav 	COPY_MATCH_STRING_OPTS();
287e146993eSDag-Erling Smørgrav #undef M_CP_STROPT
288e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT
289e146993eSDag-Erling Smørgrav 
290d4af9e69SDag-Erling Smørgrav 	copy_set_server_options(&options, newopts, 1);
291*e4a9863fSDag-Erling Smørgrav 	free(newopts);
292d4af9e69SDag-Erling Smørgrav 
293545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
294545d5ecaSDag-Erling Smørgrav 
295545d5ecaSDag-Erling Smørgrav 	return (pw);
296545d5ecaSDag-Erling Smørgrav }
297545d5ecaSDag-Erling Smørgrav 
2981ec0d754SDag-Erling Smørgrav char *
2991ec0d754SDag-Erling Smørgrav mm_auth2_read_banner(void)
300545d5ecaSDag-Erling Smørgrav {
301545d5ecaSDag-Erling Smørgrav 	Buffer m;
302545d5ecaSDag-Erling Smørgrav 	char *banner;
303545d5ecaSDag-Erling Smørgrav 
304545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
305545d5ecaSDag-Erling Smørgrav 
306545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
307545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
308545d5ecaSDag-Erling Smørgrav 	buffer_clear(&m);
309545d5ecaSDag-Erling Smørgrav 
3101ec0d754SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
3111ec0d754SDag-Erling Smørgrav 	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
312545d5ecaSDag-Erling Smørgrav 	banner = buffer_get_string(&m, NULL);
313545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
314545d5ecaSDag-Erling Smørgrav 
3151ec0d754SDag-Erling Smørgrav 	/* treat empty banner as missing banner */
3161ec0d754SDag-Erling Smørgrav 	if (strlen(banner) == 0) {
317*e4a9863fSDag-Erling Smørgrav 		free(banner);
3181ec0d754SDag-Erling Smørgrav 		banner = NULL;
3191ec0d754SDag-Erling Smørgrav 	}
320545d5ecaSDag-Erling Smørgrav 	return (banner);
321545d5ecaSDag-Erling Smørgrav }
322545d5ecaSDag-Erling Smørgrav 
323545d5ecaSDag-Erling Smørgrav /* Inform the privileged process about service and style */
324545d5ecaSDag-Erling Smørgrav 
325545d5ecaSDag-Erling Smørgrav void
326545d5ecaSDag-Erling Smørgrav mm_inform_authserv(char *service, char *style)
327545d5ecaSDag-Erling Smørgrav {
328545d5ecaSDag-Erling Smørgrav 	Buffer m;
329545d5ecaSDag-Erling Smørgrav 
330545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
331545d5ecaSDag-Erling Smørgrav 
332545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
333545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, service);
334545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, style ? style : "");
335545d5ecaSDag-Erling Smørgrav 
336545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
337545d5ecaSDag-Erling Smørgrav 
338545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
339545d5ecaSDag-Erling Smørgrav }
340545d5ecaSDag-Erling Smørgrav 
341545d5ecaSDag-Erling Smørgrav /* Do the password authentication */
342545d5ecaSDag-Erling Smørgrav int
343545d5ecaSDag-Erling Smørgrav mm_auth_password(Authctxt *authctxt, char *password)
344545d5ecaSDag-Erling Smørgrav {
345545d5ecaSDag-Erling Smørgrav 	Buffer m;
346545d5ecaSDag-Erling Smørgrav 	int authenticated = 0;
347545d5ecaSDag-Erling Smørgrav 
348545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
349545d5ecaSDag-Erling Smørgrav 
350545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
351545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, password);
352545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
353545d5ecaSDag-Erling Smørgrav 
354545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
355545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
356545d5ecaSDag-Erling Smørgrav 
357545d5ecaSDag-Erling Smørgrav 	authenticated = buffer_get_int(&m);
358545d5ecaSDag-Erling Smørgrav 
359545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
360545d5ecaSDag-Erling Smørgrav 
361545d5ecaSDag-Erling Smørgrav 	debug3("%s: user %sauthenticated",
362545d5ecaSDag-Erling Smørgrav 	    __func__, authenticated ? "" : "not ");
363545d5ecaSDag-Erling Smørgrav 	return (authenticated);
364545d5ecaSDag-Erling Smørgrav }
365545d5ecaSDag-Erling Smørgrav 
366545d5ecaSDag-Erling Smørgrav int
367545d5ecaSDag-Erling Smørgrav mm_user_key_allowed(struct passwd *pw, Key *key)
368545d5ecaSDag-Erling Smørgrav {
369545d5ecaSDag-Erling Smørgrav 	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
370545d5ecaSDag-Erling Smørgrav }
371545d5ecaSDag-Erling Smørgrav 
372545d5ecaSDag-Erling Smørgrav int
373545d5ecaSDag-Erling Smørgrav mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
374545d5ecaSDag-Erling Smørgrav     Key *key)
375545d5ecaSDag-Erling Smørgrav {
376545d5ecaSDag-Erling Smørgrav 	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
377545d5ecaSDag-Erling Smørgrav }
378545d5ecaSDag-Erling Smørgrav 
379545d5ecaSDag-Erling Smørgrav int
380545d5ecaSDag-Erling Smørgrav mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
381545d5ecaSDag-Erling Smørgrav     char *host, Key *key)
382545d5ecaSDag-Erling Smørgrav {
383545d5ecaSDag-Erling Smørgrav 	int ret;
384545d5ecaSDag-Erling Smørgrav 
385545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA; /* XXX hack for key_to_blob */
386545d5ecaSDag-Erling Smørgrav 	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
387545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
388545d5ecaSDag-Erling Smørgrav 	return (ret);
389545d5ecaSDag-Erling Smørgrav }
390545d5ecaSDag-Erling Smørgrav 
391545d5ecaSDag-Erling Smørgrav int
392545d5ecaSDag-Erling Smørgrav mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
393545d5ecaSDag-Erling Smørgrav {
394545d5ecaSDag-Erling Smørgrav 	Buffer m;
395545d5ecaSDag-Erling Smørgrav 	u_char *blob;
396545d5ecaSDag-Erling Smørgrav 	u_int len;
397e73e9afaSDag-Erling Smørgrav 	int allowed = 0, have_forced = 0;
398545d5ecaSDag-Erling Smørgrav 
399545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
400545d5ecaSDag-Erling Smørgrav 
401545d5ecaSDag-Erling Smørgrav 	/* Convert the key to a blob and the pass it over */
402545d5ecaSDag-Erling Smørgrav 	if (!key_to_blob(key, &blob, &len))
403545d5ecaSDag-Erling Smørgrav 		return (0);
404545d5ecaSDag-Erling Smørgrav 
405545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
406545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&m, type);
407545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, user ? user : "");
408545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, host ? host : "");
409545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, len);
410*e4a9863fSDag-Erling Smørgrav 	free(blob);
411545d5ecaSDag-Erling Smørgrav 
412545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
413545d5ecaSDag-Erling Smørgrav 
414545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
415545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
416545d5ecaSDag-Erling Smørgrav 
417545d5ecaSDag-Erling Smørgrav 	allowed = buffer_get_int(&m);
418545d5ecaSDag-Erling Smørgrav 
419e73e9afaSDag-Erling Smørgrav 	/* fake forced command */
420e73e9afaSDag-Erling Smørgrav 	auth_clear_options();
421e73e9afaSDag-Erling Smørgrav 	have_forced = buffer_get_int(&m);
422e73e9afaSDag-Erling Smørgrav 	forced_command = have_forced ? xstrdup("true") : NULL;
423e73e9afaSDag-Erling Smørgrav 
424545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
425545d5ecaSDag-Erling Smørgrav 
426545d5ecaSDag-Erling Smørgrav 	return (allowed);
427545d5ecaSDag-Erling Smørgrav }
428545d5ecaSDag-Erling Smørgrav 
429545d5ecaSDag-Erling Smørgrav /*
430545d5ecaSDag-Erling Smørgrav  * This key verify needs to send the key type along, because the
431545d5ecaSDag-Erling Smørgrav  * privileged parent makes the decision if the key is allowed
432545d5ecaSDag-Erling Smørgrav  * for authentication.
433545d5ecaSDag-Erling Smørgrav  */
434545d5ecaSDag-Erling Smørgrav 
435545d5ecaSDag-Erling Smørgrav int
436545d5ecaSDag-Erling Smørgrav mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
437545d5ecaSDag-Erling Smørgrav {
438545d5ecaSDag-Erling Smørgrav 	Buffer m;
439545d5ecaSDag-Erling Smørgrav 	u_char *blob;
440545d5ecaSDag-Erling Smørgrav 	u_int len;
441545d5ecaSDag-Erling Smørgrav 	int verified = 0;
442545d5ecaSDag-Erling Smørgrav 
443545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
444545d5ecaSDag-Erling Smørgrav 
445545d5ecaSDag-Erling Smørgrav 	/* Convert the key to a blob and the pass it over */
446545d5ecaSDag-Erling Smørgrav 	if (!key_to_blob(key, &blob, &len))
447545d5ecaSDag-Erling Smørgrav 		return (0);
448545d5ecaSDag-Erling Smørgrav 
449545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
450545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, len);
451545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, sig, siglen);
452545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, data, datalen);
453*e4a9863fSDag-Erling Smørgrav 	free(blob);
454545d5ecaSDag-Erling Smørgrav 
455545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
456545d5ecaSDag-Erling Smørgrav 
457545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
458545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
459545d5ecaSDag-Erling Smørgrav 
460545d5ecaSDag-Erling Smørgrav 	verified = buffer_get_int(&m);
461545d5ecaSDag-Erling Smørgrav 
462545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
463545d5ecaSDag-Erling Smørgrav 
464545d5ecaSDag-Erling Smørgrav 	return (verified);
465545d5ecaSDag-Erling Smørgrav }
466545d5ecaSDag-Erling Smørgrav 
467545d5ecaSDag-Erling Smørgrav /* Export key state after authentication */
468545d5ecaSDag-Erling Smørgrav Newkeys *
469545d5ecaSDag-Erling Smørgrav mm_newkeys_from_blob(u_char *blob, int blen)
470545d5ecaSDag-Erling Smørgrav {
471545d5ecaSDag-Erling Smørgrav 	Buffer b;
472545d5ecaSDag-Erling Smørgrav 	u_int len;
473545d5ecaSDag-Erling Smørgrav 	Newkeys *newkey = NULL;
474545d5ecaSDag-Erling Smørgrav 	Enc *enc;
475545d5ecaSDag-Erling Smørgrav 	Mac *mac;
476545d5ecaSDag-Erling Smørgrav 	Comp *comp;
477545d5ecaSDag-Erling Smørgrav 
478545d5ecaSDag-Erling Smørgrav 	debug3("%s: %p(%d)", __func__, blob, blen);
479545d5ecaSDag-Erling Smørgrav #ifdef DEBUG_PK
480545d5ecaSDag-Erling Smørgrav 	dump_base64(stderr, blob, blen);
481545d5ecaSDag-Erling Smørgrav #endif
482545d5ecaSDag-Erling Smørgrav 	buffer_init(&b);
483545d5ecaSDag-Erling Smørgrav 	buffer_append(&b, blob, blen);
484545d5ecaSDag-Erling Smørgrav 
485545d5ecaSDag-Erling Smørgrav 	newkey = xmalloc(sizeof(*newkey));
486545d5ecaSDag-Erling Smørgrav 	enc = &newkey->enc;
487545d5ecaSDag-Erling Smørgrav 	mac = &newkey->mac;
488545d5ecaSDag-Erling Smørgrav 	comp = &newkey->comp;
489545d5ecaSDag-Erling Smørgrav 
490545d5ecaSDag-Erling Smørgrav 	/* Enc structure */
491545d5ecaSDag-Erling Smørgrav 	enc->name = buffer_get_string(&b, NULL);
492545d5ecaSDag-Erling Smørgrav 	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
493545d5ecaSDag-Erling Smørgrav 	enc->enabled = buffer_get_int(&b);
494545d5ecaSDag-Erling Smørgrav 	enc->block_size = buffer_get_int(&b);
495545d5ecaSDag-Erling Smørgrav 	enc->key = buffer_get_string(&b, &enc->key_len);
4966888a9beSDag-Erling Smørgrav 	enc->iv = buffer_get_string(&b, &enc->iv_len);
497545d5ecaSDag-Erling Smørgrav 
498545d5ecaSDag-Erling Smørgrav 	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
499545d5ecaSDag-Erling Smørgrav 		fatal("%s: bad cipher name %s or pointer %p", __func__,
500545d5ecaSDag-Erling Smørgrav 		    enc->name, enc->cipher);
501545d5ecaSDag-Erling Smørgrav 
502545d5ecaSDag-Erling Smørgrav 	/* Mac structure */
5036888a9beSDag-Erling Smørgrav 	if (cipher_authlen(enc->cipher) == 0) {
504545d5ecaSDag-Erling Smørgrav 		mac->name = buffer_get_string(&b, NULL);
505d4af9e69SDag-Erling Smørgrav 		if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
506d4af9e69SDag-Erling Smørgrav 			fatal("%s: can not setup mac %s", __func__, mac->name);
507545d5ecaSDag-Erling Smørgrav 		mac->enabled = buffer_get_int(&b);
508545d5ecaSDag-Erling Smørgrav 		mac->key = buffer_get_string(&b, &len);
509545d5ecaSDag-Erling Smørgrav 		if (len > mac->key_len)
510f388f5efSDag-Erling Smørgrav 			fatal("%s: bad mac key length: %u > %d", __func__, len,
511545d5ecaSDag-Erling Smørgrav 			    mac->key_len);
512545d5ecaSDag-Erling Smørgrav 		mac->key_len = len;
5136888a9beSDag-Erling Smørgrav 	}
514545d5ecaSDag-Erling Smørgrav 
515545d5ecaSDag-Erling Smørgrav 	/* Comp structure */
516545d5ecaSDag-Erling Smørgrav 	comp->type = buffer_get_int(&b);
517545d5ecaSDag-Erling Smørgrav 	comp->enabled = buffer_get_int(&b);
518545d5ecaSDag-Erling Smørgrav 	comp->name = buffer_get_string(&b, NULL);
519545d5ecaSDag-Erling Smørgrav 
520545d5ecaSDag-Erling Smørgrav 	len = buffer_len(&b);
521545d5ecaSDag-Erling Smørgrav 	if (len != 0)
522f388f5efSDag-Erling Smørgrav 		error("newkeys_from_blob: remaining bytes in blob %u", len);
523545d5ecaSDag-Erling Smørgrav 	buffer_free(&b);
524545d5ecaSDag-Erling Smørgrav 	return (newkey);
525545d5ecaSDag-Erling Smørgrav }
526545d5ecaSDag-Erling Smørgrav 
527545d5ecaSDag-Erling Smørgrav int
528545d5ecaSDag-Erling Smørgrav mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
529545d5ecaSDag-Erling Smørgrav {
530545d5ecaSDag-Erling Smørgrav 	Buffer b;
531545d5ecaSDag-Erling Smørgrav 	int len;
532545d5ecaSDag-Erling Smørgrav 	Enc *enc;
533545d5ecaSDag-Erling Smørgrav 	Mac *mac;
534545d5ecaSDag-Erling Smørgrav 	Comp *comp;
5357aee6ffeSDag-Erling Smørgrav 	Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
536545d5ecaSDag-Erling Smørgrav 
537545d5ecaSDag-Erling Smørgrav 	debug3("%s: converting %p", __func__, newkey);
538545d5ecaSDag-Erling Smørgrav 
539545d5ecaSDag-Erling Smørgrav 	if (newkey == NULL) {
540545d5ecaSDag-Erling Smørgrav 		error("%s: newkey == NULL", __func__);
541545d5ecaSDag-Erling Smørgrav 		return 0;
542545d5ecaSDag-Erling Smørgrav 	}
543545d5ecaSDag-Erling Smørgrav 	enc = &newkey->enc;
544545d5ecaSDag-Erling Smørgrav 	mac = &newkey->mac;
545545d5ecaSDag-Erling Smørgrav 	comp = &newkey->comp;
546545d5ecaSDag-Erling Smørgrav 
547545d5ecaSDag-Erling Smørgrav 	buffer_init(&b);
548545d5ecaSDag-Erling Smørgrav 	/* Enc structure */
549545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&b, enc->name);
550545d5ecaSDag-Erling Smørgrav 	/* The cipher struct is constant and shared, you export pointer */
551545d5ecaSDag-Erling Smørgrav 	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
552545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, enc->enabled);
553545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, enc->block_size);
554545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&b, enc->key, enc->key_len);
5556888a9beSDag-Erling Smørgrav 	packet_get_keyiv(mode, enc->iv, enc->iv_len);
5566888a9beSDag-Erling Smørgrav 	buffer_put_string(&b, enc->iv, enc->iv_len);
557545d5ecaSDag-Erling Smørgrav 
558545d5ecaSDag-Erling Smørgrav 	/* Mac structure */
5596888a9beSDag-Erling Smørgrav 	if (cipher_authlen(enc->cipher) == 0) {
560545d5ecaSDag-Erling Smørgrav 		buffer_put_cstring(&b, mac->name);
561545d5ecaSDag-Erling Smørgrav 		buffer_put_int(&b, mac->enabled);
562545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&b, mac->key, mac->key_len);
5636888a9beSDag-Erling Smørgrav 	}
564545d5ecaSDag-Erling Smørgrav 
565545d5ecaSDag-Erling Smørgrav 	/* Comp structure */
566545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, comp->type);
567545d5ecaSDag-Erling Smørgrav 	buffer_put_int(&b, comp->enabled);
568545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&b, comp->name);
569545d5ecaSDag-Erling Smørgrav 
570545d5ecaSDag-Erling Smørgrav 	len = buffer_len(&b);
571545d5ecaSDag-Erling Smørgrav 	if (lenp != NULL)
572545d5ecaSDag-Erling Smørgrav 		*lenp = len;
573f388f5efSDag-Erling Smørgrav 	if (blobp != NULL) {
574f388f5efSDag-Erling Smørgrav 		*blobp = xmalloc(len);
575f388f5efSDag-Erling Smørgrav 		memcpy(*blobp, buffer_ptr(&b), len);
576f388f5efSDag-Erling Smørgrav 	}
577f388f5efSDag-Erling Smørgrav 	memset(buffer_ptr(&b), 0, len);
578f388f5efSDag-Erling Smørgrav 	buffer_free(&b);
579545d5ecaSDag-Erling Smørgrav 	return len;
580545d5ecaSDag-Erling Smørgrav }
581545d5ecaSDag-Erling Smørgrav 
582545d5ecaSDag-Erling Smørgrav static void
583545d5ecaSDag-Erling Smørgrav mm_send_kex(Buffer *m, Kex *kex)
584545d5ecaSDag-Erling Smørgrav {
585545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, kex->session_id, kex->session_id_len);
586545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->we_need);
587545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->hostkey_type);
588545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->kex_type);
589545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
590545d5ecaSDag-Erling Smørgrav 	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
591545d5ecaSDag-Erling Smørgrav 	buffer_put_int(m, kex->flags);
592545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(m, kex->client_version_string);
593545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(m, kex->server_version_string);
594545d5ecaSDag-Erling Smørgrav }
595545d5ecaSDag-Erling Smørgrav 
596545d5ecaSDag-Erling Smørgrav void
59721e764dfSDag-Erling Smørgrav mm_send_keystate(struct monitor *monitor)
598545d5ecaSDag-Erling Smørgrav {
5997aee6ffeSDag-Erling Smørgrav 	Buffer m, *input, *output;
600545d5ecaSDag-Erling Smørgrav 	u_char *blob, *p;
601545d5ecaSDag-Erling Smørgrav 	u_int bloblen, plen;
602cf2b5f3bSDag-Erling Smørgrav 	u_int32_t seqnr, packets;
603d4af9e69SDag-Erling Smørgrav 	u_int64_t blocks, bytes;
604545d5ecaSDag-Erling Smørgrav 
605545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
606545d5ecaSDag-Erling Smørgrav 
607545d5ecaSDag-Erling Smørgrav 	if (!compat20) {
608545d5ecaSDag-Erling Smørgrav 		u_char iv[24];
609545d5ecaSDag-Erling Smørgrav 		u_char *key;
610545d5ecaSDag-Erling Smørgrav 		u_int ivlen, keylen;
611545d5ecaSDag-Erling Smørgrav 
612545d5ecaSDag-Erling Smørgrav 		buffer_put_int(&m, packet_get_protocol_flags());
613545d5ecaSDag-Erling Smørgrav 
614545d5ecaSDag-Erling Smørgrav 		buffer_put_int(&m, packet_get_ssh1_cipher());
615545d5ecaSDag-Erling Smørgrav 
616545d5ecaSDag-Erling Smørgrav 		debug3("%s: Sending ssh1 KEY+IV", __func__);
617545d5ecaSDag-Erling Smørgrav 		keylen = packet_get_encryption_key(NULL);
618545d5ecaSDag-Erling Smørgrav 		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
619545d5ecaSDag-Erling Smørgrav 		keylen = packet_get_encryption_key(key);
620545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, key, keylen);
621545d5ecaSDag-Erling Smørgrav 		memset(key, 0, keylen);
622*e4a9863fSDag-Erling Smørgrav 		free(key);
623545d5ecaSDag-Erling Smørgrav 
624545d5ecaSDag-Erling Smørgrav 		ivlen = packet_get_keyiv_len(MODE_OUT);
625545d5ecaSDag-Erling Smørgrav 		packet_get_keyiv(MODE_OUT, iv, ivlen);
626545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, iv, ivlen);
6276888a9beSDag-Erling Smørgrav 		ivlen = packet_get_keyiv_len(MODE_IN);
628545d5ecaSDag-Erling Smørgrav 		packet_get_keyiv(MODE_IN, iv, ivlen);
629545d5ecaSDag-Erling Smørgrav 		buffer_put_string(&m, iv, ivlen);
630545d5ecaSDag-Erling Smørgrav 		goto skip;
631545d5ecaSDag-Erling Smørgrav 	} else {
632545d5ecaSDag-Erling Smørgrav 		/* Kex for rekeying */
63321e764dfSDag-Erling Smørgrav 		mm_send_kex(&m, *monitor->m_pkex);
634545d5ecaSDag-Erling Smørgrav 	}
635545d5ecaSDag-Erling Smørgrav 
636545d5ecaSDag-Erling Smørgrav 	debug3("%s: Sending new keys: %p %p",
6377aee6ffeSDag-Erling Smørgrav 	    __func__, packet_get_newkeys(MODE_OUT),
6387aee6ffeSDag-Erling Smørgrav 	    packet_get_newkeys(MODE_IN));
639545d5ecaSDag-Erling Smørgrav 
640545d5ecaSDag-Erling Smørgrav 	/* Keys from Kex */
641545d5ecaSDag-Erling Smørgrav 	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
642545d5ecaSDag-Erling Smørgrav 		fatal("%s: conversion of newkeys failed", __func__);
643545d5ecaSDag-Erling Smørgrav 
644545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, bloblen);
645*e4a9863fSDag-Erling Smørgrav 	free(blob);
646545d5ecaSDag-Erling Smørgrav 
647545d5ecaSDag-Erling Smørgrav 	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
648545d5ecaSDag-Erling Smørgrav 		fatal("%s: conversion of newkeys failed", __func__);
649545d5ecaSDag-Erling Smørgrav 
650545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, bloblen);
651*e4a9863fSDag-Erling Smørgrav 	free(blob);
652545d5ecaSDag-Erling Smørgrav 
653d4af9e69SDag-Erling Smørgrav 	packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
654cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int(&m, seqnr);
655cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int64(&m, blocks);
656cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int(&m, packets);
657d4af9e69SDag-Erling Smørgrav 	buffer_put_int64(&m, bytes);
658d4af9e69SDag-Erling Smørgrav 	packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
659cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int(&m, seqnr);
660cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int64(&m, blocks);
661cf2b5f3bSDag-Erling Smørgrav 	buffer_put_int(&m, packets);
662d4af9e69SDag-Erling Smørgrav 	buffer_put_int64(&m, bytes);
663545d5ecaSDag-Erling Smørgrav 
664545d5ecaSDag-Erling Smørgrav 	debug3("%s: New keys have been sent", __func__);
665545d5ecaSDag-Erling Smørgrav  skip:
666545d5ecaSDag-Erling Smørgrav 	/* More key context */
667545d5ecaSDag-Erling Smørgrav 	plen = packet_get_keycontext(MODE_OUT, NULL);
668545d5ecaSDag-Erling Smørgrav 	p = xmalloc(plen+1);
669545d5ecaSDag-Erling Smørgrav 	packet_get_keycontext(MODE_OUT, p);
670545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, p, plen);
671*e4a9863fSDag-Erling Smørgrav 	free(p);
672545d5ecaSDag-Erling Smørgrav 
673545d5ecaSDag-Erling Smørgrav 	plen = packet_get_keycontext(MODE_IN, NULL);
674545d5ecaSDag-Erling Smørgrav 	p = xmalloc(plen+1);
675545d5ecaSDag-Erling Smørgrav 	packet_get_keycontext(MODE_IN, p);
676545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, p, plen);
677*e4a9863fSDag-Erling Smørgrav 	free(p);
678545d5ecaSDag-Erling Smørgrav 
679545d5ecaSDag-Erling Smørgrav 	/* Compression state */
680545d5ecaSDag-Erling Smørgrav 	debug3("%s: Sending compression state", __func__);
681545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
682545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
683545d5ecaSDag-Erling Smørgrav 
684545d5ecaSDag-Erling Smørgrav 	/* Network I/O buffers */
6857aee6ffeSDag-Erling Smørgrav 	input = (Buffer *)packet_get_input();
6867aee6ffeSDag-Erling Smørgrav 	output = (Buffer *)packet_get_output();
6877aee6ffeSDag-Erling Smørgrav 	buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
6887aee6ffeSDag-Erling Smørgrav 	buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
6897aee6ffeSDag-Erling Smørgrav 
6907aee6ffeSDag-Erling Smørgrav 	/* Roaming */
6917aee6ffeSDag-Erling Smørgrav 	if (compat20) {
6927aee6ffeSDag-Erling Smørgrav 		buffer_put_int64(&m, get_sent_bytes());
6937aee6ffeSDag-Erling Smørgrav 		buffer_put_int64(&m, get_recv_bytes());
6947aee6ffeSDag-Erling Smørgrav 	}
695545d5ecaSDag-Erling Smørgrav 
69621e764dfSDag-Erling Smørgrav 	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
697545d5ecaSDag-Erling Smørgrav 	debug3("%s: Finished sending state", __func__);
698545d5ecaSDag-Erling Smørgrav 
699545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
700545d5ecaSDag-Erling Smørgrav }
701545d5ecaSDag-Erling Smørgrav 
702545d5ecaSDag-Erling Smørgrav int
703333ee039SDag-Erling Smørgrav mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
704545d5ecaSDag-Erling Smørgrav {
705545d5ecaSDag-Erling Smørgrav 	Buffer m;
70621e764dfSDag-Erling Smørgrav 	char *p, *msg;
707d4af9e69SDag-Erling Smørgrav 	int success = 0, tmp1 = -1, tmp2 = -1;
708d4af9e69SDag-Erling Smørgrav 
709d4af9e69SDag-Erling Smørgrav 	/* Kludge: ensure there are fds free to receive the pty/tty */
710d4af9e69SDag-Erling Smørgrav 	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
711d4af9e69SDag-Erling Smørgrav 	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
712d4af9e69SDag-Erling Smørgrav 		error("%s: cannot allocate fds for pty", __func__);
713d4af9e69SDag-Erling Smørgrav 		if (tmp1 > 0)
714d4af9e69SDag-Erling Smørgrav 			close(tmp1);
715d4af9e69SDag-Erling Smørgrav 		if (tmp2 > 0)
716d4af9e69SDag-Erling Smørgrav 			close(tmp2);
717d4af9e69SDag-Erling Smørgrav 		return 0;
718d4af9e69SDag-Erling Smørgrav 	}
719d4af9e69SDag-Erling Smørgrav 	close(tmp1);
720d4af9e69SDag-Erling Smørgrav 	close(tmp2);
721545d5ecaSDag-Erling Smørgrav 
722545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
723545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
724545d5ecaSDag-Erling Smørgrav 
725545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
726545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
727545d5ecaSDag-Erling Smørgrav 
728545d5ecaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
729545d5ecaSDag-Erling Smørgrav 	if (success == 0) {
730545d5ecaSDag-Erling Smørgrav 		debug3("%s: pty alloc failed", __func__);
731545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
732545d5ecaSDag-Erling Smørgrav 		return (0);
733545d5ecaSDag-Erling Smørgrav 	}
734545d5ecaSDag-Erling Smørgrav 	p = buffer_get_string(&m, NULL);
73521e764dfSDag-Erling Smørgrav 	msg = buffer_get_string(&m, NULL);
736545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
737545d5ecaSDag-Erling Smørgrav 
738545d5ecaSDag-Erling Smørgrav 	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
739*e4a9863fSDag-Erling Smørgrav 	free(p);
740545d5ecaSDag-Erling Smørgrav 
74121e764dfSDag-Erling Smørgrav 	buffer_append(&loginmsg, msg, strlen(msg));
742*e4a9863fSDag-Erling Smørgrav 	free(msg);
74321e764dfSDag-Erling Smørgrav 
744d4af9e69SDag-Erling Smørgrav 	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
745d4af9e69SDag-Erling Smørgrav 	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
746d4af9e69SDag-Erling Smørgrav 		fatal("%s: receive fds failed", __func__);
747545d5ecaSDag-Erling Smørgrav 
748545d5ecaSDag-Erling Smørgrav 	/* Success */
749545d5ecaSDag-Erling Smørgrav 	return (1);
750545d5ecaSDag-Erling Smørgrav }
751545d5ecaSDag-Erling Smørgrav 
752545d5ecaSDag-Erling Smørgrav void
7531ec0d754SDag-Erling Smørgrav mm_session_pty_cleanup2(Session *s)
754545d5ecaSDag-Erling Smørgrav {
755545d5ecaSDag-Erling Smørgrav 	Buffer m;
756545d5ecaSDag-Erling Smørgrav 
757545d5ecaSDag-Erling Smørgrav 	if (s->ttyfd == -1)
758545d5ecaSDag-Erling Smørgrav 		return;
759545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
760545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, s->tty);
761545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
762545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
763545d5ecaSDag-Erling Smørgrav 
764545d5ecaSDag-Erling Smørgrav 	/* closed dup'ed master */
765d4af9e69SDag-Erling Smørgrav 	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
766d4af9e69SDag-Erling Smørgrav 		error("close(s->ptymaster/%d): %s",
767d4af9e69SDag-Erling Smørgrav 		    s->ptymaster, strerror(errno));
768545d5ecaSDag-Erling Smørgrav 
769545d5ecaSDag-Erling Smørgrav 	/* unlink pty from session */
770545d5ecaSDag-Erling Smørgrav 	s->ttyfd = -1;
771545d5ecaSDag-Erling Smørgrav }
772545d5ecaSDag-Erling Smørgrav 
77383d2307dSDag-Erling Smørgrav #ifdef USE_PAM
77483d2307dSDag-Erling Smørgrav void
7755962c0e9SDag-Erling Smørgrav mm_start_pam(Authctxt *authctxt)
77683d2307dSDag-Erling Smørgrav {
77783d2307dSDag-Erling Smørgrav 	Buffer m;
77883d2307dSDag-Erling Smørgrav 
77983d2307dSDag-Erling Smørgrav 	debug3("%s entering", __func__);
780cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
781cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
78283d2307dSDag-Erling Smørgrav 
78383d2307dSDag-Erling Smørgrav 	buffer_init(&m);
78483d2307dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
78583d2307dSDag-Erling Smørgrav 
78683d2307dSDag-Erling Smørgrav 	buffer_free(&m);
78783d2307dSDag-Erling Smørgrav }
788382d19eeSDag-Erling Smørgrav 
789cf2b5f3bSDag-Erling Smørgrav u_int
790cf2b5f3bSDag-Erling Smørgrav mm_do_pam_account(void)
791cf2b5f3bSDag-Erling Smørgrav {
792cf2b5f3bSDag-Erling Smørgrav 	Buffer m;
793cf2b5f3bSDag-Erling Smørgrav 	u_int ret;
794aa49c926SDag-Erling Smørgrav 	char *msg;
795cf2b5f3bSDag-Erling Smørgrav 
796cf2b5f3bSDag-Erling Smørgrav 	debug3("%s entering", __func__);
797cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
798cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
799cf2b5f3bSDag-Erling Smørgrav 
800cf2b5f3bSDag-Erling Smørgrav 	buffer_init(&m);
801cf2b5f3bSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
802cf2b5f3bSDag-Erling Smørgrav 
803cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
804cf2b5f3bSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_ACCOUNT, &m);
805cf2b5f3bSDag-Erling Smørgrav 	ret = buffer_get_int(&m);
806aa49c926SDag-Erling Smørgrav 	msg = buffer_get_string(&m, NULL);
807aa49c926SDag-Erling Smørgrav 	buffer_append(&loginmsg, msg, strlen(msg));
808*e4a9863fSDag-Erling Smørgrav 	free(msg);
809cf2b5f3bSDag-Erling Smørgrav 
810cf2b5f3bSDag-Erling Smørgrav 	buffer_free(&m);
811cf2b5f3bSDag-Erling Smørgrav 
812cf2b5f3bSDag-Erling Smørgrav 	debug3("%s returning %d", __func__, ret);
813cf2b5f3bSDag-Erling Smørgrav 
814cf2b5f3bSDag-Erling Smørgrav 	return (ret);
815cf2b5f3bSDag-Erling Smørgrav }
816cf2b5f3bSDag-Erling Smørgrav 
817382d19eeSDag-Erling Smørgrav void *
818cf2b5f3bSDag-Erling Smørgrav mm_sshpam_init_ctx(Authctxt *authctxt)
819382d19eeSDag-Erling Smørgrav {
820382d19eeSDag-Erling Smørgrav 	Buffer m;
821382d19eeSDag-Erling Smørgrav 	int success;
822382d19eeSDag-Erling Smørgrav 
823382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
824382d19eeSDag-Erling Smørgrav 	buffer_init(&m);
825382d19eeSDag-Erling Smørgrav 	buffer_put_cstring(&m, authctxt->user);
826382d19eeSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
827382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
828382d19eeSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
829382d19eeSDag-Erling Smørgrav 	success = buffer_get_int(&m);
830382d19eeSDag-Erling Smørgrav 	if (success == 0) {
831382d19eeSDag-Erling Smørgrav 		debug3("%s: pam_init_ctx failed", __func__);
832382d19eeSDag-Erling Smørgrav 		buffer_free(&m);
833382d19eeSDag-Erling Smørgrav 		return (NULL);
834382d19eeSDag-Erling Smørgrav 	}
835382d19eeSDag-Erling Smørgrav 	buffer_free(&m);
836382d19eeSDag-Erling Smørgrav 	return (authctxt);
837382d19eeSDag-Erling Smørgrav }
838382d19eeSDag-Erling Smørgrav 
839382d19eeSDag-Erling Smørgrav int
840cf2b5f3bSDag-Erling Smørgrav mm_sshpam_query(void *ctx, char **name, char **info,
841382d19eeSDag-Erling Smørgrav     u_int *num, char ***prompts, u_int **echo_on)
842382d19eeSDag-Erling Smørgrav {
843382d19eeSDag-Erling Smørgrav 	Buffer m;
844d4ecd108SDag-Erling Smørgrav 	u_int i;
845d4ecd108SDag-Erling Smørgrav 	int ret;
846382d19eeSDag-Erling Smørgrav 
847382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
848382d19eeSDag-Erling Smørgrav 	buffer_init(&m);
849382d19eeSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
850382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
851382d19eeSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
852382d19eeSDag-Erling Smørgrav 	ret = buffer_get_int(&m);
853382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_query returned %d", __func__, ret);
854382d19eeSDag-Erling Smørgrav 	*name = buffer_get_string(&m, NULL);
855382d19eeSDag-Erling Smørgrav 	*info = buffer_get_string(&m, NULL);
856382d19eeSDag-Erling Smørgrav 	*num = buffer_get_int(&m);
857333ee039SDag-Erling Smørgrav 	if (*num > PAM_MAX_NUM_MSG)
858333ee039SDag-Erling Smørgrav 		fatal("%s: recieved %u PAM messages, expected <= %u",
859333ee039SDag-Erling Smørgrav 		    __func__, *num, PAM_MAX_NUM_MSG);
860333ee039SDag-Erling Smørgrav 	*prompts = xcalloc((*num + 1), sizeof(char *));
861333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc((*num + 1), sizeof(u_int));
862382d19eeSDag-Erling Smørgrav 	for (i = 0; i < *num; ++i) {
863382d19eeSDag-Erling Smørgrav 		(*prompts)[i] = buffer_get_string(&m, NULL);
864382d19eeSDag-Erling Smørgrav 		(*echo_on)[i] = buffer_get_int(&m);
865382d19eeSDag-Erling Smørgrav 	}
866382d19eeSDag-Erling Smørgrav 	buffer_free(&m);
867382d19eeSDag-Erling Smørgrav 	return (ret);
868382d19eeSDag-Erling Smørgrav }
869382d19eeSDag-Erling Smørgrav 
870382d19eeSDag-Erling Smørgrav int
871cf2b5f3bSDag-Erling Smørgrav mm_sshpam_respond(void *ctx, u_int num, char **resp)
872382d19eeSDag-Erling Smørgrav {
873382d19eeSDag-Erling Smørgrav 	Buffer m;
874d4ecd108SDag-Erling Smørgrav 	u_int i;
875d4ecd108SDag-Erling Smørgrav 	int ret;
876382d19eeSDag-Erling Smørgrav 
877382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
878382d19eeSDag-Erling Smørgrav 	buffer_init(&m);
879382d19eeSDag-Erling Smørgrav 	buffer_put_int(&m, num);
880382d19eeSDag-Erling Smørgrav 	for (i = 0; i < num; ++i)
881382d19eeSDag-Erling Smørgrav 		buffer_put_cstring(&m, resp[i]);
882382d19eeSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
883382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
884382d19eeSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
885382d19eeSDag-Erling Smørgrav 	ret = buffer_get_int(&m);
886382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_respond returned %d", __func__, ret);
887382d19eeSDag-Erling Smørgrav 	buffer_free(&m);
888382d19eeSDag-Erling Smørgrav 	return (ret);
889382d19eeSDag-Erling Smørgrav }
890382d19eeSDag-Erling Smørgrav 
891382d19eeSDag-Erling Smørgrav void
892cf2b5f3bSDag-Erling Smørgrav mm_sshpam_free_ctx(void *ctxtp)
893382d19eeSDag-Erling Smørgrav {
894382d19eeSDag-Erling Smørgrav 	Buffer m;
895382d19eeSDag-Erling Smørgrav 
896382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
897382d19eeSDag-Erling Smørgrav 	buffer_init(&m);
898382d19eeSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
899382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
900382d19eeSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
901382d19eeSDag-Erling Smørgrav 	buffer_free(&m);
902382d19eeSDag-Erling Smørgrav }
90383d2307dSDag-Erling Smørgrav #endif /* USE_PAM */
90483d2307dSDag-Erling Smørgrav 
905545d5ecaSDag-Erling Smørgrav /* Request process termination */
906545d5ecaSDag-Erling Smørgrav 
907545d5ecaSDag-Erling Smørgrav void
908545d5ecaSDag-Erling Smørgrav mm_terminate(void)
909545d5ecaSDag-Erling Smørgrav {
910545d5ecaSDag-Erling Smørgrav 	Buffer m;
911545d5ecaSDag-Erling Smørgrav 
912545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
913545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
914545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
915545d5ecaSDag-Erling Smørgrav }
916545d5ecaSDag-Erling Smørgrav 
917545d5ecaSDag-Erling Smørgrav int
918545d5ecaSDag-Erling Smørgrav mm_ssh1_session_key(BIGNUM *num)
919545d5ecaSDag-Erling Smørgrav {
920545d5ecaSDag-Erling Smørgrav 	int rsafail;
921545d5ecaSDag-Erling Smørgrav 	Buffer m;
922545d5ecaSDag-Erling Smørgrav 
923545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
924545d5ecaSDag-Erling Smørgrav 	buffer_put_bignum2(&m, num);
925545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
926545d5ecaSDag-Erling Smørgrav 
927545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
928545d5ecaSDag-Erling Smørgrav 
929545d5ecaSDag-Erling Smørgrav 	rsafail = buffer_get_int(&m);
930545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, num);
931545d5ecaSDag-Erling Smørgrav 
932545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
933545d5ecaSDag-Erling Smørgrav 
934545d5ecaSDag-Erling Smørgrav 	return (rsafail);
935545d5ecaSDag-Erling Smørgrav }
936545d5ecaSDag-Erling Smørgrav 
937545d5ecaSDag-Erling Smørgrav static void
938545d5ecaSDag-Erling Smørgrav mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
939545d5ecaSDag-Erling Smørgrav     char ***prompts, u_int **echo_on)
940545d5ecaSDag-Erling Smørgrav {
941545d5ecaSDag-Erling Smørgrav 	*name = xstrdup("");
942545d5ecaSDag-Erling Smørgrav 	*infotxt = xstrdup("");
943545d5ecaSDag-Erling Smørgrav 	*numprompts = 1;
944333ee039SDag-Erling Smørgrav 	*prompts = xcalloc(*numprompts, sizeof(char *));
945333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc(*numprompts, sizeof(u_int));
946545d5ecaSDag-Erling Smørgrav 	(*echo_on)[0] = 0;
947545d5ecaSDag-Erling Smørgrav }
948545d5ecaSDag-Erling Smørgrav 
949545d5ecaSDag-Erling Smørgrav int
950545d5ecaSDag-Erling Smørgrav mm_bsdauth_query(void *ctx, char **name, char **infotxt,
951545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
952545d5ecaSDag-Erling Smørgrav {
953545d5ecaSDag-Erling Smørgrav 	Buffer m;
954e73e9afaSDag-Erling Smørgrav 	u_int success;
955545d5ecaSDag-Erling Smørgrav 	char *challenge;
956545d5ecaSDag-Erling Smørgrav 
957545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
958545d5ecaSDag-Erling Smørgrav 
959545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
960545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
961545d5ecaSDag-Erling Smørgrav 
962545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
963545d5ecaSDag-Erling Smørgrav 	    &m);
964e73e9afaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
965e73e9afaSDag-Erling Smørgrav 	if (success == 0) {
966545d5ecaSDag-Erling Smørgrav 		debug3("%s: no challenge", __func__);
967545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
968545d5ecaSDag-Erling Smørgrav 		return (-1);
969545d5ecaSDag-Erling Smørgrav 	}
970545d5ecaSDag-Erling Smørgrav 
971545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
972545d5ecaSDag-Erling Smørgrav 	challenge  = buffer_get_string(&m, NULL);
973545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
974545d5ecaSDag-Erling Smørgrav 
975545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
976545d5ecaSDag-Erling Smørgrav 	(*prompts)[0] = challenge;
977545d5ecaSDag-Erling Smørgrav 
978545d5ecaSDag-Erling Smørgrav 	debug3("%s: received challenge: %s", __func__, challenge);
979545d5ecaSDag-Erling Smørgrav 
980545d5ecaSDag-Erling Smørgrav 	return (0);
981545d5ecaSDag-Erling Smørgrav }
982545d5ecaSDag-Erling Smørgrav 
983545d5ecaSDag-Erling Smørgrav int
984545d5ecaSDag-Erling Smørgrav mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
985545d5ecaSDag-Erling Smørgrav {
986545d5ecaSDag-Erling Smørgrav 	Buffer m;
987545d5ecaSDag-Erling Smørgrav 	int authok;
988545d5ecaSDag-Erling Smørgrav 
989545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
990545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
991545d5ecaSDag-Erling Smørgrav 		return (-1);
992545d5ecaSDag-Erling Smørgrav 
993545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
994545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, responses[0]);
995545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
996545d5ecaSDag-Erling Smørgrav 
997545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
998545d5ecaSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHRESPOND, &m);
999545d5ecaSDag-Erling Smørgrav 
1000545d5ecaSDag-Erling Smørgrav 	authok = buffer_get_int(&m);
1001545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1002545d5ecaSDag-Erling Smørgrav 
1003545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
1004545d5ecaSDag-Erling Smørgrav }
1005545d5ecaSDag-Erling Smørgrav 
1006edb557f8SDag-Erling Smørgrav #ifdef SKEY
1007545d5ecaSDag-Erling Smørgrav int
1008545d5ecaSDag-Erling Smørgrav mm_skey_query(void *ctx, char **name, char **infotxt,
1009545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
1010545d5ecaSDag-Erling Smørgrav {
1011545d5ecaSDag-Erling Smørgrav 	Buffer m;
1012e73e9afaSDag-Erling Smørgrav 	u_int success;
1013333ee039SDag-Erling Smørgrav 	char *challenge;
1014545d5ecaSDag-Erling Smørgrav 
1015545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
1016545d5ecaSDag-Erling Smørgrav 
1017545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1018545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
1019545d5ecaSDag-Erling Smørgrav 
1020545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
1021545d5ecaSDag-Erling Smørgrav 	    &m);
1022e73e9afaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
1023e73e9afaSDag-Erling Smørgrav 	if (success == 0) {
1024545d5ecaSDag-Erling Smørgrav 		debug3("%s: no challenge", __func__);
1025545d5ecaSDag-Erling Smørgrav 		buffer_free(&m);
1026545d5ecaSDag-Erling Smørgrav 		return (-1);
1027545d5ecaSDag-Erling Smørgrav 	}
1028545d5ecaSDag-Erling Smørgrav 
1029545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
1030545d5ecaSDag-Erling Smørgrav 	challenge  = buffer_get_string(&m, NULL);
1031545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1032545d5ecaSDag-Erling Smørgrav 
1033545d5ecaSDag-Erling Smørgrav 	debug3("%s: received challenge: %s", __func__, challenge);
1034545d5ecaSDag-Erling Smørgrav 
1035545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
1036545d5ecaSDag-Erling Smørgrav 
1037333ee039SDag-Erling Smørgrav 	xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
1038*e4a9863fSDag-Erling Smørgrav 	free(challenge);
1039545d5ecaSDag-Erling Smørgrav 
1040545d5ecaSDag-Erling Smørgrav 	return (0);
1041545d5ecaSDag-Erling Smørgrav }
1042545d5ecaSDag-Erling Smørgrav 
1043545d5ecaSDag-Erling Smørgrav int
1044545d5ecaSDag-Erling Smørgrav mm_skey_respond(void *ctx, u_int numresponses, char **responses)
1045545d5ecaSDag-Erling Smørgrav {
1046545d5ecaSDag-Erling Smørgrav 	Buffer m;
1047545d5ecaSDag-Erling Smørgrav 	int authok;
1048545d5ecaSDag-Erling Smørgrav 
1049545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
1050545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
1051545d5ecaSDag-Erling Smørgrav 		return (-1);
1052545d5ecaSDag-Erling Smørgrav 
1053545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1054545d5ecaSDag-Erling Smørgrav 	buffer_put_cstring(&m, responses[0]);
1055545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
1056545d5ecaSDag-Erling Smørgrav 
1057545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1058545d5ecaSDag-Erling Smørgrav 	    MONITOR_ANS_SKEYRESPOND, &m);
1059545d5ecaSDag-Erling Smørgrav 
1060545d5ecaSDag-Erling Smørgrav 	authok = buffer_get_int(&m);
1061545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1062545d5ecaSDag-Erling Smørgrav 
1063545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
1064545d5ecaSDag-Erling Smørgrav }
106521e764dfSDag-Erling Smørgrav #endif /* SKEY */
1066545d5ecaSDag-Erling Smørgrav 
1067545d5ecaSDag-Erling Smørgrav void
1068545d5ecaSDag-Erling Smørgrav mm_ssh1_session_id(u_char session_id[16])
1069545d5ecaSDag-Erling Smørgrav {
1070545d5ecaSDag-Erling Smørgrav 	Buffer m;
1071545d5ecaSDag-Erling Smørgrav 	int i;
1072545d5ecaSDag-Erling Smørgrav 
1073545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
1074545d5ecaSDag-Erling Smørgrav 
1075545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1076545d5ecaSDag-Erling Smørgrav 	for (i = 0; i < 16; i++)
1077545d5ecaSDag-Erling Smørgrav 		buffer_put_char(&m, session_id[i]);
1078545d5ecaSDag-Erling Smørgrav 
1079545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
1080545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1081545d5ecaSDag-Erling Smørgrav }
1082545d5ecaSDag-Erling Smørgrav 
1083545d5ecaSDag-Erling Smørgrav int
1084545d5ecaSDag-Erling Smørgrav mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
1085545d5ecaSDag-Erling Smørgrav {
1086545d5ecaSDag-Erling Smørgrav 	Buffer m;
1087545d5ecaSDag-Erling Smørgrav 	Key *key;
1088545d5ecaSDag-Erling Smørgrav 	u_char *blob;
1089545d5ecaSDag-Erling Smørgrav 	u_int blen;
1090e73e9afaSDag-Erling Smørgrav 	int allowed = 0, have_forced = 0;
1091545d5ecaSDag-Erling Smørgrav 
1092545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
1093545d5ecaSDag-Erling Smørgrav 
1094545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1095545d5ecaSDag-Erling Smørgrav 	buffer_put_bignum2(&m, client_n);
1096545d5ecaSDag-Erling Smørgrav 
1097545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
1098545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
1099545d5ecaSDag-Erling Smørgrav 
1100545d5ecaSDag-Erling Smørgrav 	allowed = buffer_get_int(&m);
1101545d5ecaSDag-Erling Smørgrav 
1102e73e9afaSDag-Erling Smørgrav 	/* fake forced command */
1103e73e9afaSDag-Erling Smørgrav 	auth_clear_options();
1104e73e9afaSDag-Erling Smørgrav 	have_forced = buffer_get_int(&m);
1105e73e9afaSDag-Erling Smørgrav 	forced_command = have_forced ? xstrdup("true") : NULL;
1106e73e9afaSDag-Erling Smørgrav 
1107545d5ecaSDag-Erling Smørgrav 	if (allowed && rkey != NULL) {
1108545d5ecaSDag-Erling Smørgrav 		blob = buffer_get_string(&m, &blen);
1109545d5ecaSDag-Erling Smørgrav 		if ((key = key_from_blob(blob, blen)) == NULL)
1110545d5ecaSDag-Erling Smørgrav 			fatal("%s: key_from_blob failed", __func__);
1111545d5ecaSDag-Erling Smørgrav 		*rkey = key;
1112*e4a9863fSDag-Erling Smørgrav 		free(blob);
1113545d5ecaSDag-Erling Smørgrav 	}
1114545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1115545d5ecaSDag-Erling Smørgrav 
1116545d5ecaSDag-Erling Smørgrav 	return (allowed);
1117545d5ecaSDag-Erling Smørgrav }
1118545d5ecaSDag-Erling Smørgrav 
1119545d5ecaSDag-Erling Smørgrav BIGNUM *
1120545d5ecaSDag-Erling Smørgrav mm_auth_rsa_generate_challenge(Key *key)
1121545d5ecaSDag-Erling Smørgrav {
1122545d5ecaSDag-Erling Smørgrav 	Buffer m;
1123545d5ecaSDag-Erling Smørgrav 	BIGNUM *challenge;
1124545d5ecaSDag-Erling Smørgrav 	u_char *blob;
1125545d5ecaSDag-Erling Smørgrav 	u_int blen;
1126545d5ecaSDag-Erling Smørgrav 
1127545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
1128545d5ecaSDag-Erling Smørgrav 
1129545d5ecaSDag-Erling Smørgrav 	if ((challenge = BN_new()) == NULL)
1130545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
1131545d5ecaSDag-Erling Smørgrav 
1132545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
1133545d5ecaSDag-Erling Smørgrav 	if (key_to_blob(key, &blob, &blen) == 0)
1134545d5ecaSDag-Erling Smørgrav 		fatal("%s: key_to_blob failed", __func__);
1135545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
1136545d5ecaSDag-Erling Smørgrav 
1137545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1138545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, blen);
1139*e4a9863fSDag-Erling Smørgrav 	free(blob);
1140545d5ecaSDag-Erling Smørgrav 
1141545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
1142545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
1143545d5ecaSDag-Erling Smørgrav 
1144545d5ecaSDag-Erling Smørgrav 	buffer_get_bignum2(&m, challenge);
1145545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1146545d5ecaSDag-Erling Smørgrav 
1147545d5ecaSDag-Erling Smørgrav 	return (challenge);
1148545d5ecaSDag-Erling Smørgrav }
1149545d5ecaSDag-Erling Smørgrav 
1150545d5ecaSDag-Erling Smørgrav int
1151545d5ecaSDag-Erling Smørgrav mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
1152545d5ecaSDag-Erling Smørgrav {
1153545d5ecaSDag-Erling Smørgrav 	Buffer m;
1154545d5ecaSDag-Erling Smørgrav 	u_char *blob;
1155545d5ecaSDag-Erling Smørgrav 	u_int blen;
1156545d5ecaSDag-Erling Smørgrav 	int success = 0;
1157545d5ecaSDag-Erling Smørgrav 
1158545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
1159545d5ecaSDag-Erling Smørgrav 
1160545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
1161545d5ecaSDag-Erling Smørgrav 	if (key_to_blob(key, &blob, &blen) == 0)
1162545d5ecaSDag-Erling Smørgrav 		fatal("%s: key_to_blob failed", __func__);
1163545d5ecaSDag-Erling Smørgrav 	key->type = KEY_RSA1;
1164545d5ecaSDag-Erling Smørgrav 
1165545d5ecaSDag-Erling Smørgrav 	buffer_init(&m);
1166545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, blob, blen);
1167545d5ecaSDag-Erling Smørgrav 	buffer_put_string(&m, response, 16);
1168*e4a9863fSDag-Erling Smørgrav 	free(blob);
1169545d5ecaSDag-Erling Smørgrav 
1170545d5ecaSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
1171545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
1172545d5ecaSDag-Erling Smørgrav 
1173545d5ecaSDag-Erling Smørgrav 	success = buffer_get_int(&m);
1174545d5ecaSDag-Erling Smørgrav 	buffer_free(&m);
1175545d5ecaSDag-Erling Smørgrav 
1176545d5ecaSDag-Erling Smørgrav 	return (success);
1177545d5ecaSDag-Erling Smørgrav }
1178f388f5efSDag-Erling Smørgrav 
1179aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS
1180aa49c926SDag-Erling Smørgrav void
1181aa49c926SDag-Erling Smørgrav mm_audit_event(ssh_audit_event_t event)
1182aa49c926SDag-Erling Smørgrav {
1183aa49c926SDag-Erling Smørgrav 	Buffer m;
1184aa49c926SDag-Erling Smørgrav 
1185aa49c926SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1186aa49c926SDag-Erling Smørgrav 
1187aa49c926SDag-Erling Smørgrav 	buffer_init(&m);
1188aa49c926SDag-Erling Smørgrav 	buffer_put_int(&m, event);
1189aa49c926SDag-Erling Smørgrav 
1190aa49c926SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
1191aa49c926SDag-Erling Smørgrav 	buffer_free(&m);
1192aa49c926SDag-Erling Smørgrav }
1193aa49c926SDag-Erling Smørgrav 
1194aa49c926SDag-Erling Smørgrav void
1195aa49c926SDag-Erling Smørgrav mm_audit_run_command(const char *command)
1196aa49c926SDag-Erling Smørgrav {
1197aa49c926SDag-Erling Smørgrav 	Buffer m;
1198aa49c926SDag-Erling Smørgrav 
1199aa49c926SDag-Erling Smørgrav 	debug3("%s entering command %s", __func__, command);
1200aa49c926SDag-Erling Smørgrav 
1201aa49c926SDag-Erling Smørgrav 	buffer_init(&m);
1202aa49c926SDag-Erling Smørgrav 	buffer_put_cstring(&m, command);
1203aa49c926SDag-Erling Smørgrav 
1204aa49c926SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
1205aa49c926SDag-Erling Smørgrav 	buffer_free(&m);
1206aa49c926SDag-Erling Smørgrav }
1207aa49c926SDag-Erling Smørgrav #endif /* SSH_AUDIT_EVENTS */
1208aa49c926SDag-Erling Smørgrav 
1209cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
1210cf2b5f3bSDag-Erling Smørgrav OM_uint32
121121e764dfSDag-Erling Smørgrav mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
1212f388f5efSDag-Erling Smørgrav {
1213f388f5efSDag-Erling Smørgrav 	Buffer m;
1214cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
1215f388f5efSDag-Erling Smørgrav 
1216cf2b5f3bSDag-Erling Smørgrav 	/* Client doesn't get to see the context */
1217cf2b5f3bSDag-Erling Smørgrav 	*ctx = NULL;
1218f388f5efSDag-Erling Smørgrav 
1219f388f5efSDag-Erling Smørgrav 	buffer_init(&m);
122021e764dfSDag-Erling Smørgrav 	buffer_put_string(&m, goid->elements, goid->length);
1221f388f5efSDag-Erling Smørgrav 
1222cf2b5f3bSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1223cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1224f388f5efSDag-Erling Smørgrav 
1225cf2b5f3bSDag-Erling Smørgrav 	major = buffer_get_int(&m);
1226cf2b5f3bSDag-Erling Smørgrav 
1227f388f5efSDag-Erling Smørgrav 	buffer_free(&m);
1228cf2b5f3bSDag-Erling Smørgrav 	return (major);
1229f388f5efSDag-Erling Smørgrav }
1230f388f5efSDag-Erling Smørgrav 
1231cf2b5f3bSDag-Erling Smørgrav OM_uint32
1232cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1233cf2b5f3bSDag-Erling Smørgrav     gss_buffer_desc *out, OM_uint32 *flags)
1234f388f5efSDag-Erling Smørgrav {
1235f388f5efSDag-Erling Smørgrav 	Buffer m;
1236cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
1237f388f5efSDag-Erling Smørgrav 	u_int len;
1238f388f5efSDag-Erling Smørgrav 
1239cf2b5f3bSDag-Erling Smørgrav 	buffer_init(&m);
1240cf2b5f3bSDag-Erling Smørgrav 	buffer_put_string(&m, in->value, in->length);
1241cf2b5f3bSDag-Erling Smørgrav 
1242cf2b5f3bSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1243cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1244cf2b5f3bSDag-Erling Smørgrav 
1245cf2b5f3bSDag-Erling Smørgrav 	major = buffer_get_int(&m);
1246cf2b5f3bSDag-Erling Smørgrav 	out->value = buffer_get_string(&m, &len);
1247cf2b5f3bSDag-Erling Smørgrav 	out->length = len;
1248cf2b5f3bSDag-Erling Smørgrav 	if (flags)
1249cf2b5f3bSDag-Erling Smørgrav 		*flags = buffer_get_int(&m);
1250f388f5efSDag-Erling Smørgrav 
1251f388f5efSDag-Erling Smørgrav 	buffer_free(&m);
1252cf2b5f3bSDag-Erling Smørgrav 
1253cf2b5f3bSDag-Erling Smørgrav 	return (major);
1254f388f5efSDag-Erling Smørgrav }
1255cf2b5f3bSDag-Erling Smørgrav 
12561ec0d754SDag-Erling Smørgrav OM_uint32
12571ec0d754SDag-Erling Smørgrav mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
12581ec0d754SDag-Erling Smørgrav {
12591ec0d754SDag-Erling Smørgrav 	Buffer m;
12601ec0d754SDag-Erling Smørgrav 	OM_uint32 major;
12611ec0d754SDag-Erling Smørgrav 
12621ec0d754SDag-Erling Smørgrav 	buffer_init(&m);
12631ec0d754SDag-Erling Smørgrav 	buffer_put_string(&m, gssbuf->value, gssbuf->length);
12641ec0d754SDag-Erling Smørgrav 	buffer_put_string(&m, gssmic->value, gssmic->length);
12651ec0d754SDag-Erling Smørgrav 
12661ec0d754SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
12671ec0d754SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
12681ec0d754SDag-Erling Smørgrav 	    &m);
12691ec0d754SDag-Erling Smørgrav 
12701ec0d754SDag-Erling Smørgrav 	major = buffer_get_int(&m);
12711ec0d754SDag-Erling Smørgrav 	buffer_free(&m);
12721ec0d754SDag-Erling Smørgrav 	return(major);
12731ec0d754SDag-Erling Smørgrav }
12741ec0d754SDag-Erling Smørgrav 
1275cf2b5f3bSDag-Erling Smørgrav int
1276cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_userok(char *user)
1277cf2b5f3bSDag-Erling Smørgrav {
1278cf2b5f3bSDag-Erling Smørgrav 	Buffer m;
1279cf2b5f3bSDag-Erling Smørgrav 	int authenticated = 0;
1280cf2b5f3bSDag-Erling Smørgrav 
1281cf2b5f3bSDag-Erling Smørgrav 	buffer_init(&m);
1282cf2b5f3bSDag-Erling Smørgrav 
1283cf2b5f3bSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1284cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1285cf2b5f3bSDag-Erling Smørgrav 				  &m);
1286cf2b5f3bSDag-Erling Smørgrav 
1287cf2b5f3bSDag-Erling Smørgrav 	authenticated = buffer_get_int(&m);
1288cf2b5f3bSDag-Erling Smørgrav 
1289cf2b5f3bSDag-Erling Smørgrav 	buffer_free(&m);
1290cf2b5f3bSDag-Erling Smørgrav 	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1291cf2b5f3bSDag-Erling Smørgrav 	return (authenticated);
1292cf2b5f3bSDag-Erling Smørgrav }
1293cf2b5f3bSDag-Erling Smørgrav #endif /* GSSAPI */
1294cce7d346SDag-Erling Smørgrav 
1295cce7d346SDag-Erling Smørgrav #ifdef JPAKE
1296cce7d346SDag-Erling Smørgrav void
1297cce7d346SDag-Erling Smørgrav mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
1298cce7d346SDag-Erling Smørgrav     char **hash_scheme, char **salt)
1299cce7d346SDag-Erling Smørgrav {
1300cce7d346SDag-Erling Smørgrav 	Buffer m;
1301cce7d346SDag-Erling Smørgrav 
1302cce7d346SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1303cce7d346SDag-Erling Smørgrav 
1304cce7d346SDag-Erling Smørgrav 	buffer_init(&m);
1305cce7d346SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd,
1306cce7d346SDag-Erling Smørgrav 	    MONITOR_REQ_JPAKE_GET_PWDATA, &m);
1307cce7d346SDag-Erling Smørgrav 
1308cce7d346SDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
1309cce7d346SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1310cce7d346SDag-Erling Smørgrav 	    MONITOR_ANS_JPAKE_GET_PWDATA, &m);
1311cce7d346SDag-Erling Smørgrav 
1312cce7d346SDag-Erling Smørgrav 	*hash_scheme = buffer_get_string(&m, NULL);
1313cce7d346SDag-Erling Smørgrav 	*salt = buffer_get_string(&m, NULL);
1314cce7d346SDag-Erling Smørgrav 
1315cce7d346SDag-Erling Smørgrav 	buffer_free(&m);
1316cce7d346SDag-Erling Smørgrav }
1317cce7d346SDag-Erling Smørgrav 
1318cce7d346SDag-Erling Smørgrav void
13197aee6ffeSDag-Erling Smørgrav mm_jpake_step1(struct modp_group *grp,
1320cce7d346SDag-Erling Smørgrav     u_char **id, u_int *id_len,
1321cce7d346SDag-Erling Smørgrav     BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
1322cce7d346SDag-Erling Smørgrav     u_char **priv1_proof, u_int *priv1_proof_len,
1323cce7d346SDag-Erling Smørgrav     u_char **priv2_proof, u_int *priv2_proof_len)
1324cce7d346SDag-Erling Smørgrav {
1325cce7d346SDag-Erling Smørgrav 	Buffer m;
1326cce7d346SDag-Erling Smørgrav 
1327cce7d346SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1328cce7d346SDag-Erling Smørgrav 
1329cce7d346SDag-Erling Smørgrav 	buffer_init(&m);
1330cce7d346SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd,
1331cce7d346SDag-Erling Smørgrav 	    MONITOR_REQ_JPAKE_STEP1, &m);
1332cce7d346SDag-Erling Smørgrav 
1333cce7d346SDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
1334cce7d346SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1335cce7d346SDag-Erling Smørgrav 	    MONITOR_ANS_JPAKE_STEP1, &m);
1336cce7d346SDag-Erling Smørgrav 
1337cce7d346SDag-Erling Smørgrav 	if ((*priv1 = BN_new()) == NULL ||
1338cce7d346SDag-Erling Smørgrav 	    (*priv2 = BN_new()) == NULL ||
1339cce7d346SDag-Erling Smørgrav 	    (*g_priv1 = BN_new()) == NULL ||
1340cce7d346SDag-Erling Smørgrav 	    (*g_priv2 = BN_new()) == NULL)
1341cce7d346SDag-Erling Smørgrav 		fatal("%s: BN_new", __func__);
1342cce7d346SDag-Erling Smørgrav 
1343cce7d346SDag-Erling Smørgrav 	*id = buffer_get_string(&m, id_len);
1344cce7d346SDag-Erling Smørgrav 	/* priv1 and priv2 are, well, private */
1345cce7d346SDag-Erling Smørgrav 	buffer_get_bignum2(&m, *g_priv1);
1346cce7d346SDag-Erling Smørgrav 	buffer_get_bignum2(&m, *g_priv2);
1347cce7d346SDag-Erling Smørgrav 	*priv1_proof = buffer_get_string(&m, priv1_proof_len);
1348cce7d346SDag-Erling Smørgrav 	*priv2_proof = buffer_get_string(&m, priv2_proof_len);
1349cce7d346SDag-Erling Smørgrav 
1350cce7d346SDag-Erling Smørgrav 	buffer_free(&m);
1351cce7d346SDag-Erling Smørgrav }
1352cce7d346SDag-Erling Smørgrav 
1353cce7d346SDag-Erling Smørgrav void
13547aee6ffeSDag-Erling Smørgrav mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
1355cce7d346SDag-Erling Smørgrav     BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
1356cce7d346SDag-Erling Smørgrav     const u_char *theirid, u_int theirid_len,
1357cce7d346SDag-Erling Smørgrav     const u_char *myid, u_int myid_len,
1358cce7d346SDag-Erling Smørgrav     const u_char *theirpub1_proof, u_int theirpub1_proof_len,
1359cce7d346SDag-Erling Smørgrav     const u_char *theirpub2_proof, u_int theirpub2_proof_len,
1360cce7d346SDag-Erling Smørgrav     BIGNUM **newpub,
1361cce7d346SDag-Erling Smørgrav     u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
1362cce7d346SDag-Erling Smørgrav {
1363cce7d346SDag-Erling Smørgrav 	Buffer m;
1364cce7d346SDag-Erling Smørgrav 
1365cce7d346SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1366cce7d346SDag-Erling Smørgrav 
1367cce7d346SDag-Erling Smørgrav 	buffer_init(&m);
1368cce7d346SDag-Erling Smørgrav 	/* monitor already has all bignums except theirpub1, theirpub2 */
1369cce7d346SDag-Erling Smørgrav 	buffer_put_bignum2(&m, theirpub1);
1370cce7d346SDag-Erling Smørgrav 	buffer_put_bignum2(&m, theirpub2);
1371cce7d346SDag-Erling Smørgrav 	/* monitor already knows our id */
1372cce7d346SDag-Erling Smørgrav 	buffer_put_string(&m, theirid, theirid_len);
1373cce7d346SDag-Erling Smørgrav 	buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
1374cce7d346SDag-Erling Smørgrav 	buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
1375cce7d346SDag-Erling Smørgrav 
1376cce7d346SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd,
1377cce7d346SDag-Erling Smørgrav 	    MONITOR_REQ_JPAKE_STEP2, &m);
1378cce7d346SDag-Erling Smørgrav 
1379cce7d346SDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
1380cce7d346SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1381cce7d346SDag-Erling Smørgrav 	    MONITOR_ANS_JPAKE_STEP2, &m);
1382cce7d346SDag-Erling Smørgrav 
1383cce7d346SDag-Erling Smørgrav 	if ((*newpub = BN_new()) == NULL)
1384cce7d346SDag-Erling Smørgrav 		fatal("%s: BN_new", __func__);
1385cce7d346SDag-Erling Smørgrav 
1386cce7d346SDag-Erling Smørgrav 	buffer_get_bignum2(&m, *newpub);
1387cce7d346SDag-Erling Smørgrav 	*newpub_exponent_proof = buffer_get_string(&m,
1388cce7d346SDag-Erling Smørgrav 	    newpub_exponent_proof_len);
1389cce7d346SDag-Erling Smørgrav 
1390cce7d346SDag-Erling Smørgrav 	buffer_free(&m);
1391cce7d346SDag-Erling Smørgrav }
1392cce7d346SDag-Erling Smørgrav 
1393cce7d346SDag-Erling Smørgrav void
13947aee6ffeSDag-Erling Smørgrav mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
1395cce7d346SDag-Erling Smørgrav     BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
1396cce7d346SDag-Erling Smørgrav     BIGNUM *theirpub1, BIGNUM *theirpub2,
1397cce7d346SDag-Erling Smørgrav     const u_char *my_id, u_int my_id_len,
1398cce7d346SDag-Erling Smørgrav     const u_char *their_id, u_int their_id_len,
1399cce7d346SDag-Erling Smørgrav     const u_char *sess_id, u_int sess_id_len,
1400cce7d346SDag-Erling Smørgrav     const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
1401cce7d346SDag-Erling Smørgrav     BIGNUM **k,
1402cce7d346SDag-Erling Smørgrav     u_char **confirm_hash, u_int *confirm_hash_len)
1403cce7d346SDag-Erling Smørgrav {
1404cce7d346SDag-Erling Smørgrav 	Buffer m;
1405cce7d346SDag-Erling Smørgrav 
1406cce7d346SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1407cce7d346SDag-Erling Smørgrav 
1408cce7d346SDag-Erling Smørgrav 	buffer_init(&m);
1409cce7d346SDag-Erling Smørgrav 	/* monitor already has all bignums except step2_val */
1410cce7d346SDag-Erling Smørgrav 	buffer_put_bignum2(&m, step2_val);
1411cce7d346SDag-Erling Smørgrav 	/* monitor already knows all the ids */
1412cce7d346SDag-Erling Smørgrav 	buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
1413cce7d346SDag-Erling Smørgrav 
1414cce7d346SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd,
1415cce7d346SDag-Erling Smørgrav 	    MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
1416cce7d346SDag-Erling Smørgrav 
1417cce7d346SDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
1418cce7d346SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1419cce7d346SDag-Erling Smørgrav 	    MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
1420cce7d346SDag-Erling Smørgrav 
1421cce7d346SDag-Erling Smørgrav 	/* 'k' is sensitive and stays in the monitor */
1422cce7d346SDag-Erling Smørgrav 	*confirm_hash = buffer_get_string(&m, confirm_hash_len);
1423cce7d346SDag-Erling Smørgrav 
1424cce7d346SDag-Erling Smørgrav 	buffer_free(&m);
1425cce7d346SDag-Erling Smørgrav }
1426cce7d346SDag-Erling Smørgrav 
1427cce7d346SDag-Erling Smørgrav int
1428cce7d346SDag-Erling Smørgrav mm_jpake_check_confirm(const BIGNUM *k,
1429cce7d346SDag-Erling Smørgrav     const u_char *peer_id, u_int peer_id_len,
1430cce7d346SDag-Erling Smørgrav     const u_char *sess_id, u_int sess_id_len,
1431cce7d346SDag-Erling Smørgrav     const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
1432cce7d346SDag-Erling Smørgrav {
1433cce7d346SDag-Erling Smørgrav 	Buffer m;
1434cce7d346SDag-Erling Smørgrav 	int success = 0;
1435cce7d346SDag-Erling Smørgrav 
1436cce7d346SDag-Erling Smørgrav 	debug3("%s entering", __func__);
1437cce7d346SDag-Erling Smørgrav 
1438cce7d346SDag-Erling Smørgrav 	buffer_init(&m);
1439cce7d346SDag-Erling Smørgrav 	/* k is dummy in slave, ignored */
1440cce7d346SDag-Erling Smørgrav 	/* monitor knows all the ids */
1441cce7d346SDag-Erling Smørgrav 	buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
1442cce7d346SDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd,
1443cce7d346SDag-Erling Smørgrav 	    MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
1444cce7d346SDag-Erling Smørgrav 
1445cce7d346SDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
1446cce7d346SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1447cce7d346SDag-Erling Smørgrav 	    MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
1448cce7d346SDag-Erling Smørgrav 
1449cce7d346SDag-Erling Smørgrav 	success = buffer_get_int(&m);
1450cce7d346SDag-Erling Smørgrav 	buffer_free(&m);
1451cce7d346SDag-Erling Smørgrav 
1452cce7d346SDag-Erling Smørgrav 	debug3("%s: success = %d", __func__, success);
1453cce7d346SDag-Erling Smørgrav 	return success;
1454cce7d346SDag-Erling Smørgrav }
1455cce7d346SDag-Erling Smørgrav #endif /* JPAKE */
1456