1323136Sdes/* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */
298675Sdes/*
398675Sdes * Copyright 2002 Niels Provos <provos@citi.umich.edu>
498675Sdes * Copyright 2002 Markus Friedl <markus@openbsd.org>
598675Sdes * All rights reserved.
698675Sdes *
798675Sdes * Redistribution and use in source and binary forms, with or without
898675Sdes * modification, are permitted provided that the following conditions
998675Sdes * are met:
1098675Sdes * 1. Redistributions of source code must retain the above copyright
1198675Sdes *    notice, this list of conditions and the following disclaimer.
1298675Sdes * 2. Redistributions in binary form must reproduce the above copyright
1398675Sdes *    notice, this list of conditions and the following disclaimer in the
1498675Sdes *    documentation and/or other materials provided with the distribution.
1598675Sdes *
1698675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1798675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1898675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1998675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2098675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2198675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2298675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2398675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2498675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2598675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2698675Sdes */
2798675Sdes
2898675Sdes#include "includes.h"
2998675Sdes
30162856Sdes#include <sys/types.h>
31162856Sdes#include <sys/socket.h>
32162856Sdes#include "openbsd-compat/sys-tree.h"
33162856Sdes#include <sys/wait.h>
3498675Sdes
35162856Sdes#include <errno.h>
36162856Sdes#include <fcntl.h>
37323129Sdes#include <limits.h>
38162856Sdes#ifdef HAVE_PATHS_H
39162856Sdes#include <paths.h>
40162856Sdes#endif
41162856Sdes#include <pwd.h>
42162856Sdes#include <signal.h>
43294332Sdes#ifdef HAVE_STDINT_H
44294332Sdes#include <stdint.h>
45294332Sdes#endif
46162856Sdes#include <stdlib.h>
47162856Sdes#include <string.h>
48294328Sdes#include <stdarg.h>
49294328Sdes#include <stdio.h>
50162856Sdes#include <unistd.h>
51226046Sdes#ifdef HAVE_POLL_H
52226046Sdes#include <poll.h>
53226046Sdes#else
54226046Sdes# ifdef HAVE_SYS_POLL_H
55226046Sdes#  include <sys/poll.h>
56226046Sdes# endif
57226046Sdes#endif
58162856Sdes
5998675Sdes#ifdef SKEY
6098941Sdes#include <skey.h>
6198675Sdes#endif
6298675Sdes
63294328Sdes#ifdef WITH_OPENSSL
64162856Sdes#include <openssl/dh.h>
65294328Sdes#endif
66162856Sdes
67181111Sdes#include "openbsd-compat/sys-queue.h"
68226046Sdes#include "atomicio.h"
69162856Sdes#include "xmalloc.h"
7098675Sdes#include "ssh.h"
71162856Sdes#include "key.h"
72162856Sdes#include "buffer.h"
73162856Sdes#include "hostfile.h"
7498675Sdes#include "auth.h"
75162856Sdes#include "cipher.h"
7698675Sdes#include "kex.h"
7798675Sdes#include "dh.h"
78323129Sdes#include "auth-pam.h"
79128460Sdes#ifdef TARGET_OS_MAC	/* XXX Broken krb5 headers on Mac */
80128460Sdes#undef TARGET_OS_MAC
8198675Sdes#include "zlib.h"
82128460Sdes#define TARGET_OS_MAC 1
83128460Sdes#else
84128460Sdes#include "zlib.h"
85128460Sdes#endif
8698675Sdes#include "packet.h"
8798675Sdes#include "auth-options.h"
8898675Sdes#include "sshpty.h"
8998675Sdes#include "channels.h"
9098675Sdes#include "session.h"
9198675Sdes#include "sshlogin.h"
9298675Sdes#include "canohost.h"
9398675Sdes#include "log.h"
94294328Sdes#include "misc.h"
9598675Sdes#include "servconf.h"
9698675Sdes#include "monitor.h"
97162856Sdes#ifdef GSSAPI
98162856Sdes#include "ssh-gss.h"
99162856Sdes#endif
10098675Sdes#include "monitor_wrap.h"
10198675Sdes#include "monitor_fdpass.h"
10298675Sdes#include "compat.h"
10398675Sdes#include "ssh2.h"
104255767Sdes#include "authfd.h"
105294332Sdes#include "match.h"
106294332Sdes#include "ssherr.h"
10798675Sdes
108124211Sdes#ifdef GSSAPI
109124211Sdesstatic Gssctxt *gsscontext = NULL;
110124211Sdes#endif
111124211Sdes
11298675Sdes/* Imports */
11398675Sdesextern ServerOptions options;
11498675Sdesextern u_int utmp_len;
11598675Sdesextern u_char session_id[];
11698675Sdesextern Buffer auth_debug;
11798675Sdesextern int auth_debug_init;
118137019Sdesextern Buffer loginmsg;
11998675Sdes
12098675Sdes/* State exported from the child */
121294332Sdesstatic struct sshbuf *child_state;
12298675Sdes
123124211Sdes/* Functions on the monitor that answer unprivileged requests */
12498675Sdes
12598675Sdesint mm_answer_moduli(int, Buffer *);
12698675Sdesint mm_answer_sign(int, Buffer *);
12798675Sdesint mm_answer_pwnamallow(int, Buffer *);
12898675Sdesint mm_answer_auth2_read_banner(int, Buffer *);
12998675Sdesint mm_answer_authserv(int, Buffer *);
13098675Sdesint mm_answer_authpassword(int, Buffer *);
13198675Sdesint mm_answer_bsdauthquery(int, Buffer *);
13298675Sdesint mm_answer_bsdauthrespond(int, Buffer *);
13398675Sdesint mm_answer_skeyquery(int, Buffer *);
13498675Sdesint mm_answer_skeyrespond(int, Buffer *);
13598675Sdesint mm_answer_keyallowed(int, Buffer *);
13698675Sdesint mm_answer_keyverify(int, Buffer *);
13798675Sdesint mm_answer_pty(int, Buffer *);
13898675Sdesint mm_answer_pty_cleanup(int, Buffer *);
13998675Sdesint mm_answer_term(int, Buffer *);
14098675Sdesint mm_answer_rsa_keyallowed(int, Buffer *);
14198675Sdesint mm_answer_rsa_challenge(int, Buffer *);
14298675Sdesint mm_answer_rsa_response(int, Buffer *);
14398675Sdesint mm_answer_sesskey(int, Buffer *);
14498675Sdesint mm_answer_sessid(int, Buffer *);
14598675Sdes
14698941Sdes#ifdef USE_PAM
14798941Sdesint mm_answer_pam_start(int, Buffer *);
148124211Sdesint mm_answer_pam_account(int, Buffer *);
14999052Sdesint mm_answer_pam_init_ctx(int, Buffer *);
15099052Sdesint mm_answer_pam_query(int, Buffer *);
15199052Sdesint mm_answer_pam_respond(int, Buffer *);
15299052Sdesint mm_answer_pam_free_ctx(int, Buffer *);
15398941Sdes#endif
15498941Sdes
155124211Sdes#ifdef GSSAPI
156124211Sdesint mm_answer_gss_setup_ctx(int, Buffer *);
157124211Sdesint mm_answer_gss_accept_ctx(int, Buffer *);
158124211Sdesint mm_answer_gss_userok(int, Buffer *);
159126277Sdesint mm_answer_gss_checkmic(int, Buffer *);
160106130Sdes#endif
161106130Sdes
162147005Sdes#ifdef SSH_AUDIT_EVENTS
163147005Sdesint mm_answer_audit_event(int, Buffer *);
164147005Sdesint mm_answer_audit_command(int, Buffer *);
165147005Sdes#endif
166147005Sdes
167226046Sdesstatic int monitor_read_log(struct monitor *);
168226046Sdes
16998675Sdesstatic Authctxt *authctxt;
170294328Sdes
17198675Sdes/* local state for key verify */
17298675Sdesstatic u_char *key_blob = NULL;
17398675Sdesstatic u_int key_bloblen = 0;
17498675Sdesstatic int key_blobtype = MM_NOKEY;
175106130Sdesstatic char *hostbased_cuser = NULL;
176106130Sdesstatic char *hostbased_chost = NULL;
17798675Sdesstatic char *auth_method = "unknown";
178248619Sdesstatic char *auth_submethod = NULL;
179124211Sdesstatic u_int session_id2_len = 0;
18098675Sdesstatic u_char *session_id2 = NULL;
181124211Sdesstatic pid_t monitor_child_pid;
18298675Sdes
18398675Sdesstruct mon_table {
18498675Sdes	enum monitor_reqtype type;
18598675Sdes	int flags;
18698675Sdes	int (*f)(int, Buffer *);
18798675Sdes};
18898675Sdes
18998675Sdes#define MON_ISAUTH	0x0004	/* Required for Authentication */
19098675Sdes#define MON_AUTHDECIDE	0x0008	/* Decides Authentication */
19198675Sdes#define MON_ONCE	0x0010	/* Disable after calling */
192162856Sdes#define MON_ALOG	0x0020	/* Log auth attempt without authenticating */
19398675Sdes
19498675Sdes#define MON_AUTH	(MON_ISAUTH|MON_AUTHDECIDE)
19598675Sdes
19698675Sdes#define MON_PERMIT	0x1000	/* Request is permitted */
19798675Sdes
19898675Sdesstruct mon_table mon_dispatch_proto20[] = {
199294328Sdes#ifdef WITH_OPENSSL
20098675Sdes    {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
201294328Sdes#endif
20298675Sdes    {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
20398675Sdes    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
20498675Sdes    {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
20598675Sdes    {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
20698675Sdes    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
20798941Sdes#ifdef USE_PAM
20898941Sdes    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
209124211Sdes    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
210323134Sdes    {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
211323134Sdes    {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
212323134Sdes    {MONITOR_REQ_PAM_RESPOND, MON_ONCE, mm_answer_pam_respond},
21399052Sdes    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
21498941Sdes#endif
215147005Sdes#ifdef SSH_AUDIT_EVENTS
216147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
217147005Sdes#endif
21898675Sdes#ifdef BSD_AUTH
21998675Sdes    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
220162856Sdes    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
22198675Sdes#endif
22298675Sdes#ifdef SKEY
22398675Sdes    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
22498675Sdes    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
22598675Sdes#endif
22698675Sdes    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
22798675Sdes    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
228124211Sdes#ifdef GSSAPI
229124211Sdes    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
230323134Sdes    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
231323134Sdes    {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
232323134Sdes    {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
233124211Sdes#endif
23498675Sdes    {0, 0, NULL}
23598675Sdes};
23698675Sdes
23798675Sdesstruct mon_table mon_dispatch_postauth20[] = {
238294328Sdes#ifdef WITH_OPENSSL
23998675Sdes    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
240294328Sdes#endif
24198675Sdes    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
24298675Sdes    {MONITOR_REQ_PTY, 0, mm_answer_pty},
24398675Sdes    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
24498675Sdes    {MONITOR_REQ_TERM, 0, mm_answer_term},
245147005Sdes#ifdef SSH_AUDIT_EVENTS
246147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
247147005Sdes    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
248147005Sdes#endif
24998675Sdes    {0, 0, NULL}
25098675Sdes};
25198675Sdes
25298675Sdesstruct mon_table *mon_dispatch;
25398675Sdes
25498675Sdes/* Specifies if a certain message is allowed at the moment */
25598675Sdes
25698675Sdesstatic void
25798675Sdesmonitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
25898675Sdes{
25998675Sdes	while (ent->f != NULL) {
26098675Sdes		if (ent->type == type) {
26198675Sdes			ent->flags &= ~MON_PERMIT;
26298675Sdes			ent->flags |= permit ? MON_PERMIT : 0;
26398675Sdes			return;
26498675Sdes		}
26598675Sdes		ent++;
26698675Sdes	}
26798675Sdes}
26898675Sdes
26998675Sdesstatic void
27098675Sdesmonitor_permit_authentications(int permit)
27198675Sdes{
27298675Sdes	struct mon_table *ent = mon_dispatch;
27398675Sdes
27498675Sdes	while (ent->f != NULL) {
27598675Sdes		if (ent->flags & MON_AUTH) {
27698675Sdes			ent->flags &= ~MON_PERMIT;
27798675Sdes			ent->flags |= permit ? MON_PERMIT : 0;
27898675Sdes		}
27998675Sdes		ent++;
28098675Sdes	}
28198675Sdes}
28298675Sdes
283126277Sdesvoid
284126277Sdesmonitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
28598675Sdes{
286323136Sdes	struct ssh *ssh = active_state;	/* XXX */
28798675Sdes	struct mon_table *ent;
288248619Sdes	int authenticated = 0, partial = 0;
28998675Sdes
29098675Sdes	debug3("preauth child monitor started");
29198675Sdes
292226046Sdes	close(pmonitor->m_recvfd);
293226046Sdes	close(pmonitor->m_log_sendfd);
294226046Sdes	pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
295226046Sdes
296126277Sdes	authctxt = _authctxt;
297126277Sdes	memset(authctxt, 0, sizeof(*authctxt));
298126277Sdes
299147005Sdes	authctxt->loginmsg = &loginmsg;
300147005Sdes
301323134Sdes	mon_dispatch = mon_dispatch_proto20;
302323134Sdes	/* Permit requests for moduli and signatures */
303323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
304323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
30598675Sdes
30698675Sdes	/* The first few requests do not require asynchronous access */
30798675Sdes	while (!authenticated) {
308248619Sdes		partial = 0;
309162856Sdes		auth_method = "unknown";
310248619Sdes		auth_submethod = NULL;
311164149Sdes		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
312248619Sdes
313248619Sdes		/* Special handling for multiple required authentications */
314248619Sdes		if (options.num_auth_methods != 0) {
315248619Sdes			if (authenticated &&
316248619Sdes			    !auth2_update_methods_lists(authctxt,
317255767Sdes			    auth_method, auth_submethod)) {
318248619Sdes				debug3("%s: method %s: partial", __func__,
319248619Sdes				    auth_method);
320248619Sdes				authenticated = 0;
321248619Sdes				partial = 1;
322248619Sdes			}
323248619Sdes		}
324248619Sdes
32598675Sdes		if (authenticated) {
32698675Sdes			if (!(ent->flags & MON_AUTHDECIDE))
32798675Sdes				fatal("%s: unexpected authentication from %d",
32898675Sdes				    __func__, ent->type);
32998675Sdes			if (authctxt->pw->pw_uid == 0 &&
33098675Sdes			    !auth_root_allowed(auth_method))
33198675Sdes				authenticated = 0;
332124211Sdes#ifdef USE_PAM
333124211Sdes			/* PAM needs to perform account checks after auth */
334126277Sdes			if (options.use_pam && authenticated) {
335124211Sdes				Buffer m;
336124211Sdes
337124211Sdes				buffer_init(&m);
338126277Sdes				mm_request_receive_expect(pmonitor->m_sendfd,
339124211Sdes				    MONITOR_REQ_PAM_ACCOUNT, &m);
340124211Sdes				authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
341124211Sdes				buffer_free(&m);
342124211Sdes			}
343124211Sdes#endif
34498675Sdes		}
345162856Sdes		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
346248619Sdes			auth_log(authctxt, authenticated, partial,
347255767Sdes			    auth_method, auth_submethod);
348294336Sdes			if (!partial && !authenticated)
34998675Sdes				authctxt->failures++;
35098675Sdes		}
35198675Sdes	}
35298675Sdes
35398675Sdes	if (!authctxt->valid)
35498675Sdes		fatal("%s: authenticated invalid user", __func__);
355162856Sdes	if (strcmp(auth_method, "unknown") == 0)
356162856Sdes		fatal("%s: authentication method name unknown", __func__);
35798675Sdes
35898675Sdes	debug("%s: %s has been authenticated by privileged process",
35998675Sdes	    __func__, authctxt->user);
360323136Sdes	ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
36198675Sdes
36298675Sdes	mm_get_keystate(pmonitor);
363226046Sdes
364248619Sdes	/* Drain any buffered messages from the child */
365248619Sdes	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
366248619Sdes		;
367248619Sdes
368226046Sdes	close(pmonitor->m_sendfd);
369226046Sdes	close(pmonitor->m_log_recvfd);
370226046Sdes	pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
37198675Sdes}
37298675Sdes
373124211Sdesstatic void
374124211Sdesmonitor_set_child_handler(pid_t pid)
375124211Sdes{
376124211Sdes	monitor_child_pid = pid;
377124211Sdes}
378124211Sdes
379124211Sdesstatic void
380137019Sdesmonitor_child_handler(int sig)
381124211Sdes{
382137019Sdes	kill(monitor_child_pid, sig);
383124211Sdes}
384124211Sdes
38598675Sdesvoid
38698675Sdesmonitor_child_postauth(struct monitor *pmonitor)
38798675Sdes{
388226046Sdes	close(pmonitor->m_recvfd);
389226046Sdes	pmonitor->m_recvfd = -1;
390226046Sdes
391124211Sdes	monitor_set_child_handler(pmonitor->m_pid);
392124211Sdes	signal(SIGHUP, &monitor_child_handler);
393124211Sdes	signal(SIGTERM, &monitor_child_handler);
394181111Sdes	signal(SIGINT, &monitor_child_handler);
395294328Sdes#ifdef SIGXFSZ
396294328Sdes	signal(SIGXFSZ, SIG_IGN);
397294328Sdes#endif
398124211Sdes
399323134Sdes	mon_dispatch = mon_dispatch_postauth20;
40098675Sdes
401323134Sdes	/* Permit requests for moduli and signatures */
402323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
403323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
404323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
405323134Sdes
40698675Sdes	if (!no_pty_flag) {
40798675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
40898675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
40998675Sdes	}
41098675Sdes
41198675Sdes	for (;;)
41298675Sdes		monitor_read(pmonitor, mon_dispatch, NULL);
41398675Sdes}
41498675Sdes
415226046Sdesstatic int
416226046Sdesmonitor_read_log(struct monitor *pmonitor)
417226046Sdes{
418226046Sdes	Buffer logmsg;
419226046Sdes	u_int len, level;
420226046Sdes	char *msg;
421226046Sdes
422226046Sdes	buffer_init(&logmsg);
423226046Sdes
424226046Sdes	/* Read length */
425226046Sdes	buffer_append_space(&logmsg, 4);
426226046Sdes	if (atomicio(read, pmonitor->m_log_recvfd,
427226046Sdes	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
428226046Sdes		if (errno == EPIPE) {
429240075Sdes			buffer_free(&logmsg);
430226046Sdes			debug("%s: child log fd closed", __func__);
431226046Sdes			close(pmonitor->m_log_recvfd);
432226046Sdes			pmonitor->m_log_recvfd = -1;
433226046Sdes			return -1;
434226046Sdes		}
435226046Sdes		fatal("%s: log fd read: %s", __func__, strerror(errno));
436226046Sdes	}
437226046Sdes	len = buffer_get_int(&logmsg);
438226046Sdes	if (len <= 4 || len > 8192)
439226046Sdes		fatal("%s: invalid log message length %u", __func__, len);
440226046Sdes
441226046Sdes	/* Read severity, message */
442226046Sdes	buffer_clear(&logmsg);
443226046Sdes	buffer_append_space(&logmsg, len);
444226046Sdes	if (atomicio(read, pmonitor->m_log_recvfd,
445226046Sdes	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
446226046Sdes		fatal("%s: log fd read: %s", __func__, strerror(errno));
447226046Sdes
448226046Sdes	/* Log it */
449226046Sdes	level = buffer_get_int(&logmsg);
450226046Sdes	msg = buffer_get_string(&logmsg, NULL);
451226046Sdes	if (log_level_name(level) == NULL)
452226046Sdes		fatal("%s: invalid log level %u (corrupted message?)",
453226046Sdes		    __func__, level);
454226046Sdes	do_log2(level, "%s [preauth]", msg);
455226046Sdes
456226046Sdes	buffer_free(&logmsg);
457255767Sdes	free(msg);
458226046Sdes
459226046Sdes	return 0;
460226046Sdes}
461226046Sdes
46298675Sdesint
46398675Sdesmonitor_read(struct monitor *pmonitor, struct mon_table *ent,
46498675Sdes    struct mon_table **pent)
46598675Sdes{
46698675Sdes	Buffer m;
46798675Sdes	int ret;
46898675Sdes	u_char type;
469226046Sdes	struct pollfd pfd[2];
47098675Sdes
471226046Sdes	for (;;) {
472263712Sdes		memset(&pfd, 0, sizeof(pfd));
473226046Sdes		pfd[0].fd = pmonitor->m_sendfd;
474226046Sdes		pfd[0].events = POLLIN;
475226046Sdes		pfd[1].fd = pmonitor->m_log_recvfd;
476226046Sdes		pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
477226046Sdes		if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
478226046Sdes			if (errno == EINTR || errno == EAGAIN)
479226046Sdes				continue;
480226046Sdes			fatal("%s: poll: %s", __func__, strerror(errno));
481226046Sdes		}
482226046Sdes		if (pfd[1].revents) {
483226046Sdes			/*
484226046Sdes			 * Drain all log messages before processing next
485226046Sdes			 * monitor request.
486226046Sdes			 */
487226046Sdes			monitor_read_log(pmonitor);
488226046Sdes			continue;
489226046Sdes		}
490226046Sdes		if (pfd[0].revents)
491226046Sdes			break;  /* Continues below */
492226046Sdes	}
493226046Sdes
49498675Sdes	buffer_init(&m);
49598675Sdes
49698675Sdes	mm_request_receive(pmonitor->m_sendfd, &m);
49798675Sdes	type = buffer_get_char(&m);
49898675Sdes
49998675Sdes	debug3("%s: checking request %d", __func__, type);
50098675Sdes
50198675Sdes	while (ent->f != NULL) {
50298675Sdes		if (ent->type == type)
50398675Sdes			break;
50498675Sdes		ent++;
50598675Sdes	}
50698675Sdes
50798675Sdes	if (ent->f != NULL) {
50898675Sdes		if (!(ent->flags & MON_PERMIT))
50998675Sdes			fatal("%s: unpermitted request %d", __func__,
51098675Sdes			    type);
51198675Sdes		ret = (*ent->f)(pmonitor->m_sendfd, &m);
51298675Sdes		buffer_free(&m);
51398675Sdes
51498675Sdes		/* The child may use this request only once, disable it */
51598675Sdes		if (ent->flags & MON_ONCE) {
51698675Sdes			debug2("%s: %d used once, disabling now", __func__,
51798675Sdes			    type);
51898675Sdes			ent->flags &= ~MON_PERMIT;
51998675Sdes		}
52098675Sdes
52198675Sdes		if (pent != NULL)
52298675Sdes			*pent = ent;
52398675Sdes
52498675Sdes		return ret;
52598675Sdes	}
52698675Sdes
52798675Sdes	fatal("%s: unsupported request: %d", __func__, type);
52898675Sdes
52998675Sdes	/* NOTREACHED */
53098675Sdes	return (-1);
53198675Sdes}
53298675Sdes
53398675Sdes/* allowed key state */
53498675Sdesstatic int
53598675Sdesmonitor_allowed_key(u_char *blob, u_int bloblen)
53698675Sdes{
53798675Sdes	/* make sure key is allowed */
53898675Sdes	if (key_blob == NULL || key_bloblen != bloblen ||
539215116Sdes	    timingsafe_bcmp(key_blob, blob, key_bloblen))
54098675Sdes		return (0);
54198675Sdes	return (1);
54298675Sdes}
54398675Sdes
54498675Sdesstatic void
54598675Sdesmonitor_reset_key_state(void)
54698675Sdes{
54798675Sdes	/* reset state */
548255767Sdes	free(key_blob);
549255767Sdes	free(hostbased_cuser);
550255767Sdes	free(hostbased_chost);
55198675Sdes	key_blob = NULL;
55298675Sdes	key_bloblen = 0;
55398675Sdes	key_blobtype = MM_NOKEY;
55498675Sdes	hostbased_cuser = NULL;
55598675Sdes	hostbased_chost = NULL;
55698675Sdes}
55798675Sdes
558294328Sdes#ifdef WITH_OPENSSL
55998675Sdesint
560137019Sdesmm_answer_moduli(int sock, Buffer *m)
56198675Sdes{
56298675Sdes	DH *dh;
56398675Sdes	int min, want, max;
56498675Sdes
56598675Sdes	min = buffer_get_int(m);
56698675Sdes	want = buffer_get_int(m);
56798675Sdes	max = buffer_get_int(m);
56898675Sdes
56998675Sdes	debug3("%s: got parameters: %d %d %d",
57098675Sdes	    __func__, min, want, max);
57198675Sdes	/* We need to check here, too, in case the child got corrupted */
57298675Sdes	if (max < min || want < min || max < want)
57398675Sdes		fatal("%s: bad parameters: %d %d %d",
57498675Sdes		    __func__, min, want, max);
57598675Sdes
57698675Sdes	buffer_clear(m);
57798675Sdes
57898675Sdes	dh = choose_dh(min, want, max);
57998675Sdes	if (dh == NULL) {
58098675Sdes		buffer_put_char(m, 0);
58198675Sdes		return (0);
58298675Sdes	} else {
58398675Sdes		/* Send first bignum */
58498675Sdes		buffer_put_char(m, 1);
58598675Sdes		buffer_put_bignum2(m, dh->p);
58698675Sdes		buffer_put_bignum2(m, dh->g);
58798675Sdes
58898675Sdes		DH_free(dh);
58998675Sdes	}
590137019Sdes	mm_request_send(sock, MONITOR_ANS_MODULI, m);
59198675Sdes	return (0);
59298675Sdes}
593294328Sdes#endif
59498675Sdes
59598675Sdesint
596137019Sdesmm_answer_sign(int sock, Buffer *m)
59798675Sdes{
598294332Sdes	struct ssh *ssh = active_state; 	/* XXX */
599294332Sdes	extern int auth_sock;			/* XXX move to state struct? */
600294332Sdes	struct sshkey *key;
601296633Sdes	struct sshbuf *sigbuf = NULL;
602296633Sdes	u_char *p = NULL, *signature = NULL;
603296633Sdes	char *alg = NULL;
604296633Sdes	size_t datlen, siglen, alglen;
605323129Sdes	int r, is_proof = 0;
606323129Sdes	u_int keyid;
607294332Sdes	const char proof_req[] = "hostkeys-prove-00@openssh.com";
60898675Sdes
60998675Sdes	debug3("%s", __func__);
61098675Sdes
611294332Sdes	if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
612296633Sdes	    (r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
613296633Sdes	    (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0)
614294332Sdes		fatal("%s: buffer error: %s", __func__, ssh_err(r));
615323129Sdes	if (keyid > INT_MAX)
616323129Sdes		fatal("%s: invalid key ID", __func__);
61798675Sdes
618162856Sdes	/*
619221420Sdes	 * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
620221420Sdes	 * SHA384 (48 bytes) and SHA512 (64 bytes).
621294332Sdes	 *
622294332Sdes	 * Otherwise, verify the signature request is for a hostkey
623294332Sdes	 * proof.
624294332Sdes	 *
625294332Sdes	 * XXX perform similar check for KEX signature requests too?
626294332Sdes	 * it's not trivial, since what is signed is the hash, rather
627294332Sdes	 * than the full kex structure...
628162856Sdes	 */
629294332Sdes	if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) {
630294332Sdes		/*
631294332Sdes		 * Construct expected hostkey proof and compare it to what
632294332Sdes		 * the client sent us.
633294332Sdes		 */
634294332Sdes		if (session_id2_len == 0) /* hostkeys is never first */
635294332Sdes			fatal("%s: bad data length: %zu", __func__, datlen);
636294332Sdes		if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL)
637294332Sdes			fatal("%s: no hostkey for index %d", __func__, keyid);
638294332Sdes		if ((sigbuf = sshbuf_new()) == NULL)
639294332Sdes			fatal("%s: sshbuf_new", __func__);
640294332Sdes		if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 ||
641294332Sdes		    (r = sshbuf_put_string(sigbuf, session_id2,
642296633Sdes		    session_id2_len)) != 0 ||
643294332Sdes		    (r = sshkey_puts(key, sigbuf)) != 0)
644294332Sdes			fatal("%s: couldn't prepare private key "
645294332Sdes			    "proof buffer: %s", __func__, ssh_err(r));
646294332Sdes		if (datlen != sshbuf_len(sigbuf) ||
647294332Sdes		    memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0)
648294332Sdes			fatal("%s: bad data length: %zu, hostkey proof len %zu",
649294332Sdes			    __func__, datlen, sshbuf_len(sigbuf));
650294332Sdes		sshbuf_free(sigbuf);
651294332Sdes		is_proof = 1;
652294332Sdes	}
65398675Sdes
65498675Sdes	/* save session id, it will be passed on the first call */
65598675Sdes	if (session_id2_len == 0) {
65698675Sdes		session_id2_len = datlen;
65798675Sdes		session_id2 = xmalloc(session_id2_len);
65898675Sdes		memcpy(session_id2, p, session_id2_len);
65998675Sdes	}
66098675Sdes
661255767Sdes	if ((key = get_hostkey_by_index(keyid)) != NULL) {
662296633Sdes		if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
663294332Sdes		    datafellows)) != 0)
664294332Sdes			fatal("%s: sshkey_sign failed: %s",
665294332Sdes			    __func__, ssh_err(r));
666294332Sdes	} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
667294332Sdes	    auth_sock > 0) {
668294332Sdes		if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
669296633Sdes		    p, datlen, alg, datafellows)) != 0) {
670294332Sdes			fatal("%s: ssh_agent_sign failed: %s",
671294332Sdes			    __func__, ssh_err(r));
672294332Sdes		}
673255767Sdes	} else
67498675Sdes		fatal("%s: no hostkey from index %d", __func__, keyid);
67598675Sdes
676294332Sdes	debug3("%s: %s signature %p(%zu)", __func__,
677294332Sdes	    is_proof ? "KEX" : "hostkey proof", signature, siglen);
67898675Sdes
679294332Sdes	sshbuf_reset(m);
680294332Sdes	if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
681294332Sdes		fatal("%s: buffer error: %s", __func__, ssh_err(r));
68298675Sdes
683296633Sdes	free(alg);
684255767Sdes	free(p);
685255767Sdes	free(signature);
68698675Sdes
687137019Sdes	mm_request_send(sock, MONITOR_ANS_SIGN, m);
68898675Sdes
68998675Sdes	/* Turn on permissions for getpwnam */
69098675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
69198675Sdes
69298675Sdes	return (0);
69398675Sdes}
69498675Sdes
69598675Sdes/* Retrieves the password entry and also checks if the user is permitted */
69698675Sdes
69798675Sdesint
698137019Sdesmm_answer_pwnamallow(int sock, Buffer *m)
69998675Sdes{
700323136Sdes	struct ssh *ssh = active_state;	/* XXX */
701137019Sdes	char *username;
70298675Sdes	struct passwd *pwent;
70398675Sdes	int allowed = 0;
704226046Sdes	u_int i;
70598675Sdes
70698675Sdes	debug3("%s", __func__);
70798675Sdes
70898675Sdes	if (authctxt->attempt++ != 0)
70998675Sdes		fatal("%s: multiple attempts for getpwnam", __func__);
71098675Sdes
711137019Sdes	username = buffer_get_string(m, NULL);
71298675Sdes
713137019Sdes	pwent = getpwnamallow(username);
71498675Sdes
715137019Sdes	authctxt->user = xstrdup(username);
716137019Sdes	setproctitle("%s [priv]", pwent ? username : "unknown");
717255767Sdes	free(username);
71898675Sdes
71998675Sdes	buffer_clear(m);
72098675Sdes
72198675Sdes	if (pwent == NULL) {
72298675Sdes		buffer_put_char(m, 0);
723126277Sdes		authctxt->pw = fakepw();
72498675Sdes		goto out;
72598675Sdes	}
72698675Sdes
72798675Sdes	allowed = 1;
72898675Sdes	authctxt->pw = pwent;
72998675Sdes	authctxt->valid = 1;
73098675Sdes
73198675Sdes	buffer_put_char(m, 1);
73298675Sdes	buffer_put_string(m, pwent, sizeof(struct passwd));
73398675Sdes	buffer_put_cstring(m, pwent->pw_name);
73498675Sdes	buffer_put_cstring(m, "*");
735255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
73698675Sdes	buffer_put_cstring(m, pwent->pw_gecos);
737255767Sdes#endif
738255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
73998675Sdes	buffer_put_cstring(m, pwent->pw_class);
74098941Sdes#endif
74198675Sdes	buffer_put_cstring(m, pwent->pw_dir);
74298675Sdes	buffer_put_cstring(m, pwent->pw_shell);
74398675Sdes
74498675Sdes out:
745323136Sdes	ssh_packet_set_log_preamble(ssh, "%suser %s",
746323136Sdes	    authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
747181111Sdes	buffer_put_string(m, &options, sizeof(options));
748226046Sdes
749226046Sdes#define M_CP_STROPT(x) do { \
750226046Sdes		if (options.x != NULL) \
751226046Sdes			buffer_put_cstring(m, options.x); \
752226046Sdes	} while (0)
753226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \
754226046Sdes		for (i = 0; i < options.nx; i++) \
755226046Sdes			buffer_put_cstring(m, options.x[i]); \
756226046Sdes	} while (0)
757226046Sdes	/* See comment in servconf.h */
758226046Sdes	COPY_MATCH_STRING_OPTS();
759226046Sdes#undef M_CP_STROPT
760226046Sdes#undef M_CP_STRARRAYOPT
761248619Sdes
762248619Sdes	/* Create valid auth method lists */
763323134Sdes	if (auth2_setup_methods_lists(authctxt) != 0) {
764248619Sdes		/*
765248619Sdes		 * The monitor will continue long enough to let the child
766248619Sdes		 * run to it's packet_disconnect(), but it must not allow any
767248619Sdes		 * authentication to succeed.
768248619Sdes		 */
769248619Sdes		debug("%s: no valid authentication method lists", __func__);
770248619Sdes	}
771248619Sdes
77298675Sdes	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
773137019Sdes	mm_request_send(sock, MONITOR_ANS_PWNAM, m);
77498675Sdes
775323134Sdes	/* Allow service/style information on the auth context */
776323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
777323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
778323134Sdes
77998941Sdes#ifdef USE_PAM
780124211Sdes	if (options.use_pam)
781124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
78298941Sdes#endif
78398675Sdes
78498675Sdes	return (0);
78598675Sdes}
78698675Sdes
787137019Sdesint mm_answer_auth2_read_banner(int sock, Buffer *m)
78898675Sdes{
78998675Sdes	char *banner;
79098675Sdes
79198675Sdes	buffer_clear(m);
79298675Sdes	banner = auth2_read_banner();
79398675Sdes	buffer_put_cstring(m, banner != NULL ? banner : "");
794137019Sdes	mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
795255767Sdes	free(banner);
79698675Sdes
79798675Sdes	return (0);
79898675Sdes}
79998675Sdes
80098675Sdesint
801137019Sdesmm_answer_authserv(int sock, Buffer *m)
80298675Sdes{
80398675Sdes	monitor_permit_authentications(1);
80498675Sdes
80598675Sdes	authctxt->service = buffer_get_string(m, NULL);
80698675Sdes	authctxt->style = buffer_get_string(m, NULL);
80798675Sdes	debug3("%s: service=%s, style=%s",
80898675Sdes	    __func__, authctxt->service, authctxt->style);
80998675Sdes
81098675Sdes	if (strlen(authctxt->style) == 0) {
811255767Sdes		free(authctxt->style);
81298675Sdes		authctxt->style = NULL;
81398675Sdes	}
81498675Sdes
81598675Sdes	return (0);
81698675Sdes}
81798675Sdes
81898675Sdesint
819137019Sdesmm_answer_authpassword(int sock, Buffer *m)
82098675Sdes{
82198675Sdes	static int call_count;
82298675Sdes	char *passwd;
823106130Sdes	int authenticated;
824106130Sdes	u_int plen;
82598675Sdes
826323134Sdes	if (!options.password_authentication)
827323134Sdes		fatal("%s: password authentication not enabled", __func__);
82898675Sdes	passwd = buffer_get_string(m, &plen);
82998675Sdes	/* Only authenticate if the context is valid */
83098675Sdes	authenticated = options.password_authentication &&
831124211Sdes	    auth_password(authctxt, passwd);
832263712Sdes	explicit_bzero(passwd, strlen(passwd));
833255767Sdes	free(passwd);
83498675Sdes
83598675Sdes	buffer_clear(m);
83698675Sdes	buffer_put_int(m, authenticated);
837323129Sdes#ifdef USE_PAM
838323129Sdes	buffer_put_int(m, sshpam_get_maxtries_reached());
839323129Sdes#endif
84098675Sdes
84198675Sdes	debug3("%s: sending result %d", __func__, authenticated);
842137019Sdes	mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
84398675Sdes
84498675Sdes	call_count++;
84598675Sdes	if (plen == 0 && call_count == 1)
84698675Sdes		auth_method = "none";
84798675Sdes	else
84898675Sdes		auth_method = "password";
84998675Sdes
85098675Sdes	/* Causes monitor loop to terminate if authenticated */
85198675Sdes	return (authenticated);
85298675Sdes}
85398675Sdes
85498675Sdes#ifdef BSD_AUTH
85598675Sdesint
856137019Sdesmm_answer_bsdauthquery(int sock, Buffer *m)
85798675Sdes{
85898675Sdes	char *name, *infotxt;
85998675Sdes	u_int numprompts;
86098675Sdes	u_int *echo_on;
86198675Sdes	char **prompts;
862113911Sdes	u_int success;
86398675Sdes
864323134Sdes	if (!options.kbd_interactive_authentication)
865323134Sdes		fatal("%s: kbd-int authentication not enabled", __func__);
866113911Sdes	success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
867113911Sdes	    &prompts, &echo_on) < 0 ? 0 : 1;
86898675Sdes
86998675Sdes	buffer_clear(m);
870113911Sdes	buffer_put_int(m, success);
871113911Sdes	if (success)
87298675Sdes		buffer_put_cstring(m, prompts[0]);
87398675Sdes
874113911Sdes	debug3("%s: sending challenge success: %u", __func__, success);
875137019Sdes	mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
87698675Sdes
877113911Sdes	if (success) {
878255767Sdes		free(name);
879255767Sdes		free(infotxt);
880255767Sdes		free(prompts);
881255767Sdes		free(echo_on);
88298675Sdes	}
88398675Sdes
88498675Sdes	return (0);
88598675Sdes}
88698675Sdes
88798675Sdesint
888137019Sdesmm_answer_bsdauthrespond(int sock, Buffer *m)
88998675Sdes{
89098675Sdes	char *response;
89198675Sdes	int authok;
89298675Sdes
893323134Sdes	if (!options.kbd_interactive_authentication)
894323134Sdes		fatal("%s: kbd-int authentication not enabled", __func__);
895296633Sdes	if (authctxt->as == NULL)
89698675Sdes		fatal("%s: no bsd auth session", __func__);
89798675Sdes
89898675Sdes	response = buffer_get_string(m, NULL);
89998675Sdes	authok = options.challenge_response_authentication &&
90098675Sdes	    auth_userresponse(authctxt->as, response, 0);
90198675Sdes	authctxt->as = NULL;
90298675Sdes	debug3("%s: <%s> = <%d>", __func__, response, authok);
903255767Sdes	free(response);
90498675Sdes
90598675Sdes	buffer_clear(m);
90698675Sdes	buffer_put_int(m, authok);
90798675Sdes
90898675Sdes	debug3("%s: sending authenticated: %d", __func__, authok);
909137019Sdes	mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
91098675Sdes
911323134Sdes	auth_method = "keyboard-interactive";
912323134Sdes	auth_submethod = "bsdauth";
91398675Sdes
91498675Sdes	return (authok != 0);
91598675Sdes}
91698675Sdes#endif
91798675Sdes
91898675Sdes#ifdef SKEY
91998675Sdesint
920137019Sdesmm_answer_skeyquery(int sock, Buffer *m)
92198675Sdes{
92298941Sdes	struct skey skey;
92398675Sdes	char challenge[1024];
924113911Sdes	u_int success;
92598675Sdes
926128460Sdes	success = _compat_skeychallenge(&skey, authctxt->user, challenge,
927128460Sdes	    sizeof(challenge)) < 0 ? 0 : 1;
92898675Sdes
92998675Sdes	buffer_clear(m);
930113911Sdes	buffer_put_int(m, success);
931113911Sdes	if (success)
93298675Sdes		buffer_put_cstring(m, challenge);
93398675Sdes
934113911Sdes	debug3("%s: sending challenge success: %u", __func__, success);
935137019Sdes	mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
93698675Sdes
93798675Sdes	return (0);
93898675Sdes}
93998675Sdes
94098675Sdesint
941137019Sdesmm_answer_skeyrespond(int sock, Buffer *m)
94298675Sdes{
94398675Sdes	char *response;
94498675Sdes	int authok;
94598675Sdes
94698675Sdes	response = buffer_get_string(m, NULL);
94798675Sdes
94898675Sdes	authok = (options.challenge_response_authentication &&
94998675Sdes	    authctxt->valid &&
95098941Sdes	    skey_haskey(authctxt->pw->pw_name) == 0 &&
95198941Sdes	    skey_passcheck(authctxt->pw->pw_name, response) != -1);
95298675Sdes
953255767Sdes	free(response);
95498675Sdes
95598675Sdes	buffer_clear(m);
95698675Sdes	buffer_put_int(m, authok);
95798675Sdes
95898675Sdes	debug3("%s: sending authenticated: %d", __func__, authok);
959137019Sdes	mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
96098675Sdes
961296633Sdes	auth_method = "keyboard-interactive";
962296633Sdes	auth_submethod = "skey";
96398675Sdes
96498675Sdes	return (authok != 0);
96598675Sdes}
96698675Sdes#endif
96798675Sdes
96898941Sdes#ifdef USE_PAM
96998941Sdesint
970137019Sdesmm_answer_pam_start(int sock, Buffer *m)
97198941Sdes{
972124211Sdes	if (!options.use_pam)
973124211Sdes		fatal("UsePAM not set, but ended up in %s anyway", __func__);
974124211Sdes
975128460Sdes	start_pam(authctxt);
97698941Sdes
977124211Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
978323134Sdes	if (options.kbd_interactive_authentication)
979323134Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
980124211Sdes
98198941Sdes	return (0);
98298941Sdes}
98399052Sdes
984124211Sdesint
985137019Sdesmm_answer_pam_account(int sock, Buffer *m)
986124211Sdes{
987124211Sdes	u_int ret;
988126277Sdes
989124211Sdes	if (!options.use_pam)
990323134Sdes		fatal("%s: PAM not enabled", __func__);
99199052Sdes
992124211Sdes	ret = do_pam_account();
993124211Sdes
994124211Sdes	buffer_put_int(m, ret);
995157019Sdes	buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
996124211Sdes
997137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
998124211Sdes
999124211Sdes	return (ret);
1000124211Sdes}
1001124211Sdes
1002124211Sdesstatic void *sshpam_ctxt, *sshpam_authok;
1003124211Sdesextern KbdintDevice sshpam_device;
1004124211Sdes
100599052Sdesint
1006137019Sdesmm_answer_pam_init_ctx(int sock, Buffer *m)
100799052Sdes{
100899052Sdes	debug3("%s", __func__);
1009323134Sdes	if (!options.kbd_interactive_authentication)
1010323134Sdes		fatal("%s: kbd-int authentication not enabled", __func__);
1011323134Sdes	if (sshpam_ctxt != NULL)
1012323134Sdes		fatal("%s: already called", __func__);
1013124211Sdes	sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
1014124211Sdes	sshpam_authok = NULL;
101599052Sdes	buffer_clear(m);
1016124211Sdes	if (sshpam_ctxt != NULL) {
101799052Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
1018323134Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_QUERY, 1);
101999052Sdes		buffer_put_int(m, 1);
102099052Sdes	} else {
102199052Sdes		buffer_put_int(m, 0);
102299052Sdes	}
1023137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
102499052Sdes	return (0);
102599052Sdes}
102699052Sdes
102799052Sdesint
1028137019Sdesmm_answer_pam_query(int sock, Buffer *m)
102999052Sdes{
1030215116Sdes	char *name = NULL, *info = NULL, **prompts = NULL;
1031215116Sdes	u_int i, num = 0, *echo_on = 0;
1032149753Sdes	int ret;
103399052Sdes
103499052Sdes	debug3("%s", __func__);
1035124211Sdes	sshpam_authok = NULL;
1036323134Sdes	if (sshpam_ctxt == NULL)
1037323134Sdes		fatal("%s: no context", __func__);
1038323134Sdes	ret = (sshpam_device.query)(sshpam_ctxt, &name, &info,
1039323134Sdes	    &num, &prompts, &echo_on);
1040110138Sdes	if (ret == 0 && num == 0)
1041124211Sdes		sshpam_authok = sshpam_ctxt;
104299052Sdes	if (num > 1 || name == NULL || info == NULL)
1043323134Sdes		fatal("sshpam_device.query failed");
1044323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_RESPOND, 1);
104599747Sdes	buffer_clear(m);
104699052Sdes	buffer_put_int(m, ret);
104799052Sdes	buffer_put_cstring(m, name);
1048255767Sdes	free(name);
104999052Sdes	buffer_put_cstring(m, info);
1050255767Sdes	free(info);
1051323129Sdes	buffer_put_int(m, sshpam_get_maxtries_reached());
105299052Sdes	buffer_put_int(m, num);
105399052Sdes	for (i = 0; i < num; ++i) {
105499052Sdes		buffer_put_cstring(m, prompts[i]);
1055255767Sdes		free(prompts[i]);
105699052Sdes		buffer_put_int(m, echo_on[i]);
105799052Sdes	}
1058255767Sdes	free(prompts);
1059255767Sdes	free(echo_on);
1060248619Sdes	auth_method = "keyboard-interactive";
1061248619Sdes	auth_submethod = "pam";
1062137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
106399052Sdes	return (0);
106499052Sdes}
106599052Sdes
106699052Sdesint
1067137019Sdesmm_answer_pam_respond(int sock, Buffer *m)
106899052Sdes{
106999052Sdes	char **resp;
1070149753Sdes	u_int i, num;
1071149753Sdes	int ret;
107299052Sdes
107399052Sdes	debug3("%s", __func__);
1074323134Sdes	if (sshpam_ctxt == NULL)
1075323134Sdes		fatal("%s: no context", __func__);
1076124211Sdes	sshpam_authok = NULL;
107799052Sdes	num = buffer_get_int(m);
107899052Sdes	if (num > 0) {
1079162856Sdes		resp = xcalloc(num, sizeof(char *));
108099052Sdes		for (i = 0; i < num; ++i)
108199052Sdes			resp[i] = buffer_get_string(m, NULL);
1082124211Sdes		ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
108399052Sdes		for (i = 0; i < num; ++i)
1084255767Sdes			free(resp[i]);
1085255767Sdes		free(resp);
108699052Sdes	} else {
1087124211Sdes		ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
108899052Sdes	}
108999052Sdes	buffer_clear(m);
109099052Sdes	buffer_put_int(m, ret);
1091137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
1092248619Sdes	auth_method = "keyboard-interactive";
1093248619Sdes	auth_submethod = "pam";
109499052Sdes	if (ret == 0)
1095124211Sdes		sshpam_authok = sshpam_ctxt;
109699258Sdes	return (0);
109799052Sdes}
109899052Sdes
109999052Sdesint
1100137019Sdesmm_answer_pam_free_ctx(int sock, Buffer *m)
110199052Sdes{
1102287143Sdelphij	int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt;
110399052Sdes
110499052Sdes	debug3("%s", __func__);
1105323134Sdes	if (sshpam_ctxt == NULL)
1106323134Sdes		fatal("%s: no context", __func__);
1107124211Sdes	(sshpam_device.free_ctx)(sshpam_ctxt);
1108287143Sdelphij	sshpam_ctxt = sshpam_authok = NULL;
110999052Sdes	buffer_clear(m);
1110137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
1111323134Sdes	/* Allow another attempt */
1112323134Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
1113248619Sdes	auth_method = "keyboard-interactive";
1114248619Sdes	auth_submethod = "pam";
1115287143Sdelphij	return r;
111699052Sdes}
111798941Sdes#endif
111898941Sdes
111998675Sdesint
1120137019Sdesmm_answer_keyallowed(int sock, Buffer *m)
112198675Sdes{
112298675Sdes	Key *key;
1123106130Sdes	char *cuser, *chost;
1124106130Sdes	u_char *blob;
1125294336Sdes	u_int bloblen, pubkey_auth_attempt;
112698675Sdes	enum mm_keytype type = 0;
112798675Sdes	int allowed = 0;
112898675Sdes
112998675Sdes	debug3("%s entering", __func__);
113098675Sdes
113198675Sdes	type = buffer_get_int(m);
113298675Sdes	cuser = buffer_get_string(m, NULL);
113398675Sdes	chost = buffer_get_string(m, NULL);
113498675Sdes	blob = buffer_get_string(m, &bloblen);
1135294336Sdes	pubkey_auth_attempt = buffer_get_int(m);
113698675Sdes
113798675Sdes	key = key_from_blob(blob, bloblen);
113898675Sdes
113998675Sdes	debug3("%s: key_from_blob: %p", __func__, key);
114098675Sdes
1141126277Sdes	if (key != NULL && authctxt->valid) {
1142294332Sdes		/* These should not make it past the privsep child */
1143294332Sdes		if (key_type_plain(key->type) == KEY_RSA &&
1144294332Sdes		    (datafellows & SSH_BUG_RSASIGMD5) != 0)
1145294332Sdes			fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
1146294332Sdes
1147147005Sdes		switch (type) {
114898675Sdes		case MM_USERKEY:
114998675Sdes			allowed = options.pubkey_authentication &&
1150294332Sdes			    !auth2_userkey_already_used(authctxt, key) &&
1151294332Sdes			    match_pattern_list(sshkey_ssh_name(key),
1152294336Sdes			    options.pubkey_key_types, 0) == 1 &&
1153294336Sdes			    user_key_allowed(authctxt->pw, key,
1154294336Sdes			    pubkey_auth_attempt);
1155255767Sdes			pubkey_auth_info(authctxt, key, NULL);
1156162856Sdes			auth_method = "publickey";
1157294336Sdes			if (options.pubkey_authentication &&
1158294336Sdes			    (!pubkey_auth_attempt || allowed != 1))
1159181111Sdes				auth_clear_options();
116098675Sdes			break;
116198675Sdes		case MM_HOSTKEY:
116298675Sdes			allowed = options.hostbased_authentication &&
1163294332Sdes			    match_pattern_list(sshkey_ssh_name(key),
1164294336Sdes			    options.hostbased_key_types, 0) == 1 &&
116598675Sdes			    hostbased_key_allowed(authctxt->pw,
116698675Sdes			    cuser, chost, key);
1167255767Sdes			pubkey_auth_info(authctxt, key,
1168255767Sdes			    "client user \"%.100s\", client host \"%.100s\"",
1169255767Sdes			    cuser, chost);
1170162856Sdes			auth_method = "hostbased";
117198675Sdes			break;
117298675Sdes		default:
117398675Sdes			fatal("%s: unknown key type %d", __func__, type);
117498675Sdes			break;
117598675Sdes		}
1176113911Sdes	}
1177323129Sdes
1178323129Sdes	debug3("%s: key %p is %s",
1179323129Sdes	    __func__, key, allowed ? "allowed" : "not allowed");
1180323129Sdes
1181113911Sdes	if (key != NULL)
118298675Sdes		key_free(key);
118398675Sdes
118498675Sdes	/* clear temporarily storage (used by verify) */
118598675Sdes	monitor_reset_key_state();
118698675Sdes
118798675Sdes	if (allowed) {
118898675Sdes		/* Save temporarily for comparison in verify */
118998675Sdes		key_blob = blob;
119098675Sdes		key_bloblen = bloblen;
119198675Sdes		key_blobtype = type;
119298675Sdes		hostbased_cuser = cuser;
119398675Sdes		hostbased_chost = chost;
1194162856Sdes	} else {
1195162856Sdes		/* Log failed attempt */
1196255767Sdes		auth_log(authctxt, 0, 0, auth_method, NULL);
1197255767Sdes		free(blob);
1198255767Sdes		free(cuser);
1199255767Sdes		free(chost);
120098675Sdes	}
120198675Sdes
120298675Sdes	buffer_clear(m);
120398675Sdes	buffer_put_int(m, allowed);
1204113911Sdes	buffer_put_int(m, forced_command != NULL);
120598675Sdes
1206137019Sdes	mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
120798675Sdes
120898675Sdes	return (0);
120998675Sdes}
121098675Sdes
121198675Sdesstatic int
121298675Sdesmonitor_valid_userblob(u_char *data, u_int datalen)
121398675Sdes{
121498675Sdes	Buffer b;
1215323129Sdes	u_char *p;
1216323129Sdes	char *userstyle, *cp;
121798675Sdes	u_int len;
121898675Sdes	int fail = 0;
121998675Sdes
122098675Sdes	buffer_init(&b);
122198675Sdes	buffer_append(&b, data, datalen);
122298675Sdes
122398675Sdes	if (datafellows & SSH_OLD_SESSIONID) {
122498675Sdes		p = buffer_ptr(&b);
122598675Sdes		len = buffer_len(&b);
122698675Sdes		if ((session_id2 == NULL) ||
122798675Sdes		    (len < session_id2_len) ||
1228215116Sdes		    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
122998675Sdes			fail++;
123098675Sdes		buffer_consume(&b, session_id2_len);
123198675Sdes	} else {
123298675Sdes		p = buffer_get_string(&b, &len);
123398675Sdes		if ((session_id2 == NULL) ||
123498675Sdes		    (len != session_id2_len) ||
1235215116Sdes		    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
123698675Sdes			fail++;
1237255767Sdes		free(p);
123898675Sdes	}
123998675Sdes	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
124098675Sdes		fail++;
1241323129Sdes	cp = buffer_get_cstring(&b, NULL);
1242255767Sdes	xasprintf(&userstyle, "%s%s%s", authctxt->user,
1243255767Sdes	    authctxt->style ? ":" : "",
1244255767Sdes	    authctxt->style ? authctxt->style : "");
1245323129Sdes	if (strcmp(userstyle, cp) != 0) {
1246323129Sdes		logit("wrong user name passed to monitor: "
1247323129Sdes		    "expected %s != %.100s", userstyle, cp);
124898675Sdes		fail++;
124998675Sdes	}
1250255767Sdes	free(userstyle);
1251323129Sdes	free(cp);
125298675Sdes	buffer_skip_string(&b);
125398675Sdes	if (datafellows & SSH_BUG_PKAUTH) {
125498675Sdes		if (!buffer_get_char(&b))
125598675Sdes			fail++;
125698675Sdes	} else {
1257323129Sdes		cp = buffer_get_cstring(&b, NULL);
1258323129Sdes		if (strcmp("publickey", cp) != 0)
125998675Sdes			fail++;
1260323129Sdes		free(cp);
126198675Sdes		if (!buffer_get_char(&b))
126298675Sdes			fail++;
126398675Sdes		buffer_skip_string(&b);
126498675Sdes	}
126598675Sdes	buffer_skip_string(&b);
126698675Sdes	if (buffer_len(&b) != 0)
126798675Sdes		fail++;
126898675Sdes	buffer_free(&b);
126998675Sdes	return (fail == 0);
127098675Sdes}
127198675Sdes
127298675Sdesstatic int
1273106130Sdesmonitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
1274106130Sdes    char *chost)
127598675Sdes{
127698675Sdes	Buffer b;
1277255767Sdes	char *p, *userstyle;
127898675Sdes	u_int len;
127998675Sdes	int fail = 0;
128098675Sdes
128198675Sdes	buffer_init(&b);
128298675Sdes	buffer_append(&b, data, datalen);
128398675Sdes
128498675Sdes	p = buffer_get_string(&b, &len);
128598675Sdes	if ((session_id2 == NULL) ||
128698675Sdes	    (len != session_id2_len) ||
1287215116Sdes	    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
128898675Sdes		fail++;
1289255767Sdes	free(p);
129098675Sdes
129198675Sdes	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
129298675Sdes		fail++;
1293255767Sdes	p = buffer_get_cstring(&b, NULL);
1294255767Sdes	xasprintf(&userstyle, "%s%s%s", authctxt->user,
1295255767Sdes	    authctxt->style ? ":" : "",
1296255767Sdes	    authctxt->style ? authctxt->style : "");
1297255767Sdes	if (strcmp(userstyle, p) != 0) {
1298124211Sdes		logit("wrong user name passed to monitor: expected %s != %.100s",
1299255767Sdes		    userstyle, p);
130098675Sdes		fail++;
130198675Sdes	}
1302255767Sdes	free(userstyle);
1303255767Sdes	free(p);
130498675Sdes	buffer_skip_string(&b);	/* service */
1305255767Sdes	p = buffer_get_cstring(&b, NULL);
130698675Sdes	if (strcmp(p, "hostbased") != 0)
130798675Sdes		fail++;
1308255767Sdes	free(p);
130998675Sdes	buffer_skip_string(&b);	/* pkalg */
131098675Sdes	buffer_skip_string(&b);	/* pkblob */
131198675Sdes
131298675Sdes	/* verify client host, strip trailing dot if necessary */
131398675Sdes	p = buffer_get_string(&b, NULL);
131498675Sdes	if (((len = strlen(p)) > 0) && p[len - 1] == '.')
131598675Sdes		p[len - 1] = '\0';
131698675Sdes	if (strcmp(p, chost) != 0)
131798675Sdes		fail++;
1318255767Sdes	free(p);
131998675Sdes
132098675Sdes	/* verify client user */
132198675Sdes	p = buffer_get_string(&b, NULL);
132298675Sdes	if (strcmp(p, cuser) != 0)
132398675Sdes		fail++;
1324255767Sdes	free(p);
132598675Sdes
132698675Sdes	if (buffer_len(&b) != 0)
132798675Sdes		fail++;
132898675Sdes	buffer_free(&b);
132998675Sdes	return (fail == 0);
133098675Sdes}
133198675Sdes
133298675Sdesint
1333137019Sdesmm_answer_keyverify(int sock, Buffer *m)
133498675Sdes{
133598675Sdes	Key *key;
133698675Sdes	u_char *signature, *data, *blob;
133798675Sdes	u_int signaturelen, datalen, bloblen;
133898675Sdes	int verified = 0;
133998675Sdes	int valid_data = 0;
134098675Sdes
134198675Sdes	blob = buffer_get_string(m, &bloblen);
134298675Sdes	signature = buffer_get_string(m, &signaturelen);
134398675Sdes	data = buffer_get_string(m, &datalen);
134498675Sdes
134598675Sdes	if (hostbased_cuser == NULL || hostbased_chost == NULL ||
134698675Sdes	  !monitor_allowed_key(blob, bloblen))
134798675Sdes		fatal("%s: bad key, not previously allowed", __func__);
134898675Sdes
134998675Sdes	key = key_from_blob(blob, bloblen);
135098675Sdes	if (key == NULL)
135198675Sdes		fatal("%s: bad public key blob", __func__);
135298675Sdes
135398675Sdes	switch (key_blobtype) {
135498675Sdes	case MM_USERKEY:
135598675Sdes		valid_data = monitor_valid_userblob(data, datalen);
135698675Sdes		break;
135798675Sdes	case MM_HOSTKEY:
135898675Sdes		valid_data = monitor_valid_hostbasedblob(data, datalen,
135998675Sdes		    hostbased_cuser, hostbased_chost);
136098675Sdes		break;
136198675Sdes	default:
136298675Sdes		valid_data = 0;
136398675Sdes		break;
136498675Sdes	}
136598675Sdes	if (!valid_data)
136698675Sdes		fatal("%s: bad signature data blob", __func__);
136798675Sdes
136898675Sdes	verified = key_verify(key, signature, signaturelen, data, datalen);
136998675Sdes	debug3("%s: key %p signature %s",
1370164149Sdes	    __func__, key, (verified == 1) ? "verified" : "unverified");
137198675Sdes
1372294332Sdes	/* If auth was successful then record key to ensure it isn't reused */
1373296633Sdes	if (verified == 1 && key_blobtype == MM_USERKEY)
1374294332Sdes		auth2_record_userkey(authctxt, key);
1375294332Sdes	else
1376294332Sdes		key_free(key);
1377294332Sdes
1378255767Sdes	free(blob);
1379255767Sdes	free(signature);
1380255767Sdes	free(data);
138198675Sdes
138299063Sdes	auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
138399063Sdes
138498675Sdes	monitor_reset_key_state();
138598675Sdes
138698675Sdes	buffer_clear(m);
138798675Sdes	buffer_put_int(m, verified);
1388137019Sdes	mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
138998675Sdes
1390164149Sdes	return (verified == 1);
139198675Sdes}
139298675Sdes
139398675Sdesstatic void
139498675Sdesmm_record_login(Session *s, struct passwd *pw)
139598675Sdes{
1396323129Sdes	struct ssh *ssh = active_state;	/* XXX */
139798675Sdes	socklen_t fromlen;
139898675Sdes	struct sockaddr_storage from;
139998675Sdes
140098675Sdes	/*
140198675Sdes	 * Get IP address of client. If the connection is not a socket, let
140298675Sdes	 * the address be 0.0.0.0.
140398675Sdes	 */
140498675Sdes	memset(&from, 0, sizeof(from));
1405103134Sume	fromlen = sizeof(from);
140698675Sdes	if (packet_connection_is_on_socket()) {
140798675Sdes		if (getpeername(packet_get_connection_in(),
1408162856Sdes		    (struct sockaddr *)&from, &fromlen) < 0) {
140998675Sdes			debug("getpeername: %.100s", strerror(errno));
1410126277Sdes			cleanup_exit(255);
141198675Sdes		}
141298675Sdes	}
141398675Sdes	/* Record that there was a login on that tty from the remote host. */
141498675Sdes	record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
1415323129Sdes	    session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns),
1416103134Sume	    (struct sockaddr *)&from, fromlen);
141798675Sdes}
141898675Sdes
141998675Sdesstatic void
142098675Sdesmm_session_close(Session *s)
142198675Sdes{
1422124211Sdes	debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
142398675Sdes	if (s->ttyfd != -1) {
1424162856Sdes		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
142598675Sdes		session_pty_cleanup2(s);
142698675Sdes	}
1427181111Sdes	session_unused(s->self);
142898675Sdes}
142998675Sdes
143098675Sdesint
1431137019Sdesmm_answer_pty(int sock, Buffer *m)
143298675Sdes{
143398675Sdes	extern struct monitor *pmonitor;
143498675Sdes	Session *s;
143598675Sdes	int res, fd0;
143698675Sdes
143798675Sdes	debug3("%s entering", __func__);
143898675Sdes
143998675Sdes	buffer_clear(m);
144098675Sdes	s = session_new();
144198675Sdes	if (s == NULL)
144298675Sdes		goto error;
144398675Sdes	s->authctxt = authctxt;
144498675Sdes	s->pw = authctxt->pw;
144598675Sdes	s->pid = pmonitor->m_pid;
144698675Sdes	res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
144798675Sdes	if (res == 0)
144898675Sdes		goto error;
144998675Sdes	pty_setowner(authctxt->pw, s->tty);
145098675Sdes
145198675Sdes	buffer_put_int(m, 1);
145298675Sdes	buffer_put_cstring(m, s->tty);
145398675Sdes
145498675Sdes	/* We need to trick ttyslot */
145598675Sdes	if (dup2(s->ttyfd, 0) == -1)
145698675Sdes		fatal("%s: dup2", __func__);
145798675Sdes
145898675Sdes	mm_record_login(s, authctxt->pw);
145998675Sdes
146098675Sdes	/* Now we can close the file descriptor again */
146198675Sdes	close(0);
146298675Sdes
1463137019Sdes	/* send messages generated by record_login */
1464137019Sdes	buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
1465137019Sdes	buffer_clear(&loginmsg);
1466137019Sdes
1467137019Sdes	mm_request_send(sock, MONITOR_ANS_PTY, m);
1468137019Sdes
1469181111Sdes	if (mm_send_fd(sock, s->ptyfd) == -1 ||
1470181111Sdes	    mm_send_fd(sock, s->ttyfd) == -1)
1471181111Sdes		fatal("%s: send fds failed", __func__);
1472137019Sdes
147398675Sdes	/* make sure nothing uses fd 0 */
147498675Sdes	if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
147598675Sdes		fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
147698675Sdes	if (fd0 != 0)
147798675Sdes		error("%s: fd0 %d != 0", __func__, fd0);
147898675Sdes
147998675Sdes	/* slave is not needed */
148098675Sdes	close(s->ttyfd);
148198675Sdes	s->ttyfd = s->ptyfd;
148298675Sdes	/* no need to dup() because nobody closes ptyfd */
148398675Sdes	s->ptymaster = s->ptyfd;
148498675Sdes
1485162856Sdes	debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
148698675Sdes
148798675Sdes	return (0);
148898675Sdes
148998675Sdes error:
149098675Sdes	if (s != NULL)
149198675Sdes		mm_session_close(s);
149298675Sdes	buffer_put_int(m, 0);
1493137019Sdes	mm_request_send(sock, MONITOR_ANS_PTY, m);
149498675Sdes	return (0);
149598675Sdes}
149698675Sdes
149798675Sdesint
1498137019Sdesmm_answer_pty_cleanup(int sock, Buffer *m)
149998675Sdes{
150098675Sdes	Session *s;
150198675Sdes	char *tty;
150298675Sdes
150398675Sdes	debug3("%s entering", __func__);
150498675Sdes
150598675Sdes	tty = buffer_get_string(m, NULL);
150698675Sdes	if ((s = session_by_tty(tty)) != NULL)
150798675Sdes		mm_session_close(s);
150898675Sdes	buffer_clear(m);
1509255767Sdes	free(tty);
151098675Sdes	return (0);
151198675Sdes}
151298675Sdes
151398675Sdesint
1514137019Sdesmm_answer_term(int sock, Buffer *req)
151598675Sdes{
151698675Sdes	extern struct monitor *pmonitor;
151798675Sdes	int res, status;
151898675Sdes
151998675Sdes	debug3("%s: tearing down sessions", __func__);
152098675Sdes
152198675Sdes	/* The child is terminating */
152298675Sdes	session_destroy_all(&mm_session_close);
152398675Sdes
1524181111Sdes#ifdef USE_PAM
1525181111Sdes	if (options.use_pam)
1526181111Sdes		sshpam_cleanup();
1527181111Sdes#endif
1528181111Sdes
152998675Sdes	while (waitpid(pmonitor->m_pid, &status, 0) == -1)
153098675Sdes		if (errno != EINTR)
153198675Sdes			exit(1);
153298675Sdes
153398675Sdes	res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
153498675Sdes
153598675Sdes	/* Terminate process */
1536137019Sdes	exit(res);
153798675Sdes}
153898675Sdes
1539147005Sdes#ifdef SSH_AUDIT_EVENTS
1540147005Sdes/* Report that an audit event occurred */
1541147005Sdesint
1542147005Sdesmm_answer_audit_event(int socket, Buffer *m)
1543147005Sdes{
1544147005Sdes	ssh_audit_event_t event;
1545147005Sdes
1546147005Sdes	debug3("%s entering", __func__);
1547147005Sdes
1548147005Sdes	event = buffer_get_int(m);
1549147005Sdes	switch(event) {
1550147005Sdes	case SSH_AUTH_FAIL_PUBKEY:
1551147005Sdes	case SSH_AUTH_FAIL_HOSTBASED:
1552147005Sdes	case SSH_AUTH_FAIL_GSSAPI:
1553147005Sdes	case SSH_LOGIN_EXCEED_MAXTRIES:
1554147005Sdes	case SSH_LOGIN_ROOT_DENIED:
1555147005Sdes	case SSH_CONNECTION_CLOSE:
1556147005Sdes	case SSH_INVALID_USER:
1557147005Sdes		audit_event(event);
1558147005Sdes		break;
1559147005Sdes	default:
1560147005Sdes		fatal("Audit event type %d not permitted", event);
1561147005Sdes	}
1562147005Sdes
1563147005Sdes	return (0);
1564147005Sdes}
1565147005Sdes
1566147005Sdesint
1567147005Sdesmm_answer_audit_command(int socket, Buffer *m)
1568147005Sdes{
1569147005Sdes	u_int len;
1570147005Sdes	char *cmd;
1571147005Sdes
1572147005Sdes	debug3("%s entering", __func__);
1573147005Sdes	cmd = buffer_get_string(m, &len);
1574147005Sdes	/* sanity check command, if so how? */
1575147005Sdes	audit_run_command(cmd);
1576255767Sdes	free(cmd);
1577147005Sdes	return (0);
1578147005Sdes}
1579147005Sdes#endif /* SSH_AUDIT_EVENTS */
1580147005Sdes
158198675Sdesvoid
158298675Sdesmonitor_apply_keystate(struct monitor *pmonitor)
158398675Sdes{
1584294332Sdes	struct ssh *ssh = active_state;	/* XXX */
1585294332Sdes	struct kex *kex;
1586294332Sdes	int r;
158798675Sdes
1588294332Sdes	debug3("%s: packet_set_state", __func__);
1589294332Sdes	if ((r = ssh_packet_set_state(ssh, child_state)) != 0)
1590294332Sdes                fatal("%s: packet_set_state: %s", __func__, ssh_err(r));
1591294332Sdes	sshbuf_free(child_state);
1592294332Sdes	child_state = NULL;
159398675Sdes
1594296633Sdes	if ((kex = ssh->kex) != NULL) {
1595294332Sdes		/* XXX set callbacks */
1596294332Sdes#ifdef WITH_OPENSSL
1597294332Sdes		kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
1598294332Sdes		kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
1599323129Sdes		kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
1600323129Sdes		kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
1601323129Sdes		kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
1602294332Sdes		kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1603294332Sdes		kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1604294332Sdes# ifdef OPENSSL_HAS_ECC
1605294332Sdes		kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
1606294332Sdes# endif
1607294332Sdes#endif /* WITH_OPENSSL */
1608294332Sdes		kex->kex[KEX_C25519_SHA256] = kexc25519_server;
1609294332Sdes		kex->load_host_public_key=&get_hostkey_public_by_type;
1610294332Sdes		kex->load_host_private_key=&get_hostkey_private_by_type;
1611294332Sdes		kex->host_key_index=&get_hostkey_index;
1612294332Sdes		kex->sign = sshd_hostkey_sign;
161398675Sdes	}
161498675Sdes}
161598675Sdes
161698675Sdes/* This function requries careful sanity checking */
161798675Sdes
161898675Sdesvoid
161998675Sdesmm_get_keystate(struct monitor *pmonitor)
162098675Sdes{
162198675Sdes	debug3("%s: Waiting for new keys", __func__);
162298675Sdes
1623294332Sdes	if ((child_state = sshbuf_new()) == NULL)
1624294332Sdes		fatal("%s: sshbuf_new failed", __func__);
1625294332Sdes	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,
1626294332Sdes	    child_state);
1627294332Sdes	debug3("%s: GOT new keys", __func__);
162898675Sdes}
162998675Sdes
163098675Sdes
163198675Sdes/* XXX */
163298675Sdes
163398675Sdes#define FD_CLOSEONEXEC(x) do { \
1634226046Sdes	if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
163598675Sdes		fatal("fcntl(%d, F_SETFD)", x); \
163698675Sdes} while (0)
163798675Sdes
163898675Sdesstatic void
1639226046Sdesmonitor_openfds(struct monitor *mon, int do_logfds)
164098675Sdes{
1641226046Sdes	int pair[2];
1642226046Sdes
164398675Sdes	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1644226046Sdes		fatal("%s: socketpair: %s", __func__, strerror(errno));
164598675Sdes	FD_CLOSEONEXEC(pair[0]);
164698675Sdes	FD_CLOSEONEXEC(pair[1]);
1647226046Sdes	mon->m_recvfd = pair[0];
1648226046Sdes	mon->m_sendfd = pair[1];
1649226046Sdes
1650226046Sdes	if (do_logfds) {
1651226046Sdes		if (pipe(pair) == -1)
1652226046Sdes			fatal("%s: pipe: %s", __func__, strerror(errno));
1653226046Sdes		FD_CLOSEONEXEC(pair[0]);
1654226046Sdes		FD_CLOSEONEXEC(pair[1]);
1655226046Sdes		mon->m_log_recvfd = pair[0];
1656226046Sdes		mon->m_log_sendfd = pair[1];
1657226046Sdes	} else
1658226046Sdes		mon->m_log_recvfd = mon->m_log_sendfd = -1;
165998675Sdes}
166098675Sdes
166198675Sdes#define MM_MEMSIZE	65536
166298675Sdes
166398675Sdesstruct monitor *
166498675Sdesmonitor_init(void)
166598675Sdes{
166698675Sdes	struct monitor *mon;
166798675Sdes
1668162856Sdes	mon = xcalloc(1, sizeof(*mon));
1669226046Sdes	monitor_openfds(mon, 1);
167098675Sdes
167198675Sdes	return mon;
167298675Sdes}
167398675Sdes
167498675Sdesvoid
167598675Sdesmonitor_reinit(struct monitor *mon)
167698675Sdes{
1677226046Sdes	monitor_openfds(mon, 0);
167898675Sdes}
1679124211Sdes
1680124211Sdes#ifdef GSSAPI
1681124211Sdesint
1682137019Sdesmm_answer_gss_setup_ctx(int sock, Buffer *m)
1683124211Sdes{
1684137019Sdes	gss_OID_desc goid;
1685124211Sdes	OM_uint32 major;
1686124211Sdes	u_int len;
1687124211Sdes
1688323134Sdes	if (!options.gss_authentication)
1689323134Sdes		fatal("%s: GSSAPI authentication not enabled", __func__);
1690323134Sdes
1691137019Sdes	goid.elements = buffer_get_string(m, &len);
1692137019Sdes	goid.length = len;
1693124211Sdes
1694137019Sdes	major = ssh_gssapi_server_ctx(&gsscontext, &goid);
1695124211Sdes
1696255767Sdes	free(goid.elements);
1697124211Sdes
1698124211Sdes	buffer_clear(m);
1699124211Sdes	buffer_put_int(m, major);
1700124211Sdes
1701157019Sdes	mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
1702124211Sdes
1703124211Sdes	/* Now we have a context, enable the step */
1704124211Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
1705124211Sdes
1706124211Sdes	return (0);
1707124211Sdes}
1708124211Sdes
1709124211Sdesint
1710137019Sdesmm_answer_gss_accept_ctx(int sock, Buffer *m)
1711124211Sdes{
1712124211Sdes	gss_buffer_desc in;
1713124211Sdes	gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
1714157019Sdes	OM_uint32 major, minor;
1715124211Sdes	OM_uint32 flags = 0; /* GSI needs this */
1716124211Sdes	u_int len;
1717124211Sdes
1718323134Sdes	if (!options.gss_authentication)
1719323134Sdes		fatal("%s: GSSAPI authentication not enabled", __func__);
1720323134Sdes
1721124211Sdes	in.value = buffer_get_string(m, &len);
1722124211Sdes	in.length = len;
1723124211Sdes	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
1724255767Sdes	free(in.value);
1725124211Sdes
1726124211Sdes	buffer_clear(m);
1727124211Sdes	buffer_put_int(m, major);
1728124211Sdes	buffer_put_string(m, out.value, out.length);
1729124211Sdes	buffer_put_int(m, flags);
1730137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
1731124211Sdes
1732124211Sdes	gss_release_buffer(&minor, &out);
1733124211Sdes
1734157019Sdes	if (major == GSS_S_COMPLETE) {
1735124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
1736124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
1737126277Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
1738124211Sdes	}
1739124211Sdes	return (0);
1740124211Sdes}
1741124211Sdes
1742124211Sdesint
1743137019Sdesmm_answer_gss_checkmic(int sock, Buffer *m)
1744126277Sdes{
1745126277Sdes	gss_buffer_desc gssbuf, mic;
1746126277Sdes	OM_uint32 ret;
1747126277Sdes	u_int len;
1748126277Sdes
1749323134Sdes	if (!options.gss_authentication)
1750323134Sdes		fatal("%s: GSSAPI authentication not enabled", __func__);
1751323134Sdes
1752126277Sdes	gssbuf.value = buffer_get_string(m, &len);
1753126277Sdes	gssbuf.length = len;
1754126277Sdes	mic.value = buffer_get_string(m, &len);
1755126277Sdes	mic.length = len;
1756126277Sdes
1757126277Sdes	ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
1758126277Sdes
1759255767Sdes	free(gssbuf.value);
1760255767Sdes	free(mic.value);
1761126277Sdes
1762126277Sdes	buffer_clear(m);
1763126277Sdes	buffer_put_int(m, ret);
1764126277Sdes
1765137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
1766126277Sdes
1767126277Sdes	if (!GSS_ERROR(ret))
1768126277Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
1769126277Sdes
1770126277Sdes	return (0);
1771126277Sdes}
1772126277Sdes
1773126277Sdesint
1774137019Sdesmm_answer_gss_userok(int sock, Buffer *m)
1775124211Sdes{
1776124211Sdes	int authenticated;
1777124211Sdes
1778323134Sdes	if (!options.gss_authentication)
1779323134Sdes		fatal("%s: GSSAPI authentication not enabled", __func__);
1780323134Sdes
1781124211Sdes	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
1782124211Sdes
1783124211Sdes	buffer_clear(m);
1784124211Sdes	buffer_put_int(m, authenticated);
1785124211Sdes
1786124211Sdes	debug3("%s: sending result %d", __func__, authenticated);
1787137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
1788124211Sdes
1789157019Sdes	auth_method = "gssapi-with-mic";
1790124211Sdes
1791124211Sdes	/* Monitor loop will terminate if authenticated */
1792124211Sdes	return (authenticated);
1793124211Sdes}
1794124211Sdes#endif /* GSSAPI */
1795192595Sdes
1796