xref: /freebsd/crypto/openssh/monitor_wrap.c (revision 0fdf8fae8b569bf9fff3b5171e669dcd7cf9c79e)
1*0fdf8faeSEd Maste /* $OpenBSD: monitor_wrap.c,v 1.136 2024/06/19 23:24:47 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>
32*0fdf8faeSEd Maste #include <sys/wait.h>
33333ee039SDag-Erling Smørgrav 
34333ee039SDag-Erling Smørgrav #include <errno.h>
35333ee039SDag-Erling Smørgrav #include <pwd.h>
36333ee039SDag-Erling Smørgrav #include <signal.h>
37333ee039SDag-Erling Smørgrav #include <stdarg.h>
38333ee039SDag-Erling Smørgrav #include <stdio.h>
39333ee039SDag-Erling Smørgrav #include <string.h>
40333ee039SDag-Erling Smørgrav #include <unistd.h>
41545d5ecaSDag-Erling Smørgrav 
42a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
43545d5ecaSDag-Erling Smørgrav #include <openssl/bn.h>
44545d5ecaSDag-Erling Smørgrav #include <openssl/dh.h>
45cce7d346SDag-Erling Smørgrav #include <openssl/evp.h>
46a0ee8cc6SDag-Erling Smørgrav #endif
47545d5ecaSDag-Erling Smørgrav 
48d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h"
49333ee039SDag-Erling Smørgrav #include "xmalloc.h"
50545d5ecaSDag-Erling Smørgrav #include "ssh.h"
51a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
52545d5ecaSDag-Erling Smørgrav #include "dh.h"
53a0ee8cc6SDag-Erling Smørgrav #endif
54190cef3dSDag-Erling Smørgrav #include "sshbuf.h"
55190cef3dSDag-Erling Smørgrav #include "sshkey.h"
56333ee039SDag-Erling Smørgrav #include "cipher.h"
57545d5ecaSDag-Erling Smørgrav #include "kex.h"
58333ee039SDag-Erling Smørgrav #include "hostfile.h"
59545d5ecaSDag-Erling Smørgrav #include "auth.h"
60e73e9afaSDag-Erling Smørgrav #include "auth-options.h"
61545d5ecaSDag-Erling Smørgrav #include "packet.h"
62545d5ecaSDag-Erling Smørgrav #include "mac.h"
63545d5ecaSDag-Erling Smørgrav #include "log.h"
64076ad2f8SDag-Erling Smørgrav #include "auth-pam.h"
65545d5ecaSDag-Erling Smørgrav #include "monitor.h"
66cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
67cf2b5f3bSDag-Erling Smørgrav #include "ssh-gss.h"
68cf2b5f3bSDag-Erling Smørgrav #endif
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"
76*0fdf8faeSEd Maste #include "monitor_wrap.h"
77*0fdf8faeSEd Maste #include "srclimit.h"
78cf2b5f3bSDag-Erling Smørgrav 
79bc5531deSDag-Erling Smørgrav #include "ssherr.h"
80bc5531deSDag-Erling Smørgrav 
81545d5ecaSDag-Erling Smørgrav /* Imports */
82545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor;
83190cef3dSDag-Erling Smørgrav extern struct sshbuf *loginmsg;
84cf2b5f3bSDag-Erling Smørgrav extern ServerOptions options;
85545d5ecaSDag-Erling Smørgrav 
86e146993eSDag-Erling Smørgrav void
mm_log_handler(LogLevel level,int forced,const char * msg,void * ctx)8719261079SEd Maste mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx)
88e146993eSDag-Erling Smørgrav {
89190cef3dSDag-Erling Smørgrav 	struct sshbuf *log_msg;
90e146993eSDag-Erling Smørgrav 	struct monitor *mon = (struct monitor *)ctx;
91190cef3dSDag-Erling Smørgrav 	int r;
92190cef3dSDag-Erling Smørgrav 	size_t len;
93e146993eSDag-Erling Smørgrav 
94e146993eSDag-Erling Smørgrav 	if (mon->m_log_sendfd == -1)
9519261079SEd Maste 		fatal_f("no log channel");
96e146993eSDag-Erling Smørgrav 
97190cef3dSDag-Erling Smørgrav 	if ((log_msg = sshbuf_new()) == NULL)
9819261079SEd Maste 		fatal_f("sshbuf_new failed");
99e146993eSDag-Erling Smørgrav 
100190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
101190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(log_msg, level)) != 0 ||
10219261079SEd Maste 	    (r = sshbuf_put_u32(log_msg, forced)) != 0 ||
103190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(log_msg, msg)) != 0)
10419261079SEd Maste 		fatal_fr(r, "assemble");
105190cef3dSDag-Erling Smørgrav 	if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
10619261079SEd Maste 		fatal_f("bad length %zu", len);
107190cef3dSDag-Erling Smørgrav 	POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
108190cef3dSDag-Erling Smørgrav 	if (atomicio(vwrite, mon->m_log_sendfd,
109190cef3dSDag-Erling Smørgrav 	    sshbuf_mutable_ptr(log_msg), len) != len)
11019261079SEd Maste 		fatal_f("write: %s", strerror(errno));
111190cef3dSDag-Erling Smørgrav 	sshbuf_free(log_msg);
112e146993eSDag-Erling Smørgrav }
113e146993eSDag-Erling Smørgrav 
1141ec0d754SDag-Erling Smørgrav int
mm_is_monitor(void)1151ec0d754SDag-Erling Smørgrav mm_is_monitor(void)
1161ec0d754SDag-Erling Smørgrav {
1171ec0d754SDag-Erling Smørgrav 	/*
1181ec0d754SDag-Erling Smørgrav 	 * m_pid is only set in the privileged part, and
1191ec0d754SDag-Erling Smørgrav 	 * points to the unprivileged child.
1201ec0d754SDag-Erling Smørgrav 	 */
1211ec0d754SDag-Erling Smørgrav 	return (pmonitor && pmonitor->m_pid > 0);
1221ec0d754SDag-Erling Smørgrav }
1231ec0d754SDag-Erling Smørgrav 
124*0fdf8faeSEd Maste static void
mm_reap(void)125*0fdf8faeSEd Maste mm_reap(void)
126*0fdf8faeSEd Maste {
127*0fdf8faeSEd Maste 	int status = -1;
128*0fdf8faeSEd Maste 
129*0fdf8faeSEd Maste 	if (!mm_is_monitor())
130*0fdf8faeSEd Maste 		return;
131*0fdf8faeSEd Maste 	while (waitpid(pmonitor->m_pid, &status, 0) == -1) {
132*0fdf8faeSEd Maste 		if (errno == EINTR)
133*0fdf8faeSEd Maste 			continue;
134*0fdf8faeSEd Maste 		pmonitor->m_pid = -1;
135*0fdf8faeSEd Maste 		fatal_f("waitpid: %s", strerror(errno));
136*0fdf8faeSEd Maste 	}
137*0fdf8faeSEd Maste 	if (WIFEXITED(status)) {
138*0fdf8faeSEd Maste 		if (WEXITSTATUS(status) != 0) {
139*0fdf8faeSEd Maste 			debug_f("preauth child exited with status %d",
140*0fdf8faeSEd Maste 			    WEXITSTATUS(status));
141*0fdf8faeSEd Maste 			cleanup_exit(255);
142*0fdf8faeSEd Maste 		}
143*0fdf8faeSEd Maste 	} else if (WIFSIGNALED(status)) {
144*0fdf8faeSEd Maste 		error_f("preauth child terminated by signal %d",
145*0fdf8faeSEd Maste 		    WTERMSIG(status));
146*0fdf8faeSEd Maste 		cleanup_exit(signal_is_crash(WTERMSIG(status)) ?
147*0fdf8faeSEd Maste 		    EXIT_CHILD_CRASH : 255);
148*0fdf8faeSEd Maste 	} else {
149*0fdf8faeSEd Maste 		error_f("preauth child terminated abnormally (status=0x%x)",
150*0fdf8faeSEd Maste 		    status);
151*0fdf8faeSEd Maste 		cleanup_exit(EXIT_CHILD_CRASH);
152*0fdf8faeSEd Maste 	}
153*0fdf8faeSEd Maste }
154*0fdf8faeSEd Maste 
155545d5ecaSDag-Erling Smørgrav void
mm_request_send(int sock,enum monitor_reqtype type,struct sshbuf * m)156190cef3dSDag-Erling Smørgrav mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
157545d5ecaSDag-Erling Smørgrav {
158190cef3dSDag-Erling Smørgrav 	size_t mlen = sshbuf_len(m);
159f388f5efSDag-Erling Smørgrav 	u_char buf[5];
160545d5ecaSDag-Erling Smørgrav 
16119261079SEd Maste 	debug3_f("entering, type %d", type);
162545d5ecaSDag-Erling Smørgrav 
163190cef3dSDag-Erling Smørgrav 	if (mlen >= 0xffffffff)
16419261079SEd Maste 		fatal_f("bad length %zu", mlen);
165190cef3dSDag-Erling Smørgrav 	POKE_U32(buf, mlen + 1);
166545d5ecaSDag-Erling Smørgrav 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
167*0fdf8faeSEd Maste 	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf) ||
168*0fdf8faeSEd Maste 	    atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen) {
169*0fdf8faeSEd Maste 		if (errno == EPIPE) {
170*0fdf8faeSEd Maste 			debug3_f("monitor fd closed");
171*0fdf8faeSEd Maste 			mm_reap();
172*0fdf8faeSEd Maste 			cleanup_exit(255);
173*0fdf8faeSEd Maste 		}
17419261079SEd Maste 		fatal_f("write: %s", strerror(errno));
175*0fdf8faeSEd Maste 	}
176545d5ecaSDag-Erling Smørgrav }
177545d5ecaSDag-Erling Smørgrav 
178545d5ecaSDag-Erling Smørgrav void
mm_request_receive(int sock,struct sshbuf * m)179190cef3dSDag-Erling Smørgrav mm_request_receive(int sock, struct sshbuf *m)
180545d5ecaSDag-Erling Smørgrav {
181190cef3dSDag-Erling Smørgrav 	u_char buf[4], *p = NULL;
182545d5ecaSDag-Erling Smørgrav 	u_int msg_len;
183*0fdf8faeSEd Maste 	int oerrno, r;
184545d5ecaSDag-Erling Smørgrav 
18519261079SEd Maste 	debug3_f("entering");
186545d5ecaSDag-Erling Smørgrav 
187d4ecd108SDag-Erling Smørgrav 	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
188*0fdf8faeSEd Maste 		if (errno == EPIPE) {
189*0fdf8faeSEd Maste 			debug3_f("monitor fd closed");
190*0fdf8faeSEd Maste 			mm_reap();
1911ec0d754SDag-Erling Smørgrav 			cleanup_exit(255);
192*0fdf8faeSEd Maste 		}
19319261079SEd Maste 		fatal_f("read: %s", strerror(errno));
194545d5ecaSDag-Erling Smørgrav 	}
195190cef3dSDag-Erling Smørgrav 	msg_len = PEEK_U32(buf);
196545d5ecaSDag-Erling Smørgrav 	if (msg_len > 256 * 1024)
19719261079SEd Maste 		fatal_f("read: bad msg_len %d", msg_len);
198190cef3dSDag-Erling Smørgrav 	sshbuf_reset(m);
199190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
20019261079SEd Maste 		fatal_fr(r, "reserve");
201*0fdf8faeSEd Maste 	if (atomicio(read, sock, p, msg_len) != msg_len) {
202*0fdf8faeSEd Maste 		oerrno = errno;
203*0fdf8faeSEd Maste 		error_f("read: %s", strerror(errno));
204*0fdf8faeSEd Maste 		if (oerrno == EPIPE)
205*0fdf8faeSEd Maste 			mm_reap();
206*0fdf8faeSEd Maste 		cleanup_exit(255);
207*0fdf8faeSEd Maste 	}
208545d5ecaSDag-Erling Smørgrav }
209545d5ecaSDag-Erling Smørgrav 
210545d5ecaSDag-Erling Smørgrav void
mm_request_receive_expect(int sock,enum monitor_reqtype type,struct sshbuf * m)211190cef3dSDag-Erling Smørgrav mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
212545d5ecaSDag-Erling Smørgrav {
213545d5ecaSDag-Erling Smørgrav 	u_char rtype;
214190cef3dSDag-Erling Smørgrav 	int r;
215545d5ecaSDag-Erling Smørgrav 
21619261079SEd Maste 	debug3_f("entering, type %d", type);
217545d5ecaSDag-Erling Smørgrav 
21821e764dfSDag-Erling Smørgrav 	mm_request_receive(sock, m);
219190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &rtype)) != 0)
22019261079SEd Maste 		fatal_fr(r, "parse");
221545d5ecaSDag-Erling Smørgrav 	if (rtype != type)
22219261079SEd Maste 		fatal_f("read: rtype %d != type %d", rtype, type);
223545d5ecaSDag-Erling Smørgrav }
224545d5ecaSDag-Erling Smørgrav 
225a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL
226545d5ecaSDag-Erling Smørgrav DH *
mm_choose_dh(int min,int nbits,int max)227545d5ecaSDag-Erling Smørgrav mm_choose_dh(int min, int nbits, int max)
228545d5ecaSDag-Erling Smørgrav {
229545d5ecaSDag-Erling Smørgrav 	BIGNUM *p, *g;
230190cef3dSDag-Erling Smørgrav 	int r;
231190cef3dSDag-Erling Smørgrav 	u_char success = 0;
232190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
233545d5ecaSDag-Erling Smørgrav 
234190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
23519261079SEd Maste 		fatal_f("sshbuf_new failed");
236190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, min)) != 0 ||
237190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, nbits)) != 0 ||
238190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, max)) != 0)
23919261079SEd Maste 		fatal_fr(r, "assemble");
240545d5ecaSDag-Erling Smørgrav 
241190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
242545d5ecaSDag-Erling Smørgrav 
24319261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_MODULI");
244190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
245545d5ecaSDag-Erling Smørgrav 
246190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &success)) != 0)
24719261079SEd Maste 		fatal_fr(r, "parse success");
248545d5ecaSDag-Erling Smørgrav 	if (success == 0)
24919261079SEd Maste 		fatal_f("MONITOR_ANS_MODULI failed");
250545d5ecaSDag-Erling Smørgrav 
25119261079SEd Maste 	if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
25219261079SEd Maste 	    (r = sshbuf_get_bignum2(m, &g)) != 0)
25319261079SEd Maste 		fatal_fr(r, "parse group");
254545d5ecaSDag-Erling Smørgrav 
25519261079SEd Maste 	debug3_f("remaining %zu", sshbuf_len(m));
256190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
257545d5ecaSDag-Erling Smørgrav 
258545d5ecaSDag-Erling Smørgrav 	return (dh_new_group(g, p));
259545d5ecaSDag-Erling Smørgrav }
260a0ee8cc6SDag-Erling Smørgrav #endif
261545d5ecaSDag-Erling Smørgrav 
262545d5ecaSDag-Erling Smørgrav int
mm_sshkey_sign(struct ssh * ssh,struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * hostkey_alg,const char * sk_provider,const char * sk_pin,u_int compat)26319261079SEd Maste mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
26419261079SEd Maste     const u_char *data, size_t datalen, const char *hostkey_alg,
26519261079SEd Maste     const char *sk_provider, const char *sk_pin, u_int compat)
266545d5ecaSDag-Erling Smørgrav {
267bc5531deSDag-Erling Smørgrav 	struct kex *kex = *pmonitor->m_pkex;
268190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
26919261079SEd Maste 	u_int ndx = kex->host_key_index(key, 0, ssh);
270190cef3dSDag-Erling Smørgrav 	int r;
271545d5ecaSDag-Erling Smørgrav 
27219261079SEd Maste 	debug3_f("entering");
273190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
27419261079SEd Maste 		fatal_f("sshbuf_new failed");
275190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
276190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
277190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
278190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, compat)) != 0)
27919261079SEd Maste 		fatal_fr(r, "assemble");
280545d5ecaSDag-Erling Smørgrav 
281190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
282545d5ecaSDag-Erling Smørgrav 
28319261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_SIGN");
284190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
285190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
28619261079SEd Maste 		fatal_fr(r, "parse");
287190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
288545d5ecaSDag-Erling Smørgrav 
289545d5ecaSDag-Erling Smørgrav 	return (0);
290545d5ecaSDag-Erling Smørgrav }
291545d5ecaSDag-Erling Smørgrav 
292*0fdf8faeSEd Maste void
mm_decode_activate_server_options(struct ssh * ssh,struct sshbuf * m)293*0fdf8faeSEd Maste mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m)
294*0fdf8faeSEd Maste {
295*0fdf8faeSEd Maste 	const u_char *p;
296*0fdf8faeSEd Maste 	size_t len;
297*0fdf8faeSEd Maste 	u_int i;
298*0fdf8faeSEd Maste 	ServerOptions *newopts;
299*0fdf8faeSEd Maste 	int r;
300*0fdf8faeSEd Maste 
301*0fdf8faeSEd Maste 	if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
302*0fdf8faeSEd Maste 		fatal_fr(r, "parse opts");
303*0fdf8faeSEd Maste 	if (len != sizeof(*newopts))
304*0fdf8faeSEd Maste 		fatal_f("option block size mismatch");
305*0fdf8faeSEd Maste 	newopts = xcalloc(sizeof(*newopts), 1);
306*0fdf8faeSEd Maste 	memcpy(newopts, p, sizeof(*newopts));
307*0fdf8faeSEd Maste 
308*0fdf8faeSEd Maste #define M_CP_STROPT(x) do { \
309*0fdf8faeSEd Maste 		if (newopts->x != NULL && \
310*0fdf8faeSEd Maste 		    (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \
311*0fdf8faeSEd Maste 			fatal_fr(r, "parse %s", #x); \
312*0fdf8faeSEd Maste 	} while (0)
313*0fdf8faeSEd Maste #define M_CP_STRARRAYOPT(x, nx) do { \
314*0fdf8faeSEd Maste 		newopts->x = newopts->nx == 0 ? \
315*0fdf8faeSEd Maste 		    NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
316*0fdf8faeSEd Maste 		for (i = 0; i < newopts->nx; i++) { \
317*0fdf8faeSEd Maste 			if ((r = sshbuf_get_cstring(m, \
318*0fdf8faeSEd Maste 			    &newopts->x[i], NULL)) != 0) \
319*0fdf8faeSEd Maste 				fatal_fr(r, "parse %s", #x); \
320*0fdf8faeSEd Maste 		} \
321*0fdf8faeSEd Maste 	} while (0)
322*0fdf8faeSEd Maste 	/* See comment in servconf.h */
323*0fdf8faeSEd Maste 	COPY_MATCH_STRING_OPTS();
324*0fdf8faeSEd Maste #undef M_CP_STROPT
325*0fdf8faeSEd Maste #undef M_CP_STRARRAYOPT
326*0fdf8faeSEd Maste 
327*0fdf8faeSEd Maste 	copy_set_server_options(&options, newopts, 1);
328*0fdf8faeSEd Maste 	log_change_level(options.log_level);
329*0fdf8faeSEd Maste 	log_verbose_reset();
330*0fdf8faeSEd Maste 	for (i = 0; i < options.num_log_verbose; i++)
331*0fdf8faeSEd Maste 		log_verbose_add(options.log_verbose[i]);
332*0fdf8faeSEd Maste 	free(newopts);
333*0fdf8faeSEd Maste }
334*0fdf8faeSEd Maste 
33519261079SEd Maste #define GETPW(b, id) \
33619261079SEd Maste 	do { \
33719261079SEd Maste 		if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \
33819261079SEd Maste 			fatal_fr(r, "parse pw %s", #id); \
33919261079SEd Maste 		if (len != sizeof(pw->id)) \
34019261079SEd Maste 			fatal_fr(r, "bad length for %s", #id); \
34119261079SEd Maste 		memcpy(&pw->id, p, len); \
34219261079SEd Maste 	} while (0)
34319261079SEd Maste 
344545d5ecaSDag-Erling Smørgrav struct passwd *
mm_getpwnamallow(struct ssh * ssh,const char * username)34519261079SEd Maste mm_getpwnamallow(struct ssh *ssh, const char *username)
346545d5ecaSDag-Erling Smørgrav {
347190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
348545d5ecaSDag-Erling Smørgrav 	struct passwd *pw;
349190cef3dSDag-Erling Smørgrav 	size_t len;
350190cef3dSDag-Erling Smørgrav 	int r;
351190cef3dSDag-Erling Smørgrav 	u_char ok;
352190cef3dSDag-Erling Smørgrav 	const u_char *p;
353545d5ecaSDag-Erling Smørgrav 
35419261079SEd Maste 	debug3_f("entering");
355545d5ecaSDag-Erling Smørgrav 
356190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
35719261079SEd Maste 		fatal_f("sshbuf_new failed");
358190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, username)) != 0)
35919261079SEd Maste 		fatal_fr(r, "assemble");
360545d5ecaSDag-Erling Smørgrav 
361190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
362545d5ecaSDag-Erling Smørgrav 
36319261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_PWNAM");
364190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
365545d5ecaSDag-Erling Smørgrav 
366190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u8(m, &ok)) != 0)
36719261079SEd Maste 		fatal_fr(r, "parse success");
368190cef3dSDag-Erling Smørgrav 	if (ok == 0) {
369d4af9e69SDag-Erling Smørgrav 		pw = NULL;
370d4af9e69SDag-Erling Smørgrav 		goto out;
371545d5ecaSDag-Erling Smørgrav 	}
372190cef3dSDag-Erling Smørgrav 
37327ceebbcSEd Maste 	/* XXX don't like passing struct passwd like this */
37427ceebbcSEd Maste 	pw = xcalloc(sizeof(*pw), 1);
37519261079SEd Maste 	GETPW(m, pw_uid);
37619261079SEd Maste 	GETPW(m, pw_gid);
37719261079SEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
37819261079SEd Maste 	GETPW(m, pw_change);
37919261079SEd Maste #endif
38019261079SEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
38119261079SEd Maste 	GETPW(m, pw_expire);
38219261079SEd Maste #endif
38327ceebbcSEd Maste 	if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
38427ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
38527ceebbcSEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
38627ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
38727ceebbcSEd Maste #endif
38827ceebbcSEd Maste #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
38927ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
39027ceebbcSEd Maste #endif
39127ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
39227ceebbcSEd Maste 	    (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
39319261079SEd Maste 		fatal_fr(r, "parse pw");
394d4af9e69SDag-Erling Smørgrav 
395d4af9e69SDag-Erling Smørgrav out:
396d4af9e69SDag-Erling Smørgrav 	/* copy options block as a Match directive may have changed some */
397*0fdf8faeSEd Maste 	mm_decode_activate_server_options(ssh, m);
398*0fdf8faeSEd Maste 	server_process_permitopen(ssh);
399*0fdf8faeSEd Maste 	server_process_channel_timeouts(ssh);
400069ac184SEd Maste 	kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
401190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
402545d5ecaSDag-Erling Smørgrav 
403545d5ecaSDag-Erling Smørgrav 	return (pw);
404545d5ecaSDag-Erling Smørgrav }
405545d5ecaSDag-Erling Smørgrav 
4061ec0d754SDag-Erling Smørgrav char *
mm_auth2_read_banner(void)4071ec0d754SDag-Erling Smørgrav mm_auth2_read_banner(void)
408545d5ecaSDag-Erling Smørgrav {
409190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
410545d5ecaSDag-Erling Smørgrav 	char *banner;
411190cef3dSDag-Erling Smørgrav 	int r;
412545d5ecaSDag-Erling Smørgrav 
41319261079SEd Maste 	debug3_f("entering");
414545d5ecaSDag-Erling Smørgrav 
415190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
41619261079SEd Maste 		fatal_f("sshbuf_new failed");
417190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
418190cef3dSDag-Erling Smørgrav 	sshbuf_reset(m);
419545d5ecaSDag-Erling Smørgrav 
4201ec0d754SDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
421190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_AUTH2_READ_BANNER, m);
422190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
42319261079SEd Maste 		fatal_fr(r, "parse");
424190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
425545d5ecaSDag-Erling Smørgrav 
4261ec0d754SDag-Erling Smørgrav 	/* treat empty banner as missing banner */
4271ec0d754SDag-Erling Smørgrav 	if (strlen(banner) == 0) {
428e4a9863fSDag-Erling Smørgrav 		free(banner);
4291ec0d754SDag-Erling Smørgrav 		banner = NULL;
4301ec0d754SDag-Erling Smørgrav 	}
431545d5ecaSDag-Erling Smørgrav 	return (banner);
432545d5ecaSDag-Erling Smørgrav }
433545d5ecaSDag-Erling Smørgrav 
434545d5ecaSDag-Erling Smørgrav /* Inform the privileged process about service and style */
435545d5ecaSDag-Erling Smørgrav 
436545d5ecaSDag-Erling Smørgrav void
mm_inform_authserv(char * service,char * style)437545d5ecaSDag-Erling Smørgrav mm_inform_authserv(char *service, char *style)
438545d5ecaSDag-Erling Smørgrav {
439190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
440190cef3dSDag-Erling Smørgrav 	int r;
441545d5ecaSDag-Erling Smørgrav 
44219261079SEd Maste 	debug3_f("entering");
443545d5ecaSDag-Erling Smørgrav 
444190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
44519261079SEd Maste 		fatal_f("sshbuf_new failed");
446190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, service)) != 0 ||
447190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
44819261079SEd Maste 		fatal_fr(r, "assemble");
449545d5ecaSDag-Erling Smørgrav 
450190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
451545d5ecaSDag-Erling Smørgrav 
452190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
453545d5ecaSDag-Erling Smørgrav }
454545d5ecaSDag-Erling Smørgrav 
455545d5ecaSDag-Erling Smørgrav /* Do the password authentication */
456545d5ecaSDag-Erling Smørgrav int
mm_auth_password(struct ssh * ssh,char * password)45747dd1d1bSDag-Erling Smørgrav mm_auth_password(struct ssh *ssh, char *password)
458545d5ecaSDag-Erling Smørgrav {
459190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
460190cef3dSDag-Erling Smørgrav 	int r, authenticated = 0;
461190cef3dSDag-Erling Smørgrav #ifdef USE_PAM
462190cef3dSDag-Erling Smørgrav 	u_int maxtries = 0;
463190cef3dSDag-Erling Smørgrav #endif
464545d5ecaSDag-Erling Smørgrav 
46519261079SEd Maste 	debug3_f("entering");
466545d5ecaSDag-Erling Smørgrav 
467190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
46819261079SEd Maste 		fatal_f("sshbuf_new failed");
469190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, password)) != 0)
47019261079SEd Maste 		fatal_fr(r, "assemble");
471190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
472545d5ecaSDag-Erling Smørgrav 
47319261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD");
474190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
475190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_AUTHPASSWORD, m);
476545d5ecaSDag-Erling Smørgrav 
477190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
47819261079SEd Maste 		fatal_fr(r, "parse");
479076ad2f8SDag-Erling Smørgrav #ifdef USE_PAM
480190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
48119261079SEd Maste 		fatal_fr(r, "parse PAM");
482190cef3dSDag-Erling Smørgrav 	if (maxtries > INT_MAX)
48319261079SEd Maste 		fatal_fr(r, "bad maxtries");
484190cef3dSDag-Erling Smørgrav 	sshpam_set_maxtries_reached(maxtries);
485076ad2f8SDag-Erling Smørgrav #endif
486545d5ecaSDag-Erling Smørgrav 
487190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
488545d5ecaSDag-Erling Smørgrav 
48919261079SEd Maste 	debug3_f("user %sauthenticated", authenticated ? "" : "not ");
490545d5ecaSDag-Erling Smørgrav 	return (authenticated);
491545d5ecaSDag-Erling Smørgrav }
492545d5ecaSDag-Erling Smørgrav 
493545d5ecaSDag-Erling Smørgrav int
mm_user_key_allowed(struct ssh * ssh,struct passwd * pw,struct sshkey * key,int pubkey_auth_attempt,struct sshauthopt ** authoptp)49447dd1d1bSDag-Erling Smørgrav mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
49547dd1d1bSDag-Erling Smørgrav     int pubkey_auth_attempt, struct sshauthopt **authoptp)
496545d5ecaSDag-Erling Smørgrav {
497557f75e5SDag-Erling Smørgrav 	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
49847dd1d1bSDag-Erling Smørgrav 	    pubkey_auth_attempt, authoptp));
499545d5ecaSDag-Erling Smørgrav }
500545d5ecaSDag-Erling Smørgrav 
501545d5ecaSDag-Erling Smørgrav int
mm_hostbased_key_allowed(struct ssh * ssh,struct passwd * pw,const char * user,const char * host,struct sshkey * key)50219261079SEd Maste mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
50319261079SEd Maste     const char *user, const char *host, struct sshkey *key)
504545d5ecaSDag-Erling Smørgrav {
50547dd1d1bSDag-Erling Smørgrav 	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
506545d5ecaSDag-Erling Smørgrav }
507545d5ecaSDag-Erling Smørgrav 
508545d5ecaSDag-Erling Smørgrav int
mm_key_allowed(enum mm_keytype type,const char * user,const char * host,struct sshkey * key,int pubkey_auth_attempt,struct sshauthopt ** authoptp)509076ad2f8SDag-Erling Smørgrav mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
51047dd1d1bSDag-Erling Smørgrav     struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
511545d5ecaSDag-Erling Smørgrav {
512190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
51347dd1d1bSDag-Erling Smørgrav 	int r, allowed = 0;
51447dd1d1bSDag-Erling Smørgrav 	struct sshauthopt *opts = NULL;
515545d5ecaSDag-Erling Smørgrav 
51619261079SEd Maste 	debug3_f("entering");
517545d5ecaSDag-Erling Smørgrav 
51847dd1d1bSDag-Erling Smørgrav 	if (authoptp != NULL)
51947dd1d1bSDag-Erling Smørgrav 		*authoptp = NULL;
52047dd1d1bSDag-Erling Smørgrav 
521190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
52219261079SEd Maste 		fatal_f("sshbuf_new failed");
523190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, type)) != 0 ||
524190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
525190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
526190cef3dSDag-Erling Smørgrav 	    (r = sshkey_puts(key, m)) != 0 ||
527190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
52819261079SEd Maste 		fatal_fr(r, "assemble");
529545d5ecaSDag-Erling Smørgrav 
530190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
531545d5ecaSDag-Erling Smørgrav 
53219261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_KEYALLOWED");
53347dd1d1bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
534190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_KEYALLOWED, m);
535545d5ecaSDag-Erling Smørgrav 
536190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &allowed)) != 0)
53719261079SEd Maste 		fatal_fr(r, "parse");
53819261079SEd Maste 	if (allowed && type == MM_USERKEY &&
53919261079SEd Maste 	    (r = sshauthopt_deserialise(m, &opts)) != 0)
54019261079SEd Maste 		fatal_fr(r, "sshauthopt_deserialise");
541190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
542545d5ecaSDag-Erling Smørgrav 
54347dd1d1bSDag-Erling Smørgrav 	if (authoptp != NULL) {
54447dd1d1bSDag-Erling Smørgrav 		*authoptp = opts;
54547dd1d1bSDag-Erling Smørgrav 		opts = NULL;
54647dd1d1bSDag-Erling Smørgrav 	}
54747dd1d1bSDag-Erling Smørgrav 	sshauthopt_free(opts);
54847dd1d1bSDag-Erling Smørgrav 
54947dd1d1bSDag-Erling Smørgrav 	return allowed;
550545d5ecaSDag-Erling Smørgrav }
551545d5ecaSDag-Erling Smørgrav 
552545d5ecaSDag-Erling Smørgrav /*
553545d5ecaSDag-Erling Smørgrav  * This key verify needs to send the key type along, because the
554545d5ecaSDag-Erling Smørgrav  * privileged parent makes the decision if the key is allowed
555545d5ecaSDag-Erling Smørgrav  * for authentication.
556545d5ecaSDag-Erling Smørgrav  */
557545d5ecaSDag-Erling Smørgrav 
558545d5ecaSDag-Erling Smørgrav int
mm_sshkey_verify(const struct sshkey * key,const u_char * sig,size_t siglen,const u_char * data,size_t datalen,const char * sigalg,u_int compat,struct sshkey_sig_details ** sig_detailsp)5594f52dfbbSDag-Erling Smørgrav mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
56019261079SEd Maste     const u_char *data, size_t datalen, const char *sigalg, u_int compat,
56119261079SEd Maste     struct sshkey_sig_details **sig_detailsp)
562545d5ecaSDag-Erling Smørgrav {
563190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
5644f52dfbbSDag-Erling Smørgrav 	u_int encoded_ret = 0;
565190cef3dSDag-Erling Smørgrav 	int r;
56619261079SEd Maste 	u_char sig_details_present, flags;
56719261079SEd Maste 	u_int counter;
568545d5ecaSDag-Erling Smørgrav 
56919261079SEd Maste 	debug3_f("entering");
570545d5ecaSDag-Erling Smørgrav 
57119261079SEd Maste 	if (sig_detailsp != NULL)
57219261079SEd Maste 		*sig_detailsp = NULL;
573190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
57419261079SEd Maste 		fatal_f("sshbuf_new failed");
575190cef3dSDag-Erling Smørgrav 	if ((r = sshkey_puts(key, m)) != 0 ||
576190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, sig, siglen)) != 0 ||
577190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
578190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
57919261079SEd Maste 		fatal_fr(r, "assemble");
580545d5ecaSDag-Erling Smørgrav 
581190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
582545d5ecaSDag-Erling Smørgrav 
58319261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_KEYVERIFY");
584190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
585190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_KEYVERIFY, m);
586545d5ecaSDag-Erling Smørgrav 
58719261079SEd Maste 	if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 ||
58819261079SEd Maste 	    (r = sshbuf_get_u8(m, &sig_details_present)) != 0)
58919261079SEd Maste 		fatal_fr(r, "parse");
59019261079SEd Maste 	if (sig_details_present && encoded_ret == 0) {
59119261079SEd Maste 		if ((r = sshbuf_get_u32(m, &counter)) != 0 ||
59219261079SEd Maste 		    (r = sshbuf_get_u8(m, &flags)) != 0)
59319261079SEd Maste 			fatal_fr(r, "parse sig_details");
59419261079SEd Maste 		if (sig_detailsp != NULL) {
59519261079SEd Maste 			*sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
59619261079SEd Maste 			(*sig_detailsp)->sk_counter = counter;
59719261079SEd Maste 			(*sig_detailsp)->sk_flags = flags;
59819261079SEd Maste 		}
59919261079SEd Maste 	}
600545d5ecaSDag-Erling Smørgrav 
601190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
602545d5ecaSDag-Erling Smørgrav 
6034f52dfbbSDag-Erling Smørgrav 	if (encoded_ret != 0)
6044f52dfbbSDag-Erling Smørgrav 		return SSH_ERR_SIGNATURE_INVALID;
6054f52dfbbSDag-Erling Smørgrav 	return 0;
606545d5ecaSDag-Erling Smørgrav }
607545d5ecaSDag-Erling Smørgrav 
608545d5ecaSDag-Erling Smørgrav void
mm_send_keystate(struct ssh * ssh,struct monitor * monitor)60919261079SEd Maste mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
610545d5ecaSDag-Erling Smørgrav {
611bc5531deSDag-Erling Smørgrav 	struct sshbuf *m;
612bc5531deSDag-Erling Smørgrav 	int r;
613545d5ecaSDag-Erling Smørgrav 
614bc5531deSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
61519261079SEd Maste 		fatal_f("sshbuf_new failed");
616bc5531deSDag-Erling Smørgrav 	if ((r = ssh_packet_get_state(ssh, m)) != 0)
61719261079SEd Maste 		fatal_fr(r, "ssh_packet_get_state");
618bc5531deSDag-Erling Smørgrav 	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
61919261079SEd Maste 	debug3_f("Finished sending state");
620bc5531deSDag-Erling Smørgrav 	sshbuf_free(m);
621545d5ecaSDag-Erling Smørgrav }
622545d5ecaSDag-Erling Smørgrav 
623545d5ecaSDag-Erling Smørgrav int
mm_pty_allocate(int * ptyfd,int * ttyfd,char * namebuf,size_t namebuflen)624333ee039SDag-Erling Smørgrav mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
625545d5ecaSDag-Erling Smørgrav {
626190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
62721e764dfSDag-Erling Smørgrav 	char *p, *msg;
628190cef3dSDag-Erling Smørgrav 	int success = 0, tmp1 = -1, tmp2 = -1, r;
629d4af9e69SDag-Erling Smørgrav 
630d4af9e69SDag-Erling Smørgrav 	/* Kludge: ensure there are fds free to receive the pty/tty */
631d4af9e69SDag-Erling Smørgrav 	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
632d4af9e69SDag-Erling Smørgrav 	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
63319261079SEd Maste 		error_f("cannot allocate fds for pty");
634535af610SEd Maste 		if (tmp1 >= 0)
635d4af9e69SDag-Erling Smørgrav 			close(tmp1);
636d4af9e69SDag-Erling Smørgrav 		return 0;
637d4af9e69SDag-Erling Smørgrav 	}
638d4af9e69SDag-Erling Smørgrav 	close(tmp1);
639d4af9e69SDag-Erling Smørgrav 	close(tmp2);
640545d5ecaSDag-Erling Smørgrav 
641190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
64219261079SEd Maste 		fatal_f("sshbuf_new failed");
643190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
644545d5ecaSDag-Erling Smørgrav 
64519261079SEd Maste 	debug3_f("waiting for MONITOR_ANS_PTY");
646190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
647545d5ecaSDag-Erling Smørgrav 
648190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
64919261079SEd Maste 		fatal_fr(r, "parse success");
650545d5ecaSDag-Erling Smørgrav 	if (success == 0) {
65119261079SEd Maste 		debug3_f("pty alloc failed");
652190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
653545d5ecaSDag-Erling Smørgrav 		return (0);
654545d5ecaSDag-Erling Smørgrav 	}
655190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
656190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
65719261079SEd Maste 		fatal_fr(r, "parse");
658190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
659545d5ecaSDag-Erling Smørgrav 
660545d5ecaSDag-Erling Smørgrav 	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
661e4a9863fSDag-Erling Smørgrav 	free(p);
662545d5ecaSDag-Erling Smørgrav 
663190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
66419261079SEd Maste 		fatal_fr(r, "put loginmsg");
665e4a9863fSDag-Erling Smørgrav 	free(msg);
66621e764dfSDag-Erling Smørgrav 
667d4af9e69SDag-Erling Smørgrav 	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
668d4af9e69SDag-Erling Smørgrav 	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
66919261079SEd Maste 		fatal_f("receive fds failed");
670545d5ecaSDag-Erling Smørgrav 
671545d5ecaSDag-Erling Smørgrav 	/* Success */
672545d5ecaSDag-Erling Smørgrav 	return (1);
673545d5ecaSDag-Erling Smørgrav }
674545d5ecaSDag-Erling Smørgrav 
675545d5ecaSDag-Erling Smørgrav void
mm_session_pty_cleanup2(Session * s)6761ec0d754SDag-Erling Smørgrav mm_session_pty_cleanup2(Session *s)
677545d5ecaSDag-Erling Smørgrav {
678190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
679190cef3dSDag-Erling Smørgrav 	int r;
680545d5ecaSDag-Erling Smørgrav 
681545d5ecaSDag-Erling Smørgrav 	if (s->ttyfd == -1)
682545d5ecaSDag-Erling Smørgrav 		return;
683190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
68419261079SEd Maste 		fatal_f("sshbuf_new failed");
685190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
68619261079SEd Maste 		fatal_fr(r, "assmble");
687190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
688190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
689545d5ecaSDag-Erling Smørgrav 
690545d5ecaSDag-Erling Smørgrav 	/* closed dup'ed master */
69119261079SEd Maste 	if (s->ptymaster != -1 && close(s->ptymaster) == -1)
692d4af9e69SDag-Erling Smørgrav 		error("close(s->ptymaster/%d): %s",
693d4af9e69SDag-Erling Smørgrav 		    s->ptymaster, strerror(errno));
694545d5ecaSDag-Erling Smørgrav 
695545d5ecaSDag-Erling Smørgrav 	/* unlink pty from session */
696545d5ecaSDag-Erling Smørgrav 	s->ttyfd = -1;
697545d5ecaSDag-Erling Smørgrav }
698545d5ecaSDag-Erling Smørgrav 
69983d2307dSDag-Erling Smørgrav #ifdef USE_PAM
70083d2307dSDag-Erling Smørgrav void
mm_start_pam(struct ssh * ssh)70119261079SEd Maste mm_start_pam(struct ssh *ssh)
70283d2307dSDag-Erling Smørgrav {
703190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
70483d2307dSDag-Erling Smørgrav 
70583d2307dSDag-Erling Smørgrav 	debug3("%s entering", __func__);
706cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
707cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
708190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
709190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
710190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
71183d2307dSDag-Erling Smørgrav 
712190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
71383d2307dSDag-Erling Smørgrav }
714382d19eeSDag-Erling Smørgrav 
715cf2b5f3bSDag-Erling Smørgrav u_int
mm_do_pam_account(void)716cf2b5f3bSDag-Erling Smørgrav mm_do_pam_account(void)
717cf2b5f3bSDag-Erling Smørgrav {
718190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
719cf2b5f3bSDag-Erling Smørgrav 	u_int ret;
720aa49c926SDag-Erling Smørgrav 	char *msg;
721190cef3dSDag-Erling Smørgrav 	size_t msglen;
722190cef3dSDag-Erling Smørgrav 	int r;
723cf2b5f3bSDag-Erling Smørgrav 
724cf2b5f3bSDag-Erling Smørgrav 	debug3("%s entering", __func__);
725cf2b5f3bSDag-Erling Smørgrav 	if (!options.use_pam)
726cf2b5f3bSDag-Erling Smørgrav 		fatal("UsePAM=no, but ended up in %s anyway", __func__);
727cf2b5f3bSDag-Erling Smørgrav 
728190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
729190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
730190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
731cf2b5f3bSDag-Erling Smørgrav 
732cf2b5f3bSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
733190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_ACCOUNT, m);
734190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
735190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 ||
736190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put(loginmsg, msg, msglen)) != 0)
737190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
738cf2b5f3bSDag-Erling Smørgrav 
739190cef3dSDag-Erling Smørgrav 	free(msg);
740190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
741cf2b5f3bSDag-Erling Smørgrav 
742cf2b5f3bSDag-Erling Smørgrav 	debug3("%s returning %d", __func__, ret);
743cf2b5f3bSDag-Erling Smørgrav 
744cf2b5f3bSDag-Erling Smørgrav 	return (ret);
745cf2b5f3bSDag-Erling Smørgrav }
746cf2b5f3bSDag-Erling Smørgrav 
747382d19eeSDag-Erling Smørgrav void *
mm_sshpam_init_ctx(Authctxt * authctxt)748cf2b5f3bSDag-Erling Smørgrav mm_sshpam_init_ctx(Authctxt *authctxt)
749382d19eeSDag-Erling Smørgrav {
750190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
751190cef3dSDag-Erling Smørgrav 	int r, success;
752382d19eeSDag-Erling Smørgrav 
753382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
754190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
755190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
756190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
757382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
758190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
759190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_INIT_CTX, m);
760190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
761190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
762382d19eeSDag-Erling Smørgrav 	if (success == 0) {
763382d19eeSDag-Erling Smørgrav 		debug3("%s: pam_init_ctx failed", __func__);
764190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
765382d19eeSDag-Erling Smørgrav 		return (NULL);
766382d19eeSDag-Erling Smørgrav 	}
767190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
768382d19eeSDag-Erling Smørgrav 	return (authctxt);
769382d19eeSDag-Erling Smørgrav }
770382d19eeSDag-Erling Smørgrav 
771382d19eeSDag-Erling Smørgrav int
mm_sshpam_query(void * ctx,char ** name,char ** info,u_int * num,char *** prompts,u_int ** echo_on)772cf2b5f3bSDag-Erling Smørgrav mm_sshpam_query(void *ctx, char **name, char **info,
773382d19eeSDag-Erling Smørgrav     u_int *num, char ***prompts, u_int **echo_on)
774382d19eeSDag-Erling Smørgrav {
775190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
776190cef3dSDag-Erling Smørgrav 	u_int i, n;
777190cef3dSDag-Erling Smørgrav 	int r, ret;
778382d19eeSDag-Erling Smørgrav 
779382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
780190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
781190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
782190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
783382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
784190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
785190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
786190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
787190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
788190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_u32(m, &n)) != 0 ||
789190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_get_u32(m, num)) != 0)
790190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
791382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_query returned %d", __func__, ret);
792190cef3dSDag-Erling Smørgrav 	sshpam_set_maxtries_reached(n);
793333ee039SDag-Erling Smørgrav 	if (*num > PAM_MAX_NUM_MSG)
794190cef3dSDag-Erling Smørgrav 		fatal("%s: received %u PAM messages, expected <= %u",
795333ee039SDag-Erling Smørgrav 		    __func__, *num, PAM_MAX_NUM_MSG);
796333ee039SDag-Erling Smørgrav 	*prompts = xcalloc((*num + 1), sizeof(char *));
797333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc((*num + 1), sizeof(u_int));
798382d19eeSDag-Erling Smørgrav 	for (i = 0; i < *num; ++i) {
799190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 ||
800190cef3dSDag-Erling Smørgrav 		    (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0)
801190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
802382d19eeSDag-Erling Smørgrav 	}
803190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
804382d19eeSDag-Erling Smørgrav 	return (ret);
805382d19eeSDag-Erling Smørgrav }
806382d19eeSDag-Erling Smørgrav 
807382d19eeSDag-Erling Smørgrav int
mm_sshpam_respond(void * ctx,u_int num,char ** resp)808cf2b5f3bSDag-Erling Smørgrav mm_sshpam_respond(void *ctx, u_int num, char **resp)
809382d19eeSDag-Erling Smørgrav {
810190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
811190cef3dSDag-Erling Smørgrav 	u_int n, i;
812190cef3dSDag-Erling Smørgrav 	int r, ret;
813382d19eeSDag-Erling Smørgrav 
814382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
815190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
816190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
817190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, num)) != 0)
818190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
819190cef3dSDag-Erling Smørgrav 	for (i = 0; i < num; ++i) {
820190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_put_cstring(m, resp[i])) != 0)
821190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
822190cef3dSDag-Erling Smørgrav 	}
823190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
824382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
825190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
826190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_RESPOND, m);
827190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &n)) != 0)
828190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
829190cef3dSDag-Erling Smørgrav 	ret = (int)n; /* XXX */
830382d19eeSDag-Erling Smørgrav 	debug3("%s: pam_respond returned %d", __func__, ret);
831190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
832382d19eeSDag-Erling Smørgrav 	return (ret);
833382d19eeSDag-Erling Smørgrav }
834382d19eeSDag-Erling Smørgrav 
835382d19eeSDag-Erling Smørgrav void
mm_sshpam_free_ctx(void * ctxtp)836cf2b5f3bSDag-Erling Smørgrav mm_sshpam_free_ctx(void *ctxtp)
837382d19eeSDag-Erling Smørgrav {
838190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
839382d19eeSDag-Erling Smørgrav 
840382d19eeSDag-Erling Smørgrav 	debug3("%s", __func__);
841190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
842190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
843190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
844382d19eeSDag-Erling Smørgrav 	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
845190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
846190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_PAM_FREE_CTX, m);
847190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
848382d19eeSDag-Erling Smørgrav }
84983d2307dSDag-Erling Smørgrav #endif /* USE_PAM */
85083d2307dSDag-Erling Smørgrav 
851545d5ecaSDag-Erling Smørgrav /* Request process termination */
852545d5ecaSDag-Erling Smørgrav 
853545d5ecaSDag-Erling Smørgrav void
mm_terminate(void)854545d5ecaSDag-Erling Smørgrav mm_terminate(void)
855545d5ecaSDag-Erling Smørgrav {
856190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
857545d5ecaSDag-Erling Smørgrav 
858190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
85919261079SEd Maste 		fatal_f("sshbuf_new failed");
860190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
861190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
862545d5ecaSDag-Erling Smørgrav }
863545d5ecaSDag-Erling Smørgrav 
864545d5ecaSDag-Erling Smørgrav static void
mm_chall_setup(char ** name,char ** infotxt,u_int * numprompts,char *** prompts,u_int ** echo_on)865545d5ecaSDag-Erling Smørgrav mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
866545d5ecaSDag-Erling Smørgrav     char ***prompts, u_int **echo_on)
867545d5ecaSDag-Erling Smørgrav {
868545d5ecaSDag-Erling Smørgrav 	*name = xstrdup("");
869545d5ecaSDag-Erling Smørgrav 	*infotxt = xstrdup("");
870545d5ecaSDag-Erling Smørgrav 	*numprompts = 1;
871333ee039SDag-Erling Smørgrav 	*prompts = xcalloc(*numprompts, sizeof(char *));
872333ee039SDag-Erling Smørgrav 	*echo_on = xcalloc(*numprompts, sizeof(u_int));
873545d5ecaSDag-Erling Smørgrav 	(*echo_on)[0] = 0;
874545d5ecaSDag-Erling Smørgrav }
875545d5ecaSDag-Erling Smørgrav 
876545d5ecaSDag-Erling Smørgrav int
mm_bsdauth_query(void * ctx,char ** name,char ** infotxt,u_int * numprompts,char *** prompts,u_int ** echo_on)877545d5ecaSDag-Erling Smørgrav mm_bsdauth_query(void *ctx, char **name, char **infotxt,
878545d5ecaSDag-Erling Smørgrav    u_int *numprompts, char ***prompts, u_int **echo_on)
879545d5ecaSDag-Erling Smørgrav {
880190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
881e73e9afaSDag-Erling Smørgrav 	u_int success;
882545d5ecaSDag-Erling Smørgrav 	char *challenge;
883190cef3dSDag-Erling Smørgrav 	int r;
884545d5ecaSDag-Erling Smørgrav 
88519261079SEd Maste 	debug3_f("entering");
886545d5ecaSDag-Erling Smørgrav 
887190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
88819261079SEd Maste 		fatal_f("sshbuf_new failed");
889190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
890545d5ecaSDag-Erling Smørgrav 
891190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
892190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHQUERY, m);
893190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &success)) != 0)
89419261079SEd Maste 		fatal_fr(r, "parse success");
895e73e9afaSDag-Erling Smørgrav 	if (success == 0) {
89619261079SEd Maste 		debug3_f("no challenge");
897190cef3dSDag-Erling Smørgrav 		sshbuf_free(m);
898545d5ecaSDag-Erling Smørgrav 		return (-1);
899545d5ecaSDag-Erling Smørgrav 	}
900545d5ecaSDag-Erling Smørgrav 
901545d5ecaSDag-Erling Smørgrav 	/* Get the challenge, and format the response */
902190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
90319261079SEd Maste 		fatal_fr(r, "parse challenge");
904190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
905545d5ecaSDag-Erling Smørgrav 
906545d5ecaSDag-Erling Smørgrav 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
907545d5ecaSDag-Erling Smørgrav 	(*prompts)[0] = challenge;
908545d5ecaSDag-Erling Smørgrav 
90919261079SEd Maste 	debug3_f("received challenge: %s", challenge);
910545d5ecaSDag-Erling Smørgrav 
911545d5ecaSDag-Erling Smørgrav 	return (0);
912545d5ecaSDag-Erling Smørgrav }
913545d5ecaSDag-Erling Smørgrav 
914545d5ecaSDag-Erling Smørgrav int
mm_bsdauth_respond(void * ctx,u_int numresponses,char ** responses)915545d5ecaSDag-Erling Smørgrav mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
916545d5ecaSDag-Erling Smørgrav {
917190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
918190cef3dSDag-Erling Smørgrav 	int r, authok;
919545d5ecaSDag-Erling Smørgrav 
92019261079SEd Maste 	debug3_f("entering");
921545d5ecaSDag-Erling Smørgrav 	if (numresponses != 1)
922545d5ecaSDag-Erling Smørgrav 		return (-1);
923545d5ecaSDag-Erling Smørgrav 
924190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
92519261079SEd Maste 		fatal_f("sshbuf_new failed");
926190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
92719261079SEd Maste 		fatal_fr(r, "assemble");
928190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
929545d5ecaSDag-Erling Smørgrav 
930545d5ecaSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
931190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_BSDAUTHRESPOND, m);
932545d5ecaSDag-Erling Smørgrav 
933190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authok)) != 0)
93419261079SEd Maste 		fatal_fr(r, "parse");
935190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
936545d5ecaSDag-Erling Smørgrav 
937545d5ecaSDag-Erling Smørgrav 	return ((authok == 0) ? -1 : 0);
938545d5ecaSDag-Erling Smørgrav }
939545d5ecaSDag-Erling Smørgrav 
940aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS
941aa49c926SDag-Erling Smørgrav void
mm_audit_event(struct ssh * ssh,ssh_audit_event_t event)94219261079SEd Maste mm_audit_event(struct ssh *ssh, ssh_audit_event_t event)
943aa49c926SDag-Erling Smørgrav {
944190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
945190cef3dSDag-Erling Smørgrav 	int r;
946aa49c926SDag-Erling Smørgrav 
947aa49c926SDag-Erling Smørgrav 	debug3("%s entering", __func__);
948aa49c926SDag-Erling Smørgrav 
949190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
950190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
951190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_u32(m, event)) != 0)
952190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
953aa49c926SDag-Erling Smørgrav 
954190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m);
955190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
956aa49c926SDag-Erling Smørgrav }
957aa49c926SDag-Erling Smørgrav 
958aa49c926SDag-Erling Smørgrav void
mm_audit_run_command(const char * command)959aa49c926SDag-Erling Smørgrav mm_audit_run_command(const char *command)
960aa49c926SDag-Erling Smørgrav {
961190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
962190cef3dSDag-Erling Smørgrav 	int r;
963aa49c926SDag-Erling Smørgrav 
964aa49c926SDag-Erling Smørgrav 	debug3("%s entering command %s", __func__, command);
965aa49c926SDag-Erling Smørgrav 
966190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
967190cef3dSDag-Erling Smørgrav 		fatal("%s: sshbuf_new failed", __func__);
968190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_cstring(m, command)) != 0)
969190cef3dSDag-Erling Smørgrav 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
970aa49c926SDag-Erling Smørgrav 
971190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
972190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
973aa49c926SDag-Erling Smørgrav }
974aa49c926SDag-Erling Smørgrav #endif /* SSH_AUDIT_EVENTS */
975aa49c926SDag-Erling Smørgrav 
976cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
977cf2b5f3bSDag-Erling Smørgrav OM_uint32
mm_ssh_gssapi_server_ctx(Gssctxt ** ctx,gss_OID goid)97821e764dfSDag-Erling Smørgrav mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
979f388f5efSDag-Erling Smørgrav {
980190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
981cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
982190cef3dSDag-Erling Smørgrav 	int r;
983f388f5efSDag-Erling Smørgrav 
984cf2b5f3bSDag-Erling Smørgrav 	/* Client doesn't get to see the context */
985cf2b5f3bSDag-Erling Smørgrav 	*ctx = NULL;
986f388f5efSDag-Erling Smørgrav 
987190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
98819261079SEd Maste 		fatal_f("sshbuf_new failed");
989190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
99019261079SEd Maste 		fatal_fr(r, "assemble");
991f388f5efSDag-Erling Smørgrav 
992190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
993190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
994f388f5efSDag-Erling Smørgrav 
995190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0)
99619261079SEd Maste 		fatal_fr(r, "parse");
997cf2b5f3bSDag-Erling Smørgrav 
998190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
999cf2b5f3bSDag-Erling Smørgrav 	return (major);
1000f388f5efSDag-Erling Smørgrav }
1001f388f5efSDag-Erling Smørgrav 
1002cf2b5f3bSDag-Erling Smørgrav OM_uint32
mm_ssh_gssapi_accept_ctx(Gssctxt * ctx,gss_buffer_desc * in,gss_buffer_desc * out,OM_uint32 * flagsp)1003cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1004190cef3dSDag-Erling Smørgrav     gss_buffer_desc *out, OM_uint32 *flagsp)
1005f388f5efSDag-Erling Smørgrav {
1006190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
1007cf2b5f3bSDag-Erling Smørgrav 	OM_uint32 major;
1008190cef3dSDag-Erling Smørgrav 	u_int flags;
1009190cef3dSDag-Erling Smørgrav 	int r;
1010f388f5efSDag-Erling Smørgrav 
1011190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
101219261079SEd Maste 		fatal_f("sshbuf_new failed");
1013190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
101419261079SEd Maste 		fatal_fr(r, "assemble");
1015cf2b5f3bSDag-Erling Smørgrav 
1016190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
1017190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
1018cf2b5f3bSDag-Erling Smørgrav 
1019190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0 ||
1020190cef3dSDag-Erling Smørgrav 	    (r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
102119261079SEd Maste 		fatal_fr(r, "parse");
1022190cef3dSDag-Erling Smørgrav 	if (flagsp != NULL) {
1023190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_get_u32(m, &flags)) != 0)
102419261079SEd Maste 			fatal_fr(r, "parse flags");
1025190cef3dSDag-Erling Smørgrav 		*flagsp = flags;
1026190cef3dSDag-Erling Smørgrav 	}
1027f388f5efSDag-Erling Smørgrav 
1028190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
1029cf2b5f3bSDag-Erling Smørgrav 
1030cf2b5f3bSDag-Erling Smørgrav 	return (major);
1031f388f5efSDag-Erling Smørgrav }
1032cf2b5f3bSDag-Erling Smørgrav 
10331ec0d754SDag-Erling Smørgrav OM_uint32
mm_ssh_gssapi_checkmic(Gssctxt * ctx,gss_buffer_t gssbuf,gss_buffer_t gssmic)10341ec0d754SDag-Erling Smørgrav mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
10351ec0d754SDag-Erling Smørgrav {
1036190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
10371ec0d754SDag-Erling Smørgrav 	OM_uint32 major;
1038190cef3dSDag-Erling Smørgrav 	int r;
10391ec0d754SDag-Erling Smørgrav 
1040190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
104119261079SEd Maste 		fatal_f("sshbuf_new failed");
1042190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
1043190cef3dSDag-Erling Smørgrav 	    (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
104419261079SEd Maste 		fatal_fr(r, "assemble");
10451ec0d754SDag-Erling Smørgrav 
1046190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
1047190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1048190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_GSSCHECKMIC, m);
10491ec0d754SDag-Erling Smørgrav 
1050190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &major)) != 0)
105119261079SEd Maste 		fatal_fr(r, "parse");
1052190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
10531ec0d754SDag-Erling Smørgrav 	return(major);
10541ec0d754SDag-Erling Smørgrav }
10551ec0d754SDag-Erling Smørgrav 
1056cf2b5f3bSDag-Erling Smørgrav int
mm_ssh_gssapi_userok(char * user)1057cf2b5f3bSDag-Erling Smørgrav mm_ssh_gssapi_userok(char *user)
1058cf2b5f3bSDag-Erling Smørgrav {
1059190cef3dSDag-Erling Smørgrav 	struct sshbuf *m;
1060190cef3dSDag-Erling Smørgrav 	int r, authenticated = 0;
1061cf2b5f3bSDag-Erling Smørgrav 
1062190cef3dSDag-Erling Smørgrav 	if ((m = sshbuf_new()) == NULL)
106319261079SEd Maste 		fatal_f("sshbuf_new failed");
1064cf2b5f3bSDag-Erling Smørgrav 
1065190cef3dSDag-Erling Smørgrav 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
1066190cef3dSDag-Erling Smørgrav 	mm_request_receive_expect(pmonitor->m_recvfd,
1067190cef3dSDag-Erling Smørgrav 	    MONITOR_ANS_GSSUSEROK, m);
1068cf2b5f3bSDag-Erling Smørgrav 
1069190cef3dSDag-Erling Smørgrav 	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
107019261079SEd Maste 		fatal_fr(r, "parse");
1071cf2b5f3bSDag-Erling Smørgrav 
1072190cef3dSDag-Erling Smørgrav 	sshbuf_free(m);
107319261079SEd Maste 	debug3_f("user %sauthenticated", authenticated ? "" : "not ");
1074cf2b5f3bSDag-Erling Smørgrav 	return (authenticated);
1075cf2b5f3bSDag-Erling Smørgrav }
1076cf2b5f3bSDag-Erling Smørgrav #endif /* GSSAPI */
1077*0fdf8faeSEd Maste 
1078*0fdf8faeSEd Maste /*
1079*0fdf8faeSEd Maste  * Inform channels layer of permitopen options for a single forwarding
1080*0fdf8faeSEd Maste  * direction (local/remote).
1081*0fdf8faeSEd Maste  */
1082*0fdf8faeSEd Maste static void
server_process_permitopen_list(struct ssh * ssh,int listen,char ** opens,u_int num_opens)1083*0fdf8faeSEd Maste server_process_permitopen_list(struct ssh *ssh, int listen,
1084*0fdf8faeSEd Maste     char **opens, u_int num_opens)
1085*0fdf8faeSEd Maste {
1086*0fdf8faeSEd Maste 	u_int i;
1087*0fdf8faeSEd Maste 	int port;
1088*0fdf8faeSEd Maste 	char *host, *arg, *oarg;
1089*0fdf8faeSEd Maste 	int where = listen ? FORWARD_REMOTE : FORWARD_LOCAL;
1090*0fdf8faeSEd Maste 	const char *what = listen ? "permitlisten" : "permitopen";
1091*0fdf8faeSEd Maste 
1092*0fdf8faeSEd Maste 	channel_clear_permission(ssh, FORWARD_ADM, where);
1093*0fdf8faeSEd Maste 	if (num_opens == 0)
1094*0fdf8faeSEd Maste 		return; /* permit any */
1095*0fdf8faeSEd Maste 
1096*0fdf8faeSEd Maste 	/* handle keywords: "any" / "none" */
1097*0fdf8faeSEd Maste 	if (num_opens == 1 && strcmp(opens[0], "any") == 0)
1098*0fdf8faeSEd Maste 		return;
1099*0fdf8faeSEd Maste 	if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
1100*0fdf8faeSEd Maste 		channel_disable_admin(ssh, where);
1101*0fdf8faeSEd Maste 		return;
1102*0fdf8faeSEd Maste 	}
1103*0fdf8faeSEd Maste 	/* Otherwise treat it as a list of permitted host:port */
1104*0fdf8faeSEd Maste 	for (i = 0; i < num_opens; i++) {
1105*0fdf8faeSEd Maste 		oarg = arg = xstrdup(opens[i]);
1106*0fdf8faeSEd Maste 		host = hpdelim(&arg);
1107*0fdf8faeSEd Maste 		if (host == NULL)
1108*0fdf8faeSEd Maste 			fatal_f("missing host in %s", what);
1109*0fdf8faeSEd Maste 		host = cleanhostname(host);
1110*0fdf8faeSEd Maste 		if (arg == NULL || ((port = permitopen_port(arg)) < 0))
1111*0fdf8faeSEd Maste 			fatal_f("bad port number in %s", what);
1112*0fdf8faeSEd Maste 		/* Send it to channels layer */
1113*0fdf8faeSEd Maste 		channel_add_permission(ssh, FORWARD_ADM,
1114*0fdf8faeSEd Maste 		    where, host, port);
1115*0fdf8faeSEd Maste 		free(oarg);
1116*0fdf8faeSEd Maste 	}
1117*0fdf8faeSEd Maste }
1118*0fdf8faeSEd Maste 
1119*0fdf8faeSEd Maste /*
1120*0fdf8faeSEd Maste  * Inform channels layer of permitopen options from configuration.
1121*0fdf8faeSEd Maste  */
1122*0fdf8faeSEd Maste void
server_process_permitopen(struct ssh * ssh)1123*0fdf8faeSEd Maste server_process_permitopen(struct ssh *ssh)
1124*0fdf8faeSEd Maste {
1125*0fdf8faeSEd Maste 	server_process_permitopen_list(ssh, 0,
1126*0fdf8faeSEd Maste 	    options.permitted_opens, options.num_permitted_opens);
1127*0fdf8faeSEd Maste 	server_process_permitopen_list(ssh, 1,
1128*0fdf8faeSEd Maste 	    options.permitted_listens, options.num_permitted_listens);
1129*0fdf8faeSEd Maste }
1130*0fdf8faeSEd Maste 
1131*0fdf8faeSEd Maste void
server_process_channel_timeouts(struct ssh * ssh)1132*0fdf8faeSEd Maste server_process_channel_timeouts(struct ssh *ssh)
1133*0fdf8faeSEd Maste {
1134*0fdf8faeSEd Maste 	u_int i, secs;
1135*0fdf8faeSEd Maste 	char *type;
1136*0fdf8faeSEd Maste 
1137*0fdf8faeSEd Maste 	debug3_f("setting %u timeouts", options.num_channel_timeouts);
1138*0fdf8faeSEd Maste 	channel_clear_timeouts(ssh);
1139*0fdf8faeSEd Maste 	for (i = 0; i < options.num_channel_timeouts; i++) {
1140*0fdf8faeSEd Maste 		if (parse_pattern_interval(options.channel_timeouts[i],
1141*0fdf8faeSEd Maste 		    &type, &secs) != 0) {
1142*0fdf8faeSEd Maste 			fatal_f("internal error: bad timeout %s",
1143*0fdf8faeSEd Maste 			    options.channel_timeouts[i]);
1144*0fdf8faeSEd Maste 		}
1145*0fdf8faeSEd Maste 		channel_add_timeout(ssh, type, secs);
1146*0fdf8faeSEd Maste 		free(type);
1147*0fdf8faeSEd Maste 	}
1148*0fdf8faeSEd Maste }
1149*0fdf8faeSEd Maste 
1150*0fdf8faeSEd Maste struct connection_info *
server_get_connection_info(struct ssh * ssh,int populate,int use_dns)1151*0fdf8faeSEd Maste server_get_connection_info(struct ssh *ssh, int populate, int use_dns)
1152*0fdf8faeSEd Maste {
1153*0fdf8faeSEd Maste 	static struct connection_info ci;
1154*0fdf8faeSEd Maste 
1155*0fdf8faeSEd Maste 	if (ssh == NULL || !populate)
1156*0fdf8faeSEd Maste 		return &ci;
1157*0fdf8faeSEd Maste 	ci.host = use_dns ? ssh_remote_hostname(ssh) : ssh_remote_ipaddr(ssh);
1158*0fdf8faeSEd Maste 	ci.address = ssh_remote_ipaddr(ssh);
1159*0fdf8faeSEd Maste 	ci.laddress = ssh_local_ipaddr(ssh);
1160*0fdf8faeSEd Maste 	ci.lport = ssh_local_port(ssh);
1161*0fdf8faeSEd Maste 	ci.rdomain = ssh_packet_rdomain_in(ssh);
1162*0fdf8faeSEd Maste 	return &ci;
1163*0fdf8faeSEd Maste }
1164*0fdf8faeSEd Maste 
1165