1323124Sdes/* $OpenBSD: monitor.c,v 1.161 2016/07/22 03:39:13 djm Exp $ */ 298675Sdes/* 398675Sdes * Copyright 2002 Niels Provos <provos@citi.umich.edu> 498675Sdes * Copyright 2002 Markus Friedl <markus@openbsd.org> 598675Sdes * All rights reserved. 698675Sdes * 798675Sdes * Redistribution and use in source and binary forms, with or without 898675Sdes * modification, are permitted provided that the following conditions 998675Sdes * are met: 1098675Sdes * 1. Redistributions of source code must retain the above copyright 1198675Sdes * notice, this list of conditions and the following disclaimer. 1298675Sdes * 2. Redistributions in binary form must reproduce the above copyright 1398675Sdes * notice, this list of conditions and the following disclaimer in the 1498675Sdes * documentation and/or other materials provided with the distribution. 1598675Sdes * 1698675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1798675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1898675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1998675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2098675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2198675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2298675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2398675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2498675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2598675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2698675Sdes */ 2798675Sdes 2898675Sdes#include "includes.h" 2998675Sdes 30162856Sdes#include <sys/types.h> 31162856Sdes#include <sys/socket.h> 32162856Sdes#include "openbsd-compat/sys-tree.h" 33162856Sdes#include <sys/wait.h> 3498675Sdes 35162856Sdes#include <errno.h> 36162856Sdes#include <fcntl.h> 37323124Sdes#include <limits.h> 38162856Sdes#ifdef HAVE_PATHS_H 39162856Sdes#include <paths.h> 40162856Sdes#endif 41162856Sdes#include <pwd.h> 42162856Sdes#include <signal.h> 43295367Sdes#ifdef HAVE_STDINT_H 44295367Sdes#include <stdint.h> 45295367Sdes#endif 46162856Sdes#include <stdlib.h> 47162856Sdes#include <string.h> 48295367Sdes#include <stdarg.h> 49295367Sdes#include <stdio.h> 50162856Sdes#include <unistd.h> 51226046Sdes#ifdef HAVE_POLL_H 52226046Sdes#include <poll.h> 53226046Sdes#else 54226046Sdes# ifdef HAVE_SYS_POLL_H 55226046Sdes# include <sys/poll.h> 56226046Sdes# endif 57226046Sdes#endif 58162856Sdes 5998675Sdes#ifdef SKEY 6098941Sdes#include <skey.h> 6198675Sdes#endif 6298675Sdes 63295367Sdes#ifdef WITH_OPENSSL 64162856Sdes#include <openssl/dh.h> 65295367Sdes#endif 66162856Sdes 67181111Sdes#include "openbsd-compat/sys-queue.h" 68226046Sdes#include "atomicio.h" 69162856Sdes#include "xmalloc.h" 7098675Sdes#include "ssh.h" 71162856Sdes#include "key.h" 72162856Sdes#include "buffer.h" 73162856Sdes#include "hostfile.h" 7498675Sdes#include "auth.h" 75162856Sdes#include "cipher.h" 7698675Sdes#include "kex.h" 7798675Sdes#include "dh.h" 78323124Sdes#include "auth-pam.h" 79128460Sdes#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */ 80128460Sdes#undef TARGET_OS_MAC 8198675Sdes#include "zlib.h" 82128460Sdes#define TARGET_OS_MAC 1 83128460Sdes#else 84128460Sdes#include "zlib.h" 85128460Sdes#endif 8698675Sdes#include "packet.h" 8798675Sdes#include "auth-options.h" 8898675Sdes#include "sshpty.h" 8998675Sdes#include "channels.h" 9098675Sdes#include "session.h" 9198675Sdes#include "sshlogin.h" 9298675Sdes#include "canohost.h" 9398675Sdes#include "log.h" 94295367Sdes#include "misc.h" 9598675Sdes#include "servconf.h" 9698675Sdes#include "monitor.h" 9798675Sdes#include "monitor_mm.h" 98162856Sdes#ifdef GSSAPI 99162856Sdes#include "ssh-gss.h" 100162856Sdes#endif 10198675Sdes#include "monitor_wrap.h" 10298675Sdes#include "monitor_fdpass.h" 10398675Sdes#include "compat.h" 10498675Sdes#include "ssh2.h" 105255767Sdes#include "authfd.h" 106295367Sdes#include "match.h" 107295367Sdes#include "ssherr.h" 10898675Sdes 109124211Sdes#ifdef GSSAPI 110124211Sdesstatic Gssctxt *gsscontext = NULL; 111124211Sdes#endif 112124211Sdes 11398675Sdes/* Imports */ 11498675Sdesextern ServerOptions options; 11598675Sdesextern u_int utmp_len; 11698675Sdesextern u_char session_id[]; 11798675Sdesextern Buffer auth_debug; 11898675Sdesextern int auth_debug_init; 119137019Sdesextern Buffer loginmsg; 12098675Sdes 12198675Sdes/* State exported from the child */ 122295367Sdesstatic struct sshbuf *child_state; 12398675Sdes 124124211Sdes/* Functions on the monitor that answer unprivileged requests */ 12598675Sdes 12698675Sdesint mm_answer_moduli(int, Buffer *); 12798675Sdesint mm_answer_sign(int, Buffer *); 12898675Sdesint mm_answer_pwnamallow(int, Buffer *); 12998675Sdesint mm_answer_auth2_read_banner(int, Buffer *); 13098675Sdesint mm_answer_authserv(int, Buffer *); 13198675Sdesint mm_answer_authpassword(int, Buffer *); 13298675Sdesint mm_answer_bsdauthquery(int, Buffer *); 13398675Sdesint mm_answer_bsdauthrespond(int, Buffer *); 13498675Sdesint mm_answer_skeyquery(int, Buffer *); 13598675Sdesint mm_answer_skeyrespond(int, Buffer *); 13698675Sdesint mm_answer_keyallowed(int, Buffer *); 13798675Sdesint mm_answer_keyverify(int, Buffer *); 13898675Sdesint mm_answer_pty(int, Buffer *); 13998675Sdesint mm_answer_pty_cleanup(int, Buffer *); 14098675Sdesint mm_answer_term(int, Buffer *); 14198675Sdesint mm_answer_rsa_keyallowed(int, Buffer *); 14298675Sdesint mm_answer_rsa_challenge(int, Buffer *); 14398675Sdesint mm_answer_rsa_response(int, Buffer *); 14498675Sdesint mm_answer_sesskey(int, Buffer *); 14598675Sdesint mm_answer_sessid(int, Buffer *); 14698675Sdes 14798941Sdes#ifdef USE_PAM 14898941Sdesint mm_answer_pam_start(int, Buffer *); 149124211Sdesint mm_answer_pam_account(int, Buffer *); 15099052Sdesint mm_answer_pam_init_ctx(int, Buffer *); 15199052Sdesint mm_answer_pam_query(int, Buffer *); 15299052Sdesint mm_answer_pam_respond(int, Buffer *); 15399052Sdesint mm_answer_pam_free_ctx(int, Buffer *); 15498941Sdes#endif 15598941Sdes 156124211Sdes#ifdef GSSAPI 157124211Sdesint mm_answer_gss_setup_ctx(int, Buffer *); 158124211Sdesint mm_answer_gss_accept_ctx(int, Buffer *); 159124211Sdesint mm_answer_gss_userok(int, Buffer *); 160126277Sdesint mm_answer_gss_checkmic(int, Buffer *); 161106130Sdes#endif 162106130Sdes 163147005Sdes#ifdef SSH_AUDIT_EVENTS 164147005Sdesint mm_answer_audit_event(int, Buffer *); 165147005Sdesint mm_answer_audit_command(int, Buffer *); 166147005Sdes#endif 167147005Sdes 168226046Sdesstatic int monitor_read_log(struct monitor *); 169226046Sdes 17098675Sdesstatic Authctxt *authctxt; 171295367Sdes 172295367Sdes#ifdef WITH_SSH1 17398675Sdesstatic BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 174295367Sdes#endif 17598675Sdes 17698675Sdes/* local state for key verify */ 17798675Sdesstatic u_char *key_blob = NULL; 17898675Sdesstatic u_int key_bloblen = 0; 17998675Sdesstatic int key_blobtype = MM_NOKEY; 180106130Sdesstatic char *hostbased_cuser = NULL; 181106130Sdesstatic char *hostbased_chost = NULL; 18298675Sdesstatic char *auth_method = "unknown"; 183248619Sdesstatic char *auth_submethod = NULL; 184124211Sdesstatic u_int session_id2_len = 0; 18598675Sdesstatic u_char *session_id2 = NULL; 186124211Sdesstatic pid_t monitor_child_pid; 18798675Sdes 18898675Sdesstruct mon_table { 18998675Sdes enum monitor_reqtype type; 19098675Sdes int flags; 19198675Sdes int (*f)(int, Buffer *); 19298675Sdes}; 19398675Sdes 19498675Sdes#define MON_ISAUTH 0x0004 /* Required for Authentication */ 19598675Sdes#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ 19698675Sdes#define MON_ONCE 0x0010 /* Disable after calling */ 197162856Sdes#define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ 19898675Sdes 19998675Sdes#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) 20098675Sdes 20198675Sdes#define MON_PERMIT 0x1000 /* Request is permitted */ 20298675Sdes 20398675Sdesstruct mon_table mon_dispatch_proto20[] = { 204295367Sdes#ifdef WITH_OPENSSL 20598675Sdes {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 206295367Sdes#endif 20798675Sdes {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 20898675Sdes {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 20998675Sdes {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 21098675Sdes {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 21198675Sdes {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 21298941Sdes#ifdef USE_PAM 21398941Sdes {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 214124211Sdes {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 21599052Sdes {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 21699052Sdes {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 21799052Sdes {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 21899052Sdes {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 21998941Sdes#endif 220147005Sdes#ifdef SSH_AUDIT_EVENTS 221147005Sdes {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 222147005Sdes#endif 22398675Sdes#ifdef BSD_AUTH 22498675Sdes {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 225162856Sdes {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 22698675Sdes#endif 22798675Sdes#ifdef SKEY 22898675Sdes {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 22998675Sdes {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 23098675Sdes#endif 23198675Sdes {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, 23298675Sdes {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, 233124211Sdes#ifdef GSSAPI 234124211Sdes {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, 235124211Sdes {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, 236124211Sdes {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 237126277Sdes {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 238124211Sdes#endif 23998675Sdes {0, 0, NULL} 24098675Sdes}; 24198675Sdes 24298675Sdesstruct mon_table mon_dispatch_postauth20[] = { 243295367Sdes#ifdef WITH_OPENSSL 24498675Sdes {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 245295367Sdes#endif 24698675Sdes {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 24798675Sdes {MONITOR_REQ_PTY, 0, mm_answer_pty}, 24898675Sdes {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 24998675Sdes {MONITOR_REQ_TERM, 0, mm_answer_term}, 250147005Sdes#ifdef SSH_AUDIT_EVENTS 251147005Sdes {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 252147005Sdes {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 253147005Sdes#endif 25498675Sdes {0, 0, NULL} 25598675Sdes}; 25698675Sdes 25798675Sdesstruct mon_table mon_dispatch_proto15[] = { 258295367Sdes#ifdef WITH_SSH1 25998675Sdes {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 26098675Sdes {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, 26198675Sdes {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, 26298675Sdes {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 263162856Sdes {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, 264162856Sdes {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, 26598675Sdes {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, 26698675Sdes {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, 26798675Sdes#ifdef BSD_AUTH 26898675Sdes {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 269162856Sdes {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 27098675Sdes#endif 27198675Sdes#ifdef SKEY 27298675Sdes {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 27398675Sdes {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 27498675Sdes#endif 27599063Sdes#ifdef USE_PAM 27699063Sdes {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 277124211Sdes {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 27899063Sdes {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 27999063Sdes {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 28099063Sdes {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 28199063Sdes {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 28299063Sdes#endif 283147005Sdes#ifdef SSH_AUDIT_EVENTS 284147005Sdes {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 285147005Sdes#endif 286295367Sdes#endif /* WITH_SSH1 */ 28798675Sdes {0, 0, NULL} 28898675Sdes}; 28998675Sdes 29098675Sdesstruct mon_table mon_dispatch_postauth15[] = { 291295367Sdes#ifdef WITH_SSH1 29298675Sdes {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, 29398675Sdes {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, 29498675Sdes {MONITOR_REQ_TERM, 0, mm_answer_term}, 295147005Sdes#ifdef SSH_AUDIT_EVENTS 296147005Sdes {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 297162360Sdes {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, 298147005Sdes#endif 299295367Sdes#endif /* WITH_SSH1 */ 30098675Sdes {0, 0, NULL} 30198675Sdes}; 30298675Sdes 30398675Sdesstruct mon_table *mon_dispatch; 30498675Sdes 30598675Sdes/* Specifies if a certain message is allowed at the moment */ 30698675Sdes 30798675Sdesstatic void 30898675Sdesmonitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) 30998675Sdes{ 31098675Sdes while (ent->f != NULL) { 31198675Sdes if (ent->type == type) { 31298675Sdes ent->flags &= ~MON_PERMIT; 31398675Sdes ent->flags |= permit ? MON_PERMIT : 0; 31498675Sdes return; 31598675Sdes } 31698675Sdes ent++; 31798675Sdes } 31898675Sdes} 31998675Sdes 32098675Sdesstatic void 32198675Sdesmonitor_permit_authentications(int permit) 32298675Sdes{ 32398675Sdes struct mon_table *ent = mon_dispatch; 32498675Sdes 32598675Sdes while (ent->f != NULL) { 32698675Sdes if (ent->flags & MON_AUTH) { 32798675Sdes ent->flags &= ~MON_PERMIT; 32898675Sdes ent->flags |= permit ? MON_PERMIT : 0; 32998675Sdes } 33098675Sdes ent++; 33198675Sdes } 33298675Sdes} 33398675Sdes 334126277Sdesvoid 335126277Sdesmonitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 33698675Sdes{ 33798675Sdes struct mon_table *ent; 338248619Sdes int authenticated = 0, partial = 0; 33998675Sdes 34098675Sdes debug3("preauth child monitor started"); 34198675Sdes 342226046Sdes close(pmonitor->m_recvfd); 343226046Sdes close(pmonitor->m_log_sendfd); 344226046Sdes pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; 345226046Sdes 346126277Sdes authctxt = _authctxt; 347126277Sdes memset(authctxt, 0, sizeof(*authctxt)); 348126277Sdes 349147005Sdes authctxt->loginmsg = &loginmsg; 350147005Sdes 35198675Sdes if (compat20) { 35298675Sdes mon_dispatch = mon_dispatch_proto20; 35398675Sdes 35498675Sdes /* Permit requests for moduli and signatures */ 35598675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 35698675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 35798675Sdes } else { 35898675Sdes mon_dispatch = mon_dispatch_proto15; 35998675Sdes 36098675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); 36198675Sdes } 36298675Sdes 36398675Sdes /* The first few requests do not require asynchronous access */ 36498675Sdes while (!authenticated) { 365248619Sdes partial = 0; 366162856Sdes auth_method = "unknown"; 367248619Sdes auth_submethod = NULL; 368164149Sdes authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); 369248619Sdes 370248619Sdes /* Special handling for multiple required authentications */ 371248619Sdes if (options.num_auth_methods != 0) { 372248619Sdes if (!compat20) 373248619Sdes fatal("AuthenticationMethods is not supported" 374248619Sdes "with SSH protocol 1"); 375248619Sdes if (authenticated && 376248619Sdes !auth2_update_methods_lists(authctxt, 377255767Sdes auth_method, auth_submethod)) { 378248619Sdes debug3("%s: method %s: partial", __func__, 379248619Sdes auth_method); 380248619Sdes authenticated = 0; 381248619Sdes partial = 1; 382248619Sdes } 383248619Sdes } 384248619Sdes 38598675Sdes if (authenticated) { 38698675Sdes if (!(ent->flags & MON_AUTHDECIDE)) 38798675Sdes fatal("%s: unexpected authentication from %d", 38898675Sdes __func__, ent->type); 38998675Sdes if (authctxt->pw->pw_uid == 0 && 39098675Sdes !auth_root_allowed(auth_method)) 39198675Sdes authenticated = 0; 392124211Sdes#ifdef USE_PAM 393124211Sdes /* PAM needs to perform account checks after auth */ 394126277Sdes if (options.use_pam && authenticated) { 395124211Sdes Buffer m; 396124211Sdes 397124211Sdes buffer_init(&m); 398126277Sdes mm_request_receive_expect(pmonitor->m_sendfd, 399124211Sdes MONITOR_REQ_PAM_ACCOUNT, &m); 400124211Sdes authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m); 401124211Sdes buffer_free(&m); 402124211Sdes } 403124211Sdes#endif 40498675Sdes } 405162856Sdes if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { 406248619Sdes auth_log(authctxt, authenticated, partial, 407255767Sdes auth_method, auth_submethod); 408295367Sdes if (!partial && !authenticated) 40998675Sdes authctxt->failures++; 41098675Sdes } 41198675Sdes } 41298675Sdes 41398675Sdes if (!authctxt->valid) 41498675Sdes fatal("%s: authenticated invalid user", __func__); 415162856Sdes if (strcmp(auth_method, "unknown") == 0) 416162856Sdes fatal("%s: authentication method name unknown", __func__); 41798675Sdes 41898675Sdes debug("%s: %s has been authenticated by privileged process", 41998675Sdes __func__, authctxt->user); 42098675Sdes 42198675Sdes mm_get_keystate(pmonitor); 422226046Sdes 423248619Sdes /* Drain any buffered messages from the child */ 424248619Sdes while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) 425248619Sdes ; 426248619Sdes 427226046Sdes close(pmonitor->m_sendfd); 428226046Sdes close(pmonitor->m_log_recvfd); 429226046Sdes pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 43098675Sdes} 43198675Sdes 432124211Sdesstatic void 433124211Sdesmonitor_set_child_handler(pid_t pid) 434124211Sdes{ 435124211Sdes monitor_child_pid = pid; 436124211Sdes} 437124211Sdes 438124211Sdesstatic void 439137019Sdesmonitor_child_handler(int sig) 440124211Sdes{ 441137019Sdes kill(monitor_child_pid, sig); 442124211Sdes} 443124211Sdes 44498675Sdesvoid 44598675Sdesmonitor_child_postauth(struct monitor *pmonitor) 44698675Sdes{ 447226046Sdes close(pmonitor->m_recvfd); 448226046Sdes pmonitor->m_recvfd = -1; 449226046Sdes 450124211Sdes monitor_set_child_handler(pmonitor->m_pid); 451124211Sdes signal(SIGHUP, &monitor_child_handler); 452124211Sdes signal(SIGTERM, &monitor_child_handler); 453181111Sdes signal(SIGINT, &monitor_child_handler); 454295367Sdes#ifdef SIGXFSZ 455295367Sdes signal(SIGXFSZ, SIG_IGN); 456295367Sdes#endif 457124211Sdes 45898675Sdes if (compat20) { 45998675Sdes mon_dispatch = mon_dispatch_postauth20; 46098675Sdes 46198675Sdes /* Permit requests for moduli and signatures */ 46298675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 46398675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 46498675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 46598675Sdes } else { 46698675Sdes mon_dispatch = mon_dispatch_postauth15; 46798675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 46898675Sdes } 46998675Sdes if (!no_pty_flag) { 47098675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 47198675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 47298675Sdes } 47398675Sdes 47498675Sdes for (;;) 47598675Sdes monitor_read(pmonitor, mon_dispatch, NULL); 47698675Sdes} 47798675Sdes 47898675Sdesvoid 47998675Sdesmonitor_sync(struct monitor *pmonitor) 48098675Sdes{ 48198675Sdes if (options.compression) { 48298675Sdes /* The member allocation is not visible, so sync it */ 48398675Sdes mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); 48498675Sdes } 48598675Sdes} 48698675Sdes 487295367Sdes/* Allocation functions for zlib */ 488295367Sdesstatic void * 489295367Sdesmm_zalloc(struct mm_master *mm, u_int ncount, u_int size) 490295367Sdes{ 491296781Sdes if (size == 0 || ncount == 0 || ncount > SIZE_MAX / size) 492295367Sdes fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); 493295367Sdes 494296781Sdes return mm_malloc(mm, size * ncount); 495295367Sdes} 496295367Sdes 497295367Sdesstatic void 498295367Sdesmm_zfree(struct mm_master *mm, void *address) 499295367Sdes{ 500295367Sdes mm_free(mm, address); 501295367Sdes} 502295367Sdes 503226046Sdesstatic int 504226046Sdesmonitor_read_log(struct monitor *pmonitor) 505226046Sdes{ 506226046Sdes Buffer logmsg; 507226046Sdes u_int len, level; 508226046Sdes char *msg; 509226046Sdes 510226046Sdes buffer_init(&logmsg); 511226046Sdes 512226046Sdes /* Read length */ 513226046Sdes buffer_append_space(&logmsg, 4); 514226046Sdes if (atomicio(read, pmonitor->m_log_recvfd, 515226046Sdes buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) { 516226046Sdes if (errno == EPIPE) { 517240075Sdes buffer_free(&logmsg); 518226046Sdes debug("%s: child log fd closed", __func__); 519226046Sdes close(pmonitor->m_log_recvfd); 520226046Sdes pmonitor->m_log_recvfd = -1; 521226046Sdes return -1; 522226046Sdes } 523226046Sdes fatal("%s: log fd read: %s", __func__, strerror(errno)); 524226046Sdes } 525226046Sdes len = buffer_get_int(&logmsg); 526226046Sdes if (len <= 4 || len > 8192) 527226046Sdes fatal("%s: invalid log message length %u", __func__, len); 528226046Sdes 529226046Sdes /* Read severity, message */ 530226046Sdes buffer_clear(&logmsg); 531226046Sdes buffer_append_space(&logmsg, len); 532226046Sdes if (atomicio(read, pmonitor->m_log_recvfd, 533226046Sdes buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) 534226046Sdes fatal("%s: log fd read: %s", __func__, strerror(errno)); 535226046Sdes 536226046Sdes /* Log it */ 537226046Sdes level = buffer_get_int(&logmsg); 538226046Sdes msg = buffer_get_string(&logmsg, NULL); 539226046Sdes if (log_level_name(level) == NULL) 540226046Sdes fatal("%s: invalid log level %u (corrupted message?)", 541226046Sdes __func__, level); 542226046Sdes do_log2(level, "%s [preauth]", msg); 543226046Sdes 544226046Sdes buffer_free(&logmsg); 545255767Sdes free(msg); 546226046Sdes 547226046Sdes return 0; 548226046Sdes} 549226046Sdes 55098675Sdesint 55198675Sdesmonitor_read(struct monitor *pmonitor, struct mon_table *ent, 55298675Sdes struct mon_table **pent) 55398675Sdes{ 55498675Sdes Buffer m; 55598675Sdes int ret; 55698675Sdes u_char type; 557226046Sdes struct pollfd pfd[2]; 55898675Sdes 559226046Sdes for (;;) { 560264377Sdes memset(&pfd, 0, sizeof(pfd)); 561226046Sdes pfd[0].fd = pmonitor->m_sendfd; 562226046Sdes pfd[0].events = POLLIN; 563226046Sdes pfd[1].fd = pmonitor->m_log_recvfd; 564226046Sdes pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; 565226046Sdes if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { 566226046Sdes if (errno == EINTR || errno == EAGAIN) 567226046Sdes continue; 568226046Sdes fatal("%s: poll: %s", __func__, strerror(errno)); 569226046Sdes } 570226046Sdes if (pfd[1].revents) { 571226046Sdes /* 572226046Sdes * Drain all log messages before processing next 573226046Sdes * monitor request. 574226046Sdes */ 575226046Sdes monitor_read_log(pmonitor); 576226046Sdes continue; 577226046Sdes } 578226046Sdes if (pfd[0].revents) 579226046Sdes break; /* Continues below */ 580226046Sdes } 581226046Sdes 58298675Sdes buffer_init(&m); 58398675Sdes 58498675Sdes mm_request_receive(pmonitor->m_sendfd, &m); 58598675Sdes type = buffer_get_char(&m); 58698675Sdes 58798675Sdes debug3("%s: checking request %d", __func__, type); 58898675Sdes 58998675Sdes while (ent->f != NULL) { 59098675Sdes if (ent->type == type) 59198675Sdes break; 59298675Sdes ent++; 59398675Sdes } 59498675Sdes 59598675Sdes if (ent->f != NULL) { 59698675Sdes if (!(ent->flags & MON_PERMIT)) 59798675Sdes fatal("%s: unpermitted request %d", __func__, 59898675Sdes type); 59998675Sdes ret = (*ent->f)(pmonitor->m_sendfd, &m); 60098675Sdes buffer_free(&m); 60198675Sdes 60298675Sdes /* The child may use this request only once, disable it */ 60398675Sdes if (ent->flags & MON_ONCE) { 60498675Sdes debug2("%s: %d used once, disabling now", __func__, 60598675Sdes type); 60698675Sdes ent->flags &= ~MON_PERMIT; 60798675Sdes } 60898675Sdes 60998675Sdes if (pent != NULL) 61098675Sdes *pent = ent; 61198675Sdes 61298675Sdes return ret; 61398675Sdes } 61498675Sdes 61598675Sdes fatal("%s: unsupported request: %d", __func__, type); 61698675Sdes 61798675Sdes /* NOTREACHED */ 61898675Sdes return (-1); 61998675Sdes} 62098675Sdes 62198675Sdes/* allowed key state */ 62298675Sdesstatic int 62398675Sdesmonitor_allowed_key(u_char *blob, u_int bloblen) 62498675Sdes{ 62598675Sdes /* make sure key is allowed */ 62698675Sdes if (key_blob == NULL || key_bloblen != bloblen || 627215116Sdes timingsafe_bcmp(key_blob, blob, key_bloblen)) 62898675Sdes return (0); 62998675Sdes return (1); 63098675Sdes} 63198675Sdes 63298675Sdesstatic void 63398675Sdesmonitor_reset_key_state(void) 63498675Sdes{ 63598675Sdes /* reset state */ 636255767Sdes free(key_blob); 637255767Sdes free(hostbased_cuser); 638255767Sdes free(hostbased_chost); 63998675Sdes key_blob = NULL; 64098675Sdes key_bloblen = 0; 64198675Sdes key_blobtype = MM_NOKEY; 64298675Sdes hostbased_cuser = NULL; 64398675Sdes hostbased_chost = NULL; 64498675Sdes} 64598675Sdes 646295367Sdes#ifdef WITH_OPENSSL 64798675Sdesint 648137019Sdesmm_answer_moduli(int sock, Buffer *m) 64998675Sdes{ 65098675Sdes DH *dh; 65198675Sdes int min, want, max; 65298675Sdes 65398675Sdes min = buffer_get_int(m); 65498675Sdes want = buffer_get_int(m); 65598675Sdes max = buffer_get_int(m); 65698675Sdes 65798675Sdes debug3("%s: got parameters: %d %d %d", 65898675Sdes __func__, min, want, max); 65998675Sdes /* We need to check here, too, in case the child got corrupted */ 66098675Sdes if (max < min || want < min || max < want) 66198675Sdes fatal("%s: bad parameters: %d %d %d", 66298675Sdes __func__, min, want, max); 66398675Sdes 66498675Sdes buffer_clear(m); 66598675Sdes 66698675Sdes dh = choose_dh(min, want, max); 66798675Sdes if (dh == NULL) { 66898675Sdes buffer_put_char(m, 0); 66998675Sdes return (0); 67098675Sdes } else { 67198675Sdes /* Send first bignum */ 67298675Sdes buffer_put_char(m, 1); 67398675Sdes buffer_put_bignum2(m, dh->p); 67498675Sdes buffer_put_bignum2(m, dh->g); 67598675Sdes 67698675Sdes DH_free(dh); 67798675Sdes } 678137019Sdes mm_request_send(sock, MONITOR_ANS_MODULI, m); 67998675Sdes return (0); 68098675Sdes} 681295367Sdes#endif 68298675Sdes 68398675Sdesint 684137019Sdesmm_answer_sign(int sock, Buffer *m) 68598675Sdes{ 686295367Sdes struct ssh *ssh = active_state; /* XXX */ 687295367Sdes extern int auth_sock; /* XXX move to state struct? */ 688295367Sdes struct sshkey *key; 689296781Sdes struct sshbuf *sigbuf = NULL; 690296781Sdes u_char *p = NULL, *signature = NULL; 691296781Sdes char *alg = NULL; 692296781Sdes size_t datlen, siglen, alglen; 693323124Sdes int r, is_proof = 0; 694323124Sdes u_int keyid; 695295367Sdes const char proof_req[] = "hostkeys-prove-00@openssh.com"; 69698675Sdes 69798675Sdes debug3("%s", __func__); 69898675Sdes 699295367Sdes if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 700296781Sdes (r = sshbuf_get_string(m, &p, &datlen)) != 0 || 701296781Sdes (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0) 702295367Sdes fatal("%s: buffer error: %s", __func__, ssh_err(r)); 703323124Sdes if (keyid > INT_MAX) 704323124Sdes fatal("%s: invalid key ID", __func__); 70598675Sdes 706162856Sdes /* 707221420Sdes * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), 708221420Sdes * SHA384 (48 bytes) and SHA512 (64 bytes). 709295367Sdes * 710295367Sdes * Otherwise, verify the signature request is for a hostkey 711295367Sdes * proof. 712295367Sdes * 713295367Sdes * XXX perform similar check for KEX signature requests too? 714295367Sdes * it's not trivial, since what is signed is the hash, rather 715295367Sdes * than the full kex structure... 716162856Sdes */ 717295367Sdes if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { 718295367Sdes /* 719295367Sdes * Construct expected hostkey proof and compare it to what 720295367Sdes * the client sent us. 721295367Sdes */ 722295367Sdes if (session_id2_len == 0) /* hostkeys is never first */ 723295367Sdes fatal("%s: bad data length: %zu", __func__, datlen); 724295367Sdes if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) 725295367Sdes fatal("%s: no hostkey for index %d", __func__, keyid); 726295367Sdes if ((sigbuf = sshbuf_new()) == NULL) 727295367Sdes fatal("%s: sshbuf_new", __func__); 728295367Sdes if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || 729295367Sdes (r = sshbuf_put_string(sigbuf, session_id2, 730296781Sdes session_id2_len)) != 0 || 731295367Sdes (r = sshkey_puts(key, sigbuf)) != 0) 732295367Sdes fatal("%s: couldn't prepare private key " 733295367Sdes "proof buffer: %s", __func__, ssh_err(r)); 734295367Sdes if (datlen != sshbuf_len(sigbuf) || 735295367Sdes memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) 736295367Sdes fatal("%s: bad data length: %zu, hostkey proof len %zu", 737295367Sdes __func__, datlen, sshbuf_len(sigbuf)); 738295367Sdes sshbuf_free(sigbuf); 739295367Sdes is_proof = 1; 740295367Sdes } 74198675Sdes 74298675Sdes /* save session id, it will be passed on the first call */ 74398675Sdes if (session_id2_len == 0) { 74498675Sdes session_id2_len = datlen; 74598675Sdes session_id2 = xmalloc(session_id2_len); 74698675Sdes memcpy(session_id2, p, session_id2_len); 74798675Sdes } 74898675Sdes 749255767Sdes if ((key = get_hostkey_by_index(keyid)) != NULL) { 750296781Sdes if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, 751295367Sdes datafellows)) != 0) 752295367Sdes fatal("%s: sshkey_sign failed: %s", 753295367Sdes __func__, ssh_err(r)); 754295367Sdes } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 755295367Sdes auth_sock > 0) { 756295367Sdes if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 757296781Sdes p, datlen, alg, datafellows)) != 0) { 758295367Sdes fatal("%s: ssh_agent_sign failed: %s", 759295367Sdes __func__, ssh_err(r)); 760295367Sdes } 761255767Sdes } else 76298675Sdes fatal("%s: no hostkey from index %d", __func__, keyid); 76398675Sdes 764295367Sdes debug3("%s: %s signature %p(%zu)", __func__, 765295367Sdes is_proof ? "KEX" : "hostkey proof", signature, siglen); 76698675Sdes 767295367Sdes sshbuf_reset(m); 768295367Sdes if ((r = sshbuf_put_string(m, signature, siglen)) != 0) 769295367Sdes fatal("%s: buffer error: %s", __func__, ssh_err(r)); 77098675Sdes 771296781Sdes free(alg); 772255767Sdes free(p); 773255767Sdes free(signature); 77498675Sdes 775137019Sdes mm_request_send(sock, MONITOR_ANS_SIGN, m); 77698675Sdes 77798675Sdes /* Turn on permissions for getpwnam */ 77898675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 77998675Sdes 78098675Sdes return (0); 78198675Sdes} 78298675Sdes 78398675Sdes/* Retrieves the password entry and also checks if the user is permitted */ 78498675Sdes 78598675Sdesint 786137019Sdesmm_answer_pwnamallow(int sock, Buffer *m) 78798675Sdes{ 788137019Sdes char *username; 78998675Sdes struct passwd *pwent; 79098675Sdes int allowed = 0; 791226046Sdes u_int i; 79298675Sdes 79398675Sdes debug3("%s", __func__); 79498675Sdes 79598675Sdes if (authctxt->attempt++ != 0) 79698675Sdes fatal("%s: multiple attempts for getpwnam", __func__); 79798675Sdes 798137019Sdes username = buffer_get_string(m, NULL); 79998675Sdes 800137019Sdes pwent = getpwnamallow(username); 80198675Sdes 802137019Sdes authctxt->user = xstrdup(username); 803137019Sdes setproctitle("%s [priv]", pwent ? username : "unknown"); 804255767Sdes free(username); 80598675Sdes 80698675Sdes buffer_clear(m); 80798675Sdes 80898675Sdes if (pwent == NULL) { 80998675Sdes buffer_put_char(m, 0); 810126277Sdes authctxt->pw = fakepw(); 81198675Sdes goto out; 81298675Sdes } 81398675Sdes 81498675Sdes allowed = 1; 81598675Sdes authctxt->pw = pwent; 81698675Sdes authctxt->valid = 1; 81798675Sdes 81898675Sdes buffer_put_char(m, 1); 81998675Sdes buffer_put_string(m, pwent, sizeof(struct passwd)); 82098675Sdes buffer_put_cstring(m, pwent->pw_name); 82198675Sdes buffer_put_cstring(m, "*"); 822255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS 82398675Sdes buffer_put_cstring(m, pwent->pw_gecos); 824255767Sdes#endif 825255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS 82698675Sdes buffer_put_cstring(m, pwent->pw_class); 82798941Sdes#endif 82898675Sdes buffer_put_cstring(m, pwent->pw_dir); 82998675Sdes buffer_put_cstring(m, pwent->pw_shell); 83098675Sdes 83198675Sdes out: 832181111Sdes buffer_put_string(m, &options, sizeof(options)); 833226046Sdes 834226046Sdes#define M_CP_STROPT(x) do { \ 835226046Sdes if (options.x != NULL) \ 836226046Sdes buffer_put_cstring(m, options.x); \ 837226046Sdes } while (0) 838226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \ 839226046Sdes for (i = 0; i < options.nx; i++) \ 840226046Sdes buffer_put_cstring(m, options.x[i]); \ 841226046Sdes } while (0) 842226046Sdes /* See comment in servconf.h */ 843226046Sdes COPY_MATCH_STRING_OPTS(); 844226046Sdes#undef M_CP_STROPT 845226046Sdes#undef M_CP_STRARRAYOPT 846248619Sdes 847248619Sdes /* Create valid auth method lists */ 848248619Sdes if (compat20 && auth2_setup_methods_lists(authctxt) != 0) { 849248619Sdes /* 850248619Sdes * The monitor will continue long enough to let the child 851248619Sdes * run to it's packet_disconnect(), but it must not allow any 852248619Sdes * authentication to succeed. 853248619Sdes */ 854248619Sdes debug("%s: no valid authentication method lists", __func__); 855248619Sdes } 856248619Sdes 85798675Sdes debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); 858137019Sdes mm_request_send(sock, MONITOR_ANS_PWNAM, m); 85998675Sdes 86098675Sdes /* For SSHv1 allow authentication now */ 86198675Sdes if (!compat20) 86298675Sdes monitor_permit_authentications(1); 86398675Sdes else { 86498675Sdes /* Allow service/style information on the auth context */ 86598675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 86698675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 86798675Sdes } 86898941Sdes#ifdef USE_PAM 869124211Sdes if (options.use_pam) 870124211Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); 87198941Sdes#endif 87298675Sdes 87398675Sdes return (0); 87498675Sdes} 87598675Sdes 876137019Sdesint mm_answer_auth2_read_banner(int sock, Buffer *m) 87798675Sdes{ 87898675Sdes char *banner; 87998675Sdes 88098675Sdes buffer_clear(m); 88198675Sdes banner = auth2_read_banner(); 88298675Sdes buffer_put_cstring(m, banner != NULL ? banner : ""); 883137019Sdes mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); 884255767Sdes free(banner); 88598675Sdes 88698675Sdes return (0); 88798675Sdes} 88898675Sdes 88998675Sdesint 890137019Sdesmm_answer_authserv(int sock, Buffer *m) 89198675Sdes{ 89298675Sdes monitor_permit_authentications(1); 89398675Sdes 89498675Sdes authctxt->service = buffer_get_string(m, NULL); 89598675Sdes authctxt->style = buffer_get_string(m, NULL); 89698675Sdes debug3("%s: service=%s, style=%s", 89798675Sdes __func__, authctxt->service, authctxt->style); 89898675Sdes 89998675Sdes if (strlen(authctxt->style) == 0) { 900255767Sdes free(authctxt->style); 90198675Sdes authctxt->style = NULL; 90298675Sdes } 90398675Sdes 90498675Sdes return (0); 90598675Sdes} 90698675Sdes 90798675Sdesint 908137019Sdesmm_answer_authpassword(int sock, Buffer *m) 90998675Sdes{ 91098675Sdes static int call_count; 91198675Sdes char *passwd; 912106130Sdes int authenticated; 913106130Sdes u_int plen; 91498675Sdes 91598675Sdes passwd = buffer_get_string(m, &plen); 91698675Sdes /* Only authenticate if the context is valid */ 91798675Sdes authenticated = options.password_authentication && 918124211Sdes auth_password(authctxt, passwd); 919264377Sdes explicit_bzero(passwd, strlen(passwd)); 920255767Sdes free(passwd); 92198675Sdes 92298675Sdes buffer_clear(m); 92398675Sdes buffer_put_int(m, authenticated); 924323124Sdes#ifdef USE_PAM 925323124Sdes buffer_put_int(m, sshpam_get_maxtries_reached()); 926323124Sdes#endif 92798675Sdes 92898675Sdes debug3("%s: sending result %d", __func__, authenticated); 929137019Sdes mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); 93098675Sdes 93198675Sdes call_count++; 93298675Sdes if (plen == 0 && call_count == 1) 93398675Sdes auth_method = "none"; 93498675Sdes else 93598675Sdes auth_method = "password"; 93698675Sdes 93798675Sdes /* Causes monitor loop to terminate if authenticated */ 93898675Sdes return (authenticated); 93998675Sdes} 94098675Sdes 94198675Sdes#ifdef BSD_AUTH 94298675Sdesint 943137019Sdesmm_answer_bsdauthquery(int sock, Buffer *m) 94498675Sdes{ 94598675Sdes char *name, *infotxt; 94698675Sdes u_int numprompts; 94798675Sdes u_int *echo_on; 94898675Sdes char **prompts; 949113911Sdes u_int success; 95098675Sdes 951113911Sdes success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 952113911Sdes &prompts, &echo_on) < 0 ? 0 : 1; 95398675Sdes 95498675Sdes buffer_clear(m); 955113911Sdes buffer_put_int(m, success); 956113911Sdes if (success) 95798675Sdes buffer_put_cstring(m, prompts[0]); 95898675Sdes 959113911Sdes debug3("%s: sending challenge success: %u", __func__, success); 960137019Sdes mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); 96198675Sdes 962113911Sdes if (success) { 963255767Sdes free(name); 964255767Sdes free(infotxt); 965255767Sdes free(prompts); 966255767Sdes free(echo_on); 96798675Sdes } 96898675Sdes 96998675Sdes return (0); 97098675Sdes} 97198675Sdes 97298675Sdesint 973137019Sdesmm_answer_bsdauthrespond(int sock, Buffer *m) 97498675Sdes{ 97598675Sdes char *response; 97698675Sdes int authok; 97798675Sdes 978296781Sdes if (authctxt->as == NULL) 97998675Sdes fatal("%s: no bsd auth session", __func__); 98098675Sdes 98198675Sdes response = buffer_get_string(m, NULL); 98298675Sdes authok = options.challenge_response_authentication && 98398675Sdes auth_userresponse(authctxt->as, response, 0); 98498675Sdes authctxt->as = NULL; 98598675Sdes debug3("%s: <%s> = <%d>", __func__, response, authok); 986255767Sdes free(response); 98798675Sdes 98898675Sdes buffer_clear(m); 98998675Sdes buffer_put_int(m, authok); 99098675Sdes 99198675Sdes debug3("%s: sending authenticated: %d", __func__, authok); 992137019Sdes mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); 99398675Sdes 994255767Sdes if (compat20) { 995255767Sdes auth_method = "keyboard-interactive"; 996255767Sdes auth_submethod = "bsdauth"; 997255767Sdes } else 998248619Sdes auth_method = "bsdauth"; 99998675Sdes 100098675Sdes return (authok != 0); 100198675Sdes} 100298675Sdes#endif 100398675Sdes 100498675Sdes#ifdef SKEY 100598675Sdesint 1006137019Sdesmm_answer_skeyquery(int sock, Buffer *m) 100798675Sdes{ 100898941Sdes struct skey skey; 100998675Sdes char challenge[1024]; 1010113911Sdes u_int success; 101198675Sdes 1012128460Sdes success = _compat_skeychallenge(&skey, authctxt->user, challenge, 1013128460Sdes sizeof(challenge)) < 0 ? 0 : 1; 101498675Sdes 101598675Sdes buffer_clear(m); 1016113911Sdes buffer_put_int(m, success); 1017113911Sdes if (success) 101898675Sdes buffer_put_cstring(m, challenge); 101998675Sdes 1020113911Sdes debug3("%s: sending challenge success: %u", __func__, success); 1021137019Sdes mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m); 102298675Sdes 102398675Sdes return (0); 102498675Sdes} 102598675Sdes 102698675Sdesint 1027137019Sdesmm_answer_skeyrespond(int sock, Buffer *m) 102898675Sdes{ 102998675Sdes char *response; 103098675Sdes int authok; 103198675Sdes 103298675Sdes response = buffer_get_string(m, NULL); 103398675Sdes 103498675Sdes authok = (options.challenge_response_authentication && 103598675Sdes authctxt->valid && 103698941Sdes skey_haskey(authctxt->pw->pw_name) == 0 && 103798941Sdes skey_passcheck(authctxt->pw->pw_name, response) != -1); 103898675Sdes 1039255767Sdes free(response); 104098675Sdes 104198675Sdes buffer_clear(m); 104298675Sdes buffer_put_int(m, authok); 104398675Sdes 104498675Sdes debug3("%s: sending authenticated: %d", __func__, authok); 1045137019Sdes mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); 104698675Sdes 1047296781Sdes auth_method = "keyboard-interactive"; 1048296781Sdes auth_submethod = "skey"; 104998675Sdes 105098675Sdes return (authok != 0); 105198675Sdes} 105298675Sdes#endif 105398675Sdes 105498941Sdes#ifdef USE_PAM 105598941Sdesint 1056137019Sdesmm_answer_pam_start(int sock, Buffer *m) 105798941Sdes{ 1058124211Sdes if (!options.use_pam) 1059124211Sdes fatal("UsePAM not set, but ended up in %s anyway", __func__); 1060124211Sdes 1061128460Sdes start_pam(authctxt); 106298941Sdes 1063124211Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); 1064124211Sdes 106598941Sdes return (0); 106698941Sdes} 106799052Sdes 1068124211Sdesint 1069137019Sdesmm_answer_pam_account(int sock, Buffer *m) 1070124211Sdes{ 1071124211Sdes u_int ret; 1072126277Sdes 1073124211Sdes if (!options.use_pam) 1074124211Sdes fatal("UsePAM not set, but ended up in %s anyway", __func__); 107599052Sdes 1076124211Sdes ret = do_pam_account(); 1077124211Sdes 1078124211Sdes buffer_put_int(m, ret); 1079157019Sdes buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 1080124211Sdes 1081137019Sdes mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); 1082124211Sdes 1083124211Sdes return (ret); 1084124211Sdes} 1085124211Sdes 1086124211Sdesstatic void *sshpam_ctxt, *sshpam_authok; 1087124211Sdesextern KbdintDevice sshpam_device; 1088124211Sdes 108999052Sdesint 1090137019Sdesmm_answer_pam_init_ctx(int sock, Buffer *m) 109199052Sdes{ 109299052Sdes debug3("%s", __func__); 1093124211Sdes sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); 1094124211Sdes sshpam_authok = NULL; 109599052Sdes buffer_clear(m); 1096124211Sdes if (sshpam_ctxt != NULL) { 109799052Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 109899052Sdes buffer_put_int(m, 1); 109999052Sdes } else { 110099052Sdes buffer_put_int(m, 0); 110199052Sdes } 1102137019Sdes mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); 110399052Sdes return (0); 110499052Sdes} 110599052Sdes 110699052Sdesint 1107137019Sdesmm_answer_pam_query(int sock, Buffer *m) 110899052Sdes{ 1109215116Sdes char *name = NULL, *info = NULL, **prompts = NULL; 1110215116Sdes u_int i, num = 0, *echo_on = 0; 1111149753Sdes int ret; 111299052Sdes 111399052Sdes debug3("%s", __func__); 1114124211Sdes sshpam_authok = NULL; 1115124211Sdes ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on); 1116110138Sdes if (ret == 0 && num == 0) 1117124211Sdes sshpam_authok = sshpam_ctxt; 111899052Sdes if (num > 1 || name == NULL || info == NULL) 111999052Sdes ret = -1; 112099747Sdes buffer_clear(m); 112199052Sdes buffer_put_int(m, ret); 112299052Sdes buffer_put_cstring(m, name); 1123255767Sdes free(name); 112499052Sdes buffer_put_cstring(m, info); 1125255767Sdes free(info); 1126323124Sdes buffer_put_int(m, sshpam_get_maxtries_reached()); 112799052Sdes buffer_put_int(m, num); 112899052Sdes for (i = 0; i < num; ++i) { 112999052Sdes buffer_put_cstring(m, prompts[i]); 1130255767Sdes free(prompts[i]); 113199052Sdes buffer_put_int(m, echo_on[i]); 113299052Sdes } 1133255767Sdes free(prompts); 1134255767Sdes free(echo_on); 1135248619Sdes auth_method = "keyboard-interactive"; 1136248619Sdes auth_submethod = "pam"; 1137137019Sdes mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); 113899052Sdes return (0); 113999052Sdes} 114099052Sdes 114199052Sdesint 1142137019Sdesmm_answer_pam_respond(int sock, Buffer *m) 114399052Sdes{ 114499052Sdes char **resp; 1145149753Sdes u_int i, num; 1146149753Sdes int ret; 114799052Sdes 114899052Sdes debug3("%s", __func__); 1149124211Sdes sshpam_authok = NULL; 115099052Sdes num = buffer_get_int(m); 115199052Sdes if (num > 0) { 1152162856Sdes resp = xcalloc(num, sizeof(char *)); 115399052Sdes for (i = 0; i < num; ++i) 115499052Sdes resp[i] = buffer_get_string(m, NULL); 1155124211Sdes ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); 115699052Sdes for (i = 0; i < num; ++i) 1157255767Sdes free(resp[i]); 1158255767Sdes free(resp); 115999052Sdes } else { 1160124211Sdes ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); 116199052Sdes } 116299052Sdes buffer_clear(m); 116399052Sdes buffer_put_int(m, ret); 1164137019Sdes mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); 1165248619Sdes auth_method = "keyboard-interactive"; 1166248619Sdes auth_submethod = "pam"; 116799052Sdes if (ret == 0) 1168124211Sdes sshpam_authok = sshpam_ctxt; 116999258Sdes return (0); 117099052Sdes} 117199052Sdes 117299052Sdesint 1173137019Sdesmm_answer_pam_free_ctx(int sock, Buffer *m) 117499052Sdes{ 1175287144Sdelphij int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; 117699052Sdes 117799052Sdes debug3("%s", __func__); 1178124211Sdes (sshpam_device.free_ctx)(sshpam_ctxt); 1179287144Sdelphij sshpam_ctxt = sshpam_authok = NULL; 118099052Sdes buffer_clear(m); 1181137019Sdes mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); 1182248619Sdes auth_method = "keyboard-interactive"; 1183248619Sdes auth_submethod = "pam"; 1184287144Sdelphij return r; 118599052Sdes} 118698941Sdes#endif 118798941Sdes 118898675Sdesint 1189137019Sdesmm_answer_keyallowed(int sock, Buffer *m) 119098675Sdes{ 119198675Sdes Key *key; 1192106130Sdes char *cuser, *chost; 1193106130Sdes u_char *blob; 1194295367Sdes u_int bloblen, pubkey_auth_attempt; 119598675Sdes enum mm_keytype type = 0; 119698675Sdes int allowed = 0; 119798675Sdes 119898675Sdes debug3("%s entering", __func__); 119998675Sdes 120098675Sdes type = buffer_get_int(m); 120198675Sdes cuser = buffer_get_string(m, NULL); 120298675Sdes chost = buffer_get_string(m, NULL); 120398675Sdes blob = buffer_get_string(m, &bloblen); 1204295367Sdes pubkey_auth_attempt = buffer_get_int(m); 120598675Sdes 120698675Sdes key = key_from_blob(blob, bloblen); 120798675Sdes 120898675Sdes if ((compat20 && type == MM_RSAHOSTKEY) || 120998675Sdes (!compat20 && type != MM_RSAHOSTKEY)) 121098675Sdes fatal("%s: key type and protocol mismatch", __func__); 121198675Sdes 121298675Sdes debug3("%s: key_from_blob: %p", __func__, key); 121398675Sdes 1214126277Sdes if (key != NULL && authctxt->valid) { 1215295367Sdes /* These should not make it past the privsep child */ 1216295367Sdes if (key_type_plain(key->type) == KEY_RSA && 1217295367Sdes (datafellows & SSH_BUG_RSASIGMD5) != 0) 1218295367Sdes fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); 1219295367Sdes 1220147005Sdes switch (type) { 122198675Sdes case MM_USERKEY: 122298675Sdes allowed = options.pubkey_authentication && 1223295367Sdes !auth2_userkey_already_used(authctxt, key) && 1224295367Sdes match_pattern_list(sshkey_ssh_name(key), 1225295367Sdes options.pubkey_key_types, 0) == 1 && 1226295367Sdes user_key_allowed(authctxt->pw, key, 1227295367Sdes pubkey_auth_attempt); 1228255767Sdes pubkey_auth_info(authctxt, key, NULL); 1229162856Sdes auth_method = "publickey"; 1230295367Sdes if (options.pubkey_authentication && 1231295367Sdes (!pubkey_auth_attempt || allowed != 1)) 1232181111Sdes auth_clear_options(); 123398675Sdes break; 123498675Sdes case MM_HOSTKEY: 123598675Sdes allowed = options.hostbased_authentication && 1236295367Sdes match_pattern_list(sshkey_ssh_name(key), 1237295367Sdes options.hostbased_key_types, 0) == 1 && 123898675Sdes hostbased_key_allowed(authctxt->pw, 123998675Sdes cuser, chost, key); 1240255767Sdes pubkey_auth_info(authctxt, key, 1241255767Sdes "client user \"%.100s\", client host \"%.100s\"", 1242255767Sdes cuser, chost); 1243162856Sdes auth_method = "hostbased"; 124498675Sdes break; 1245295367Sdes#ifdef WITH_SSH1 124698675Sdes case MM_RSAHOSTKEY: 124798675Sdes key->type = KEY_RSA1; /* XXX */ 124898675Sdes allowed = options.rhosts_rsa_authentication && 124998675Sdes auth_rhosts_rsa_key_allowed(authctxt->pw, 125098675Sdes cuser, chost, key); 1251181111Sdes if (options.rhosts_rsa_authentication && allowed != 1) 1252181111Sdes auth_clear_options(); 1253162856Sdes auth_method = "rsa"; 125498675Sdes break; 1255295367Sdes#endif 125698675Sdes default: 125798675Sdes fatal("%s: unknown key type %d", __func__, type); 125898675Sdes break; 125998675Sdes } 1260113911Sdes } 1261323124Sdes 1262323124Sdes debug3("%s: key %p is %s", 1263323124Sdes __func__, key, allowed ? "allowed" : "not allowed"); 1264323124Sdes 1265113911Sdes if (key != NULL) 126698675Sdes key_free(key); 126798675Sdes 126898675Sdes /* clear temporarily storage (used by verify) */ 126998675Sdes monitor_reset_key_state(); 127098675Sdes 127198675Sdes if (allowed) { 127298675Sdes /* Save temporarily for comparison in verify */ 127398675Sdes key_blob = blob; 127498675Sdes key_bloblen = bloblen; 127598675Sdes key_blobtype = type; 127698675Sdes hostbased_cuser = cuser; 127798675Sdes hostbased_chost = chost; 1278162856Sdes } else { 1279162856Sdes /* Log failed attempt */ 1280255767Sdes auth_log(authctxt, 0, 0, auth_method, NULL); 1281255767Sdes free(blob); 1282255767Sdes free(cuser); 1283255767Sdes free(chost); 128498675Sdes } 128598675Sdes 128698675Sdes buffer_clear(m); 128798675Sdes buffer_put_int(m, allowed); 1288113911Sdes buffer_put_int(m, forced_command != NULL); 128998675Sdes 1290137019Sdes mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); 129198675Sdes 129298675Sdes if (type == MM_RSAHOSTKEY) 129398675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 129498675Sdes 129598675Sdes return (0); 129698675Sdes} 129798675Sdes 129898675Sdesstatic int 129998675Sdesmonitor_valid_userblob(u_char *data, u_int datalen) 130098675Sdes{ 130198675Sdes Buffer b; 1302323124Sdes u_char *p; 1303323124Sdes char *userstyle, *cp; 130498675Sdes u_int len; 130598675Sdes int fail = 0; 130698675Sdes 130798675Sdes buffer_init(&b); 130898675Sdes buffer_append(&b, data, datalen); 130998675Sdes 131098675Sdes if (datafellows & SSH_OLD_SESSIONID) { 131198675Sdes p = buffer_ptr(&b); 131298675Sdes len = buffer_len(&b); 131398675Sdes if ((session_id2 == NULL) || 131498675Sdes (len < session_id2_len) || 1315215116Sdes (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 131698675Sdes fail++; 131798675Sdes buffer_consume(&b, session_id2_len); 131898675Sdes } else { 131998675Sdes p = buffer_get_string(&b, &len); 132098675Sdes if ((session_id2 == NULL) || 132198675Sdes (len != session_id2_len) || 1322215116Sdes (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 132398675Sdes fail++; 1324255767Sdes free(p); 132598675Sdes } 132698675Sdes if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 132798675Sdes fail++; 1328323124Sdes cp = buffer_get_cstring(&b, NULL); 1329255767Sdes xasprintf(&userstyle, "%s%s%s", authctxt->user, 1330255767Sdes authctxt->style ? ":" : "", 1331255767Sdes authctxt->style ? authctxt->style : ""); 1332323124Sdes if (strcmp(userstyle, cp) != 0) { 1333323124Sdes logit("wrong user name passed to monitor: " 1334323124Sdes "expected %s != %.100s", userstyle, cp); 133598675Sdes fail++; 133698675Sdes } 1337255767Sdes free(userstyle); 1338323124Sdes free(cp); 133998675Sdes buffer_skip_string(&b); 134098675Sdes if (datafellows & SSH_BUG_PKAUTH) { 134198675Sdes if (!buffer_get_char(&b)) 134298675Sdes fail++; 134398675Sdes } else { 1344323124Sdes cp = buffer_get_cstring(&b, NULL); 1345323124Sdes if (strcmp("publickey", cp) != 0) 134698675Sdes fail++; 1347323124Sdes free(cp); 134898675Sdes if (!buffer_get_char(&b)) 134998675Sdes fail++; 135098675Sdes buffer_skip_string(&b); 135198675Sdes } 135298675Sdes buffer_skip_string(&b); 135398675Sdes if (buffer_len(&b) != 0) 135498675Sdes fail++; 135598675Sdes buffer_free(&b); 135698675Sdes return (fail == 0); 135798675Sdes} 135898675Sdes 135998675Sdesstatic int 1360106130Sdesmonitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 1361106130Sdes char *chost) 136298675Sdes{ 136398675Sdes Buffer b; 1364255767Sdes char *p, *userstyle; 136598675Sdes u_int len; 136698675Sdes int fail = 0; 136798675Sdes 136898675Sdes buffer_init(&b); 136998675Sdes buffer_append(&b, data, datalen); 137098675Sdes 137198675Sdes p = buffer_get_string(&b, &len); 137298675Sdes if ((session_id2 == NULL) || 137398675Sdes (len != session_id2_len) || 1374215116Sdes (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 137598675Sdes fail++; 1376255767Sdes free(p); 137798675Sdes 137898675Sdes if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 137998675Sdes fail++; 1380255767Sdes p = buffer_get_cstring(&b, NULL); 1381255767Sdes xasprintf(&userstyle, "%s%s%s", authctxt->user, 1382255767Sdes authctxt->style ? ":" : "", 1383255767Sdes authctxt->style ? authctxt->style : ""); 1384255767Sdes if (strcmp(userstyle, p) != 0) { 1385124211Sdes logit("wrong user name passed to monitor: expected %s != %.100s", 1386255767Sdes userstyle, p); 138798675Sdes fail++; 138898675Sdes } 1389255767Sdes free(userstyle); 1390255767Sdes free(p); 139198675Sdes buffer_skip_string(&b); /* service */ 1392255767Sdes p = buffer_get_cstring(&b, NULL); 139398675Sdes if (strcmp(p, "hostbased") != 0) 139498675Sdes fail++; 1395255767Sdes free(p); 139698675Sdes buffer_skip_string(&b); /* pkalg */ 139798675Sdes buffer_skip_string(&b); /* pkblob */ 139898675Sdes 139998675Sdes /* verify client host, strip trailing dot if necessary */ 140098675Sdes p = buffer_get_string(&b, NULL); 140198675Sdes if (((len = strlen(p)) > 0) && p[len - 1] == '.') 140298675Sdes p[len - 1] = '\0'; 140398675Sdes if (strcmp(p, chost) != 0) 140498675Sdes fail++; 1405255767Sdes free(p); 140698675Sdes 140798675Sdes /* verify client user */ 140898675Sdes p = buffer_get_string(&b, NULL); 140998675Sdes if (strcmp(p, cuser) != 0) 141098675Sdes fail++; 1411255767Sdes free(p); 141298675Sdes 141398675Sdes if (buffer_len(&b) != 0) 141498675Sdes fail++; 141598675Sdes buffer_free(&b); 141698675Sdes return (fail == 0); 141798675Sdes} 141898675Sdes 141998675Sdesint 1420137019Sdesmm_answer_keyverify(int sock, Buffer *m) 142198675Sdes{ 142298675Sdes Key *key; 142398675Sdes u_char *signature, *data, *blob; 142498675Sdes u_int signaturelen, datalen, bloblen; 142598675Sdes int verified = 0; 142698675Sdes int valid_data = 0; 142798675Sdes 142898675Sdes blob = buffer_get_string(m, &bloblen); 142998675Sdes signature = buffer_get_string(m, &signaturelen); 143098675Sdes data = buffer_get_string(m, &datalen); 143198675Sdes 143298675Sdes if (hostbased_cuser == NULL || hostbased_chost == NULL || 143398675Sdes !monitor_allowed_key(blob, bloblen)) 143498675Sdes fatal("%s: bad key, not previously allowed", __func__); 143598675Sdes 143698675Sdes key = key_from_blob(blob, bloblen); 143798675Sdes if (key == NULL) 143898675Sdes fatal("%s: bad public key blob", __func__); 143998675Sdes 144098675Sdes switch (key_blobtype) { 144198675Sdes case MM_USERKEY: 144298675Sdes valid_data = monitor_valid_userblob(data, datalen); 144398675Sdes break; 144498675Sdes case MM_HOSTKEY: 144598675Sdes valid_data = monitor_valid_hostbasedblob(data, datalen, 144698675Sdes hostbased_cuser, hostbased_chost); 144798675Sdes break; 144898675Sdes default: 144998675Sdes valid_data = 0; 145098675Sdes break; 145198675Sdes } 145298675Sdes if (!valid_data) 145398675Sdes fatal("%s: bad signature data blob", __func__); 145498675Sdes 145598675Sdes verified = key_verify(key, signature, signaturelen, data, datalen); 145698675Sdes debug3("%s: key %p signature %s", 1457164149Sdes __func__, key, (verified == 1) ? "verified" : "unverified"); 145898675Sdes 1459295367Sdes /* If auth was successful then record key to ensure it isn't reused */ 1460296781Sdes if (verified == 1 && key_blobtype == MM_USERKEY) 1461295367Sdes auth2_record_userkey(authctxt, key); 1462295367Sdes else 1463295367Sdes key_free(key); 1464295367Sdes 1465255767Sdes free(blob); 1466255767Sdes free(signature); 1467255767Sdes free(data); 146898675Sdes 146999063Sdes auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; 147099063Sdes 147198675Sdes monitor_reset_key_state(); 147298675Sdes 147398675Sdes buffer_clear(m); 147498675Sdes buffer_put_int(m, verified); 1475137019Sdes mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 147698675Sdes 1477164149Sdes return (verified == 1); 147898675Sdes} 147998675Sdes 148098675Sdesstatic void 148198675Sdesmm_record_login(Session *s, struct passwd *pw) 148298675Sdes{ 1483323124Sdes struct ssh *ssh = active_state; /* XXX */ 148498675Sdes socklen_t fromlen; 148598675Sdes struct sockaddr_storage from; 148698675Sdes 1487295367Sdes if (options.use_login) 1488295367Sdes return; 1489295367Sdes 149098675Sdes /* 149198675Sdes * Get IP address of client. If the connection is not a socket, let 149298675Sdes * the address be 0.0.0.0. 149398675Sdes */ 149498675Sdes memset(&from, 0, sizeof(from)); 1495103134Sume fromlen = sizeof(from); 149698675Sdes if (packet_connection_is_on_socket()) { 149798675Sdes if (getpeername(packet_get_connection_in(), 1498162856Sdes (struct sockaddr *)&from, &fromlen) < 0) { 149998675Sdes debug("getpeername: %.100s", strerror(errno)); 1500126277Sdes cleanup_exit(255); 150198675Sdes } 150298675Sdes } 150398675Sdes /* Record that there was a login on that tty from the remote host. */ 150498675Sdes record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 1505323124Sdes session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), 1506103134Sume (struct sockaddr *)&from, fromlen); 150798675Sdes} 150898675Sdes 150998675Sdesstatic void 151098675Sdesmm_session_close(Session *s) 151198675Sdes{ 1512124211Sdes debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); 151398675Sdes if (s->ttyfd != -1) { 1514162856Sdes debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); 151598675Sdes session_pty_cleanup2(s); 151698675Sdes } 1517181111Sdes session_unused(s->self); 151898675Sdes} 151998675Sdes 152098675Sdesint 1521137019Sdesmm_answer_pty(int sock, Buffer *m) 152298675Sdes{ 152398675Sdes extern struct monitor *pmonitor; 152498675Sdes Session *s; 152598675Sdes int res, fd0; 152698675Sdes 152798675Sdes debug3("%s entering", __func__); 152898675Sdes 152998675Sdes buffer_clear(m); 153098675Sdes s = session_new(); 153198675Sdes if (s == NULL) 153298675Sdes goto error; 153398675Sdes s->authctxt = authctxt; 153498675Sdes s->pw = authctxt->pw; 153598675Sdes s->pid = pmonitor->m_pid; 153698675Sdes res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 153798675Sdes if (res == 0) 153898675Sdes goto error; 153998675Sdes pty_setowner(authctxt->pw, s->tty); 154098675Sdes 154198675Sdes buffer_put_int(m, 1); 154298675Sdes buffer_put_cstring(m, s->tty); 154398675Sdes 154498675Sdes /* We need to trick ttyslot */ 154598675Sdes if (dup2(s->ttyfd, 0) == -1) 154698675Sdes fatal("%s: dup2", __func__); 154798675Sdes 154898675Sdes mm_record_login(s, authctxt->pw); 154998675Sdes 155098675Sdes /* Now we can close the file descriptor again */ 155198675Sdes close(0); 155298675Sdes 1553137019Sdes /* send messages generated by record_login */ 1554137019Sdes buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 1555137019Sdes buffer_clear(&loginmsg); 1556137019Sdes 1557137019Sdes mm_request_send(sock, MONITOR_ANS_PTY, m); 1558137019Sdes 1559181111Sdes if (mm_send_fd(sock, s->ptyfd) == -1 || 1560181111Sdes mm_send_fd(sock, s->ttyfd) == -1) 1561181111Sdes fatal("%s: send fds failed", __func__); 1562137019Sdes 156398675Sdes /* make sure nothing uses fd 0 */ 156498675Sdes if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 156598675Sdes fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); 156698675Sdes if (fd0 != 0) 156798675Sdes error("%s: fd0 %d != 0", __func__, fd0); 156898675Sdes 156998675Sdes /* slave is not needed */ 157098675Sdes close(s->ttyfd); 157198675Sdes s->ttyfd = s->ptyfd; 157298675Sdes /* no need to dup() because nobody closes ptyfd */ 157398675Sdes s->ptymaster = s->ptyfd; 157498675Sdes 1575162856Sdes debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); 157698675Sdes 157798675Sdes return (0); 157898675Sdes 157998675Sdes error: 158098675Sdes if (s != NULL) 158198675Sdes mm_session_close(s); 158298675Sdes buffer_put_int(m, 0); 1583137019Sdes mm_request_send(sock, MONITOR_ANS_PTY, m); 158498675Sdes return (0); 158598675Sdes} 158698675Sdes 158798675Sdesint 1588137019Sdesmm_answer_pty_cleanup(int sock, Buffer *m) 158998675Sdes{ 159098675Sdes Session *s; 159198675Sdes char *tty; 159298675Sdes 159398675Sdes debug3("%s entering", __func__); 159498675Sdes 159598675Sdes tty = buffer_get_string(m, NULL); 159698675Sdes if ((s = session_by_tty(tty)) != NULL) 159798675Sdes mm_session_close(s); 159898675Sdes buffer_clear(m); 1599255767Sdes free(tty); 160098675Sdes return (0); 160198675Sdes} 160298675Sdes 1603295367Sdes#ifdef WITH_SSH1 160498675Sdesint 1605137019Sdesmm_answer_sesskey(int sock, Buffer *m) 160698675Sdes{ 160798675Sdes BIGNUM *p; 160898675Sdes int rsafail; 160998675Sdes 161098675Sdes /* Turn off permissions */ 1611147005Sdes monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); 161298675Sdes 161398675Sdes if ((p = BN_new()) == NULL) 161498675Sdes fatal("%s: BN_new", __func__); 161598675Sdes 161698675Sdes buffer_get_bignum2(m, p); 161798675Sdes 161898675Sdes rsafail = ssh1_session_key(p); 161998675Sdes 162098675Sdes buffer_clear(m); 162198675Sdes buffer_put_int(m, rsafail); 162298675Sdes buffer_put_bignum2(m, p); 162398675Sdes 162498675Sdes BN_clear_free(p); 162598675Sdes 1626137019Sdes mm_request_send(sock, MONITOR_ANS_SESSKEY, m); 162798675Sdes 162898675Sdes /* Turn on permissions for sessid passing */ 162998675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); 163098675Sdes 163198675Sdes return (0); 163298675Sdes} 163398675Sdes 163498675Sdesint 1635137019Sdesmm_answer_sessid(int sock, Buffer *m) 163698675Sdes{ 163798675Sdes int i; 163898675Sdes 163998675Sdes debug3("%s entering", __func__); 164098675Sdes 164198675Sdes if (buffer_len(m) != 16) 164298675Sdes fatal("%s: bad ssh1 session id", __func__); 164398675Sdes for (i = 0; i < 16; i++) 164498675Sdes session_id[i] = buffer_get_char(m); 164598675Sdes 164698675Sdes /* Turn on permissions for getpwnam */ 164798675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 164898675Sdes 164998675Sdes return (0); 165098675Sdes} 165198675Sdes 165298675Sdesint 1653137019Sdesmm_answer_rsa_keyallowed(int sock, Buffer *m) 165498675Sdes{ 165598675Sdes BIGNUM *client_n; 165698675Sdes Key *key = NULL; 165798675Sdes u_char *blob = NULL; 165898675Sdes u_int blen = 0; 165998675Sdes int allowed = 0; 166098675Sdes 166198675Sdes debug3("%s entering", __func__); 166298675Sdes 1663162856Sdes auth_method = "rsa"; 166498675Sdes if (options.rsa_authentication && authctxt->valid) { 166598675Sdes if ((client_n = BN_new()) == NULL) 166698675Sdes fatal("%s: BN_new", __func__); 166798675Sdes buffer_get_bignum2(m, client_n); 166898675Sdes allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); 166998675Sdes BN_clear_free(client_n); 167098675Sdes } 167198675Sdes buffer_clear(m); 167298675Sdes buffer_put_int(m, allowed); 1673113911Sdes buffer_put_int(m, forced_command != NULL); 167498675Sdes 167598675Sdes /* clear temporarily storage (used by generate challenge) */ 167698675Sdes monitor_reset_key_state(); 167798675Sdes 167898675Sdes if (allowed && key != NULL) { 167998675Sdes key->type = KEY_RSA; /* cheat for key_to_blob */ 168098675Sdes if (key_to_blob(key, &blob, &blen) == 0) 168198675Sdes fatal("%s: key_to_blob failed", __func__); 168298675Sdes buffer_put_string(m, blob, blen); 168398675Sdes 168498675Sdes /* Save temporarily for comparison in verify */ 168598675Sdes key_blob = blob; 168698675Sdes key_bloblen = blen; 168798675Sdes key_blobtype = MM_RSAUSERKEY; 1688113911Sdes } 1689113911Sdes if (key != NULL) 169098675Sdes key_free(key); 169198675Sdes 1692137019Sdes mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); 169398675Sdes 169498675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 169598675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); 169698675Sdes return (0); 169798675Sdes} 169898675Sdes 169998675Sdesint 1700137019Sdesmm_answer_rsa_challenge(int sock, Buffer *m) 170198675Sdes{ 170298675Sdes Key *key = NULL; 170398675Sdes u_char *blob; 170498675Sdes u_int blen; 170598675Sdes 170698675Sdes debug3("%s entering", __func__); 170798675Sdes 170898675Sdes if (!authctxt->valid) 170998675Sdes fatal("%s: authctxt not valid", __func__); 171098675Sdes blob = buffer_get_string(m, &blen); 171198675Sdes if (!monitor_allowed_key(blob, blen)) 171298675Sdes fatal("%s: bad key, not previously allowed", __func__); 171398675Sdes if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 171498675Sdes fatal("%s: key type mismatch", __func__); 171598675Sdes if ((key = key_from_blob(blob, blen)) == NULL) 171698675Sdes fatal("%s: received bad key", __func__); 1717192595Sdes if (key->type != KEY_RSA) 1718192595Sdes fatal("%s: received bad key type %d", __func__, key->type); 1719192595Sdes key->type = KEY_RSA1; 172098675Sdes if (ssh1_challenge) 172198675Sdes BN_clear_free(ssh1_challenge); 172298675Sdes ssh1_challenge = auth_rsa_generate_challenge(key); 172398675Sdes 172498675Sdes buffer_clear(m); 172598675Sdes buffer_put_bignum2(m, ssh1_challenge); 172698675Sdes 172798675Sdes debug3("%s sending reply", __func__); 1728137019Sdes mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); 172998675Sdes 173098675Sdes monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); 1731113911Sdes 1732255767Sdes free(blob); 1733113911Sdes key_free(key); 173498675Sdes return (0); 173598675Sdes} 173698675Sdes 173798675Sdesint 1738137019Sdesmm_answer_rsa_response(int sock, Buffer *m) 173998675Sdes{ 174098675Sdes Key *key = NULL; 174198675Sdes u_char *blob, *response; 174298675Sdes u_int blen, len; 174398675Sdes int success; 174498675Sdes 174598675Sdes debug3("%s entering", __func__); 174698675Sdes 174798675Sdes if (!authctxt->valid) 174898675Sdes fatal("%s: authctxt not valid", __func__); 174998675Sdes if (ssh1_challenge == NULL) 175098675Sdes fatal("%s: no ssh1_challenge", __func__); 175198675Sdes 175298675Sdes blob = buffer_get_string(m, &blen); 175398675Sdes if (!monitor_allowed_key(blob, blen)) 175498675Sdes fatal("%s: bad key, not previously allowed", __func__); 175598675Sdes if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 175698675Sdes fatal("%s: key type mismatch: %d", __func__, key_blobtype); 175798675Sdes if ((key = key_from_blob(blob, blen)) == NULL) 175898675Sdes fatal("%s: received bad key", __func__); 175998675Sdes response = buffer_get_string(m, &len); 176098675Sdes if (len != 16) 176198675Sdes fatal("%s: received bad response to challenge", __func__); 176298675Sdes success = auth_rsa_verify_response(key, ssh1_challenge, response); 176398675Sdes 1764255767Sdes free(blob); 176598675Sdes key_free(key); 1766255767Sdes free(response); 176798675Sdes 176898675Sdes auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; 176998675Sdes 177098675Sdes /* reset state */ 177198675Sdes BN_clear_free(ssh1_challenge); 177298675Sdes ssh1_challenge = NULL; 177398675Sdes monitor_reset_key_state(); 177498675Sdes 177598675Sdes buffer_clear(m); 177698675Sdes buffer_put_int(m, success); 1777137019Sdes mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); 177898675Sdes 177998675Sdes return (success); 178098675Sdes} 1781295367Sdes#endif 178298675Sdes 178398675Sdesint 1784137019Sdesmm_answer_term(int sock, Buffer *req) 178598675Sdes{ 178698675Sdes extern struct monitor *pmonitor; 178798675Sdes int res, status; 178898675Sdes 178998675Sdes debug3("%s: tearing down sessions", __func__); 179098675Sdes 179198675Sdes /* The child is terminating */ 179298675Sdes session_destroy_all(&mm_session_close); 179398675Sdes 1794181111Sdes#ifdef USE_PAM 1795181111Sdes if (options.use_pam) 1796181111Sdes sshpam_cleanup(); 1797181111Sdes#endif 1798181111Sdes 179998675Sdes while (waitpid(pmonitor->m_pid, &status, 0) == -1) 180098675Sdes if (errno != EINTR) 180198675Sdes exit(1); 180298675Sdes 180398675Sdes res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 180498675Sdes 180598675Sdes /* Terminate process */ 1806137019Sdes exit(res); 180798675Sdes} 180898675Sdes 1809147005Sdes#ifdef SSH_AUDIT_EVENTS 1810147005Sdes/* Report that an audit event occurred */ 1811147005Sdesint 1812147005Sdesmm_answer_audit_event(int socket, Buffer *m) 1813147005Sdes{ 1814147005Sdes ssh_audit_event_t event; 1815147005Sdes 1816147005Sdes debug3("%s entering", __func__); 1817147005Sdes 1818147005Sdes event = buffer_get_int(m); 1819147005Sdes switch(event) { 1820147005Sdes case SSH_AUTH_FAIL_PUBKEY: 1821147005Sdes case SSH_AUTH_FAIL_HOSTBASED: 1822147005Sdes case SSH_AUTH_FAIL_GSSAPI: 1823147005Sdes case SSH_LOGIN_EXCEED_MAXTRIES: 1824147005Sdes case SSH_LOGIN_ROOT_DENIED: 1825147005Sdes case SSH_CONNECTION_CLOSE: 1826147005Sdes case SSH_INVALID_USER: 1827147005Sdes audit_event(event); 1828147005Sdes break; 1829147005Sdes default: 1830147005Sdes fatal("Audit event type %d not permitted", event); 1831147005Sdes } 1832147005Sdes 1833147005Sdes return (0); 1834147005Sdes} 1835147005Sdes 1836147005Sdesint 1837147005Sdesmm_answer_audit_command(int socket, Buffer *m) 1838147005Sdes{ 1839147005Sdes u_int len; 1840147005Sdes char *cmd; 1841147005Sdes 1842147005Sdes debug3("%s entering", __func__); 1843147005Sdes cmd = buffer_get_string(m, &len); 1844147005Sdes /* sanity check command, if so how? */ 1845147005Sdes audit_run_command(cmd); 1846255767Sdes free(cmd); 1847147005Sdes return (0); 1848147005Sdes} 1849147005Sdes#endif /* SSH_AUDIT_EVENTS */ 1850147005Sdes 185198675Sdesvoid 185298675Sdesmonitor_apply_keystate(struct monitor *pmonitor) 185398675Sdes{ 1854295367Sdes struct ssh *ssh = active_state; /* XXX */ 1855295367Sdes struct kex *kex; 1856295367Sdes int r; 185798675Sdes 1858295367Sdes debug3("%s: packet_set_state", __func__); 1859295367Sdes if ((r = ssh_packet_set_state(ssh, child_state)) != 0) 1860295367Sdes fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); 1861295367Sdes sshbuf_free(child_state); 1862295367Sdes child_state = NULL; 186398675Sdes 1864296781Sdes if ((kex = ssh->kex) != NULL) { 1865295367Sdes /* XXX set callbacks */ 1866295367Sdes#ifdef WITH_OPENSSL 1867295367Sdes kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 1868295367Sdes kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1869323124Sdes kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 1870323124Sdes kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 1871323124Sdes kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 1872295367Sdes kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1873295367Sdes kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1874295367Sdes# ifdef OPENSSL_HAS_ECC 1875295367Sdes kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1876295367Sdes# endif 1877295367Sdes#endif /* WITH_OPENSSL */ 1878295367Sdes kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1879295367Sdes kex->load_host_public_key=&get_hostkey_public_by_type; 1880295367Sdes kex->load_host_private_key=&get_hostkey_private_by_type; 1881295367Sdes kex->host_key_index=&get_hostkey_index; 1882295367Sdes kex->sign = sshd_hostkey_sign; 188398675Sdes } 188498675Sdes 188598675Sdes /* Update with new address */ 1886295367Sdes if (options.compression) { 1887295367Sdes ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, 1888295367Sdes (ssh_packet_comp_alloc_func *)mm_zalloc, 1889295367Sdes (ssh_packet_comp_free_func *)mm_zfree); 1890295367Sdes } 189198675Sdes} 189298675Sdes 189398675Sdes/* This function requries careful sanity checking */ 189498675Sdes 189598675Sdesvoid 189698675Sdesmm_get_keystate(struct monitor *pmonitor) 189798675Sdes{ 189898675Sdes debug3("%s: Waiting for new keys", __func__); 189998675Sdes 1900295367Sdes if ((child_state = sshbuf_new()) == NULL) 1901295367Sdes fatal("%s: sshbuf_new failed", __func__); 1902295367Sdes mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, 1903295367Sdes child_state); 1904295367Sdes debug3("%s: GOT new keys", __func__); 190598675Sdes} 190698675Sdes 190798675Sdes 190898675Sdes/* XXX */ 190998675Sdes 191098675Sdes#define FD_CLOSEONEXEC(x) do { \ 1911226046Sdes if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ 191298675Sdes fatal("fcntl(%d, F_SETFD)", x); \ 191398675Sdes} while (0) 191498675Sdes 191598675Sdesstatic void 1916226046Sdesmonitor_openfds(struct monitor *mon, int do_logfds) 191798675Sdes{ 1918226046Sdes int pair[2]; 1919226046Sdes 192098675Sdes if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 1921226046Sdes fatal("%s: socketpair: %s", __func__, strerror(errno)); 192298675Sdes FD_CLOSEONEXEC(pair[0]); 192398675Sdes FD_CLOSEONEXEC(pair[1]); 1924226046Sdes mon->m_recvfd = pair[0]; 1925226046Sdes mon->m_sendfd = pair[1]; 1926226046Sdes 1927226046Sdes if (do_logfds) { 1928226046Sdes if (pipe(pair) == -1) 1929226046Sdes fatal("%s: pipe: %s", __func__, strerror(errno)); 1930226046Sdes FD_CLOSEONEXEC(pair[0]); 1931226046Sdes FD_CLOSEONEXEC(pair[1]); 1932226046Sdes mon->m_log_recvfd = pair[0]; 1933226046Sdes mon->m_log_sendfd = pair[1]; 1934226046Sdes } else 1935226046Sdes mon->m_log_recvfd = mon->m_log_sendfd = -1; 193698675Sdes} 193798675Sdes 193898675Sdes#define MM_MEMSIZE 65536 193998675Sdes 194098675Sdesstruct monitor * 194198675Sdesmonitor_init(void) 194298675Sdes{ 1943295367Sdes struct ssh *ssh = active_state; /* XXX */ 194498675Sdes struct monitor *mon; 194598675Sdes 1946162856Sdes mon = xcalloc(1, sizeof(*mon)); 194798675Sdes 1948226046Sdes monitor_openfds(mon, 1); 194998675Sdes 195098675Sdes /* Used to share zlib space across processes */ 195198675Sdes if (options.compression) { 195298675Sdes mon->m_zback = mm_create(NULL, MM_MEMSIZE); 195398675Sdes mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); 195498675Sdes 195598675Sdes /* Compression needs to share state across borders */ 1956295367Sdes ssh_packet_set_compress_hooks(ssh, mon->m_zlib, 1957295367Sdes (ssh_packet_comp_alloc_func *)mm_zalloc, 1958295367Sdes (ssh_packet_comp_free_func *)mm_zfree); 195998675Sdes } 196098675Sdes 196198675Sdes return mon; 196298675Sdes} 196398675Sdes 196498675Sdesvoid 196598675Sdesmonitor_reinit(struct monitor *mon) 196698675Sdes{ 1967226046Sdes monitor_openfds(mon, 0); 196898675Sdes} 1969124211Sdes 1970124211Sdes#ifdef GSSAPI 1971124211Sdesint 1972137019Sdesmm_answer_gss_setup_ctx(int sock, Buffer *m) 1973124211Sdes{ 1974137019Sdes gss_OID_desc goid; 1975124211Sdes OM_uint32 major; 1976124211Sdes u_int len; 1977124211Sdes 1978137019Sdes goid.elements = buffer_get_string(m, &len); 1979137019Sdes goid.length = len; 1980124211Sdes 1981137019Sdes major = ssh_gssapi_server_ctx(&gsscontext, &goid); 1982124211Sdes 1983255767Sdes free(goid.elements); 1984124211Sdes 1985124211Sdes buffer_clear(m); 1986124211Sdes buffer_put_int(m, major); 1987124211Sdes 1988157019Sdes mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); 1989124211Sdes 1990124211Sdes /* Now we have a context, enable the step */ 1991124211Sdes monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); 1992124211Sdes 1993124211Sdes return (0); 1994124211Sdes} 1995124211Sdes 1996124211Sdesint 1997137019Sdesmm_answer_gss_accept_ctx(int sock, Buffer *m) 1998124211Sdes{ 1999124211Sdes gss_buffer_desc in; 2000124211Sdes gss_buffer_desc out = GSS_C_EMPTY_BUFFER; 2001157019Sdes OM_uint32 major, minor; 2002124211Sdes OM_uint32 flags = 0; /* GSI needs this */ 2003124211Sdes u_int len; 2004124211Sdes 2005124211Sdes in.value = buffer_get_string(m, &len); 2006124211Sdes in.length = len; 2007124211Sdes major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 2008255767Sdes free(in.value); 2009124211Sdes 2010124211Sdes buffer_clear(m); 2011124211Sdes buffer_put_int(m, major); 2012124211Sdes buffer_put_string(m, out.value, out.length); 2013124211Sdes buffer_put_int(m, flags); 2014137019Sdes mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); 2015124211Sdes 2016124211Sdes gss_release_buffer(&minor, &out); 2017124211Sdes 2018157019Sdes if (major == GSS_S_COMPLETE) { 2019124211Sdes monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 2020124211Sdes monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 2021126277Sdes monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 2022124211Sdes } 2023124211Sdes return (0); 2024124211Sdes} 2025124211Sdes 2026124211Sdesint 2027137019Sdesmm_answer_gss_checkmic(int sock, Buffer *m) 2028126277Sdes{ 2029126277Sdes gss_buffer_desc gssbuf, mic; 2030126277Sdes OM_uint32 ret; 2031126277Sdes u_int len; 2032126277Sdes 2033126277Sdes gssbuf.value = buffer_get_string(m, &len); 2034126277Sdes gssbuf.length = len; 2035126277Sdes mic.value = buffer_get_string(m, &len); 2036126277Sdes mic.length = len; 2037126277Sdes 2038126277Sdes ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); 2039126277Sdes 2040255767Sdes free(gssbuf.value); 2041255767Sdes free(mic.value); 2042126277Sdes 2043126277Sdes buffer_clear(m); 2044126277Sdes buffer_put_int(m, ret); 2045126277Sdes 2046137019Sdes mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); 2047126277Sdes 2048126277Sdes if (!GSS_ERROR(ret)) 2049126277Sdes monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 2050126277Sdes 2051126277Sdes return (0); 2052126277Sdes} 2053126277Sdes 2054126277Sdesint 2055137019Sdesmm_answer_gss_userok(int sock, Buffer *m) 2056124211Sdes{ 2057124211Sdes int authenticated; 2058124211Sdes 2059124211Sdes authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 2060124211Sdes 2061124211Sdes buffer_clear(m); 2062124211Sdes buffer_put_int(m, authenticated); 2063124211Sdes 2064124211Sdes debug3("%s: sending result %d", __func__, authenticated); 2065137019Sdes mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); 2066124211Sdes 2067157019Sdes auth_method = "gssapi-with-mic"; 2068124211Sdes 2069124211Sdes /* Monitor loop will terminate if authenticated */ 2070124211Sdes return (authenticated); 2071124211Sdes} 2072124211Sdes#endif /* GSSAPI */ 2073192595Sdes 2074