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