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