xref: /freebsd/crypto/openssh/monitor_wrap.c (revision 27ceebbc2402e4c98203c7eef9696f4bd3d326f8)
1190cef3dSDag-Erling Smørgrav /* $OpenBSD: monitor_wrap.c,v 1.107 2018/07/20 03:46:34 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 
41a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
42545d5ecaSDag-Erling Smørgrav #include <openssl/bn.h>
43545d5ecaSDag-Erling Smørgrav #include <openssl/dh.h>
44cce7d346SDag-Erling Smørgrav #include <openssl/evp.h>
45a0ee8cc6SDag-Erling Smørgrav #endif
46545d5ecaSDag-Erling Smørgrav 
47d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h"
48333ee039SDag-Erling Smørgrav #include "xmalloc.h"
49545d5ecaSDag-Erling Smørgrav #include "ssh.h"
50a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
51545d5ecaSDag-Erling Smørgrav #include "dh.h"
52a0ee8cc6SDag-Erling Smørgrav #endif
53190cef3dSDag-Erling Smørgrav #include "sshbuf.h"
54190cef3dSDag-Erling Smørgrav #include "sshkey.h"
55333ee039SDag-Erling Smørgrav #include "cipher.h"
56545d5ecaSDag-Erling Smørgrav #include "kex.h"
57333ee039SDag-Erling Smørgrav #include "hostfile.h"
58545d5ecaSDag-Erling Smørgrav #include "auth.h"
59e73e9afaSDag-Erling Smørgrav #include "auth-options.h"
60545d5ecaSDag-Erling Smørgrav #include "packet.h"
61545d5ecaSDag-Erling Smørgrav #include "mac.h"
62545d5ecaSDag-Erling Smørgrav #include "log.h"
63076ad2f8SDag-Erling Smørgrav #include "auth-pam.h"
64545d5ecaSDag-Erling Smørgrav #include "monitor.h"
65cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
66cf2b5f3bSDag-Erling Smørgrav #include "ssh-gss.h"
67cf2b5f3bSDag-Erling Smørgrav #endif
68333ee039SDag-Erling Smørgrav #include "monitor_wrap.h"
69333ee039SDag-Erling Smørgrav #include "atomicio.h"
70333ee039SDag-Erling Smørgrav #include "monitor_fdpass.h"
71333ee039SDag-Erling Smørgrav #include "misc.h"
72333ee039SDag-Erling Smørgrav 
73333ee039SDag-Erling Smørgrav #include "channels.h"
74333ee039SDag-Erling Smørgrav #include "session.h"
75d4af9e69SDag-Erling Smørgrav #include "servconf.h"
76cf2b5f3bSDag-Erling Smørgrav 
77bc5531deSDag-Erling Smørgrav #include "ssherr.h"
78bc5531deSDag-Erling Smørgrav 
79545d5ecaSDag-Erling Smørgrav /* Imports */
80545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor;
81190cef3dSDag-Erling Smørgrav extern struct sshbuf *loginmsg;
82cf2b5f3bSDag-Erling Smørgrav extern ServerOptions options;
83545d5ecaSDag-Erling Smørgrav 
84e146993eSDag-Erling Smørgrav void
85e146993eSDag-Erling Smørgrav mm_log_handler(LogLevel level, const char *msg, void *ctx)
86e146993eSDag-Erling Smørgrav {
87190cef3dSDag-Erling Smørgrav 	struct sshbuf *log_msg;
88e146993eSDag-Erling Smørgrav 	struct monitor *mon = (struct monitor *)ctx;
89190cef3dSDag-Erling Smørgrav 	int r;
90190cef3dSDag-Erling Smørgrav 	size_t len;
91e146993eSDag-Erling Smørgrav 
92e146993eSDag-Erling Smørgrav 	if (mon->m_log_sendfd == -1)
93e146993eSDag-Erling Smørgrav 		fatal("%s: no log channel", __func__);
94e146993eSDag-Erling Smørgrav 
95190cef3dSDag-Erling Smørgrav 	if ((log_msg = sshbuf_new()) == NULL)
96190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
97e146993eSDag-Erling Smørgrav 
98190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
99190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(log_msg, level)) != 0 ||
100190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(log_msg, msg)) != 0)
101190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
102190cef3dSDag-Erling Smørgrav 	if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
103190cef3dSDag-Erling Smørgrav 		fatal("%s: bad length %zu", __func__, len);
104190cef3dSDag-Erling Smørgrav 	POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
105190cef3dSDag-Erling Smørgrav 	if (atomicio(vwrite, mon->m_log_sendfd,
106190cef3dSDag-Erling Smørgrav 	    sshbuf_mutable_ptr(log_msg), len) != len)
107e146993eSDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
108190cef3dSDag-Erling Smørgrav 	sshbuf_free(log_msg);
109e146993eSDag-Erling Smørgrav }
110e146993eSDag-Erling Smørgrav 
1111ec0d754SDag-Erling Smørgrav int
1121ec0d754SDag-Erling Smørgrav mm_is_monitor(void)
1131ec0d754SDag-Erling Smørgrav {
1141ec0d754SDag-Erling Smørgrav 	/*
1151ec0d754SDag-Erling Smørgrav 	 * m_pid is only set in the privileged part, and
1161ec0d754SDag-Erling Smørgrav 	 * points to the unprivileged child.
1171ec0d754SDag-Erling Smørgrav 	 */
1181ec0d754SDag-Erling Smørgrav 	return (pmonitor && pmonitor->m_pid > 0);
1191ec0d754SDag-Erling Smørgrav }
1201ec0d754SDag-Erling Smørgrav 
121545d5ecaSDag-Erling Smørgrav void
122190cef3dSDag-Erling Smørgrav mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
123545d5ecaSDag-Erling Smørgrav {
124190cef3dSDag-Erling Smørgrav 	size_t mlen = sshbuf_len(m);
125f388f5efSDag-Erling Smørgrav 	u_char buf[5];
126545d5ecaSDag-Erling Smørgrav 
127545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
128545d5ecaSDag-Erling Smørgrav 
129190cef3dSDag-Erling Smørgrav 	if (mlen >= 0xffffffff)
130190cef3dSDag-Erling Smørgrav 		fatal("%s: bad length %zu", __func__, mlen);
131190cef3dSDag-Erling Smørgrav 	POKE_U32(buf, mlen + 1);
132545d5ecaSDag-Erling Smørgrav 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
13321e764dfSDag-Erling Smørgrav 	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
134d4ecd108SDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
135190cef3dSDag-Erling Smørgrav 	if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
136d4ecd108SDag-Erling Smørgrav 		fatal("%s: write: %s", __func__, strerror(errno));
137545d5ecaSDag-Erling Smørgrav }
138545d5ecaSDag-Erling Smørgrav 
139545d5ecaSDag-Erling Smørgrav void
140190cef3dSDag-Erling Smørgrav mm_request_receive(int sock, struct sshbuf *m)
141545d5ecaSDag-Erling Smørgrav {
142190cef3dSDag-Erling Smørgrav 	u_char buf[4], *p = NULL;
143545d5ecaSDag-Erling Smørgrav 	u_int msg_len;
144190cef3dSDag-Erling Smørgrav 	int r;
145545d5ecaSDag-Erling Smørgrav 
146545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
147545d5ecaSDag-Erling Smørgrav 
148d4ecd108SDag-Erling Smørgrav 	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
149557f75e5SDag-Erling Smørgrav 		if (errno == EPIPE)
1501ec0d754SDag-Erling Smørgrav 			cleanup_exit(255);
151d4ecd108SDag-Erling Smørgrav 		fatal("%s: read: %s", __func__, strerror(errno));
152545d5ecaSDag-Erling Smørgrav 	}
153190cef3dSDag-Erling Smørgrav 	msg_len = PEEK_U32(buf);
154545d5ecaSDag-Erling Smørgrav 	if (msg_len > 256 * 1024)
155545d5ecaSDag-Erling Smørgrav 		fatal("%s: read: bad msg_len %d", __func__, msg_len);
156190cef3dSDag-Erling Smørgrav 	sshbuf_reset(m);
157190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
158190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
159190cef3dSDag-Erling Smørgrav 	if (atomicio(read, sock, p, msg_len) != msg_len)
160d4ecd108SDag-Erling Smørgrav 		fatal("%s: read: %s", __func__, strerror(errno));
161545d5ecaSDag-Erling Smørgrav }
162545d5ecaSDag-Erling Smørgrav 
163545d5ecaSDag-Erling Smørgrav void
164190cef3dSDag-Erling Smørgrav mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
165545d5ecaSDag-Erling Smørgrav {
166545d5ecaSDag-Erling Smørgrav 	u_char rtype;
167190cef3dSDag-Erling Smørgrav 	int r;
168545d5ecaSDag-Erling Smørgrav 
169545d5ecaSDag-Erling Smørgrav 	debug3("%s entering: type %d", __func__, type);
170545d5ecaSDag-Erling Smørgrav 
17121e764dfSDag-Erling Smørgrav 	mm_request_receive(sock, m);
172190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &rtype)) != 0)
173190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
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 
179a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
180545d5ecaSDag-Erling Smørgrav DH *
181545d5ecaSDag-Erling Smørgrav mm_choose_dh(int min, int nbits, int max)
182545d5ecaSDag-Erling Smørgrav {
183545d5ecaSDag-Erling Smørgrav 	BIGNUM *p, *g;
184190cef3dSDag-Erling Smørgrav 	int r;
185190cef3dSDag-Erling Smørgrav 	u_char success = 0;
186190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
187545d5ecaSDag-Erling Smørgrav 
188190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
189190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
190190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, min)) != 0 ||
191190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, nbits)) != 0 ||
192190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, max)) != 0)
193190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
194545d5ecaSDag-Erling Smørgrav 
195190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
196545d5ecaSDag-Erling Smørgrav 
197545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
198190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
199545d5ecaSDag-Erling Smørgrav 
200190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &success)) != 0)
201190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
202545d5ecaSDag-Erling Smørgrav 	if (success == 0)
203545d5ecaSDag-Erling Smørgrav 		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
204545d5ecaSDag-Erling Smørgrav 
205545d5ecaSDag-Erling Smørgrav 	if ((p = BN_new()) == NULL)
206545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
207545d5ecaSDag-Erling Smørgrav 	if ((g = BN_new()) == NULL)
208545d5ecaSDag-Erling Smørgrav 		fatal("%s: BN_new failed", __func__);
209190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_bignum2(m, p)) != 0 ||
210190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_bignum2(m, g)) != 0)
211190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
212545d5ecaSDag-Erling Smørgrav 
213190cef3dSDag-Erling Smørgrav 	debug3("%s: remaining %zu", __func__, sshbuf_len(m));
214190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
215545d5ecaSDag-Erling Smørgrav 
216545d5ecaSDag-Erling Smørgrav 	return (dh_new_group(g, p));
217545d5ecaSDag-Erling Smørgrav }
218a0ee8cc6SDag-Erling Smørgrav #endif
219545d5ecaSDag-Erling Smørgrav 
220545d5ecaSDag-Erling Smørgrav int
221190cef3dSDag-Erling Smørgrav mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
222190cef3dSDag-Erling Smørgrav     const u_char *data, size_t datalen, const char *hostkey_alg, u_int compat)
223545d5ecaSDag-Erling Smørgrav {
224bc5531deSDag-Erling Smørgrav 	struct kex *kex = *pmonitor->m_pkex;
225190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
226190cef3dSDag-Erling Smørgrav 	u_int ndx = kex->host_key_index(key, 0, active_state);
227190cef3dSDag-Erling Smørgrav 	int r;
228545d5ecaSDag-Erling Smørgrav 
229545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
230545d5ecaSDag-Erling Smørgrav 
231190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
232190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
233190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
234190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
235190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
236190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, compat)) != 0)
237190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
238545d5ecaSDag-Erling Smørgrav 
239190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
240545d5ecaSDag-Erling Smørgrav 
241545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
242190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
243190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
244190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
245190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
246545d5ecaSDag-Erling Smørgrav 
247545d5ecaSDag-Erling Smørgrav 	return (0);
248545d5ecaSDag-Erling Smørgrav }
249545d5ecaSDag-Erling Smørgrav 
250545d5ecaSDag-Erling Smørgrav struct passwd *
25121e764dfSDag-Erling Smørgrav mm_getpwnamallow(const char *username)
252545d5ecaSDag-Erling Smørgrav {
2534f52dfbbSDag-Erling Smørgrav 	struct ssh *ssh = active_state;		/* XXX */
254190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
255545d5ecaSDag-Erling Smørgrav 	struct passwd *pw;
256190cef3dSDag-Erling Smørgrav 	size_t len;
257190cef3dSDag-Erling Smørgrav 	u_int i;
258d4af9e69SDag-Erling Smørgrav 	ServerOptions *newopts;
259190cef3dSDag-Erling Smørgrav 	int r;
260190cef3dSDag-Erling Smørgrav 	u_char ok;
261190cef3dSDag-Erling Smørgrav 	const u_char *p;
262545d5ecaSDag-Erling Smørgrav 
263545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
264545d5ecaSDag-Erling Smørgrav 
265190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
266190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
267190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, username)) != 0)
268190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
269545d5ecaSDag-Erling Smørgrav 
270190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
271545d5ecaSDag-Erling Smørgrav 
272545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
273190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
274545d5ecaSDag-Erling Smørgrav 
275190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &ok)) != 0)
276190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
277190cef3dSDag-Erling Smørgrav 	if (ok == 0) {
278d4af9e69SDag-Erling Smørgrav 		pw = NULL;
279d4af9e69SDag-Erling Smørgrav 		goto out;
280545d5ecaSDag-Erling Smørgrav 	}
281190cef3dSDag-Erling Smørgrav 
282*27ceebbcSEd Maste 	/* XXX don't like passing struct passwd like this */
283*27ceebbcSEd Maste 	pw = xcalloc(sizeof(*pw), 1);
284*27ceebbcSEd Maste 	if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
285*27ceebbcSEd Maste 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
286*27ceebbcSEd Maste 	if (len != sizeof(*pw))
287*27ceebbcSEd Maste 		fatal("%s: struct passwd size mismatch", __func__);
288*27ceebbcSEd Maste 	memcpy(pw, p, sizeof(*pw));
289*27ceebbcSEd Maste 
290*27ceebbcSEd Maste 	if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
291*27ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
292*27ceebbcSEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
293*27ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
294*27ceebbcSEd Maste #endif
295*27ceebbcSEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
296*27ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
297*27ceebbcSEd Maste #endif
298*27ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
299*27ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
300*27ceebbcSEd Maste 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
301d4af9e69SDag-Erling Smørgrav 
302d4af9e69SDag-Erling Smørgrav out:
303d4af9e69SDag-Erling Smørgrav 	/* copy options block as a Match directive may have changed some */
304190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
305190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
306d4af9e69SDag-Erling Smørgrav 	if (len != sizeof(*newopts))
307d4af9e69SDag-Erling Smørgrav 		fatal("%s: option block size mismatch", __func__);
308190cef3dSDag-Erling Smørgrav 	newopts = xcalloc(sizeof(*newopts), 1);
309190cef3dSDag-Erling Smørgrav 	memcpy(newopts, p, sizeof(*newopts));
310e146993eSDag-Erling Smørgrav 
311e146993eSDag-Erling Smørgrav #define M_CP_STROPT(x) do { \
312190cef3dSDag-Erling Smørgrav 		if (newopts->x != NULL) { \
313190cef3dSDag-Erling Smørgrav 			if ((r = sshbuf_get_cstring(m, \
314190cef3dSDag-Erling Smørgrav 			    &newopts->x, NULL)) != 0) \
315190cef3dSDag-Erling Smørgrav 				fatal("%s: buffer error: %s", \
316190cef3dSDag-Erling Smørgrav 				    __func__, ssh_err(r)); \
317190cef3dSDag-Erling Smørgrav 		} \
318e146993eSDag-Erling Smørgrav 	} while (0)
319e146993eSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(x, nx) do { \
3204f52dfbbSDag-Erling Smørgrav 		newopts->x = newopts->nx == 0 ? \
3214f52dfbbSDag-Erling Smørgrav 		    NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
322190cef3dSDag-Erling Smørgrav 		for (i = 0; i < newopts->nx; i++) { \
323190cef3dSDag-Erling Smørgrav 			if ((r = sshbuf_get_cstring(m, \
324190cef3dSDag-Erling Smørgrav 			    &newopts->x[i], NULL)) != 0) \
325190cef3dSDag-Erling Smørgrav 				fatal("%s: buffer error: %s", \
326190cef3dSDag-Erling Smørgrav 				    __func__, ssh_err(r)); \
327190cef3dSDag-Erling Smørgrav 		} \
3284f52dfbbSDag-Erling Smørgrav 	} while (0)
329e146993eSDag-Erling Smørgrav 	/* See comment in servconf.h */
330e146993eSDag-Erling Smørgrav 	COPY_MATCH_STRING_OPTS();
331e146993eSDag-Erling Smørgrav #undef M_CP_STROPT
332e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT
333e146993eSDag-Erling Smørgrav 
334d4af9e69SDag-Erling Smørgrav 	copy_set_server_options(&options, newopts, 1);
3354f52dfbbSDag-Erling Smørgrav 	log_change_level(options.log_level);
3364f52dfbbSDag-Erling Smørgrav 	process_permitopen(ssh, &options);
337e4a9863fSDag-Erling Smørgrav 	free(newopts);
338d4af9e69SDag-Erling Smørgrav 
339190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
340545d5ecaSDag-Erling Smørgrav 
341545d5ecaSDag-Erling Smørgrav 	return (pw);
342545d5ecaSDag-Erling Smørgrav }
343545d5ecaSDag-Erling Smørgrav 
3441ec0d754SDag-Erling Smørgrav char *
3451ec0d754SDag-Erling Smørgrav mm_auth2_read_banner(void)
346545d5ecaSDag-Erling Smørgrav {
347190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
348545d5ecaSDag-Erling Smørgrav 	char *banner;
349190cef3dSDag-Erling Smørgrav 	int r;
350545d5ecaSDag-Erling Smørgrav 
351545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
352545d5ecaSDag-Erling Smørgrav 
353190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
354190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
355190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
356190cef3dSDag-Erling Smørgrav 	sshbuf_reset(m);
357545d5ecaSDag-Erling Smørgrav 
3581ec0d754SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
359190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_AUTH2_READ_BANNER, m);
360190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
361190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
362190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
363545d5ecaSDag-Erling Smørgrav 
3641ec0d754SDag-Erling Smørgrav 	/* treat empty banner as missing banner */
3651ec0d754SDag-Erling Smørgrav 	if (strlen(banner) == 0) {
366e4a9863fSDag-Erling Smørgrav 		free(banner);
3671ec0d754SDag-Erling Smørgrav 		banner = NULL;
3681ec0d754SDag-Erling Smørgrav 	}
369545d5ecaSDag-Erling Smørgrav 	return (banner);
370545d5ecaSDag-Erling Smørgrav }
371545d5ecaSDag-Erling Smørgrav 
372545d5ecaSDag-Erling Smørgrav /* Inform the privileged process about service and style */
373545d5ecaSDag-Erling Smørgrav 
374545d5ecaSDag-Erling Smørgrav void
375545d5ecaSDag-Erling Smørgrav mm_inform_authserv(char *service, char *style)
376545d5ecaSDag-Erling Smørgrav {
377190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
378190cef3dSDag-Erling Smørgrav 	int r;
379545d5ecaSDag-Erling Smørgrav 
380545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
381545d5ecaSDag-Erling Smørgrav 
382190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
383190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
384190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, service)) != 0 ||
385190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
386190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
387545d5ecaSDag-Erling Smørgrav 
388190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
389545d5ecaSDag-Erling Smørgrav 
390190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
391545d5ecaSDag-Erling Smørgrav }
392545d5ecaSDag-Erling Smørgrav 
393545d5ecaSDag-Erling Smørgrav /* Do the password authentication */
394545d5ecaSDag-Erling Smørgrav int
39547dd1d1bSDag-Erling Smørgrav mm_auth_password(struct ssh *ssh, char *password)
396545d5ecaSDag-Erling Smørgrav {
397190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
398190cef3dSDag-Erling Smørgrav 	int r, authenticated = 0;
399190cef3dSDag-Erling Smørgrav #ifdef USE_PAM
400190cef3dSDag-Erling Smørgrav 	u_int maxtries = 0;
401190cef3dSDag-Erling Smørgrav #endif
402545d5ecaSDag-Erling Smørgrav 
403545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
404545d5ecaSDag-Erling Smørgrav 
405190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
406190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
407190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, password)) != 0)
408190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
409190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
410545d5ecaSDag-Erling Smørgrav 
411545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
412190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
413190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_AUTHPASSWORD, m);
414545d5ecaSDag-Erling Smørgrav 
415190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
416190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
417076ad2f8SDag-Erling Smørgrav #ifdef USE_PAM
418190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
419190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
420190cef3dSDag-Erling Smørgrav 	if (maxtries > INT_MAX)
421190cef3dSDag-Erling Smørgrav 		fatal("%s: bad maxtries %u", __func__, maxtries);
422190cef3dSDag-Erling Smørgrav 	sshpam_set_maxtries_reached(maxtries);
423076ad2f8SDag-Erling Smørgrav #endif
424545d5ecaSDag-Erling Smørgrav 
425190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
426545d5ecaSDag-Erling Smørgrav 
427545d5ecaSDag-Erling Smørgrav 	debug3("%s: user %sauthenticated",
428545d5ecaSDag-Erling Smørgrav 	    __func__, authenticated ? "" : "not ");
429545d5ecaSDag-Erling Smørgrav 	return (authenticated);
430545d5ecaSDag-Erling Smørgrav }
431545d5ecaSDag-Erling Smørgrav 
432545d5ecaSDag-Erling Smørgrav int
43347dd1d1bSDag-Erling Smørgrav mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
43447dd1d1bSDag-Erling Smørgrav     int pubkey_auth_attempt, struct sshauthopt **authoptp)
435545d5ecaSDag-Erling Smørgrav {
436557f75e5SDag-Erling Smørgrav 	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
43747dd1d1bSDag-Erling Smørgrav 	    pubkey_auth_attempt, authoptp));
438545d5ecaSDag-Erling Smørgrav }
439545d5ecaSDag-Erling Smørgrav 
440545d5ecaSDag-Erling Smørgrav int
441076ad2f8SDag-Erling Smørgrav mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
4424f52dfbbSDag-Erling Smørgrav     struct sshkey *key)
443545d5ecaSDag-Erling Smørgrav {
44447dd1d1bSDag-Erling Smørgrav 	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
445545d5ecaSDag-Erling Smørgrav }
446545d5ecaSDag-Erling Smørgrav 
447545d5ecaSDag-Erling Smørgrav int
448076ad2f8SDag-Erling Smørgrav mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
44947dd1d1bSDag-Erling Smørgrav     struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
450545d5ecaSDag-Erling Smørgrav {
451190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
45247dd1d1bSDag-Erling Smørgrav 	int r, allowed = 0;
45347dd1d1bSDag-Erling Smørgrav 	struct sshauthopt *opts = NULL;
454545d5ecaSDag-Erling Smørgrav 
455545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
456545d5ecaSDag-Erling Smørgrav 
45747dd1d1bSDag-Erling Smørgrav 	if (authoptp != NULL)
45847dd1d1bSDag-Erling Smørgrav 		*authoptp = NULL;
45947dd1d1bSDag-Erling Smørgrav 
460190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
461190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
462190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, type)) != 0 ||
463190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
464190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
465190cef3dSDag-Erling Smørgrav 	    (r = sshkey_puts(key, m)) != 0 ||
466190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
467190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
468545d5ecaSDag-Erling Smørgrav 
469190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
470545d5ecaSDag-Erling Smørgrav 
471545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
47247dd1d1bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
473190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_KEYALLOWED, m);
474545d5ecaSDag-Erling Smørgrav 
475190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &allowed)) != 0)
476190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
47747dd1d1bSDag-Erling Smørgrav 	if (allowed && type == MM_USERKEY) {
478190cef3dSDag-Erling Smørgrav 		if ((r = sshauthopt_deserialise(m, &opts)) != 0)
47947dd1d1bSDag-Erling Smørgrav 			fatal("%s: sshauthopt_deserialise: %s",
48047dd1d1bSDag-Erling Smørgrav 			    __func__, ssh_err(r));
48147dd1d1bSDag-Erling Smørgrav 	}
482190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
483545d5ecaSDag-Erling Smørgrav 
48447dd1d1bSDag-Erling Smørgrav 	if (authoptp != NULL) {
48547dd1d1bSDag-Erling Smørgrav 		*authoptp = opts;
48647dd1d1bSDag-Erling Smørgrav 		opts = NULL;
48747dd1d1bSDag-Erling Smørgrav 	}
48847dd1d1bSDag-Erling Smørgrav 	sshauthopt_free(opts);
48947dd1d1bSDag-Erling Smørgrav 
49047dd1d1bSDag-Erling Smørgrav 	return allowed;
491545d5ecaSDag-Erling Smørgrav }
492545d5ecaSDag-Erling Smørgrav 
493545d5ecaSDag-Erling Smørgrav /*
494545d5ecaSDag-Erling Smørgrav  * This key verify needs to send the key type along, because the
495545d5ecaSDag-Erling Smørgrav  * privileged parent makes the decision if the key is allowed
496545d5ecaSDag-Erling Smørgrav  * for authentication.
497545d5ecaSDag-Erling Smørgrav  */
498545d5ecaSDag-Erling Smørgrav 
499545d5ecaSDag-Erling Smørgrav int
5004f52dfbbSDag-Erling Smørgrav mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
50147dd1d1bSDag-Erling Smørgrav     const u_char *data, size_t datalen, const char *sigalg, u_int compat)
502545d5ecaSDag-Erling Smørgrav {
503190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
5044f52dfbbSDag-Erling Smørgrav 	u_int encoded_ret = 0;
505190cef3dSDag-Erling Smørgrav 	int r;
506545d5ecaSDag-Erling Smørgrav 
507545d5ecaSDag-Erling Smørgrav 	debug3("%s entering", __func__);
508545d5ecaSDag-Erling Smørgrav 
509545d5ecaSDag-Erling Smørgrav 
510190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
511190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
512190cef3dSDag-Erling Smørgrav 	if ((r = sshkey_puts(key, m)) != 0 ||
513190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, sig, siglen)) != 0 ||
514190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
515190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
516190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
517545d5ecaSDag-Erling Smørgrav 
518190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
519545d5ecaSDag-Erling Smørgrav 
520545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
521190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
522190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_KEYVERIFY, m);
523545d5ecaSDag-Erling Smørgrav 
524190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0)
525190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
526545d5ecaSDag-Erling Smørgrav 
527190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
528545d5ecaSDag-Erling Smørgrav 
5294f52dfbbSDag-Erling Smørgrav 	if (encoded_ret != 0)
5304f52dfbbSDag-Erling Smørgrav 		return SSH_ERR_SIGNATURE_INVALID;
5314f52dfbbSDag-Erling Smørgrav 	return 0;
532545d5ecaSDag-Erling Smørgrav }
533545d5ecaSDag-Erling Smørgrav 
534545d5ecaSDag-Erling Smørgrav void
53521e764dfSDag-Erling Smørgrav mm_send_keystate(struct monitor *monitor)
536545d5ecaSDag-Erling Smørgrav {
537bc5531deSDag-Erling Smørgrav 	struct ssh *ssh = active_state;		/* XXX */
538bc5531deSDag-Erling Smørgrav 	struct sshbuf *m;
539bc5531deSDag-Erling Smørgrav 	int r;
540545d5ecaSDag-Erling Smørgrav 
541bc5531deSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
542bc5531deSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
543bc5531deSDag-Erling Smørgrav 	if ((r = ssh_packet_get_state(ssh, m)) != 0)
544bc5531deSDag-Erling Smørgrav 		fatal("%s: get_state failed: %s",
545bc5531deSDag-Erling Smørgrav 		    __func__, ssh_err(r));
546bc5531deSDag-Erling Smørgrav 	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
547545d5ecaSDag-Erling Smørgrav 	debug3("%s: Finished sending state", __func__);
548bc5531deSDag-Erling Smørgrav 	sshbuf_free(m);
549545d5ecaSDag-Erling Smørgrav }
550545d5ecaSDag-Erling Smørgrav 
551545d5ecaSDag-Erling Smørgrav int
552333ee039SDag-Erling Smørgrav mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
553545d5ecaSDag-Erling Smørgrav {
554190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
55521e764dfSDag-Erling Smørgrav 	char *p, *msg;
556190cef3dSDag-Erling Smørgrav 	int success = 0, tmp1 = -1, tmp2 = -1, r;
557d4af9e69SDag-Erling Smørgrav 
558d4af9e69SDag-Erling Smørgrav 	/* Kludge: ensure there are fds free to receive the pty/tty */
559d4af9e69SDag-Erling Smørgrav 	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
560d4af9e69SDag-Erling Smørgrav 	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
561d4af9e69SDag-Erling Smørgrav 		error("%s: cannot allocate fds for pty", __func__);
562d4af9e69SDag-Erling Smørgrav 		if (tmp1 > 0)
563d4af9e69SDag-Erling Smørgrav 			close(tmp1);
564d4af9e69SDag-Erling Smørgrav 		if (tmp2 > 0)
565d4af9e69SDag-Erling Smørgrav 			close(tmp2);
566d4af9e69SDag-Erling Smørgrav 		return 0;
567d4af9e69SDag-Erling Smørgrav 	}
568d4af9e69SDag-Erling Smørgrav 	close(tmp1);
569d4af9e69SDag-Erling Smørgrav 	close(tmp2);
570545d5ecaSDag-Erling Smørgrav 
571190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
572190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
573190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
574545d5ecaSDag-Erling Smørgrav 
575545d5ecaSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
576190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
577545d5ecaSDag-Erling Smørgrav 
578190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
579190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
580545d5ecaSDag-Erling Smørgrav 	if (success == 0) {
581545d5ecaSDag-Erling Smørgrav 		debug3("%s: pty alloc failed", __func__);
582190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
583545d5ecaSDag-Erling Smørgrav 		return (0);
584545d5ecaSDag-Erling Smørgrav 	}
585190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
586190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
587190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
588190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
589545d5ecaSDag-Erling Smørgrav 
590545d5ecaSDag-Erling Smørgrav 	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
591e4a9863fSDag-Erling Smørgrav 	free(p);
592545d5ecaSDag-Erling Smørgrav 
593190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
594190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
595e4a9863fSDag-Erling Smørgrav 	free(msg);
59621e764dfSDag-Erling Smørgrav 
597d4af9e69SDag-Erling Smørgrav 	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
598d4af9e69SDag-Erling Smørgrav 	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
599d4af9e69SDag-Erling Smørgrav 		fatal("%s: receive fds failed", __func__);
600545d5ecaSDag-Erling Smørgrav 
601545d5ecaSDag-Erling Smørgrav 	/* Success */
602545d5ecaSDag-Erling Smørgrav 	return (1);
603545d5ecaSDag-Erling Smørgrav }
604545d5ecaSDag-Erling Smørgrav 
605545d5ecaSDag-Erling Smørgrav void
6061ec0d754SDag-Erling Smørgrav mm_session_pty_cleanup2(Session *s)
607545d5ecaSDag-Erling Smørgrav {
608190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
609190cef3dSDag-Erling Smørgrav 	int r;
610545d5ecaSDag-Erling Smørgrav 
611545d5ecaSDag-Erling Smørgrav 	if (s->ttyfd == -1)
612545d5ecaSDag-Erling Smørgrav 		return;
613190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
614190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
615190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
616190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
617190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
618190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
619545d5ecaSDag-Erling Smørgrav 
620545d5ecaSDag-Erling Smørgrav 	/* closed dup'ed master */
621d4af9e69SDag-Erling Smørgrav 	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
622d4af9e69SDag-Erling Smørgrav 		error("close(s->ptymaster/%d): %s",
623d4af9e69SDag-Erling Smørgrav 		    s->ptymaster, strerror(errno));
624545d5ecaSDag-Erling Smørgrav 
625545d5ecaSDag-Erling Smørgrav 	/* unlink pty from session */
626545d5ecaSDag-Erling Smørgrav 	s->ttyfd = -1;
627545d5ecaSDag-Erling Smørgrav }
628545d5ecaSDag-Erling Smørgrav 
62983d2307dSDag-Erling Smørgrav #ifdef USE_PAM
63083d2307dSDag-Erling Smørgrav void
6315962c0e9SDag-Erling Smørgrav mm_start_pam(Authctxt *authctxt)
63283d2307dSDag-Erling Smørgrav {
633190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
63483d2307dSDag-Erling Smørgrav 
63583d2307dSDag-Erling Smørgrav 	debug3("%s entering", __func__);
636cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
637cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
638190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
639190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
640190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
64183d2307dSDag-Erling Smørgrav 
642190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
64383d2307dSDag-Erling Smørgrav }
644382d19eeSDag-Erling Smørgrav 
645cf2b5f3bSDag-Erling Smørgrav u_int
646cf2b5f3bSDag-Erling Smørgrav mm_do_pam_account(void)
647cf2b5f3bSDag-Erling Smørgrav {
648190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
649cf2b5f3bSDag-Erling Smørgrav 	u_int ret;
650aa49c926SDag-Erling Smørgrav 	char *msg;
651190cef3dSDag-Erling Smørgrav 	size_t msglen;
652190cef3dSDag-Erling Smørgrav 	int r;
653cf2b5f3bSDag-Erling Smørgrav 
654cf2b5f3bSDag-Erling Smørgrav 	debug3("%s entering", __func__);
655cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
656cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
657cf2b5f3bSDag-Erling Smørgrav 
658190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
659190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
660190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
661cf2b5f3bSDag-Erling Smørgrav 
662cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
663190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_ACCOUNT, m);
664190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
665190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 ||
666190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put(loginmsg, msg, msglen)) != 0)
667190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
668cf2b5f3bSDag-Erling Smørgrav 
669190cef3dSDag-Erling Smørgrav 	free(msg);
670190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
671cf2b5f3bSDag-Erling Smørgrav 
672cf2b5f3bSDag-Erling Smørgrav 	debug3("%s returning %d", __func__, ret);
673cf2b5f3bSDag-Erling Smørgrav 
674cf2b5f3bSDag-Erling Smørgrav 	return (ret);
675cf2b5f3bSDag-Erling Smørgrav }
676cf2b5f3bSDag-Erling Smørgrav 
677382d19eeSDag-Erling Smørgrav void *
678cf2b5f3bSDag-Erling Smørgrav mm_sshpam_init_ctx(Authctxt *authctxt)
679382d19eeSDag-Erling Smørgrav {
680190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
681190cef3dSDag-Erling Smørgrav 	int r, success;
682382d19eeSDag-Erling Smørgrav 
683382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
684190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
685190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
686190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
687382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
688190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
689190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_INIT_CTX, m);
690190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
691190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
692382d19eeSDag-Erling Smørgrav 	if (success == 0) {
693382d19eeSDag-Erling Smørgrav 		debug3("%s: pam_init_ctx failed", __func__);
694190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
695382d19eeSDag-Erling Smørgrav 		return (NULL);
696382d19eeSDag-Erling Smørgrav 	}
697190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
698382d19eeSDag-Erling Smørgrav 	return (authctxt);
699382d19eeSDag-Erling Smørgrav }
700382d19eeSDag-Erling Smørgrav 
701382d19eeSDag-Erling Smørgrav int
702cf2b5f3bSDag-Erling Smørgrav mm_sshpam_query(void *ctx, char **name, char **info,
703382d19eeSDag-Erling Smørgrav     u_int *num, char ***prompts, u_int **echo_on)
704382d19eeSDag-Erling Smørgrav {
705190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
706190cef3dSDag-Erling Smørgrav 	u_int i, n;
707190cef3dSDag-Erling Smørgrav 	int r, ret;
708382d19eeSDag-Erling Smørgrav 
709382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
710190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
711190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
712190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
713382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
714190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
715190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
716190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
717190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
718190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_u32(m, &n)) != 0 ||
719190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_u32(m, num)) != 0)
720190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
721382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_query returned %d", __func__, ret);
722190cef3dSDag-Erling Smørgrav 	sshpam_set_maxtries_reached(n);
723333ee039SDag-Erling Smørgrav 	if (*num > PAM_MAX_NUM_MSG)
724190cef3dSDag-Erling Smørgrav 		fatal("%s: received %u PAM messages, expected <= %u",
725333ee039SDag-Erling Smørgrav 		    __func__, *num, PAM_MAX_NUM_MSG);
726333ee039SDag-Erling Smørgrav 	*prompts = xcalloc((*num + 1), sizeof(char *));
727333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc((*num + 1), sizeof(u_int));
728382d19eeSDag-Erling Smørgrav 	for (i = 0; i < *num; ++i) {
729190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 ||
730190cef3dSDag-Erling Smørgrav 		    (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0)
731190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
732382d19eeSDag-Erling Smørgrav 	}
733190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
734382d19eeSDag-Erling Smørgrav 	return (ret);
735382d19eeSDag-Erling Smørgrav }
736382d19eeSDag-Erling Smørgrav 
737382d19eeSDag-Erling Smørgrav int
738cf2b5f3bSDag-Erling Smørgrav mm_sshpam_respond(void *ctx, u_int num, char **resp)
739382d19eeSDag-Erling Smørgrav {
740190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
741190cef3dSDag-Erling Smørgrav 	u_int n, i;
742190cef3dSDag-Erling Smørgrav 	int r, ret;
743382d19eeSDag-Erling Smørgrav 
744382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
745190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
746190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
747190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, num)) != 0)
748190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
749190cef3dSDag-Erling Smørgrav 	for (i = 0; i < num; ++i) {
750190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_put_cstring(m, resp[i])) != 0)
751190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
752190cef3dSDag-Erling Smørgrav 	}
753190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
754382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
755190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
756190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_RESPOND, m);
757190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &n)) != 0)
758190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
759190cef3dSDag-Erling Smørgrav 	ret = (int)n; /* XXX */
760382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_respond returned %d", __func__, ret);
761190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
762382d19eeSDag-Erling Smørgrav 	return (ret);
763382d19eeSDag-Erling Smørgrav }
764382d19eeSDag-Erling Smørgrav 
765382d19eeSDag-Erling Smørgrav void
766cf2b5f3bSDag-Erling Smørgrav mm_sshpam_free_ctx(void *ctxtp)
767382d19eeSDag-Erling Smørgrav {
768190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
769382d19eeSDag-Erling Smørgrav 
770382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
771190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
772190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
773190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
774382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
775190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
776190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_FREE_CTX, m);
777190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
778382d19eeSDag-Erling Smørgrav }
77983d2307dSDag-Erling Smørgrav #endif /* USE_PAM */
78083d2307dSDag-Erling Smørgrav 
781545d5ecaSDag-Erling Smørgrav /* Request process termination */
782545d5ecaSDag-Erling Smørgrav 
783545d5ecaSDag-Erling Smørgrav void
784545d5ecaSDag-Erling Smørgrav mm_terminate(void)
785545d5ecaSDag-Erling Smørgrav {
786190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
787545d5ecaSDag-Erling Smørgrav 
788190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
789190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
790190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
791190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
792545d5ecaSDag-Erling Smørgrav }
793545d5ecaSDag-Erling Smørgrav 
794545d5ecaSDag-Erling Smørgrav static void
795545d5ecaSDag-Erling Smørgrav mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
796545d5ecaSDag-Erling Smørgrav     char ***prompts, u_int **echo_on)
797545d5ecaSDag-Erling Smørgrav {
798545d5ecaSDag-Erling Smørgrav 	*name = xstrdup("");
799545d5ecaSDag-Erling Smørgrav 	*infotxt = xstrdup("");
800545d5ecaSDag-Erling Smørgrav 	*numprompts = 1;
801333ee039SDag-Erling Smørgrav 	*prompts = xcalloc(*numprompts, sizeof(char *));
802333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc(*numprompts, sizeof(u_int));
803545d5ecaSDag-Erling Smørgrav 	(*echo_on)[0] = 0;
804545d5ecaSDag-Erling Smørgrav }
805545d5ecaSDag-Erling Smørgrav 
806545d5ecaSDag-Erling Smørgrav int
807545d5ecaSDag-Erling Smørgrav mm_bsdauth_query(void *ctx, char **name, char **infotxt,
808545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
809545d5ecaSDag-Erling Smørgrav {
810190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
811e73e9afaSDag-Erling Smørgrav 	u_int success;
812545d5ecaSDag-Erling Smørgrav 	char *challenge;
813190cef3dSDag-Erling Smørgrav 	int r;
814545d5ecaSDag-Erling Smørgrav 
815545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
816545d5ecaSDag-Erling Smørgrav 
817190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
818190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
819190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
820545d5ecaSDag-Erling Smørgrav 
821190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
822190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHQUERY, m);
823190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
824190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
825e73e9afaSDag-Erling Smørgrav 	if (success == 0) {
826545d5ecaSDag-Erling Smørgrav 		debug3("%s: no challenge", __func__);
827190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
828545d5ecaSDag-Erling Smørgrav 		return (-1);
829545d5ecaSDag-Erling Smørgrav 	}
830545d5ecaSDag-Erling Smørgrav 
831545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
832190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
833190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
834190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
835545d5ecaSDag-Erling Smørgrav 
836545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
837545d5ecaSDag-Erling Smørgrav 	(*prompts)[0] = challenge;
838545d5ecaSDag-Erling Smørgrav 
839545d5ecaSDag-Erling Smørgrav 	debug3("%s: received challenge: %s", __func__, challenge);
840545d5ecaSDag-Erling Smørgrav 
841545d5ecaSDag-Erling Smørgrav 	return (0);
842545d5ecaSDag-Erling Smørgrav }
843545d5ecaSDag-Erling Smørgrav 
844545d5ecaSDag-Erling Smørgrav int
845545d5ecaSDag-Erling Smørgrav mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
846545d5ecaSDag-Erling Smørgrav {
847190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
848190cef3dSDag-Erling Smørgrav 	int r, authok;
849545d5ecaSDag-Erling Smørgrav 
850545d5ecaSDag-Erling Smørgrav 	debug3("%s: entering", __func__);
851545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
852545d5ecaSDag-Erling Smørgrav 		return (-1);
853545d5ecaSDag-Erling Smørgrav 
854190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
855190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
856190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
857190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
858190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
859545d5ecaSDag-Erling Smørgrav 
860545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
861190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHRESPOND, m);
862545d5ecaSDag-Erling Smørgrav 
863190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authok)) != 0)
864190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
865190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
866545d5ecaSDag-Erling Smørgrav 
867545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
868545d5ecaSDag-Erling Smørgrav }
869545d5ecaSDag-Erling Smørgrav 
870aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS
871aa49c926SDag-Erling Smørgrav void
872aa49c926SDag-Erling Smørgrav mm_audit_event(ssh_audit_event_t event)
873aa49c926SDag-Erling Smørgrav {
874190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
875190cef3dSDag-Erling Smørgrav 	int r;
876aa49c926SDag-Erling Smørgrav 
877aa49c926SDag-Erling Smørgrav 	debug3("%s entering", __func__);
878aa49c926SDag-Erling Smørgrav 
879190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
880190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
881190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, event)) != 0)
882190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
883aa49c926SDag-Erling Smørgrav 
884190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m);
885190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
886aa49c926SDag-Erling Smørgrav }
887aa49c926SDag-Erling Smørgrav 
888aa49c926SDag-Erling Smørgrav void
889aa49c926SDag-Erling Smørgrav mm_audit_run_command(const char *command)
890aa49c926SDag-Erling Smørgrav {
891190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
892190cef3dSDag-Erling Smørgrav 	int r;
893aa49c926SDag-Erling Smørgrav 
894aa49c926SDag-Erling Smørgrav 	debug3("%s entering command %s", __func__, command);
895aa49c926SDag-Erling Smørgrav 
896190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
897190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
898190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, command)) != 0)
899190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
900aa49c926SDag-Erling Smørgrav 
901190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
902190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
903aa49c926SDag-Erling Smørgrav }
904aa49c926SDag-Erling Smørgrav #endif /* SSH_AUDIT_EVENTS */
905aa49c926SDag-Erling Smørgrav 
906cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
907cf2b5f3bSDag-Erling Smørgrav OM_uint32
90821e764dfSDag-Erling Smørgrav mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
909f388f5efSDag-Erling Smørgrav {
910190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
911cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
912190cef3dSDag-Erling Smørgrav 	int r;
913f388f5efSDag-Erling Smørgrav 
914cf2b5f3bSDag-Erling Smørgrav 	/* Client doesn't get to see the context */
915cf2b5f3bSDag-Erling Smørgrav 	*ctx = NULL;
916f388f5efSDag-Erling Smørgrav 
917190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
918190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
919190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
920190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
921f388f5efSDag-Erling Smørgrav 
922190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
923190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
924f388f5efSDag-Erling Smørgrav 
925190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0)
926190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
927cf2b5f3bSDag-Erling Smørgrav 
928190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
929cf2b5f3bSDag-Erling Smørgrav 	return (major);
930f388f5efSDag-Erling Smørgrav }
931f388f5efSDag-Erling Smørgrav 
932cf2b5f3bSDag-Erling Smørgrav OM_uint32
933cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
934190cef3dSDag-Erling Smørgrav     gss_buffer_desc *out, OM_uint32 *flagsp)
935f388f5efSDag-Erling Smørgrav {
936190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
937cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
938190cef3dSDag-Erling Smørgrav 	u_int flags;
939190cef3dSDag-Erling Smørgrav 	int r;
940f388f5efSDag-Erling Smørgrav 
941190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
942190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
943190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
944190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
945cf2b5f3bSDag-Erling Smørgrav 
946190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
947190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
948cf2b5f3bSDag-Erling Smørgrav 
949190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0 ||
950190cef3dSDag-Erling Smørgrav 	    (r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
951190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
952190cef3dSDag-Erling Smørgrav 	if (flagsp != NULL) {
953190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_get_u32(m, &flags)) != 0)
954190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
955190cef3dSDag-Erling Smørgrav 		*flagsp = flags;
956190cef3dSDag-Erling Smørgrav 	}
957f388f5efSDag-Erling Smørgrav 
958190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
959cf2b5f3bSDag-Erling Smørgrav 
960cf2b5f3bSDag-Erling Smørgrav 	return (major);
961f388f5efSDag-Erling Smørgrav }
962cf2b5f3bSDag-Erling Smørgrav 
9631ec0d754SDag-Erling Smørgrav OM_uint32
9641ec0d754SDag-Erling Smørgrav mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
9651ec0d754SDag-Erling Smørgrav {
966190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
9671ec0d754SDag-Erling Smørgrav 	OM_uint32 major;
968190cef3dSDag-Erling Smørgrav 	int r;
9691ec0d754SDag-Erling Smørgrav 
970190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
971190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
972190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
973190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
974190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
9751ec0d754SDag-Erling Smørgrav 
976190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
977190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
978190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_GSSCHECKMIC, m);
9791ec0d754SDag-Erling Smørgrav 
980190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0)
981190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
982190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
9831ec0d754SDag-Erling Smørgrav 	return(major);
9841ec0d754SDag-Erling Smørgrav }
9851ec0d754SDag-Erling Smørgrav 
986cf2b5f3bSDag-Erling Smørgrav int
987cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_userok(char *user)
988cf2b5f3bSDag-Erling Smørgrav {
989190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
990190cef3dSDag-Erling Smørgrav 	int r, authenticated = 0;
991cf2b5f3bSDag-Erling Smørgrav 
992190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
993190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
994cf2b5f3bSDag-Erling Smørgrav 
995190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
996190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
997190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_GSSUSEROK, m);
998cf2b5f3bSDag-Erling Smørgrav 
999190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
1000190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1001cf2b5f3bSDag-Erling Smørgrav 
1002190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
1003cf2b5f3bSDag-Erling Smørgrav 	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1004cf2b5f3bSDag-Erling Smørgrav 	return (authenticated);
1005cf2b5f3bSDag-Erling Smørgrav }
1006cf2b5f3bSDag-Erling Smørgrav #endif /* GSSAPI */
1007