1264377Sdes/* $OpenBSD: monitor.c,v 1.131 2014/02/02 03:44:31 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/param.h>
32162856Sdes#include <sys/socket.h>
33162856Sdes#include "openbsd-compat/sys-tree.h"
34162856Sdes#include <sys/wait.h>
3598675Sdes
36162856Sdes#include <errno.h>
37162856Sdes#include <fcntl.h>
38162856Sdes#ifdef HAVE_PATHS_H
39162856Sdes#include <paths.h>
40162856Sdes#endif
41162856Sdes#include <pwd.h>
42162856Sdes#include <signal.h>
43162856Sdes#include <stdarg.h>
44162856Sdes#include <stdlib.h>
45162856Sdes#include <string.h>
46162856Sdes#include <unistd.h>
47226046Sdes#ifdef HAVE_POLL_H
48226046Sdes#include <poll.h>
49226046Sdes#else
50226046Sdes# ifdef HAVE_SYS_POLL_H
51226046Sdes#  include <sys/poll.h>
52226046Sdes# endif
53226046Sdes#endif
54162856Sdes
5598675Sdes#ifdef SKEY
5698941Sdes#include <skey.h>
5798675Sdes#endif
5898675Sdes
59162856Sdes#include <openssl/dh.h>
60162856Sdes
61181111Sdes#include "openbsd-compat/sys-queue.h"
62226046Sdes#include "atomicio.h"
63162856Sdes#include "xmalloc.h"
6498675Sdes#include "ssh.h"
65162856Sdes#include "key.h"
66162856Sdes#include "buffer.h"
67162856Sdes#include "hostfile.h"
6898675Sdes#include "auth.h"
69162856Sdes#include "cipher.h"
7098675Sdes#include "kex.h"
7198675Sdes#include "dh.h"
72128460Sdes#ifdef TARGET_OS_MAC	/* XXX Broken krb5 headers on Mac */
73128460Sdes#undef TARGET_OS_MAC
7498675Sdes#include "zlib.h"
75128460Sdes#define TARGET_OS_MAC 1
76128460Sdes#else
77128460Sdes#include "zlib.h"
78128460Sdes#endif
7998675Sdes#include "packet.h"
8098675Sdes#include "auth-options.h"
8198675Sdes#include "sshpty.h"
8298675Sdes#include "channels.h"
8398675Sdes#include "session.h"
8498675Sdes#include "sshlogin.h"
8598675Sdes#include "canohost.h"
8698675Sdes#include "log.h"
8798675Sdes#include "servconf.h"
8898675Sdes#include "monitor.h"
8998675Sdes#include "monitor_mm.h"
90162856Sdes#ifdef GSSAPI
91162856Sdes#include "ssh-gss.h"
92162856Sdes#endif
9398675Sdes#include "monitor_wrap.h"
9498675Sdes#include "monitor_fdpass.h"
9598675Sdes#include "misc.h"
9698675Sdes#include "compat.h"
9798675Sdes#include "ssh2.h"
98197679Sdes#include "roaming.h"
99255767Sdes#include "authfd.h"
10098675Sdes
101124211Sdes#ifdef GSSAPI
102124211Sdesstatic Gssctxt *gsscontext = NULL;
103124211Sdes#endif
104124211Sdes
10598675Sdes/* Imports */
10698675Sdesextern ServerOptions options;
10798675Sdesextern u_int utmp_len;
10898675Sdesextern Newkeys *current_keys[];
10998675Sdesextern z_stream incoming_stream;
11098675Sdesextern z_stream outgoing_stream;
11198675Sdesextern u_char session_id[];
11298675Sdesextern Buffer auth_debug;
11398675Sdesextern int auth_debug_init;
114137019Sdesextern Buffer loginmsg;
11598675Sdes
11698675Sdes/* State exported from the child */
11798675Sdes
11898675Sdesstruct {
11998675Sdes	z_stream incoming;
12098675Sdes	z_stream outgoing;
12198675Sdes	u_char *keyin;
12298675Sdes	u_int keyinlen;
12398675Sdes	u_char *keyout;
12498675Sdes	u_int keyoutlen;
12598675Sdes	u_char *ivin;
12698675Sdes	u_int ivinlen;
12798675Sdes	u_char *ivout;
12898675Sdes	u_int ivoutlen;
12998675Sdes	u_char *ssh1key;
13098675Sdes	u_int ssh1keylen;
13198675Sdes	int ssh1cipher;
13298675Sdes	int ssh1protoflags;
13398675Sdes	u_char *input;
13498675Sdes	u_int ilen;
13598675Sdes	u_char *output;
13698675Sdes	u_int olen;
137197679Sdes	u_int64_t sent_bytes;
138197679Sdes	u_int64_t recv_bytes;
13998675Sdes} child_state;
14098675Sdes
141124211Sdes/* Functions on the monitor that answer unprivileged requests */
14298675Sdes
14398675Sdesint mm_answer_moduli(int, Buffer *);
14498675Sdesint mm_answer_sign(int, Buffer *);
14598675Sdesint mm_answer_pwnamallow(int, Buffer *);
14698675Sdesint mm_answer_auth2_read_banner(int, Buffer *);
14798675Sdesint mm_answer_authserv(int, Buffer *);
14898675Sdesint mm_answer_authpassword(int, Buffer *);
14998675Sdesint mm_answer_bsdauthquery(int, Buffer *);
15098675Sdesint mm_answer_bsdauthrespond(int, Buffer *);
15198675Sdesint mm_answer_skeyquery(int, Buffer *);
15298675Sdesint mm_answer_skeyrespond(int, Buffer *);
15398675Sdesint mm_answer_keyallowed(int, Buffer *);
15498675Sdesint mm_answer_keyverify(int, Buffer *);
15598675Sdesint mm_answer_pty(int, Buffer *);
15698675Sdesint mm_answer_pty_cleanup(int, Buffer *);
15798675Sdesint mm_answer_term(int, Buffer *);
15898675Sdesint mm_answer_rsa_keyallowed(int, Buffer *);
15998675Sdesint mm_answer_rsa_challenge(int, Buffer *);
16098675Sdesint mm_answer_rsa_response(int, Buffer *);
16198675Sdesint mm_answer_sesskey(int, Buffer *);
16298675Sdesint mm_answer_sessid(int, Buffer *);
16398675Sdes
16498941Sdes#ifdef USE_PAM
16598941Sdesint mm_answer_pam_start(int, Buffer *);
166124211Sdesint mm_answer_pam_account(int, Buffer *);
16799052Sdesint mm_answer_pam_init_ctx(int, Buffer *);
16899052Sdesint mm_answer_pam_query(int, Buffer *);
16999052Sdesint mm_answer_pam_respond(int, Buffer *);
17099052Sdesint mm_answer_pam_free_ctx(int, Buffer *);
17198941Sdes#endif
17298941Sdes
173124211Sdes#ifdef GSSAPI
174124211Sdesint mm_answer_gss_setup_ctx(int, Buffer *);
175124211Sdesint mm_answer_gss_accept_ctx(int, Buffer *);
176124211Sdesint mm_answer_gss_userok(int, Buffer *);
177126277Sdesint mm_answer_gss_checkmic(int, Buffer *);
178106130Sdes#endif
179106130Sdes
180147005Sdes#ifdef SSH_AUDIT_EVENTS
181147005Sdesint mm_answer_audit_event(int, Buffer *);
182147005Sdesint mm_answer_audit_command(int, Buffer *);
183147005Sdes#endif
184147005Sdes
185226046Sdesstatic int monitor_read_log(struct monitor *);
186226046Sdes
18798675Sdesstatic Authctxt *authctxt;
18898675Sdesstatic BIGNUM *ssh1_challenge = NULL;	/* used for ssh1 rsa auth */
18998675Sdes
19098675Sdes/* local state for key verify */
19198675Sdesstatic u_char *key_blob = NULL;
19298675Sdesstatic u_int key_bloblen = 0;
19398675Sdesstatic int key_blobtype = MM_NOKEY;
194106130Sdesstatic char *hostbased_cuser = NULL;
195106130Sdesstatic char *hostbased_chost = NULL;
19698675Sdesstatic char *auth_method = "unknown";
197248619Sdesstatic char *auth_submethod = NULL;
198124211Sdesstatic u_int session_id2_len = 0;
19998675Sdesstatic u_char *session_id2 = NULL;
200124211Sdesstatic pid_t monitor_child_pid;
20198675Sdes
20298675Sdesstruct mon_table {
20398675Sdes	enum monitor_reqtype type;
20498675Sdes	int flags;
20598675Sdes	int (*f)(int, Buffer *);
20698675Sdes};
20798675Sdes
20898675Sdes#define MON_ISAUTH	0x0004	/* Required for Authentication */
20998675Sdes#define MON_AUTHDECIDE	0x0008	/* Decides Authentication */
21098675Sdes#define MON_ONCE	0x0010	/* Disable after calling */
211162856Sdes#define MON_ALOG	0x0020	/* Log auth attempt without authenticating */
21298675Sdes
21398675Sdes#define MON_AUTH	(MON_ISAUTH|MON_AUTHDECIDE)
21498675Sdes
21598675Sdes#define MON_PERMIT	0x1000	/* Request is permitted */
21698675Sdes
21798675Sdesstruct mon_table mon_dispatch_proto20[] = {
21898675Sdes    {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
21998675Sdes    {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
22098675Sdes    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
22198675Sdes    {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
22298675Sdes    {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
22398675Sdes    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
22498941Sdes#ifdef USE_PAM
22598941Sdes    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
226124211Sdes    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
22799052Sdes    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
22899052Sdes    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
22999052Sdes    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
23099052Sdes    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
23198941Sdes#endif
232147005Sdes#ifdef SSH_AUDIT_EVENTS
233147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
234147005Sdes#endif
23598675Sdes#ifdef BSD_AUTH
23698675Sdes    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
237162856Sdes    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
23898675Sdes#endif
23998675Sdes#ifdef SKEY
24098675Sdes    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
24198675Sdes    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
24298675Sdes#endif
24398675Sdes    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
24498675Sdes    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
245124211Sdes#ifdef GSSAPI
246124211Sdes    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
247124211Sdes    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
248124211Sdes    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
249126277Sdes    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
250124211Sdes#endif
25198675Sdes    {0, 0, NULL}
25298675Sdes};
25398675Sdes
25498675Sdesstruct mon_table mon_dispatch_postauth20[] = {
25598675Sdes    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
25698675Sdes    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
25798675Sdes    {MONITOR_REQ_PTY, 0, mm_answer_pty},
25898675Sdes    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
25998675Sdes    {MONITOR_REQ_TERM, 0, mm_answer_term},
260147005Sdes#ifdef SSH_AUDIT_EVENTS
261147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
262147005Sdes    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
263147005Sdes#endif
26498675Sdes    {0, 0, NULL}
26598675Sdes};
26698675Sdes
26798675Sdesstruct mon_table mon_dispatch_proto15[] = {
26898675Sdes    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
26998675Sdes    {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
27098675Sdes    {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
27198675Sdes    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
272162856Sdes    {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed},
273162856Sdes    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed},
27498675Sdes    {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
27598675Sdes    {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
27698675Sdes#ifdef BSD_AUTH
27798675Sdes    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
278162856Sdes    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
27998675Sdes#endif
28098675Sdes#ifdef SKEY
28198675Sdes    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
28298675Sdes    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
28398675Sdes#endif
28499063Sdes#ifdef USE_PAM
28599063Sdes    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
286124211Sdes    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
28799063Sdes    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
28899063Sdes    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
28999063Sdes    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
29099063Sdes    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
29199063Sdes#endif
292147005Sdes#ifdef SSH_AUDIT_EVENTS
293147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
294147005Sdes#endif
29598675Sdes    {0, 0, NULL}
29698675Sdes};
29798675Sdes
29898675Sdesstruct mon_table mon_dispatch_postauth15[] = {
29998675Sdes    {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
30098675Sdes    {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
30198675Sdes    {MONITOR_REQ_TERM, 0, mm_answer_term},
302147005Sdes#ifdef SSH_AUDIT_EVENTS
303147005Sdes    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
304162360Sdes    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
305147005Sdes#endif
30698675Sdes    {0, 0, NULL}
30798675Sdes};
30898675Sdes
30998675Sdesstruct mon_table *mon_dispatch;
31098675Sdes
31198675Sdes/* Specifies if a certain message is allowed at the moment */
31298675Sdes
31398675Sdesstatic void
31498675Sdesmonitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
31598675Sdes{
31698675Sdes	while (ent->f != NULL) {
31798675Sdes		if (ent->type == type) {
31898675Sdes			ent->flags &= ~MON_PERMIT;
31998675Sdes			ent->flags |= permit ? MON_PERMIT : 0;
32098675Sdes			return;
32198675Sdes		}
32298675Sdes		ent++;
32398675Sdes	}
32498675Sdes}
32598675Sdes
32698675Sdesstatic void
32798675Sdesmonitor_permit_authentications(int permit)
32898675Sdes{
32998675Sdes	struct mon_table *ent = mon_dispatch;
33098675Sdes
33198675Sdes	while (ent->f != NULL) {
33298675Sdes		if (ent->flags & MON_AUTH) {
33398675Sdes			ent->flags &= ~MON_PERMIT;
33498675Sdes			ent->flags |= permit ? MON_PERMIT : 0;
33598675Sdes		}
33698675Sdes		ent++;
33798675Sdes	}
33898675Sdes}
33998675Sdes
340126277Sdesvoid
341126277Sdesmonitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
34298675Sdes{
34398675Sdes	struct mon_table *ent;
344248619Sdes	int authenticated = 0, partial = 0;
34598675Sdes
34698675Sdes	debug3("preauth child monitor started");
34798675Sdes
348226046Sdes	close(pmonitor->m_recvfd);
349226046Sdes	close(pmonitor->m_log_sendfd);
350226046Sdes	pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
351226046Sdes
352126277Sdes	authctxt = _authctxt;
353126277Sdes	memset(authctxt, 0, sizeof(*authctxt));
354126277Sdes
355147005Sdes	authctxt->loginmsg = &loginmsg;
356147005Sdes
35798675Sdes	if (compat20) {
35898675Sdes		mon_dispatch = mon_dispatch_proto20;
35998675Sdes
36098675Sdes		/* Permit requests for moduli and signatures */
36198675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
36298675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
36398675Sdes	} else {
36498675Sdes		mon_dispatch = mon_dispatch_proto15;
36598675Sdes
36698675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
36798675Sdes	}
36898675Sdes
36998675Sdes	/* The first few requests do not require asynchronous access */
37098675Sdes	while (!authenticated) {
371248619Sdes		partial = 0;
372162856Sdes		auth_method = "unknown";
373248619Sdes		auth_submethod = NULL;
374164149Sdes		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
375248619Sdes
376248619Sdes		/* Special handling for multiple required authentications */
377248619Sdes		if (options.num_auth_methods != 0) {
378248619Sdes			if (!compat20)
379248619Sdes				fatal("AuthenticationMethods is not supported"
380248619Sdes				    "with SSH protocol 1");
381248619Sdes			if (authenticated &&
382248619Sdes			    !auth2_update_methods_lists(authctxt,
383255767Sdes			    auth_method, auth_submethod)) {
384248619Sdes				debug3("%s: method %s: partial", __func__,
385248619Sdes				    auth_method);
386248619Sdes				authenticated = 0;
387248619Sdes				partial = 1;
388248619Sdes			}
389248619Sdes		}
390248619Sdes
39198675Sdes		if (authenticated) {
39298675Sdes			if (!(ent->flags & MON_AUTHDECIDE))
39398675Sdes				fatal("%s: unexpected authentication from %d",
39498675Sdes				    __func__, ent->type);
39598675Sdes			if (authctxt->pw->pw_uid == 0 &&
39698675Sdes			    !auth_root_allowed(auth_method))
39798675Sdes				authenticated = 0;
398124211Sdes#ifdef USE_PAM
399124211Sdes			/* PAM needs to perform account checks after auth */
400126277Sdes			if (options.use_pam && authenticated) {
401124211Sdes				Buffer m;
402124211Sdes
403124211Sdes				buffer_init(&m);
404126277Sdes				mm_request_receive_expect(pmonitor->m_sendfd,
405124211Sdes				    MONITOR_REQ_PAM_ACCOUNT, &m);
406124211Sdes				authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
407124211Sdes				buffer_free(&m);
408124211Sdes			}
409124211Sdes#endif
41098675Sdes		}
411162856Sdes		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
412248619Sdes			auth_log(authctxt, authenticated, partial,
413255767Sdes			    auth_method, auth_submethod);
41498675Sdes			if (!authenticated)
41598675Sdes				authctxt->failures++;
41698675Sdes		}
41798675Sdes	}
41898675Sdes
41998675Sdes	if (!authctxt->valid)
42098675Sdes		fatal("%s: authenticated invalid user", __func__);
421162856Sdes	if (strcmp(auth_method, "unknown") == 0)
422162856Sdes		fatal("%s: authentication method name unknown", __func__);
42398675Sdes
42498675Sdes	debug("%s: %s has been authenticated by privileged process",
42598675Sdes	    __func__, authctxt->user);
42698675Sdes
42798675Sdes	mm_get_keystate(pmonitor);
428226046Sdes
429248619Sdes	/* Drain any buffered messages from the child */
430248619Sdes	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
431248619Sdes		;
432248619Sdes
433226046Sdes	close(pmonitor->m_sendfd);
434226046Sdes	close(pmonitor->m_log_recvfd);
435226046Sdes	pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
43698675Sdes}
43798675Sdes
438124211Sdesstatic void
439124211Sdesmonitor_set_child_handler(pid_t pid)
440124211Sdes{
441124211Sdes	monitor_child_pid = pid;
442124211Sdes}
443124211Sdes
444124211Sdesstatic void
445137019Sdesmonitor_child_handler(int sig)
446124211Sdes{
447137019Sdes	kill(monitor_child_pid, sig);
448124211Sdes}
449124211Sdes
45098675Sdesvoid
45198675Sdesmonitor_child_postauth(struct monitor *pmonitor)
45298675Sdes{
453226046Sdes	close(pmonitor->m_recvfd);
454226046Sdes	pmonitor->m_recvfd = -1;
455226046Sdes
456124211Sdes	monitor_set_child_handler(pmonitor->m_pid);
457124211Sdes	signal(SIGHUP, &monitor_child_handler);
458124211Sdes	signal(SIGTERM, &monitor_child_handler);
459181111Sdes	signal(SIGINT, &monitor_child_handler);
460124211Sdes
46198675Sdes	if (compat20) {
46298675Sdes		mon_dispatch = mon_dispatch_postauth20;
46398675Sdes
46498675Sdes		/* Permit requests for moduli and signatures */
46598675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
46698675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
46798675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
46898675Sdes	} else {
46998675Sdes		mon_dispatch = mon_dispatch_postauth15;
47098675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
47198675Sdes	}
47298675Sdes	if (!no_pty_flag) {
47398675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
47498675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
47598675Sdes	}
47698675Sdes
47798675Sdes	for (;;)
47898675Sdes		monitor_read(pmonitor, mon_dispatch, NULL);
47998675Sdes}
48098675Sdes
48198675Sdesvoid
48298675Sdesmonitor_sync(struct monitor *pmonitor)
48398675Sdes{
48498675Sdes	if (options.compression) {
48598675Sdes		/* The member allocation is not visible, so sync it */
48698675Sdes		mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
48798675Sdes	}
48898675Sdes}
48998675Sdes
490226046Sdesstatic int
491226046Sdesmonitor_read_log(struct monitor *pmonitor)
492226046Sdes{
493226046Sdes	Buffer logmsg;
494226046Sdes	u_int len, level;
495226046Sdes	char *msg;
496226046Sdes
497226046Sdes	buffer_init(&logmsg);
498226046Sdes
499226046Sdes	/* Read length */
500226046Sdes	buffer_append_space(&logmsg, 4);
501226046Sdes	if (atomicio(read, pmonitor->m_log_recvfd,
502226046Sdes	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
503226046Sdes		if (errno == EPIPE) {
504240075Sdes			buffer_free(&logmsg);
505226046Sdes			debug("%s: child log fd closed", __func__);
506226046Sdes			close(pmonitor->m_log_recvfd);
507226046Sdes			pmonitor->m_log_recvfd = -1;
508226046Sdes			return -1;
509226046Sdes		}
510226046Sdes		fatal("%s: log fd read: %s", __func__, strerror(errno));
511226046Sdes	}
512226046Sdes	len = buffer_get_int(&logmsg);
513226046Sdes	if (len <= 4 || len > 8192)
514226046Sdes		fatal("%s: invalid log message length %u", __func__, len);
515226046Sdes
516226046Sdes	/* Read severity, message */
517226046Sdes	buffer_clear(&logmsg);
518226046Sdes	buffer_append_space(&logmsg, len);
519226046Sdes	if (atomicio(read, pmonitor->m_log_recvfd,
520226046Sdes	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
521226046Sdes		fatal("%s: log fd read: %s", __func__, strerror(errno));
522226046Sdes
523226046Sdes	/* Log it */
524226046Sdes	level = buffer_get_int(&logmsg);
525226046Sdes	msg = buffer_get_string(&logmsg, NULL);
526226046Sdes	if (log_level_name(level) == NULL)
527226046Sdes		fatal("%s: invalid log level %u (corrupted message?)",
528226046Sdes		    __func__, level);
529226046Sdes	do_log2(level, "%s [preauth]", msg);
530226046Sdes
531226046Sdes	buffer_free(&logmsg);
532255767Sdes	free(msg);
533226046Sdes
534226046Sdes	return 0;
535226046Sdes}
536226046Sdes
53798675Sdesint
53898675Sdesmonitor_read(struct monitor *pmonitor, struct mon_table *ent,
53998675Sdes    struct mon_table **pent)
54098675Sdes{
54198675Sdes	Buffer m;
54298675Sdes	int ret;
54398675Sdes	u_char type;
544226046Sdes	struct pollfd pfd[2];
54598675Sdes
546226046Sdes	for (;;) {
547264377Sdes		memset(&pfd, 0, sizeof(pfd));
548226046Sdes		pfd[0].fd = pmonitor->m_sendfd;
549226046Sdes		pfd[0].events = POLLIN;
550226046Sdes		pfd[1].fd = pmonitor->m_log_recvfd;
551226046Sdes		pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
552226046Sdes		if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
553226046Sdes			if (errno == EINTR || errno == EAGAIN)
554226046Sdes				continue;
555226046Sdes			fatal("%s: poll: %s", __func__, strerror(errno));
556226046Sdes		}
557226046Sdes		if (pfd[1].revents) {
558226046Sdes			/*
559226046Sdes			 * Drain all log messages before processing next
560226046Sdes			 * monitor request.
561226046Sdes			 */
562226046Sdes			monitor_read_log(pmonitor);
563226046Sdes			continue;
564226046Sdes		}
565226046Sdes		if (pfd[0].revents)
566226046Sdes			break;  /* Continues below */
567226046Sdes	}
568226046Sdes
56998675Sdes	buffer_init(&m);
57098675Sdes
57198675Sdes	mm_request_receive(pmonitor->m_sendfd, &m);
57298675Sdes	type = buffer_get_char(&m);
57398675Sdes
57498675Sdes	debug3("%s: checking request %d", __func__, type);
57598675Sdes
57698675Sdes	while (ent->f != NULL) {
57798675Sdes		if (ent->type == type)
57898675Sdes			break;
57998675Sdes		ent++;
58098675Sdes	}
58198675Sdes
58298675Sdes	if (ent->f != NULL) {
58398675Sdes		if (!(ent->flags & MON_PERMIT))
58498675Sdes			fatal("%s: unpermitted request %d", __func__,
58598675Sdes			    type);
58698675Sdes		ret = (*ent->f)(pmonitor->m_sendfd, &m);
58798675Sdes		buffer_free(&m);
58898675Sdes
58998675Sdes		/* The child may use this request only once, disable it */
59098675Sdes		if (ent->flags & MON_ONCE) {
59198675Sdes			debug2("%s: %d used once, disabling now", __func__,
59298675Sdes			    type);
59398675Sdes			ent->flags &= ~MON_PERMIT;
59498675Sdes		}
59598675Sdes
59698675Sdes		if (pent != NULL)
59798675Sdes			*pent = ent;
59898675Sdes
59998675Sdes		return ret;
60098675Sdes	}
60198675Sdes
60298675Sdes	fatal("%s: unsupported request: %d", __func__, type);
60398675Sdes
60498675Sdes	/* NOTREACHED */
60598675Sdes	return (-1);
60698675Sdes}
60798675Sdes
60898675Sdes/* allowed key state */
60998675Sdesstatic int
61098675Sdesmonitor_allowed_key(u_char *blob, u_int bloblen)
61198675Sdes{
61298675Sdes	/* make sure key is allowed */
61398675Sdes	if (key_blob == NULL || key_bloblen != bloblen ||
614215116Sdes	    timingsafe_bcmp(key_blob, blob, key_bloblen))
61598675Sdes		return (0);
61698675Sdes	return (1);
61798675Sdes}
61898675Sdes
61998675Sdesstatic void
62098675Sdesmonitor_reset_key_state(void)
62198675Sdes{
62298675Sdes	/* reset state */
623255767Sdes	free(key_blob);
624255767Sdes	free(hostbased_cuser);
625255767Sdes	free(hostbased_chost);
62698675Sdes	key_blob = NULL;
62798675Sdes	key_bloblen = 0;
62898675Sdes	key_blobtype = MM_NOKEY;
62998675Sdes	hostbased_cuser = NULL;
63098675Sdes	hostbased_chost = NULL;
63198675Sdes}
63298675Sdes
63398675Sdesint
634137019Sdesmm_answer_moduli(int sock, Buffer *m)
63598675Sdes{
63698675Sdes	DH *dh;
63798675Sdes	int min, want, max;
63898675Sdes
63998675Sdes	min = buffer_get_int(m);
64098675Sdes	want = buffer_get_int(m);
64198675Sdes	max = buffer_get_int(m);
64298675Sdes
64398675Sdes	debug3("%s: got parameters: %d %d %d",
64498675Sdes	    __func__, min, want, max);
64598675Sdes	/* We need to check here, too, in case the child got corrupted */
64698675Sdes	if (max < min || want < min || max < want)
64798675Sdes		fatal("%s: bad parameters: %d %d %d",
64898675Sdes		    __func__, min, want, max);
64998675Sdes
65098675Sdes	buffer_clear(m);
65198675Sdes
65298675Sdes	dh = choose_dh(min, want, max);
65398675Sdes	if (dh == NULL) {
65498675Sdes		buffer_put_char(m, 0);
65598675Sdes		return (0);
65698675Sdes	} else {
65798675Sdes		/* Send first bignum */
65898675Sdes		buffer_put_char(m, 1);
65998675Sdes		buffer_put_bignum2(m, dh->p);
66098675Sdes		buffer_put_bignum2(m, dh->g);
66198675Sdes
66298675Sdes		DH_free(dh);
66398675Sdes	}
664137019Sdes	mm_request_send(sock, MONITOR_ANS_MODULI, m);
66598675Sdes	return (0);
66698675Sdes}
66798675Sdes
668255767Sdesextern AuthenticationConnection *auth_conn;
669255767Sdes
67098675Sdesint
671137019Sdesmm_answer_sign(int sock, Buffer *m)
67298675Sdes{
67398675Sdes	Key *key;
67498675Sdes	u_char *p;
67598675Sdes	u_char *signature;
67698675Sdes	u_int siglen, datlen;
67798675Sdes	int keyid;
67898675Sdes
67998675Sdes	debug3("%s", __func__);
68098675Sdes
68198675Sdes	keyid = buffer_get_int(m);
68298675Sdes	p = buffer_get_string(m, &datlen);
68398675Sdes
684162856Sdes	/*
685221420Sdes	 * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
686221420Sdes	 * SHA384 (48 bytes) and SHA512 (64 bytes).
687162856Sdes	 */
688221420Sdes	if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
689106130Sdes		fatal("%s: data length incorrect: %u", __func__, datlen);
69098675Sdes
69198675Sdes	/* save session id, it will be passed on the first call */
69298675Sdes	if (session_id2_len == 0) {
69398675Sdes		session_id2_len = datlen;
69498675Sdes		session_id2 = xmalloc(session_id2_len);
69598675Sdes		memcpy(session_id2, p, session_id2_len);
69698675Sdes	}
69798675Sdes
698255767Sdes	if ((key = get_hostkey_by_index(keyid)) != NULL) {
699255767Sdes		if (key_sign(key, &signature, &siglen, p, datlen) < 0)
700255767Sdes			fatal("%s: key_sign failed", __func__);
701255767Sdes	} else if ((key = get_hostkey_public_by_index(keyid)) != NULL &&
702255767Sdes	    auth_conn != NULL) {
703255767Sdes		if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p,
704255767Sdes		    datlen) < 0)
705255767Sdes			fatal("%s: ssh_agent_sign failed", __func__);
706255767Sdes	} else
70798675Sdes		fatal("%s: no hostkey from index %d", __func__, keyid);
70898675Sdes
709106130Sdes	debug3("%s: signature %p(%u)", __func__, signature, siglen);
71098675Sdes
71198675Sdes	buffer_clear(m);
71298675Sdes	buffer_put_string(m, signature, siglen);
71398675Sdes
714255767Sdes	free(p);
715255767Sdes	free(signature);
71698675Sdes
717137019Sdes	mm_request_send(sock, MONITOR_ANS_SIGN, m);
71898675Sdes
71998675Sdes	/* Turn on permissions for getpwnam */
72098675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
72198675Sdes
72298675Sdes	return (0);
72398675Sdes}
72498675Sdes
72598675Sdes/* Retrieves the password entry and also checks if the user is permitted */
72698675Sdes
72798675Sdesint
728137019Sdesmm_answer_pwnamallow(int sock, Buffer *m)
72998675Sdes{
730137019Sdes	char *username;
73198675Sdes	struct passwd *pwent;
73298675Sdes	int allowed = 0;
733226046Sdes	u_int i;
73498675Sdes
73598675Sdes	debug3("%s", __func__);
73698675Sdes
73798675Sdes	if (authctxt->attempt++ != 0)
73898675Sdes		fatal("%s: multiple attempts for getpwnam", __func__);
73998675Sdes
740137019Sdes	username = buffer_get_string(m, NULL);
74198675Sdes
742137019Sdes	pwent = getpwnamallow(username);
74398675Sdes
744137019Sdes	authctxt->user = xstrdup(username);
745137019Sdes	setproctitle("%s [priv]", pwent ? username : "unknown");
746255767Sdes	free(username);
74798675Sdes
74898675Sdes	buffer_clear(m);
74998675Sdes
75098675Sdes	if (pwent == NULL) {
75198675Sdes		buffer_put_char(m, 0);
752126277Sdes		authctxt->pw = fakepw();
75398675Sdes		goto out;
75498675Sdes	}
75598675Sdes
75698675Sdes	allowed = 1;
75798675Sdes	authctxt->pw = pwent;
75898675Sdes	authctxt->valid = 1;
75998675Sdes
76098675Sdes	buffer_put_char(m, 1);
76198675Sdes	buffer_put_string(m, pwent, sizeof(struct passwd));
76298675Sdes	buffer_put_cstring(m, pwent->pw_name);
76398675Sdes	buffer_put_cstring(m, "*");
764255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
76598675Sdes	buffer_put_cstring(m, pwent->pw_gecos);
766255767Sdes#endif
767255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
76898675Sdes	buffer_put_cstring(m, pwent->pw_class);
76998941Sdes#endif
77098675Sdes	buffer_put_cstring(m, pwent->pw_dir);
77198675Sdes	buffer_put_cstring(m, pwent->pw_shell);
77298675Sdes
77398675Sdes out:
774181111Sdes	buffer_put_string(m, &options, sizeof(options));
775226046Sdes
776226046Sdes#define M_CP_STROPT(x) do { \
777226046Sdes		if (options.x != NULL) \
778226046Sdes			buffer_put_cstring(m, options.x); \
779226046Sdes	} while (0)
780226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \
781226046Sdes		for (i = 0; i < options.nx; i++) \
782226046Sdes			buffer_put_cstring(m, options.x[i]); \
783226046Sdes	} while (0)
784226046Sdes	/* See comment in servconf.h */
785226046Sdes	COPY_MATCH_STRING_OPTS();
786226046Sdes#undef M_CP_STROPT
787226046Sdes#undef M_CP_STRARRAYOPT
788248619Sdes
789248619Sdes	/* Create valid auth method lists */
790248619Sdes	if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
791248619Sdes		/*
792248619Sdes		 * The monitor will continue long enough to let the child
793248619Sdes		 * run to it's packet_disconnect(), but it must not allow any
794248619Sdes		 * authentication to succeed.
795248619Sdes		 */
796248619Sdes		debug("%s: no valid authentication method lists", __func__);
797248619Sdes	}
798248619Sdes
79998675Sdes	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
800137019Sdes	mm_request_send(sock, MONITOR_ANS_PWNAM, m);
80198675Sdes
80298675Sdes	/* For SSHv1 allow authentication now */
80398675Sdes	if (!compat20)
80498675Sdes		monitor_permit_authentications(1);
80598675Sdes	else {
80698675Sdes		/* Allow service/style information on the auth context */
80798675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
80898675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
80998675Sdes	}
81098941Sdes#ifdef USE_PAM
811124211Sdes	if (options.use_pam)
812124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
81398941Sdes#endif
81498675Sdes
81598675Sdes	return (0);
81698675Sdes}
81798675Sdes
818137019Sdesint mm_answer_auth2_read_banner(int sock, Buffer *m)
81998675Sdes{
82098675Sdes	char *banner;
82198675Sdes
82298675Sdes	buffer_clear(m);
82398675Sdes	banner = auth2_read_banner();
82498675Sdes	buffer_put_cstring(m, banner != NULL ? banner : "");
825137019Sdes	mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
826255767Sdes	free(banner);
82798675Sdes
82898675Sdes	return (0);
82998675Sdes}
83098675Sdes
83198675Sdesint
832137019Sdesmm_answer_authserv(int sock, Buffer *m)
83398675Sdes{
83498675Sdes	monitor_permit_authentications(1);
83598675Sdes
83698675Sdes	authctxt->service = buffer_get_string(m, NULL);
83798675Sdes	authctxt->style = buffer_get_string(m, NULL);
83898675Sdes	debug3("%s: service=%s, style=%s",
83998675Sdes	    __func__, authctxt->service, authctxt->style);
84098675Sdes
84198675Sdes	if (strlen(authctxt->style) == 0) {
842255767Sdes		free(authctxt->style);
84398675Sdes		authctxt->style = NULL;
84498675Sdes	}
84598675Sdes
84698675Sdes	return (0);
84798675Sdes}
84898675Sdes
84998675Sdesint
850137019Sdesmm_answer_authpassword(int sock, Buffer *m)
85198675Sdes{
85298675Sdes	static int call_count;
85398675Sdes	char *passwd;
854106130Sdes	int authenticated;
855106130Sdes	u_int plen;
85698675Sdes
85798675Sdes	passwd = buffer_get_string(m, &plen);
85898675Sdes	/* Only authenticate if the context is valid */
85998675Sdes	authenticated = options.password_authentication &&
860124211Sdes	    auth_password(authctxt, passwd);
861264377Sdes	explicit_bzero(passwd, strlen(passwd));
862255767Sdes	free(passwd);
86398675Sdes
86498675Sdes	buffer_clear(m);
86598675Sdes	buffer_put_int(m, authenticated);
86698675Sdes
86798675Sdes	debug3("%s: sending result %d", __func__, authenticated);
868137019Sdes	mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
86998675Sdes
87098675Sdes	call_count++;
87198675Sdes	if (plen == 0 && call_count == 1)
87298675Sdes		auth_method = "none";
87398675Sdes	else
87498675Sdes		auth_method = "password";
87598675Sdes
87698675Sdes	/* Causes monitor loop to terminate if authenticated */
87798675Sdes	return (authenticated);
87898675Sdes}
87998675Sdes
88098675Sdes#ifdef BSD_AUTH
88198675Sdesint
882137019Sdesmm_answer_bsdauthquery(int sock, Buffer *m)
88398675Sdes{
88498675Sdes	char *name, *infotxt;
88598675Sdes	u_int numprompts;
88698675Sdes	u_int *echo_on;
88798675Sdes	char **prompts;
888113911Sdes	u_int success;
88998675Sdes
890113911Sdes	success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
891113911Sdes	    &prompts, &echo_on) < 0 ? 0 : 1;
89298675Sdes
89398675Sdes	buffer_clear(m);
894113911Sdes	buffer_put_int(m, success);
895113911Sdes	if (success)
89698675Sdes		buffer_put_cstring(m, prompts[0]);
89798675Sdes
898113911Sdes	debug3("%s: sending challenge success: %u", __func__, success);
899137019Sdes	mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
90098675Sdes
901113911Sdes	if (success) {
902255767Sdes		free(name);
903255767Sdes		free(infotxt);
904255767Sdes		free(prompts);
905255767Sdes		free(echo_on);
90698675Sdes	}
90798675Sdes
90898675Sdes	return (0);
90998675Sdes}
91098675Sdes
91198675Sdesint
912137019Sdesmm_answer_bsdauthrespond(int sock, Buffer *m)
91398675Sdes{
91498675Sdes	char *response;
91598675Sdes	int authok;
91698675Sdes
91798675Sdes	if (authctxt->as == 0)
91898675Sdes		fatal("%s: no bsd auth session", __func__);
91998675Sdes
92098675Sdes	response = buffer_get_string(m, NULL);
92198675Sdes	authok = options.challenge_response_authentication &&
92298675Sdes	    auth_userresponse(authctxt->as, response, 0);
92398675Sdes	authctxt->as = NULL;
92498675Sdes	debug3("%s: <%s> = <%d>", __func__, response, authok);
925255767Sdes	free(response);
92698675Sdes
92798675Sdes	buffer_clear(m);
92898675Sdes	buffer_put_int(m, authok);
92998675Sdes
93098675Sdes	debug3("%s: sending authenticated: %d", __func__, authok);
931137019Sdes	mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
93298675Sdes
933255767Sdes	if (compat20) {
934255767Sdes		auth_method = "keyboard-interactive";
935255767Sdes		auth_submethod = "bsdauth";
936255767Sdes	} else
937248619Sdes		auth_method = "bsdauth";
93898675Sdes
93998675Sdes	return (authok != 0);
94098675Sdes}
94198675Sdes#endif
94298675Sdes
94398675Sdes#ifdef SKEY
94498675Sdesint
945137019Sdesmm_answer_skeyquery(int sock, Buffer *m)
94698675Sdes{
94798941Sdes	struct skey skey;
94898675Sdes	char challenge[1024];
949113911Sdes	u_int success;
95098675Sdes
951128460Sdes	success = _compat_skeychallenge(&skey, authctxt->user, challenge,
952128460Sdes	    sizeof(challenge)) < 0 ? 0 : 1;
95398675Sdes
95498675Sdes	buffer_clear(m);
955113911Sdes	buffer_put_int(m, success);
956113911Sdes	if (success)
95798675Sdes		buffer_put_cstring(m, challenge);
95898675Sdes
959113911Sdes	debug3("%s: sending challenge success: %u", __func__, success);
960137019Sdes	mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
96198675Sdes
96298675Sdes	return (0);
96398675Sdes}
96498675Sdes
96598675Sdesint
966137019Sdesmm_answer_skeyrespond(int sock, Buffer *m)
96798675Sdes{
96898675Sdes	char *response;
96998675Sdes	int authok;
97098675Sdes
97198675Sdes	response = buffer_get_string(m, NULL);
97298675Sdes
97398675Sdes	authok = (options.challenge_response_authentication &&
97498675Sdes	    authctxt->valid &&
97598941Sdes	    skey_haskey(authctxt->pw->pw_name) == 0 &&
97698941Sdes	    skey_passcheck(authctxt->pw->pw_name, response) != -1);
97798675Sdes
978255767Sdes	free(response);
97998675Sdes
98098675Sdes	buffer_clear(m);
98198675Sdes	buffer_put_int(m, authok);
98298675Sdes
98398675Sdes	debug3("%s: sending authenticated: %d", __func__, authok);
984137019Sdes	mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
98598675Sdes
98698675Sdes	auth_method = "skey";
98798675Sdes
98898675Sdes	return (authok != 0);
98998675Sdes}
99098675Sdes#endif
99198675Sdes
99298941Sdes#ifdef USE_PAM
99398941Sdesint
994137019Sdesmm_answer_pam_start(int sock, Buffer *m)
99598941Sdes{
996124211Sdes	if (!options.use_pam)
997124211Sdes		fatal("UsePAM not set, but ended up in %s anyway", __func__);
998124211Sdes
999128460Sdes	start_pam(authctxt);
100098941Sdes
1001124211Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
1002124211Sdes
100398941Sdes	return (0);
100498941Sdes}
100599052Sdes
1006124211Sdesint
1007137019Sdesmm_answer_pam_account(int sock, Buffer *m)
1008124211Sdes{
1009124211Sdes	u_int ret;
1010126277Sdes
1011124211Sdes	if (!options.use_pam)
1012124211Sdes		fatal("UsePAM not set, but ended up in %s anyway", __func__);
101399052Sdes
1014124211Sdes	ret = do_pam_account();
1015124211Sdes
1016124211Sdes	buffer_put_int(m, ret);
1017157019Sdes	buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
1018124211Sdes
1019137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
1020124211Sdes
1021124211Sdes	return (ret);
1022124211Sdes}
1023124211Sdes
1024124211Sdesstatic void *sshpam_ctxt, *sshpam_authok;
1025124211Sdesextern KbdintDevice sshpam_device;
1026124211Sdes
102799052Sdesint
1028137019Sdesmm_answer_pam_init_ctx(int sock, Buffer *m)
102999052Sdes{
103099052Sdes	debug3("%s", __func__);
1031124211Sdes	sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
1032124211Sdes	sshpam_authok = NULL;
103399052Sdes	buffer_clear(m);
1034124211Sdes	if (sshpam_ctxt != NULL) {
103599052Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
103699052Sdes		buffer_put_int(m, 1);
103799052Sdes	} else {
103899052Sdes		buffer_put_int(m, 0);
103999052Sdes	}
1040137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
104199052Sdes	return (0);
104299052Sdes}
104399052Sdes
104499052Sdesint
1045137019Sdesmm_answer_pam_query(int sock, Buffer *m)
104699052Sdes{
1047215116Sdes	char *name = NULL, *info = NULL, **prompts = NULL;
1048215116Sdes	u_int i, num = 0, *echo_on = 0;
1049149753Sdes	int ret;
105099052Sdes
105199052Sdes	debug3("%s", __func__);
1052124211Sdes	sshpam_authok = NULL;
1053124211Sdes	ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on);
1054110138Sdes	if (ret == 0 && num == 0)
1055124211Sdes		sshpam_authok = sshpam_ctxt;
105699052Sdes	if (num > 1 || name == NULL || info == NULL)
105799052Sdes		ret = -1;
105899747Sdes	buffer_clear(m);
105999052Sdes	buffer_put_int(m, ret);
106099052Sdes	buffer_put_cstring(m, name);
1061255767Sdes	free(name);
106299052Sdes	buffer_put_cstring(m, info);
1063255767Sdes	free(info);
106499052Sdes	buffer_put_int(m, num);
106599052Sdes	for (i = 0; i < num; ++i) {
106699052Sdes		buffer_put_cstring(m, prompts[i]);
1067255767Sdes		free(prompts[i]);
106899052Sdes		buffer_put_int(m, echo_on[i]);
106999052Sdes	}
1070255767Sdes	free(prompts);
1071255767Sdes	free(echo_on);
1072248619Sdes	auth_method = "keyboard-interactive";
1073248619Sdes	auth_submethod = "pam";
1074137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
107599052Sdes	return (0);
107699052Sdes}
107799052Sdes
107899052Sdesint
1079137019Sdesmm_answer_pam_respond(int sock, Buffer *m)
108099052Sdes{
108199052Sdes	char **resp;
1082149753Sdes	u_int i, num;
1083149753Sdes	int ret;
108499052Sdes
108599052Sdes	debug3("%s", __func__);
1086124211Sdes	sshpam_authok = NULL;
108799052Sdes	num = buffer_get_int(m);
108899052Sdes	if (num > 0) {
1089162856Sdes		resp = xcalloc(num, sizeof(char *));
109099052Sdes		for (i = 0; i < num; ++i)
109199052Sdes			resp[i] = buffer_get_string(m, NULL);
1092124211Sdes		ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
109399052Sdes		for (i = 0; i < num; ++i)
1094255767Sdes			free(resp[i]);
1095255767Sdes		free(resp);
109699052Sdes	} else {
1097124211Sdes		ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
109899052Sdes	}
109999052Sdes	buffer_clear(m);
110099052Sdes	buffer_put_int(m, ret);
1101137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
1102248619Sdes	auth_method = "keyboard-interactive";
1103248619Sdes	auth_submethod = "pam";
110499052Sdes	if (ret == 0)
1105124211Sdes		sshpam_authok = sshpam_ctxt;
110699258Sdes	return (0);
110799052Sdes}
110899052Sdes
110999052Sdesint
1110137019Sdesmm_answer_pam_free_ctx(int sock, Buffer *m)
111199052Sdes{
1112287146Sdelphij	int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt;
111399052Sdes
111499052Sdes	debug3("%s", __func__);
1115124211Sdes	(sshpam_device.free_ctx)(sshpam_ctxt);
1116287146Sdelphij	sshpam_ctxt = sshpam_authok = NULL;
111799052Sdes	buffer_clear(m);
1118137019Sdes	mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
1119248619Sdes	auth_method = "keyboard-interactive";
1120248619Sdes	auth_submethod = "pam";
1121287146Sdelphij	return r;
112299052Sdes}
112398941Sdes#endif
112498941Sdes
112598675Sdesint
1126137019Sdesmm_answer_keyallowed(int sock, Buffer *m)
112798675Sdes{
112898675Sdes	Key *key;
1129106130Sdes	char *cuser, *chost;
1130106130Sdes	u_char *blob;
113198675Sdes	u_int bloblen;
113298675Sdes	enum mm_keytype type = 0;
113398675Sdes	int allowed = 0;
113498675Sdes
113598675Sdes	debug3("%s entering", __func__);
113698675Sdes
113798675Sdes	type = buffer_get_int(m);
113898675Sdes	cuser = buffer_get_string(m, NULL);
113998675Sdes	chost = buffer_get_string(m, NULL);
114098675Sdes	blob = buffer_get_string(m, &bloblen);
114198675Sdes
114298675Sdes	key = key_from_blob(blob, bloblen);
114398675Sdes
114498675Sdes	if ((compat20 && type == MM_RSAHOSTKEY) ||
114598675Sdes	    (!compat20 && type != MM_RSAHOSTKEY))
114698675Sdes		fatal("%s: key type and protocol mismatch", __func__);
114798675Sdes
114898675Sdes	debug3("%s: key_from_blob: %p", __func__, key);
114998675Sdes
1150126277Sdes	if (key != NULL && authctxt->valid) {
1151147005Sdes		switch (type) {
115298675Sdes		case MM_USERKEY:
115398675Sdes			allowed = options.pubkey_authentication &&
115498675Sdes			    user_key_allowed(authctxt->pw, key);
1155255767Sdes			pubkey_auth_info(authctxt, key, NULL);
1156162856Sdes			auth_method = "publickey";
1157181111Sdes			if (options.pubkey_authentication && allowed != 1)
1158181111Sdes				auth_clear_options();
115998675Sdes			break;
116098675Sdes		case MM_HOSTKEY:
116198675Sdes			allowed = options.hostbased_authentication &&
116298675Sdes			    hostbased_key_allowed(authctxt->pw,
116398675Sdes			    cuser, chost, key);
1164255767Sdes			pubkey_auth_info(authctxt, key,
1165255767Sdes			    "client user \"%.100s\", client host \"%.100s\"",
1166255767Sdes			    cuser, chost);
1167162856Sdes			auth_method = "hostbased";
116898675Sdes			break;
116998675Sdes		case MM_RSAHOSTKEY:
117098675Sdes			key->type = KEY_RSA1; /* XXX */
117198675Sdes			allowed = options.rhosts_rsa_authentication &&
117298675Sdes			    auth_rhosts_rsa_key_allowed(authctxt->pw,
117398675Sdes			    cuser, chost, key);
1174181111Sdes			if (options.rhosts_rsa_authentication && allowed != 1)
1175181111Sdes				auth_clear_options();
1176162856Sdes			auth_method = "rsa";
117798675Sdes			break;
117898675Sdes		default:
117998675Sdes			fatal("%s: unknown key type %d", __func__, type);
118098675Sdes			break;
118198675Sdes		}
1182113911Sdes	}
1183113911Sdes	if (key != NULL)
118498675Sdes		key_free(key);
118598675Sdes
118698675Sdes	/* clear temporarily storage (used by verify) */
118798675Sdes	monitor_reset_key_state();
118898675Sdes
118998675Sdes	if (allowed) {
119098675Sdes		/* Save temporarily for comparison in verify */
119198675Sdes		key_blob = blob;
119298675Sdes		key_bloblen = bloblen;
119398675Sdes		key_blobtype = type;
119498675Sdes		hostbased_cuser = cuser;
119598675Sdes		hostbased_chost = chost;
1196162856Sdes	} else {
1197162856Sdes		/* Log failed attempt */
1198255767Sdes		auth_log(authctxt, 0, 0, auth_method, NULL);
1199255767Sdes		free(blob);
1200255767Sdes		free(cuser);
1201255767Sdes		free(chost);
120298675Sdes	}
120398675Sdes
120498675Sdes	debug3("%s: key %p is %s",
1205181111Sdes	    __func__, key, allowed ? "allowed" : "not allowed");
120698675Sdes
120798675Sdes	buffer_clear(m);
120898675Sdes	buffer_put_int(m, allowed);
1209113911Sdes	buffer_put_int(m, forced_command != NULL);
121098675Sdes
1211137019Sdes	mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
121298675Sdes
121398675Sdes	if (type == MM_RSAHOSTKEY)
121498675Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
121598675Sdes
121698675Sdes	return (0);
121798675Sdes}
121898675Sdes
121998675Sdesstatic int
122098675Sdesmonitor_valid_userblob(u_char *data, u_int datalen)
122198675Sdes{
122298675Sdes	Buffer b;
1223255767Sdes	char *p, *userstyle;
122498675Sdes	u_int len;
122598675Sdes	int fail = 0;
122698675Sdes
122798675Sdes	buffer_init(&b);
122898675Sdes	buffer_append(&b, data, datalen);
122998675Sdes
123098675Sdes	if (datafellows & SSH_OLD_SESSIONID) {
123198675Sdes		p = buffer_ptr(&b);
123298675Sdes		len = buffer_len(&b);
123398675Sdes		if ((session_id2 == NULL) ||
123498675Sdes		    (len < session_id2_len) ||
1235215116Sdes		    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
123698675Sdes			fail++;
123798675Sdes		buffer_consume(&b, session_id2_len);
123898675Sdes	} else {
123998675Sdes		p = buffer_get_string(&b, &len);
124098675Sdes		if ((session_id2 == NULL) ||
124198675Sdes		    (len != session_id2_len) ||
1242215116Sdes		    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
124398675Sdes			fail++;
1244255767Sdes		free(p);
124598675Sdes	}
124698675Sdes	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
124798675Sdes		fail++;
1248255767Sdes	p = buffer_get_cstring(&b, NULL);
1249255767Sdes	xasprintf(&userstyle, "%s%s%s", authctxt->user,
1250255767Sdes	    authctxt->style ? ":" : "",
1251255767Sdes	    authctxt->style ? authctxt->style : "");
1252255767Sdes	if (strcmp(userstyle, p) != 0) {
1253124211Sdes		logit("wrong user name passed to monitor: expected %s != %.100s",
1254255767Sdes		    userstyle, p);
125598675Sdes		fail++;
125698675Sdes	}
1257255767Sdes	free(userstyle);
1258255767Sdes	free(p);
125998675Sdes	buffer_skip_string(&b);
126098675Sdes	if (datafellows & SSH_BUG_PKAUTH) {
126198675Sdes		if (!buffer_get_char(&b))
126298675Sdes			fail++;
126398675Sdes	} else {
1264255767Sdes		p = buffer_get_cstring(&b, NULL);
126598675Sdes		if (strcmp("publickey", p) != 0)
126698675Sdes			fail++;
1267255767Sdes		free(p);
126898675Sdes		if (!buffer_get_char(&b))
126998675Sdes			fail++;
127098675Sdes		buffer_skip_string(&b);
127198675Sdes	}
127298675Sdes	buffer_skip_string(&b);
127398675Sdes	if (buffer_len(&b) != 0)
127498675Sdes		fail++;
127598675Sdes	buffer_free(&b);
127698675Sdes	return (fail == 0);
127798675Sdes}
127898675Sdes
127998675Sdesstatic int
1280106130Sdesmonitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
1281106130Sdes    char *chost)
128298675Sdes{
128398675Sdes	Buffer b;
1284255767Sdes	char *p, *userstyle;
128598675Sdes	u_int len;
128698675Sdes	int fail = 0;
128798675Sdes
128898675Sdes	buffer_init(&b);
128998675Sdes	buffer_append(&b, data, datalen);
129098675Sdes
129198675Sdes	p = buffer_get_string(&b, &len);
129298675Sdes	if ((session_id2 == NULL) ||
129398675Sdes	    (len != session_id2_len) ||
1294215116Sdes	    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
129598675Sdes		fail++;
1296255767Sdes	free(p);
129798675Sdes
129898675Sdes	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
129998675Sdes		fail++;
1300255767Sdes	p = buffer_get_cstring(&b, NULL);
1301255767Sdes	xasprintf(&userstyle, "%s%s%s", authctxt->user,
1302255767Sdes	    authctxt->style ? ":" : "",
1303255767Sdes	    authctxt->style ? authctxt->style : "");
1304255767Sdes	if (strcmp(userstyle, p) != 0) {
1305124211Sdes		logit("wrong user name passed to monitor: expected %s != %.100s",
1306255767Sdes		    userstyle, p);
130798675Sdes		fail++;
130898675Sdes	}
1309255767Sdes	free(userstyle);
1310255767Sdes	free(p);
131198675Sdes	buffer_skip_string(&b);	/* service */
1312255767Sdes	p = buffer_get_cstring(&b, NULL);
131398675Sdes	if (strcmp(p, "hostbased") != 0)
131498675Sdes		fail++;
1315255767Sdes	free(p);
131698675Sdes	buffer_skip_string(&b);	/* pkalg */
131798675Sdes	buffer_skip_string(&b);	/* pkblob */
131898675Sdes
131998675Sdes	/* verify client host, strip trailing dot if necessary */
132098675Sdes	p = buffer_get_string(&b, NULL);
132198675Sdes	if (((len = strlen(p)) > 0) && p[len - 1] == '.')
132298675Sdes		p[len - 1] = '\0';
132398675Sdes	if (strcmp(p, chost) != 0)
132498675Sdes		fail++;
1325255767Sdes	free(p);
132698675Sdes
132798675Sdes	/* verify client user */
132898675Sdes	p = buffer_get_string(&b, NULL);
132998675Sdes	if (strcmp(p, cuser) != 0)
133098675Sdes		fail++;
1331255767Sdes	free(p);
133298675Sdes
133398675Sdes	if (buffer_len(&b) != 0)
133498675Sdes		fail++;
133598675Sdes	buffer_free(&b);
133698675Sdes	return (fail == 0);
133798675Sdes}
133898675Sdes
133998675Sdesint
1340137019Sdesmm_answer_keyverify(int sock, Buffer *m)
134198675Sdes{
134298675Sdes	Key *key;
134398675Sdes	u_char *signature, *data, *blob;
134498675Sdes	u_int signaturelen, datalen, bloblen;
134598675Sdes	int verified = 0;
134698675Sdes	int valid_data = 0;
134798675Sdes
134898675Sdes	blob = buffer_get_string(m, &bloblen);
134998675Sdes	signature = buffer_get_string(m, &signaturelen);
135098675Sdes	data = buffer_get_string(m, &datalen);
135198675Sdes
135298675Sdes	if (hostbased_cuser == NULL || hostbased_chost == NULL ||
135398675Sdes	  !monitor_allowed_key(blob, bloblen))
135498675Sdes		fatal("%s: bad key, not previously allowed", __func__);
135598675Sdes
135698675Sdes	key = key_from_blob(blob, bloblen);
135798675Sdes	if (key == NULL)
135898675Sdes		fatal("%s: bad public key blob", __func__);
135998675Sdes
136098675Sdes	switch (key_blobtype) {
136198675Sdes	case MM_USERKEY:
136298675Sdes		valid_data = monitor_valid_userblob(data, datalen);
136398675Sdes		break;
136498675Sdes	case MM_HOSTKEY:
136598675Sdes		valid_data = monitor_valid_hostbasedblob(data, datalen,
136698675Sdes		    hostbased_cuser, hostbased_chost);
136798675Sdes		break;
136898675Sdes	default:
136998675Sdes		valid_data = 0;
137098675Sdes		break;
137198675Sdes	}
137298675Sdes	if (!valid_data)
137398675Sdes		fatal("%s: bad signature data blob", __func__);
137498675Sdes
137598675Sdes	verified = key_verify(key, signature, signaturelen, data, datalen);
137698675Sdes	debug3("%s: key %p signature %s",
1377164149Sdes	    __func__, key, (verified == 1) ? "verified" : "unverified");
137898675Sdes
137998675Sdes	key_free(key);
1380255767Sdes	free(blob);
1381255767Sdes	free(signature);
1382255767Sdes	free(data);
138398675Sdes
138499063Sdes	auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
138599063Sdes
138698675Sdes	monitor_reset_key_state();
138798675Sdes
138898675Sdes	buffer_clear(m);
138998675Sdes	buffer_put_int(m, verified);
1390137019Sdes	mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
139198675Sdes
1392164149Sdes	return (verified == 1);
139398675Sdes}
139498675Sdes
139598675Sdesstatic void
139698675Sdesmm_record_login(Session *s, struct passwd *pw)
139798675Sdes{
139898675Sdes	socklen_t fromlen;
139998675Sdes	struct sockaddr_storage from;
140098675Sdes
140198675Sdes	/*
140298675Sdes	 * Get IP address of client. If the connection is not a socket, let
140398675Sdes	 * the address be 0.0.0.0.
140498675Sdes	 */
140598675Sdes	memset(&from, 0, sizeof(from));
1406103134Sume	fromlen = sizeof(from);
140798675Sdes	if (packet_connection_is_on_socket()) {
140898675Sdes		if (getpeername(packet_get_connection_in(),
1409162856Sdes		    (struct sockaddr *)&from, &fromlen) < 0) {
141098675Sdes			debug("getpeername: %.100s", strerror(errno));
1411126277Sdes			cleanup_exit(255);
141298675Sdes		}
141398675Sdes	}
141498675Sdes	/* Record that there was a login on that tty from the remote host. */
141598675Sdes	record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
1416124211Sdes	    get_remote_name_or_ip(utmp_len, options.use_dns),
1417103134Sume	    (struct sockaddr *)&from, fromlen);
141898675Sdes}
141998675Sdes
142098675Sdesstatic void
142198675Sdesmm_session_close(Session *s)
142298675Sdes{
1423124211Sdes	debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
142498675Sdes	if (s->ttyfd != -1) {
1425162856Sdes		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
142698675Sdes		session_pty_cleanup2(s);
142798675Sdes	}
1428181111Sdes	session_unused(s->self);
142998675Sdes}
143098675Sdes
143198675Sdesint
1432137019Sdesmm_answer_pty(int sock, Buffer *m)
143398675Sdes{
143498675Sdes	extern struct monitor *pmonitor;
143598675Sdes	Session *s;
143698675Sdes	int res, fd0;
143798675Sdes
143898675Sdes	debug3("%s entering", __func__);
143998675Sdes
144098675Sdes	buffer_clear(m);
144198675Sdes	s = session_new();
144298675Sdes	if (s == NULL)
144398675Sdes		goto error;
144498675Sdes	s->authctxt = authctxt;
144598675Sdes	s->pw = authctxt->pw;
144698675Sdes	s->pid = pmonitor->m_pid;
144798675Sdes	res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
144898675Sdes	if (res == 0)
144998675Sdes		goto error;
145098675Sdes	pty_setowner(authctxt->pw, s->tty);
145198675Sdes
145298675Sdes	buffer_put_int(m, 1);
145398675Sdes	buffer_put_cstring(m, s->tty);
145498675Sdes
145598675Sdes	/* We need to trick ttyslot */
145698675Sdes	if (dup2(s->ttyfd, 0) == -1)
145798675Sdes		fatal("%s: dup2", __func__);
145898675Sdes
145998675Sdes	mm_record_login(s, authctxt->pw);
146098675Sdes
146198675Sdes	/* Now we can close the file descriptor again */
146298675Sdes	close(0);
146398675Sdes
1464137019Sdes	/* send messages generated by record_login */
1465137019Sdes	buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
1466137019Sdes	buffer_clear(&loginmsg);
1467137019Sdes
1468137019Sdes	mm_request_send(sock, MONITOR_ANS_PTY, m);
1469137019Sdes
1470181111Sdes	if (mm_send_fd(sock, s->ptyfd) == -1 ||
1471181111Sdes	    mm_send_fd(sock, s->ttyfd) == -1)
1472181111Sdes		fatal("%s: send fds failed", __func__);
1473137019Sdes
147498675Sdes	/* make sure nothing uses fd 0 */
147598675Sdes	if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
147698675Sdes		fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
147798675Sdes	if (fd0 != 0)
147898675Sdes		error("%s: fd0 %d != 0", __func__, fd0);
147998675Sdes
148098675Sdes	/* slave is not needed */
148198675Sdes	close(s->ttyfd);
148298675Sdes	s->ttyfd = s->ptyfd;
148398675Sdes	/* no need to dup() because nobody closes ptyfd */
148498675Sdes	s->ptymaster = s->ptyfd;
148598675Sdes
1486162856Sdes	debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
148798675Sdes
148898675Sdes	return (0);
148998675Sdes
149098675Sdes error:
149198675Sdes	if (s != NULL)
149298675Sdes		mm_session_close(s);
149398675Sdes	buffer_put_int(m, 0);
1494137019Sdes	mm_request_send(sock, MONITOR_ANS_PTY, m);
149598675Sdes	return (0);
149698675Sdes}
149798675Sdes
149898675Sdesint
1499137019Sdesmm_answer_pty_cleanup(int sock, Buffer *m)
150098675Sdes{
150198675Sdes	Session *s;
150298675Sdes	char *tty;
150398675Sdes
150498675Sdes	debug3("%s entering", __func__);
150598675Sdes
150698675Sdes	tty = buffer_get_string(m, NULL);
150798675Sdes	if ((s = session_by_tty(tty)) != NULL)
150898675Sdes		mm_session_close(s);
150998675Sdes	buffer_clear(m);
1510255767Sdes	free(tty);
151198675Sdes	return (0);
151298675Sdes}
151398675Sdes
151498675Sdesint
1515137019Sdesmm_answer_sesskey(int sock, Buffer *m)
151698675Sdes{
151798675Sdes	BIGNUM *p;
151898675Sdes	int rsafail;
151998675Sdes
152098675Sdes	/* Turn off permissions */
1521147005Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0);
152298675Sdes
152398675Sdes	if ((p = BN_new()) == NULL)
152498675Sdes		fatal("%s: BN_new", __func__);
152598675Sdes
152698675Sdes	buffer_get_bignum2(m, p);
152798675Sdes
152898675Sdes	rsafail = ssh1_session_key(p);
152998675Sdes
153098675Sdes	buffer_clear(m);
153198675Sdes	buffer_put_int(m, rsafail);
153298675Sdes	buffer_put_bignum2(m, p);
153398675Sdes
153498675Sdes	BN_clear_free(p);
153598675Sdes
1536137019Sdes	mm_request_send(sock, MONITOR_ANS_SESSKEY, m);
153798675Sdes
153898675Sdes	/* Turn on permissions for sessid passing */
153998675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
154098675Sdes
154198675Sdes	return (0);
154298675Sdes}
154398675Sdes
154498675Sdesint
1545137019Sdesmm_answer_sessid(int sock, Buffer *m)
154698675Sdes{
154798675Sdes	int i;
154898675Sdes
154998675Sdes	debug3("%s entering", __func__);
155098675Sdes
155198675Sdes	if (buffer_len(m) != 16)
155298675Sdes		fatal("%s: bad ssh1 session id", __func__);
155398675Sdes	for (i = 0; i < 16; i++)
155498675Sdes		session_id[i] = buffer_get_char(m);
155598675Sdes
155698675Sdes	/* Turn on permissions for getpwnam */
155798675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
155898675Sdes
155998675Sdes	return (0);
156098675Sdes}
156198675Sdes
156298675Sdesint
1563137019Sdesmm_answer_rsa_keyallowed(int sock, Buffer *m)
156498675Sdes{
156598675Sdes	BIGNUM *client_n;
156698675Sdes	Key *key = NULL;
156798675Sdes	u_char *blob = NULL;
156898675Sdes	u_int blen = 0;
156998675Sdes	int allowed = 0;
157098675Sdes
157198675Sdes	debug3("%s entering", __func__);
157298675Sdes
1573162856Sdes	auth_method = "rsa";
157498675Sdes	if (options.rsa_authentication && authctxt->valid) {
157598675Sdes		if ((client_n = BN_new()) == NULL)
157698675Sdes			fatal("%s: BN_new", __func__);
157798675Sdes		buffer_get_bignum2(m, client_n);
157898675Sdes		allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
157998675Sdes		BN_clear_free(client_n);
158098675Sdes	}
158198675Sdes	buffer_clear(m);
158298675Sdes	buffer_put_int(m, allowed);
1583113911Sdes	buffer_put_int(m, forced_command != NULL);
158498675Sdes
158598675Sdes	/* clear temporarily storage (used by generate challenge) */
158698675Sdes	monitor_reset_key_state();
158798675Sdes
158898675Sdes	if (allowed && key != NULL) {
158998675Sdes		key->type = KEY_RSA;	/* cheat for key_to_blob */
159098675Sdes		if (key_to_blob(key, &blob, &blen) == 0)
159198675Sdes			fatal("%s: key_to_blob failed", __func__);
159298675Sdes		buffer_put_string(m, blob, blen);
159398675Sdes
159498675Sdes		/* Save temporarily for comparison in verify */
159598675Sdes		key_blob = blob;
159698675Sdes		key_bloblen = blen;
159798675Sdes		key_blobtype = MM_RSAUSERKEY;
1598113911Sdes	}
1599113911Sdes	if (key != NULL)
160098675Sdes		key_free(key);
160198675Sdes
1602137019Sdes	mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m);
160398675Sdes
160498675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
160598675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
160698675Sdes	return (0);
160798675Sdes}
160898675Sdes
160998675Sdesint
1610137019Sdesmm_answer_rsa_challenge(int sock, Buffer *m)
161198675Sdes{
161298675Sdes	Key *key = NULL;
161398675Sdes	u_char *blob;
161498675Sdes	u_int blen;
161598675Sdes
161698675Sdes	debug3("%s entering", __func__);
161798675Sdes
161898675Sdes	if (!authctxt->valid)
161998675Sdes		fatal("%s: authctxt not valid", __func__);
162098675Sdes	blob = buffer_get_string(m, &blen);
162198675Sdes	if (!monitor_allowed_key(blob, blen))
162298675Sdes		fatal("%s: bad key, not previously allowed", __func__);
162398675Sdes	if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
162498675Sdes		fatal("%s: key type mismatch", __func__);
162598675Sdes	if ((key = key_from_blob(blob, blen)) == NULL)
162698675Sdes		fatal("%s: received bad key", __func__);
1627192595Sdes	if (key->type != KEY_RSA)
1628192595Sdes		fatal("%s: received bad key type %d", __func__, key->type);
1629192595Sdes	key->type = KEY_RSA1;
163098675Sdes	if (ssh1_challenge)
163198675Sdes		BN_clear_free(ssh1_challenge);
163298675Sdes	ssh1_challenge = auth_rsa_generate_challenge(key);
163398675Sdes
163498675Sdes	buffer_clear(m);
163598675Sdes	buffer_put_bignum2(m, ssh1_challenge);
163698675Sdes
163798675Sdes	debug3("%s sending reply", __func__);
1638137019Sdes	mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m);
163998675Sdes
164098675Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
1641113911Sdes
1642255767Sdes	free(blob);
1643113911Sdes	key_free(key);
164498675Sdes	return (0);
164598675Sdes}
164698675Sdes
164798675Sdesint
1648137019Sdesmm_answer_rsa_response(int sock, Buffer *m)
164998675Sdes{
165098675Sdes	Key *key = NULL;
165198675Sdes	u_char *blob, *response;
165298675Sdes	u_int blen, len;
165398675Sdes	int success;
165498675Sdes
165598675Sdes	debug3("%s entering", __func__);
165698675Sdes
165798675Sdes	if (!authctxt->valid)
165898675Sdes		fatal("%s: authctxt not valid", __func__);
165998675Sdes	if (ssh1_challenge == NULL)
166098675Sdes		fatal("%s: no ssh1_challenge", __func__);
166198675Sdes
166298675Sdes	blob = buffer_get_string(m, &blen);
166398675Sdes	if (!monitor_allowed_key(blob, blen))
166498675Sdes		fatal("%s: bad key, not previously allowed", __func__);
166598675Sdes	if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
166698675Sdes		fatal("%s: key type mismatch: %d", __func__, key_blobtype);
166798675Sdes	if ((key = key_from_blob(blob, blen)) == NULL)
166898675Sdes		fatal("%s: received bad key", __func__);
166998675Sdes	response = buffer_get_string(m, &len);
167098675Sdes	if (len != 16)
167198675Sdes		fatal("%s: received bad response to challenge", __func__);
167298675Sdes	success = auth_rsa_verify_response(key, ssh1_challenge, response);
167398675Sdes
1674255767Sdes	free(blob);
167598675Sdes	key_free(key);
1676255767Sdes	free(response);
167798675Sdes
167898675Sdes	auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
167998675Sdes
168098675Sdes	/* reset state */
168198675Sdes	BN_clear_free(ssh1_challenge);
168298675Sdes	ssh1_challenge = NULL;
168398675Sdes	monitor_reset_key_state();
168498675Sdes
168598675Sdes	buffer_clear(m);
168698675Sdes	buffer_put_int(m, success);
1687137019Sdes	mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m);
168898675Sdes
168998675Sdes	return (success);
169098675Sdes}
169198675Sdes
169298675Sdesint
1693137019Sdesmm_answer_term(int sock, Buffer *req)
169498675Sdes{
169598675Sdes	extern struct monitor *pmonitor;
169698675Sdes	int res, status;
169798675Sdes
169898675Sdes	debug3("%s: tearing down sessions", __func__);
169998675Sdes
170098675Sdes	/* The child is terminating */
170198675Sdes	session_destroy_all(&mm_session_close);
170298675Sdes
1703181111Sdes#ifdef USE_PAM
1704181111Sdes	if (options.use_pam)
1705181111Sdes		sshpam_cleanup();
1706181111Sdes#endif
1707181111Sdes
170898675Sdes	while (waitpid(pmonitor->m_pid, &status, 0) == -1)
170998675Sdes		if (errno != EINTR)
171098675Sdes			exit(1);
171198675Sdes
171298675Sdes	res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
171398675Sdes
171498675Sdes	/* Terminate process */
1715137019Sdes	exit(res);
171698675Sdes}
171798675Sdes
1718147005Sdes#ifdef SSH_AUDIT_EVENTS
1719147005Sdes/* Report that an audit event occurred */
1720147005Sdesint
1721147005Sdesmm_answer_audit_event(int socket, Buffer *m)
1722147005Sdes{
1723147005Sdes	ssh_audit_event_t event;
1724147005Sdes
1725147005Sdes	debug3("%s entering", __func__);
1726147005Sdes
1727147005Sdes	event = buffer_get_int(m);
1728147005Sdes	switch(event) {
1729147005Sdes	case SSH_AUTH_FAIL_PUBKEY:
1730147005Sdes	case SSH_AUTH_FAIL_HOSTBASED:
1731147005Sdes	case SSH_AUTH_FAIL_GSSAPI:
1732147005Sdes	case SSH_LOGIN_EXCEED_MAXTRIES:
1733147005Sdes	case SSH_LOGIN_ROOT_DENIED:
1734147005Sdes	case SSH_CONNECTION_CLOSE:
1735147005Sdes	case SSH_INVALID_USER:
1736147005Sdes		audit_event(event);
1737147005Sdes		break;
1738147005Sdes	default:
1739147005Sdes		fatal("Audit event type %d not permitted", event);
1740147005Sdes	}
1741147005Sdes
1742147005Sdes	return (0);
1743147005Sdes}
1744147005Sdes
1745147005Sdesint
1746147005Sdesmm_answer_audit_command(int socket, Buffer *m)
1747147005Sdes{
1748147005Sdes	u_int len;
1749147005Sdes	char *cmd;
1750147005Sdes
1751147005Sdes	debug3("%s entering", __func__);
1752147005Sdes	cmd = buffer_get_string(m, &len);
1753147005Sdes	/* sanity check command, if so how? */
1754147005Sdes	audit_run_command(cmd);
1755255767Sdes	free(cmd);
1756147005Sdes	return (0);
1757147005Sdes}
1758147005Sdes#endif /* SSH_AUDIT_EVENTS */
1759147005Sdes
176098675Sdesvoid
176198675Sdesmonitor_apply_keystate(struct monitor *pmonitor)
176298675Sdes{
176398675Sdes	if (compat20) {
176498675Sdes		set_newkeys(MODE_IN);
176598675Sdes		set_newkeys(MODE_OUT);
176698675Sdes	} else {
176798675Sdes		packet_set_protocol_flags(child_state.ssh1protoflags);
176898675Sdes		packet_set_encryption_key(child_state.ssh1key,
176998675Sdes		    child_state.ssh1keylen, child_state.ssh1cipher);
1770255767Sdes		free(child_state.ssh1key);
177198675Sdes	}
177298675Sdes
177398675Sdes	/* for rc4 and other stateful ciphers */
177498675Sdes	packet_set_keycontext(MODE_OUT, child_state.keyout);
1775255767Sdes	free(child_state.keyout);
177698675Sdes	packet_set_keycontext(MODE_IN, child_state.keyin);
1777255767Sdes	free(child_state.keyin);
177898675Sdes
177998675Sdes	if (!compat20) {
178098675Sdes		packet_set_iv(MODE_OUT, child_state.ivout);
1781255767Sdes		free(child_state.ivout);
178298675Sdes		packet_set_iv(MODE_IN, child_state.ivin);
1783255767Sdes		free(child_state.ivin);
178498675Sdes	}
178598675Sdes
178698675Sdes	memcpy(&incoming_stream, &child_state.incoming,
178798675Sdes	    sizeof(incoming_stream));
178898675Sdes	memcpy(&outgoing_stream, &child_state.outgoing,
178998675Sdes	    sizeof(outgoing_stream));
179098675Sdes
179198675Sdes	/* Update with new address */
179298675Sdes	if (options.compression)
179398675Sdes		mm_init_compression(pmonitor->m_zlib);
179498675Sdes
1795255767Sdes	if (options.rekey_limit || options.rekey_interval)
1796255767Sdes		packet_set_rekey_limits((u_int32_t)options.rekey_limit,
1797255767Sdes		    (time_t)options.rekey_interval);
1798255767Sdes
179998675Sdes	/* Network I/O buffers */
180098675Sdes	/* XXX inefficient for large buffers, need: buffer_init_from_string */
1801197679Sdes	buffer_clear(packet_get_input());
1802197679Sdes	buffer_append(packet_get_input(), child_state.input, child_state.ilen);
1803264377Sdes	explicit_bzero(child_state.input, child_state.ilen);
1804255767Sdes	free(child_state.input);
180598675Sdes
1806197679Sdes	buffer_clear(packet_get_output());
1807197679Sdes	buffer_append(packet_get_output(), child_state.output,
1808197679Sdes		      child_state.olen);
1809264377Sdes	explicit_bzero(child_state.output, child_state.olen);
1810255767Sdes	free(child_state.output);
1811197679Sdes
1812197679Sdes	/* Roaming */
1813197679Sdes	if (compat20)
1814197679Sdes		roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes);
181598675Sdes}
181698675Sdes
181798675Sdesstatic Kex *
181898675Sdesmm_get_kex(Buffer *m)
181998675Sdes{
182098675Sdes	Kex *kex;
182198675Sdes	void *blob;
182298675Sdes	u_int bloblen;
182398675Sdes
1824162856Sdes	kex = xcalloc(1, sizeof(*kex));
182598675Sdes	kex->session_id = buffer_get_string(m, &kex->session_id_len);
1826215116Sdes	if (session_id2 == NULL ||
1827215116Sdes	    kex->session_id_len != session_id2_len ||
1828215116Sdes	    timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
182998675Sdes		fatal("mm_get_get: internal error: bad session id");
183098675Sdes	kex->we_need = buffer_get_int(m);
1831113911Sdes	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
1832137019Sdes	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
1833113911Sdes	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1834162856Sdes	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1835221420Sdes	kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
1836262566Sdes	kex->kex[KEX_C25519_SHA256] = kexc25519_server;
183798675Sdes	kex->server = 1;
183898675Sdes	kex->hostkey_type = buffer_get_int(m);
183998675Sdes	kex->kex_type = buffer_get_int(m);
184098675Sdes	blob = buffer_get_string(m, &bloblen);
184198675Sdes	buffer_init(&kex->my);
184298675Sdes	buffer_append(&kex->my, blob, bloblen);
1843255767Sdes	free(blob);
184498675Sdes	blob = buffer_get_string(m, &bloblen);
184598675Sdes	buffer_init(&kex->peer);
184698675Sdes	buffer_append(&kex->peer, blob, bloblen);
1847255767Sdes	free(blob);
184898675Sdes	kex->done = 1;
184998675Sdes	kex->flags = buffer_get_int(m);
185098675Sdes	kex->client_version_string = buffer_get_string(m, NULL);
185198675Sdes	kex->server_version_string = buffer_get_string(m, NULL);
1852204917Sdes	kex->load_host_public_key=&get_hostkey_public_by_type;
1853204917Sdes	kex->load_host_private_key=&get_hostkey_private_by_type;
185498675Sdes	kex->host_key_index=&get_hostkey_index;
1855255767Sdes	kex->sign = sshd_hostkey_sign;
185698675Sdes
185798675Sdes	return (kex);
185898675Sdes}
185998675Sdes
186098675Sdes/* This function requries careful sanity checking */
186198675Sdes
186298675Sdesvoid
186398675Sdesmm_get_keystate(struct monitor *pmonitor)
186498675Sdes{
186598675Sdes	Buffer m;
186698675Sdes	u_char *blob, *p;
186798675Sdes	u_int bloblen, plen;
1868124211Sdes	u_int32_t seqnr, packets;
1869181111Sdes	u_int64_t blocks, bytes;
187098675Sdes
187198675Sdes	debug3("%s: Waiting for new keys", __func__);
187298675Sdes
187398675Sdes	buffer_init(&m);
187498675Sdes	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
187598675Sdes	if (!compat20) {
187698675Sdes		child_state.ssh1protoflags = buffer_get_int(&m);
187798675Sdes		child_state.ssh1cipher = buffer_get_int(&m);
187898675Sdes		child_state.ssh1key = buffer_get_string(&m,
187998675Sdes		    &child_state.ssh1keylen);
188098675Sdes		child_state.ivout = buffer_get_string(&m,
188198675Sdes		    &child_state.ivoutlen);
188298675Sdes		child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
188398675Sdes		goto skip;
188498675Sdes	} else {
188598675Sdes		/* Get the Kex for rekeying */
188698675Sdes		*pmonitor->m_pkex = mm_get_kex(&m);
188798675Sdes	}
188898675Sdes
188998675Sdes	blob = buffer_get_string(&m, &bloblen);
189098675Sdes	current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
1891255767Sdes	free(blob);
189298675Sdes
189398675Sdes	debug3("%s: Waiting for second key", __func__);
189498675Sdes	blob = buffer_get_string(&m, &bloblen);
189598675Sdes	current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
1896255767Sdes	free(blob);
189798675Sdes
189898675Sdes	/* Now get sequence numbers for the packets */
1899124211Sdes	seqnr = buffer_get_int(&m);
1900124211Sdes	blocks = buffer_get_int64(&m);
1901124211Sdes	packets = buffer_get_int(&m);
1902181111Sdes	bytes = buffer_get_int64(&m);
1903181111Sdes	packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
1904124211Sdes	seqnr = buffer_get_int(&m);
1905124211Sdes	blocks = buffer_get_int64(&m);
1906124211Sdes	packets = buffer_get_int(&m);
1907181111Sdes	bytes = buffer_get_int64(&m);
1908181111Sdes	packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);
190998675Sdes
191098675Sdes skip:
191198675Sdes	/* Get the key context */
191298675Sdes	child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
191398675Sdes	child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
191498675Sdes
191598675Sdes	debug3("%s: Getting compression state", __func__);
191698675Sdes	/* Get compression state */
191798675Sdes	p = buffer_get_string(&m, &plen);
191898675Sdes	if (plen != sizeof(child_state.outgoing))
191998675Sdes		fatal("%s: bad request size", __func__);
192098675Sdes	memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
1921255767Sdes	free(p);
192298675Sdes
192398675Sdes	p = buffer_get_string(&m, &plen);
192498675Sdes	if (plen != sizeof(child_state.incoming))
192598675Sdes		fatal("%s: bad request size", __func__);
192698675Sdes	memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
1927255767Sdes	free(p);
192898675Sdes
192998675Sdes	/* Network I/O buffers */
193098675Sdes	debug3("%s: Getting Network I/O buffers", __func__);
193198675Sdes	child_state.input = buffer_get_string(&m, &child_state.ilen);
193298675Sdes	child_state.output = buffer_get_string(&m, &child_state.olen);
193398675Sdes
1934197679Sdes	/* Roaming */
1935197679Sdes	if (compat20) {
1936197679Sdes		child_state.sent_bytes = buffer_get_int64(&m);
1937197679Sdes		child_state.recv_bytes = buffer_get_int64(&m);
1938197679Sdes	}
1939197679Sdes
194098675Sdes	buffer_free(&m);
194198675Sdes}
194298675Sdes
194398675Sdes
194498675Sdes/* Allocation functions for zlib */
194598675Sdesvoid *
194698675Sdesmm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
194798675Sdes{
1948113911Sdes	size_t len = (size_t) size * ncount;
194998675Sdes	void *address;
195098675Sdes
1951106130Sdes	if (len == 0 || ncount > SIZE_T_MAX / size)
195299063Sdes		fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
195398675Sdes
195499063Sdes	address = mm_malloc(mm, len);
195599063Sdes
195698675Sdes	return (address);
195798675Sdes}
195898675Sdes
195998675Sdesvoid
196098675Sdesmm_zfree(struct mm_master *mm, void *address)
196198675Sdes{
196298675Sdes	mm_free(mm, address);
196398675Sdes}
196498675Sdes
196598675Sdesvoid
196698675Sdesmm_init_compression(struct mm_master *mm)
196798675Sdes{
196898675Sdes	outgoing_stream.zalloc = (alloc_func)mm_zalloc;
196998675Sdes	outgoing_stream.zfree = (free_func)mm_zfree;
197098675Sdes	outgoing_stream.opaque = mm;
197198675Sdes
197298675Sdes	incoming_stream.zalloc = (alloc_func)mm_zalloc;
197398675Sdes	incoming_stream.zfree = (free_func)mm_zfree;
197498675Sdes	incoming_stream.opaque = mm;
197598675Sdes}
197698675Sdes
197798675Sdes/* XXX */
197898675Sdes
197998675Sdes#define FD_CLOSEONEXEC(x) do { \
1980226046Sdes	if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
198198675Sdes		fatal("fcntl(%d, F_SETFD)", x); \
198298675Sdes} while (0)
198398675Sdes
198498675Sdesstatic void
1985226046Sdesmonitor_openfds(struct monitor *mon, int do_logfds)
198698675Sdes{
1987226046Sdes	int pair[2];
1988226046Sdes
198998675Sdes	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1990226046Sdes		fatal("%s: socketpair: %s", __func__, strerror(errno));
199198675Sdes	FD_CLOSEONEXEC(pair[0]);
199298675Sdes	FD_CLOSEONEXEC(pair[1]);
1993226046Sdes	mon->m_recvfd = pair[0];
1994226046Sdes	mon->m_sendfd = pair[1];
1995226046Sdes
1996226046Sdes	if (do_logfds) {
1997226046Sdes		if (pipe(pair) == -1)
1998226046Sdes			fatal("%s: pipe: %s", __func__, strerror(errno));
1999226046Sdes		FD_CLOSEONEXEC(pair[0]);
2000226046Sdes		FD_CLOSEONEXEC(pair[1]);
2001226046Sdes		mon->m_log_recvfd = pair[0];
2002226046Sdes		mon->m_log_sendfd = pair[1];
2003226046Sdes	} else
2004226046Sdes		mon->m_log_recvfd = mon->m_log_sendfd = -1;
200598675Sdes}
200698675Sdes
200798675Sdes#define MM_MEMSIZE	65536
200898675Sdes
200998675Sdesstruct monitor *
201098675Sdesmonitor_init(void)
201198675Sdes{
201298675Sdes	struct monitor *mon;
201398675Sdes
2014162856Sdes	mon = xcalloc(1, sizeof(*mon));
201598675Sdes
2016226046Sdes	monitor_openfds(mon, 1);
201798675Sdes
201898675Sdes	/* Used to share zlib space across processes */
201998675Sdes	if (options.compression) {
202098675Sdes		mon->m_zback = mm_create(NULL, MM_MEMSIZE);
202198675Sdes		mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
202298675Sdes
202398675Sdes		/* Compression needs to share state across borders */
202498675Sdes		mm_init_compression(mon->m_zlib);
202598675Sdes	}
202698675Sdes
202798675Sdes	return mon;
202898675Sdes}
202998675Sdes
203098675Sdesvoid
203198675Sdesmonitor_reinit(struct monitor *mon)
203298675Sdes{
2033226046Sdes	monitor_openfds(mon, 0);
203498675Sdes}
2035124211Sdes
2036124211Sdes#ifdef GSSAPI
2037124211Sdesint
2038137019Sdesmm_answer_gss_setup_ctx(int sock, Buffer *m)
2039124211Sdes{
2040137019Sdes	gss_OID_desc goid;
2041124211Sdes	OM_uint32 major;
2042124211Sdes	u_int len;
2043124211Sdes
2044137019Sdes	goid.elements = buffer_get_string(m, &len);
2045137019Sdes	goid.length = len;
2046124211Sdes
2047137019Sdes	major = ssh_gssapi_server_ctx(&gsscontext, &goid);
2048124211Sdes
2049255767Sdes	free(goid.elements);
2050124211Sdes
2051124211Sdes	buffer_clear(m);
2052124211Sdes	buffer_put_int(m, major);
2053124211Sdes
2054157019Sdes	mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
2055124211Sdes
2056124211Sdes	/* Now we have a context, enable the step */
2057124211Sdes	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
2058124211Sdes
2059124211Sdes	return (0);
2060124211Sdes}
2061124211Sdes
2062124211Sdesint
2063137019Sdesmm_answer_gss_accept_ctx(int sock, Buffer *m)
2064124211Sdes{
2065124211Sdes	gss_buffer_desc in;
2066124211Sdes	gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
2067157019Sdes	OM_uint32 major, minor;
2068124211Sdes	OM_uint32 flags = 0; /* GSI needs this */
2069124211Sdes	u_int len;
2070124211Sdes
2071124211Sdes	in.value = buffer_get_string(m, &len);
2072124211Sdes	in.length = len;
2073124211Sdes	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
2074255767Sdes	free(in.value);
2075124211Sdes
2076124211Sdes	buffer_clear(m);
2077124211Sdes	buffer_put_int(m, major);
2078124211Sdes	buffer_put_string(m, out.value, out.length);
2079124211Sdes	buffer_put_int(m, flags);
2080137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
2081124211Sdes
2082124211Sdes	gss_release_buffer(&minor, &out);
2083124211Sdes
2084157019Sdes	if (major == GSS_S_COMPLETE) {
2085124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
2086124211Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2087126277Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
2088124211Sdes	}
2089124211Sdes	return (0);
2090124211Sdes}
2091124211Sdes
2092124211Sdesint
2093137019Sdesmm_answer_gss_checkmic(int sock, Buffer *m)
2094126277Sdes{
2095126277Sdes	gss_buffer_desc gssbuf, mic;
2096126277Sdes	OM_uint32 ret;
2097126277Sdes	u_int len;
2098126277Sdes
2099126277Sdes	gssbuf.value = buffer_get_string(m, &len);
2100126277Sdes	gssbuf.length = len;
2101126277Sdes	mic.value = buffer_get_string(m, &len);
2102126277Sdes	mic.length = len;
2103126277Sdes
2104126277Sdes	ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
2105126277Sdes
2106255767Sdes	free(gssbuf.value);
2107255767Sdes	free(mic.value);
2108126277Sdes
2109126277Sdes	buffer_clear(m);
2110126277Sdes	buffer_put_int(m, ret);
2111126277Sdes
2112137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
2113126277Sdes
2114126277Sdes	if (!GSS_ERROR(ret))
2115126277Sdes		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2116126277Sdes
2117126277Sdes	return (0);
2118126277Sdes}
2119126277Sdes
2120126277Sdesint
2121137019Sdesmm_answer_gss_userok(int sock, Buffer *m)
2122124211Sdes{
2123124211Sdes	int authenticated;
2124124211Sdes
2125124211Sdes	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
2126124211Sdes
2127124211Sdes	buffer_clear(m);
2128124211Sdes	buffer_put_int(m, authenticated);
2129124211Sdes
2130124211Sdes	debug3("%s: sending result %d", __func__, authenticated);
2131137019Sdes	mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
2132124211Sdes
2133157019Sdes	auth_method = "gssapi-with-mic";
2134124211Sdes
2135124211Sdes	/* Monitor loop will terminate if authenticated */
2136124211Sdes	return (authenticated);
2137124211Sdes}
2138124211Sdes#endif /* GSSAPI */
2139192595Sdes
2140