1/*	$NetBSD: monitor_wrap.c,v 1.34 2023/12/20 17:15:20 christos Exp $	*/
2/* $OpenBSD: monitor_wrap.c,v 1.129 2023/12/18 14:45:49 djm Exp $ */
3
4/*
5 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
6 * Copyright 2002 Markus Friedl <markus@openbsd.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "includes.h"
31__RCSID("$NetBSD: monitor_wrap.c,v 1.34 2023/12/20 17:15:20 christos Exp $");
32#include <sys/types.h>
33#include <sys/uio.h>
34#include <sys/queue.h>
35
36#include <errno.h>
37#include <pwd.h>
38#include <signal.h>
39#include <stdio.h>
40#include <string.h>
41#include <stdarg.h>
42#include <unistd.h>
43
44#ifdef WITH_OPENSSL
45#include <openssl/bn.h>
46#include <openssl/dh.h>
47#endif
48
49#include "xmalloc.h"
50#include "ssh.h"
51#ifdef WITH_OPENSSL
52#include "dh.h"
53#endif
54#include "sshbuf.h"
55#include "sshkey.h"
56#include "cipher.h"
57#include "kex.h"
58#include "hostfile.h"
59#include "auth.h"
60#include "auth-options.h"
61#include "packet.h"
62#include "mac.h"
63#include "log.h"
64#include "monitor.h"
65#ifdef GSSAPI
66#include "ssh-gss.h"
67#endif
68#include "monitor_wrap.h"
69#include "atomicio.h"
70#include "monitor_fdpass.h"
71#ifdef USE_PAM
72#include "misc.h"
73#include "servconf.h"
74#include <security/pam_appl.h>
75#endif
76#include "misc.h"
77
78#include "channels.h"
79#include "session.h"
80#include "servconf.h"
81
82#include "ssherr.h"
83
84/* Imports */
85extern struct monitor *pmonitor;
86extern struct sshbuf *loginmsg;
87extern ServerOptions options;
88
89void
90mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx)
91{
92	struct sshbuf *log_msg;
93	struct monitor *mon = (struct monitor *)ctx;
94	int r;
95	size_t len;
96
97	if (mon->m_log_sendfd == -1)
98		fatal_f("no log channel");
99
100	if ((log_msg = sshbuf_new()) == NULL)
101		fatal_f("sshbuf_new failed");
102
103	if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
104	    (r = sshbuf_put_u32(log_msg, level)) != 0 ||
105	    (r = sshbuf_put_u32(log_msg, forced)) != 0 ||
106	    (r = sshbuf_put_cstring(log_msg, msg)) != 0)
107		fatal_fr(r, "assemble");
108	if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
109		fatal_f("bad length %zu", len);
110	POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
111	if (atomicio(vwrite, mon->m_log_sendfd,
112	    sshbuf_mutable_ptr(log_msg), len) != len)
113		fatal_f("write: %s", strerror(errno));
114	sshbuf_free(log_msg);
115}
116
117int
118mm_is_monitor(void)
119{
120	/*
121	 * m_pid is only set in the privileged part, and
122	 * points to the unprivileged child.
123	 */
124	return (pmonitor && pmonitor->m_pid > 0);
125}
126
127void
128mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
129{
130	size_t mlen = sshbuf_len(m);
131	u_char buf[5];
132
133	debug3_f("entering, type %d", type);
134
135	if (mlen >= 0xffffffff)
136		fatal_f("bad length %zu", mlen);
137	POKE_U32(buf, mlen + 1);
138	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
139	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
140		fatal_f("write: %s", strerror(errno));
141	if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
142		fatal_f("write: %s", strerror(errno));
143}
144
145void
146mm_request_receive(int sock, struct sshbuf *m)
147{
148	u_char buf[4], *p = NULL;
149	u_int msg_len;
150	int r;
151
152	debug3_f("entering");
153
154	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
155		if (errno == EPIPE)
156			cleanup_exit(254);
157		fatal_f("read: %s", strerror(errno));
158	}
159	msg_len = PEEK_U32(buf);
160	if (msg_len > 256 * 1024)
161		fatal_f("read: bad msg_len %d", msg_len);
162	sshbuf_reset(m);
163	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
164		fatal_fr(r, "reserve");
165	if (atomicio(read, sock, p, msg_len) != msg_len)
166		fatal_f("read: %s", strerror(errno));
167}
168
169void
170mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
171{
172	u_char rtype;
173	int r;
174
175	debug3_f("entering, type %d", type);
176
177	mm_request_receive(sock, m);
178	if ((r = sshbuf_get_u8(m, &rtype)) != 0)
179		fatal_fr(r, "parse");
180	if (rtype != type)
181		fatal_f("read: rtype %d != type %d", rtype, type);
182}
183
184#ifdef WITH_OPENSSL
185DH *
186mm_choose_dh(int min, int nbits, int max)
187{
188	BIGNUM *p, *g;
189	int r;
190	u_char success = 0;
191	struct sshbuf *m;
192
193	if ((m = sshbuf_new()) == NULL)
194		fatal_f("sshbuf_new failed");
195	if ((r = sshbuf_put_u32(m, min)) != 0 ||
196	    (r = sshbuf_put_u32(m, nbits)) != 0 ||
197	    (r = sshbuf_put_u32(m, max)) != 0)
198		fatal_fr(r, "assemble");
199
200	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
201
202	debug3_f("waiting for MONITOR_ANS_MODULI");
203	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
204
205	if ((r = sshbuf_get_u8(m, &success)) != 0)
206		fatal_fr(r, "parse success");
207	if (success == 0)
208		fatal_f("MONITOR_ANS_MODULI failed");
209
210	if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
211	    (r = sshbuf_get_bignum2(m, &g)) != 0)
212		fatal_fr(r, "parse group");
213
214	debug3_f("remaining %zu", sshbuf_len(m));
215	sshbuf_free(m);
216
217	return (dh_new_group(g, p));
218}
219#endif
220
221int
222mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
223    const u_char *data, size_t datalen, const char *hostkey_alg,
224    const char *sk_provider, const char *sk_pin, u_int compat)
225{
226	struct kex *kex = *pmonitor->m_pkex;
227	struct sshbuf *m;
228	u_int ndx = kex->host_key_index(key, 0, ssh);
229	int r;
230
231	debug3_f("entering");
232	if ((m = sshbuf_new()) == NULL)
233		fatal_f("sshbuf_new failed");
234	if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
235	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
236	    (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
237	    (r = sshbuf_put_u32(m, compat)) != 0)
238		fatal_fr(r, "assemble");
239
240	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
241
242	debug3_f("waiting for MONITOR_ANS_SIGN");
243	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
244	if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
245		fatal_fr(r, "parse");
246	sshbuf_free(m);
247
248	return (0);
249}
250
251#define GETPW(b, id) \
252	do { \
253		if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \
254			fatal_fr(r, "parse pw %s", #id); \
255		if (len != sizeof(pw->id)) \
256			fatal_fr(r, "bad length for %s", #id); \
257		memcpy(&pw->id, p, len); \
258	} while (0)
259
260struct passwd *
261mm_getpwnamallow(struct ssh *ssh, const char *username)
262{
263	struct sshbuf *m;
264	struct passwd *pw;
265	size_t len;
266	u_int i;
267	ServerOptions *newopts;
268	int r;
269	u_char ok;
270	const u_char *p;
271
272	debug3_f("entering");
273
274	if ((m = sshbuf_new()) == NULL)
275		fatal_f("sshbuf_new failed");
276	if ((r = sshbuf_put_cstring(m, username)) != 0)
277		fatal_fr(r, "assemble");
278
279	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
280
281	debug3_f("waiting for MONITOR_ANS_PWNAM");
282	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
283
284	if ((r = sshbuf_get_u8(m, &ok)) != 0)
285		fatal_fr(r, "parse success");
286	if (ok == 0) {
287		pw = NULL;
288		goto out;
289	}
290
291	pw = xcalloc(sizeof(*pw), 1);
292	GETPW(m, pw_uid);
293	GETPW(m, pw_gid);
294	GETPW(m, pw_change);
295	GETPW(m, pw_expire);
296	if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
297	    (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
298	    (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
299	    (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
300	    (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
301	    (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
302		fatal_fr(r, "parse pw");
303
304out:
305	/* copy options block as a Match directive may have changed some */
306	if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
307		fatal_fr(r, "parse opts");
308	if (len != sizeof(*newopts))
309		fatal_f("option block size mismatch");
310	newopts = xcalloc(sizeof(*newopts), 1);
311	memcpy(newopts, p, sizeof(*newopts));
312
313#define M_CP_STROPT(x) do { \
314		if (newopts->x != NULL && \
315		    (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \
316			fatal_fr(r, "parse %s", #x); \
317	} while (0)
318#define M_CP_STRARRAYOPT(x, nx) do { \
319		newopts->x = newopts->nx == 0 ? \
320		    NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
321		for (i = 0; i < newopts->nx; i++) { \
322			if ((r = sshbuf_get_cstring(m, \
323			    &newopts->x[i], NULL)) != 0) \
324				fatal_fr(r, "parse %s", #x); \
325		} \
326	} while (0)
327	/* See comment in servconf.h */
328	COPY_MATCH_STRING_OPTS();
329#undef M_CP_STROPT
330#undef M_CP_STRARRAYOPT
331
332	copy_set_server_options(&options, newopts, 1);
333	log_change_level(options.log_level);
334	log_verbose_reset();
335	for (i = 0; i < options.num_log_verbose; i++)
336		log_verbose_add(options.log_verbose[i]);
337	process_permitopen(ssh, &options);
338	process_channel_timeouts(ssh, &options);
339	kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
340	free(newopts);
341	sshbuf_free(m);
342
343	return (pw);
344}
345
346char *
347mm_auth2_read_banner(void)
348{
349	struct sshbuf *m;
350	char *banner;
351	int r;
352
353	debug3_f("entering");
354
355	if ((m = sshbuf_new()) == NULL)
356		fatal_f("sshbuf_new failed");
357	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
358	sshbuf_reset(m);
359
360	mm_request_receive_expect(pmonitor->m_recvfd,
361	    MONITOR_ANS_AUTH2_READ_BANNER, m);
362	if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
363		fatal_fr(r, "parse");
364	sshbuf_free(m);
365
366	/* treat empty banner as missing banner */
367	if (strlen(banner) == 0) {
368		free(banner);
369		banner = NULL;
370	}
371	return (banner);
372}
373
374/* Inform the privileged process about service and style */
375
376void
377mm_inform_authserv(char *service, char *style)
378{
379	struct sshbuf *m;
380	int r;
381
382	debug3_f("entering");
383
384	if ((m = sshbuf_new()) == NULL)
385		fatal_f("sshbuf_new failed");
386	if ((r = sshbuf_put_cstring(m, service)) != 0 ||
387	    (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
388		fatal_fr(r, "assemble");
389
390	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
391
392	sshbuf_free(m);
393}
394
395/* Do the password authentication */
396int
397mm_auth_password(struct ssh *ssh, const char *password)
398{
399	struct sshbuf *m;
400	int r;
401	u_int authenticated = 0;
402
403	debug3_f("entering");
404
405	if ((m = sshbuf_new()) == NULL)
406		fatal_f("sshbuf_new failed");
407	if ((r = sshbuf_put_cstring(m, password)) != 0)
408		fatal_fr(r, "assemble");
409	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
410
411	debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD");
412	mm_request_receive_expect(pmonitor->m_recvfd,
413	    MONITOR_ANS_AUTHPASSWORD, m);
414
415	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
416		fatal_fr(r, "parse");
417
418	sshbuf_free(m);
419
420	debug3_f("user %sauthenticated", authenticated ? "" : "not ");
421	return (authenticated);
422}
423
424int
425mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
426    int pubkey_auth_attempt, struct sshauthopt **authoptp)
427{
428	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
429	    pubkey_auth_attempt, authoptp));
430}
431
432int
433mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
434    const char *user, const char *host, struct sshkey *key)
435{
436	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
437}
438
439int
440mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
441    struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
442{
443	struct sshbuf *m;
444	int r;
445	u_int allowed = 0;
446	struct sshauthopt *opts = NULL;
447
448	debug3_f("entering");
449
450	if (authoptp != NULL)
451		*authoptp = NULL;
452
453	if ((m = sshbuf_new()) == NULL)
454		fatal_f("sshbuf_new failed");
455	if ((r = sshbuf_put_u32(m, type)) != 0 ||
456	    (r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
457	    (r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
458	    (r = sshkey_puts(key, m)) != 0 ||
459	    (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
460		fatal_fr(r, "assemble");
461
462	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
463
464	debug3_f("waiting for MONITOR_ANS_KEYALLOWED");
465	mm_request_receive_expect(pmonitor->m_recvfd,
466	    MONITOR_ANS_KEYALLOWED, m);
467
468	if ((r = sshbuf_get_u32(m, &allowed)) != 0)
469		fatal_fr(r, "parse");
470	if (allowed && type == MM_USERKEY &&
471	    (r = sshauthopt_deserialise(m, &opts)) != 0)
472		fatal_fr(r, "sshauthopt_deserialise");
473	sshbuf_free(m);
474
475	if (authoptp != NULL) {
476		*authoptp = opts;
477		opts = NULL;
478	}
479	sshauthopt_free(opts);
480
481	return allowed;
482}
483
484/*
485 * This key verify needs to send the key type along, because the
486 * privileged parent makes the decision if the key is allowed
487 * for authentication.
488 */
489
490int
491mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
492    const u_char *data, size_t datalen, const char *sigalg, u_int compat,
493    struct sshkey_sig_details **sig_detailsp)
494{
495	struct sshbuf *m;
496	u_int encoded_ret = 0;
497	int r;
498	u_char sig_details_present, flags;
499	u_int counter;
500
501	debug3_f("entering");
502
503	if (sig_detailsp != NULL)
504		*sig_detailsp = NULL;
505	if ((m = sshbuf_new()) == NULL)
506		fatal_f("sshbuf_new failed");
507	if ((r = sshkey_puts(key, m)) != 0 ||
508	    (r = sshbuf_put_string(m, sig, siglen)) != 0 ||
509	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||
510	    (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
511		fatal_fr(r, "assemble");
512
513	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
514
515	debug3_f("waiting for MONITOR_ANS_KEYVERIFY");
516	mm_request_receive_expect(pmonitor->m_recvfd,
517	    MONITOR_ANS_KEYVERIFY, m);
518
519	if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 ||
520	    (r = sshbuf_get_u8(m, &sig_details_present)) != 0)
521		fatal_fr(r, "parse");
522	if (sig_details_present && encoded_ret == 0) {
523		if ((r = sshbuf_get_u32(m, &counter)) != 0 ||
524		    (r = sshbuf_get_u8(m, &flags)) != 0)
525			fatal_fr(r, "parse sig_details");
526		if (sig_detailsp != NULL) {
527			*sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
528			(*sig_detailsp)->sk_counter = counter;
529			(*sig_detailsp)->sk_flags = flags;
530		}
531	}
532
533	sshbuf_free(m);
534
535	if (encoded_ret != 0)
536		return SSH_ERR_SIGNATURE_INVALID;
537	return 0;
538}
539
540void
541mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
542{
543	struct sshbuf *m;
544	int r;
545
546	if ((m = sshbuf_new()) == NULL)
547		fatal_f("sshbuf_new failed");
548	if ((r = ssh_packet_get_state(ssh, m)) != 0)
549		fatal_fr(r, "ssh_packet_get_state");
550	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
551	debug3_f("Finished sending state");
552	sshbuf_free(m);
553}
554
555int
556mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
557{
558	struct sshbuf *m;
559	char *p, *msg;
560	u_int success = 0;
561	int tmp1 = -1, tmp2 = -1, r;
562
563	/* Kludge: ensure there are fds free to receive the pty/tty */
564	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
565	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
566		error_f("cannot allocate fds for pty");
567		if (tmp1 >= 0)
568			close(tmp1);
569		return 0;
570	}
571	close(tmp1);
572	close(tmp2);
573
574	if ((m = sshbuf_new()) == NULL)
575		fatal_f("sshbuf_new failed");
576	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
577
578	debug3_f("waiting for MONITOR_ANS_PTY");
579	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
580
581	if ((r = sshbuf_get_u32(m, &success)) != 0)
582		fatal_fr(r, "parse success");
583	if (success == 0) {
584		debug3_f("pty alloc failed");
585		sshbuf_free(m);
586		return (0);
587	}
588	if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
589	    (r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
590		fatal_fr(r, "parse");
591	sshbuf_free(m);
592
593	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
594	free(p);
595
596	if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
597		fatal_fr(r, "put loginmsg");
598	free(msg);
599
600	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
601	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
602		fatal_f("receive fds failed");
603
604	/* Success */
605	return (1);
606}
607
608void
609mm_session_pty_cleanup2(Session *s)
610{
611	struct sshbuf *m;
612	int r;
613
614	if (s->ttyfd == -1)
615		return;
616	if ((m = sshbuf_new()) == NULL)
617		fatal_f("sshbuf_new failed");
618	if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
619		fatal_fr(r, "assmble");
620	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
621	sshbuf_free(m);
622
623	/* closed dup'ed master */
624	if (s->ptymaster != -1 && close(s->ptymaster) == -1)
625		error("close(s->ptymaster/%d): %s",
626		    s->ptymaster, strerror(errno));
627
628	/* unlink pty from session */
629	s->ttyfd = -1;
630}
631
632#ifdef USE_PAM
633void
634mm_start_pam(struct ssh *ssh)
635{
636	struct sshbuf *m;
637
638	debug3("%s entering", __func__);
639	if (!options.use_pam)
640		fatal("UsePAM=no, but ended up in %s anyway", __func__);
641
642	if ((m = sshbuf_new()) == NULL)
643		fatal("%s: sshbuf_new failed", __func__);
644	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
645
646	sshbuf_free(m);
647}
648
649u_int
650mm_do_pam_account(void)
651{
652	struct sshbuf *m;
653	int r;
654	u_int ret;
655	size_t len;
656	char *msg;
657
658	debug3("%s entering", __func__);
659	if (!options.use_pam)
660		fatal("UsePAM=no, but ended up in %s anyway", __func__);
661
662	if ((m = sshbuf_new()) == NULL)
663		fatal("%s: sshbuf_new failed", __func__);
664	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
665
666	mm_request_receive_expect(pmonitor->m_recvfd,
667	    MONITOR_ANS_PAM_ACCOUNT, m);
668	if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
669	    (r = sshbuf_get_cstring(m, &msg, &len)) != 0)
670		fatal("%s: buffer error: %s", __func__, ssh_err(r));
671	sshbuf_put_cstring(loginmsg, msg);
672	free(msg);
673
674	sshbuf_free(m);
675
676	debug3("%s returning %d", __func__, ret);
677
678	return (ret);
679}
680
681void *
682mm_sshpam_init_ctx(Authctxt *authctxt)
683{
684	struct sshbuf *m;
685	u_int success;
686	int r;
687
688	debug3("%s", __func__);
689	if ((m = sshbuf_new()) == NULL)
690		fatal("%s: sshbuf_new failed", __func__);
691	sshbuf_put_cstring(m, authctxt->user);
692	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
693	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
694	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, m);
695	if ((r = sshbuf_get_u32(m, &success)) != 0)
696		fatal("%s: buffer error: %s", __func__, ssh_err(r));
697	if (success == 0) {
698		debug3("%s: pam_init_ctx failed", __func__);
699		sshbuf_free(m);
700		return (NULL);
701	}
702	sshbuf_free(m);
703	return (authctxt);
704}
705
706int
707mm_sshpam_query(void *ctx, char **name, char **info,
708    u_int *num, char ***prompts, u_int **echo_on)
709{
710	struct sshbuf *m;
711	u_int i, ret;
712	int r;
713
714	debug3("%s", __func__);
715	if ((m = sshbuf_new()) == NULL)
716		fatal("%s: sshbuf_new failed", __func__);
717	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
718	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
719	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
720	if ((r = sshbuf_get_u32(m, &ret)) != 0)
721		fatal("%s: buffer error: %s", __func__, ssh_err(r));
722	debug3("%s: pam_query returned %d", __func__, ret);
723	if ((r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
724	    (r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
725	    (r = sshbuf_get_u32(m, num)) != 0)
726		fatal("%s: buffer error: %s", __func__, ssh_err(r));
727	if (*num > PAM_MAX_NUM_MSG)
728		fatal("%s: received %u PAM messages, expected <= %u",
729		    __func__, *num, PAM_MAX_NUM_MSG);
730	*prompts = xcalloc((*num + 1), sizeof(char *));
731	*echo_on = xcalloc((*num + 1), sizeof(u_int));
732	for (i = 0; i < *num; ++i) {
733		if ((r = sshbuf_get_cstring(m, &(*prompts)[i], NULL)) != 0 ||
734		    (r = sshbuf_get_u32(m, (echo_on)[i])) != 0)
735			fatal("%s: buffer error: %s", __func__, ssh_err(r));
736	}
737	sshbuf_free(m);
738	return (ret);
739}
740
741int
742mm_sshpam_respond(void *ctx, u_int num, char **resp)
743{
744	struct sshbuf *m;
745	int r;
746	u_int i;
747	u_int ret;
748
749	debug3("%s", __func__);
750	if ((m = sshbuf_new()) == NULL)
751		fatal("%s: sshbuf_new failed", __func__);
752	sshbuf_put_u32(m, num);
753	for (i = 0; i < num; ++i)
754		sshbuf_put_cstring(m, resp[i]);
755	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
756	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
757	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, m);
758	if ((r = sshbuf_get_u32(m, &ret)) != 0)
759		fatal("%s: buffer error: %s", __func__, ssh_err(r));
760	debug3("%s: pam_respond returned %d", __func__, ret);
761	sshbuf_free(m);
762	return (ret);
763}
764
765void
766mm_sshpam_free_ctx(void *ctxtp)
767{
768	struct sshbuf *m;
769
770	debug3("%s", __func__);
771	if ((m = sshbuf_new()) == NULL)
772		fatal("%s: sshbuf_new failed", __func__);
773	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
774	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
775	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m);
776	sshbuf_free(m);
777}
778#endif /* USE_PAM */
779
780/* Request process termination */
781
782void
783mm_terminate(void)
784{
785	struct sshbuf *m;
786
787	if ((m = sshbuf_new()) == NULL)
788		fatal_f("sshbuf_new failed");
789	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
790	sshbuf_free(m);
791}
792
793#if defined(BSD_AUTH) || defined(SKEY)
794static void
795mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
796    char ***prompts, u_int **echo_on)
797{
798	*name = xstrdup("");
799	*infotxt = xstrdup("");
800	*numprompts = 1;
801	*prompts = xcalloc(*numprompts, sizeof(char *));
802	*echo_on = xcalloc(*numprompts, sizeof(u_int));
803	(*echo_on)[0] = 0;
804}
805
806#ifdef BSD_AUTH
807int
808mm_bsdauth_query(void *ctx, char **name, char **infotxt,
809   u_int *numprompts, char ***prompts, u_int **echo_on)
810{
811	struct sshbuf *m;
812	u_int success;
813	char *challenge;
814	int r;
815
816	debug3_f("entering");
817
818	if ((m = sshbuf_new()) == NULL)
819		fatal_f("sshbuf_new failed");
820	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
821
822	mm_request_receive_expect(pmonitor->m_recvfd,
823	    MONITOR_ANS_BSDAUTHQUERY, m);
824	if ((r = sshbuf_get_u32(m, &success)) != 0)
825		fatal_fr(r, "parse success");
826	if (success == 0) {
827		debug3_f("no challenge");
828		sshbuf_free(m);
829		return (-1);
830	}
831
832	/* Get the challenge, and format the response */
833	if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
834		fatal_fr(r, "parse challenge");
835	sshbuf_free(m);
836
837	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
838	(*prompts)[0] = challenge;
839
840	debug3_f("received challenge: %s", challenge);
841
842	return (0);
843}
844
845int
846mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
847{
848	struct sshbuf *m;
849	int r, authok;
850
851	debug3_f("entering");
852	if (numresponses != 1)
853		return (-1);
854
855	if ((m = sshbuf_new()) == NULL)
856		fatal_f("sshbuf_new failed");
857	if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
858		fatal_fr(r, "assemble");
859	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
860
861	mm_request_receive_expect(pmonitor->m_recvfd,
862	    MONITOR_ANS_BSDAUTHRESPOND, m);
863
864	if ((r = sshbuf_get_u32(m, &authok)) != 0)
865		fatal_fr(r, "parse");
866	sshbuf_free(m);
867
868	return ((authok == 0) ? -1 : 0);
869}
870#endif
871
872#ifdef SKEY
873int
874mm_skey_query(void *ctx, char **name, char **infotxt,
875   u_int *numprompts, char ***prompts, u_int **echo_on)
876{
877	struct sshbuf m;
878	u_int success;
879	char *challenge;
880
881	debug3("%s: entering", __func__);
882
883	sshbuf_new(&m);
884	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
885
886	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
887	    &m);
888	success = sshbuf_get_int(&m);
889	if (success == 0) {
890		debug3("%s: no challenge", __func__);
891		sshbuf_free(&m);
892		return (-1);
893	}
894
895	/* Get the challenge, and format the response */
896	challenge  = sshbuf_get_string(&m, NULL);
897	sshbuf_free(&m);
898
899	debug3("%s: received challenge: %s", __func__, challenge);
900
901	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
902
903	xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
904	free(challenge);
905
906	return (0);
907}
908
909int
910mm_skey_respond(void *ctx, u_int numresponses, char **responses)
911{
912	struct sshbuf m;
913	int authok;
914
915	debug3("%s: entering", __func__);
916	if (numresponses != 1)
917		return (-1);
918
919	sshbuf_new(&m);
920	sshbuf_put_cstring(&m, responses[0]);
921	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
922
923	mm_request_receive_expect(pmonitor->m_recvfd,
924	    MONITOR_ANS_SKEYRESPOND, &m);
925
926	authok = sshbuf_get_int(&m);
927	sshbuf_free(&m);
928
929	return ((authok == 0) ? -1 : 0);
930}
931#endif /* SKEY */
932#endif /* BSDAUTH || SKEY */
933
934#ifdef GSSAPI
935OM_uint32
936mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
937{
938	struct sshbuf *m;
939	OM_uint32 major;
940	int r;
941
942	/* Client doesn't get to see the context */
943	*ctx = NULL;
944
945	if ((m = sshbuf_new()) == NULL)
946		fatal_f("sshbuf_new failed");
947	if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
948		fatal_fr(r, "assemble");
949
950	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
951	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
952
953	if ((r = sshbuf_get_u32(m, &major)) != 0)
954		fatal_fr(r, "parse");
955
956	sshbuf_free(m);
957	return (major);
958}
959
960OM_uint32
961mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
962    gss_buffer_desc *out, OM_uint32 *flagsp)
963{
964	struct sshbuf *m;
965	OM_uint32 major;
966	u_int flags;
967	int r;
968
969	if ((m = sshbuf_new()) == NULL)
970		fatal_f("sshbuf_new failed");
971	if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
972		fatal_fr(r, "assemble");
973
974	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
975	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
976
977	if ((r = sshbuf_get_u32(m, &major)) != 0 ||
978	    (r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
979		fatal_fr(r, "parse");
980	if (flagsp != NULL) {
981		if ((r = sshbuf_get_u32(m, &flags)) != 0)
982			fatal_fr(r, "parse flags");
983		*flagsp = flags;
984	}
985
986	sshbuf_free(m);
987
988	return (major);
989}
990
991OM_uint32
992mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
993{
994	struct sshbuf *m;
995	OM_uint32 major;
996	int r;
997
998	if ((m = sshbuf_new()) == NULL)
999		fatal_f("sshbuf_new failed");
1000	if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
1001	    (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
1002		fatal_fr(r, "assemble");
1003
1004	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
1005	mm_request_receive_expect(pmonitor->m_recvfd,
1006	    MONITOR_ANS_GSSCHECKMIC, m);
1007
1008	if ((r = sshbuf_get_u32(m, &major)) != 0)
1009		fatal_fr(r, "parse");
1010	sshbuf_free(m);
1011	return(major);
1012}
1013
1014int
1015mm_ssh_gssapi_userok(char *user)
1016{
1017	struct sshbuf *m;
1018	int r;
1019	u_int authenticated = 0;
1020
1021	if ((m = sshbuf_new()) == NULL)
1022		fatal_f("sshbuf_new failed");
1023
1024	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
1025	mm_request_receive_expect(pmonitor->m_recvfd,
1026	    MONITOR_ANS_GSSUSEROK, m);
1027
1028	if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
1029		fatal_fr(r, "parse");
1030
1031	sshbuf_free(m);
1032	debug3_f("user %sauthenticated", authenticated ? "" : "not ");
1033	return (authenticated);
1034}
1035#endif /* GSSAPI */
1036
1037#ifdef KRB5
1038int
1039mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
1040{
1041	krb5_data *tkt, *reply;
1042	struct sshbuf *m;
1043	u_int success;
1044	int r;
1045
1046	debug3("%s entering", __func__);
1047	tkt = (krb5_data *) argp;
1048	reply = (krb5_data *) resp;
1049
1050	if ((m = sshbuf_new()) == NULL)
1051		fatal("%s: sshbuf_new failed", __func__);
1052	sshbuf_put_string(m, tkt->data, tkt->length);
1053
1054	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, m);
1055	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, m);
1056
1057	if ((r = sshbuf_get_u32(m, &success)) != 0)
1058		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1059	if (success) {
1060		size_t len;
1061		u_char *data;
1062
1063		if ((r = sshbuf_get_cstring(m, userp, NULL)) != 0 ||
1064		    (r = sshbuf_get_string(m, &data, &len)) != 0)
1065			fatal("%s: buffer error: %s", __func__, ssh_err(r));
1066		reply->data = data;
1067		reply->length = len;
1068	} else {
1069		memset(reply, 0, sizeof(*reply));
1070		*userp = NULL;
1071	}
1072
1073	sshbuf_free(m);
1074	return (success);
1075}
1076#endif
1077