1*ce74bacaSMatthew Dillon /* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */ 218de8d7fSPeter Avalos /* 318de8d7fSPeter Avalos * Copyright 2002 Niels Provos <provos@citi.umich.edu> 418de8d7fSPeter Avalos * Copyright 2002 Markus Friedl <markus@openbsd.org> 518de8d7fSPeter Avalos * All rights reserved. 618de8d7fSPeter Avalos * 718de8d7fSPeter Avalos * Redistribution and use in source and binary forms, with or without 818de8d7fSPeter Avalos * modification, are permitted provided that the following conditions 918de8d7fSPeter Avalos * are met: 1018de8d7fSPeter Avalos * 1. Redistributions of source code must retain the above copyright 1118de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer. 1218de8d7fSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright 1318de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer in the 1418de8d7fSPeter Avalos * documentation and/or other materials provided with the distribution. 1518de8d7fSPeter Avalos * 1618de8d7fSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1718de8d7fSPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1818de8d7fSPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1918de8d7fSPeter Avalos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2018de8d7fSPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2118de8d7fSPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2218de8d7fSPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2318de8d7fSPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2418de8d7fSPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2518de8d7fSPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2618de8d7fSPeter Avalos */ 2718de8d7fSPeter Avalos 2818de8d7fSPeter Avalos #include "includes.h" 2918de8d7fSPeter Avalos 3018de8d7fSPeter Avalos #include <sys/types.h> 3118de8d7fSPeter Avalos #include <sys/socket.h> 3218de8d7fSPeter Avalos #include "openbsd-compat/sys-tree.h" 3318de8d7fSPeter Avalos #include <sys/wait.h> 3418de8d7fSPeter Avalos 3518de8d7fSPeter Avalos #include <errno.h> 3618de8d7fSPeter Avalos #include <fcntl.h> 37e9778795SPeter Avalos #include <limits.h> 3818de8d7fSPeter Avalos #ifdef HAVE_PATHS_H 3918de8d7fSPeter Avalos #include <paths.h> 4018de8d7fSPeter Avalos #endif 4118de8d7fSPeter Avalos #include <pwd.h> 4218de8d7fSPeter Avalos #include <signal.h> 43e9778795SPeter Avalos #ifdef HAVE_STDINT_H 44e9778795SPeter Avalos #include <stdint.h> 45e9778795SPeter Avalos #endif 4618de8d7fSPeter Avalos #include <stdlib.h> 4718de8d7fSPeter Avalos #include <string.h> 4836e94dc5SPeter Avalos #include <stdarg.h> 4936e94dc5SPeter Avalos #include <stdio.h> 5018de8d7fSPeter Avalos #include <unistd.h> 511c188a7fSPeter Avalos #ifdef HAVE_POLL_H 521c188a7fSPeter Avalos #include <poll.h> 531c188a7fSPeter Avalos #else 541c188a7fSPeter Avalos # ifdef HAVE_SYS_POLL_H 551c188a7fSPeter Avalos # include <sys/poll.h> 561c188a7fSPeter Avalos # endif 571c188a7fSPeter Avalos #endif 5818de8d7fSPeter Avalos 5918de8d7fSPeter Avalos #ifdef SKEY 6018de8d7fSPeter Avalos #include <skey.h> 6118de8d7fSPeter Avalos #endif 6218de8d7fSPeter Avalos 6336e94dc5SPeter Avalos #ifdef WITH_OPENSSL 6418de8d7fSPeter Avalos #include <openssl/dh.h> 6536e94dc5SPeter Avalos #endif 6618de8d7fSPeter Avalos 6718de8d7fSPeter Avalos #include "openbsd-compat/sys-queue.h" 681c188a7fSPeter Avalos #include "atomicio.h" 6918de8d7fSPeter Avalos #include "xmalloc.h" 7018de8d7fSPeter Avalos #include "ssh.h" 7118de8d7fSPeter Avalos #include "key.h" 7218de8d7fSPeter Avalos #include "buffer.h" 7318de8d7fSPeter Avalos #include "hostfile.h" 7418de8d7fSPeter Avalos #include "auth.h" 7518de8d7fSPeter Avalos #include "cipher.h" 7618de8d7fSPeter Avalos #include "kex.h" 7718de8d7fSPeter Avalos #include "dh.h" 78e9778795SPeter Avalos #include "auth-pam.h" 7918de8d7fSPeter Avalos #ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */ 8018de8d7fSPeter Avalos #undef TARGET_OS_MAC 8118de8d7fSPeter Avalos #include "zlib.h" 8218de8d7fSPeter Avalos #define TARGET_OS_MAC 1 8318de8d7fSPeter Avalos #else 8418de8d7fSPeter Avalos #include "zlib.h" 8518de8d7fSPeter Avalos #endif 8618de8d7fSPeter Avalos #include "packet.h" 8718de8d7fSPeter Avalos #include "auth-options.h" 8818de8d7fSPeter Avalos #include "sshpty.h" 8918de8d7fSPeter Avalos #include "channels.h" 9018de8d7fSPeter Avalos #include "session.h" 9118de8d7fSPeter Avalos #include "sshlogin.h" 9218de8d7fSPeter Avalos #include "canohost.h" 9318de8d7fSPeter Avalos #include "log.h" 9436e94dc5SPeter Avalos #include "misc.h" 9518de8d7fSPeter Avalos #include "servconf.h" 9618de8d7fSPeter Avalos #include "monitor.h" 9718de8d7fSPeter Avalos #ifdef GSSAPI 9818de8d7fSPeter Avalos #include "ssh-gss.h" 9918de8d7fSPeter Avalos #endif 10018de8d7fSPeter Avalos #include "monitor_wrap.h" 10118de8d7fSPeter Avalos #include "monitor_fdpass.h" 10218de8d7fSPeter Avalos #include "compat.h" 10318de8d7fSPeter Avalos #include "ssh2.h" 10436e94dc5SPeter Avalos #include "authfd.h" 105e9778795SPeter Avalos #include "match.h" 106e9778795SPeter Avalos #include "ssherr.h" 10718de8d7fSPeter Avalos 10818de8d7fSPeter Avalos #ifdef GSSAPI 10918de8d7fSPeter Avalos static Gssctxt *gsscontext = NULL; 11018de8d7fSPeter Avalos #endif 11118de8d7fSPeter Avalos 11218de8d7fSPeter Avalos /* Imports */ 11318de8d7fSPeter Avalos extern ServerOptions options; 11418de8d7fSPeter Avalos extern u_int utmp_len; 11518de8d7fSPeter Avalos extern u_char session_id[]; 11618de8d7fSPeter Avalos extern Buffer auth_debug; 11718de8d7fSPeter Avalos extern int auth_debug_init; 11818de8d7fSPeter Avalos extern Buffer loginmsg; 11918de8d7fSPeter Avalos 12018de8d7fSPeter Avalos /* State exported from the child */ 121e9778795SPeter Avalos static struct sshbuf *child_state; 12218de8d7fSPeter Avalos 12318de8d7fSPeter Avalos /* Functions on the monitor that answer unprivileged requests */ 12418de8d7fSPeter Avalos 12518de8d7fSPeter Avalos int mm_answer_moduli(int, Buffer *); 12618de8d7fSPeter Avalos int mm_answer_sign(int, Buffer *); 12718de8d7fSPeter Avalos int mm_answer_pwnamallow(int, Buffer *); 12818de8d7fSPeter Avalos int mm_answer_auth2_read_banner(int, Buffer *); 12918de8d7fSPeter Avalos int mm_answer_authserv(int, Buffer *); 13018de8d7fSPeter Avalos int mm_answer_authpassword(int, Buffer *); 13118de8d7fSPeter Avalos int mm_answer_bsdauthquery(int, Buffer *); 13218de8d7fSPeter Avalos int mm_answer_bsdauthrespond(int, Buffer *); 13318de8d7fSPeter Avalos int mm_answer_skeyquery(int, Buffer *); 13418de8d7fSPeter Avalos int mm_answer_skeyrespond(int, Buffer *); 13518de8d7fSPeter Avalos int mm_answer_keyallowed(int, Buffer *); 13618de8d7fSPeter Avalos int mm_answer_keyverify(int, Buffer *); 13718de8d7fSPeter Avalos int mm_answer_pty(int, Buffer *); 13818de8d7fSPeter Avalos int mm_answer_pty_cleanup(int, Buffer *); 13918de8d7fSPeter Avalos int mm_answer_term(int, Buffer *); 14018de8d7fSPeter Avalos int mm_answer_rsa_keyallowed(int, Buffer *); 14118de8d7fSPeter Avalos int mm_answer_rsa_challenge(int, Buffer *); 14218de8d7fSPeter Avalos int mm_answer_rsa_response(int, Buffer *); 14318de8d7fSPeter Avalos int mm_answer_sesskey(int, Buffer *); 14418de8d7fSPeter Avalos int mm_answer_sessid(int, Buffer *); 14518de8d7fSPeter Avalos 14618de8d7fSPeter Avalos #ifdef USE_PAM 14718de8d7fSPeter Avalos int mm_answer_pam_start(int, Buffer *); 14818de8d7fSPeter Avalos int mm_answer_pam_account(int, Buffer *); 14918de8d7fSPeter Avalos int mm_answer_pam_init_ctx(int, Buffer *); 15018de8d7fSPeter Avalos int mm_answer_pam_query(int, Buffer *); 15118de8d7fSPeter Avalos int mm_answer_pam_respond(int, Buffer *); 15218de8d7fSPeter Avalos int mm_answer_pam_free_ctx(int, Buffer *); 15318de8d7fSPeter Avalos #endif 15418de8d7fSPeter Avalos 15518de8d7fSPeter Avalos #ifdef GSSAPI 15618de8d7fSPeter Avalos int mm_answer_gss_setup_ctx(int, Buffer *); 15718de8d7fSPeter Avalos int mm_answer_gss_accept_ctx(int, Buffer *); 15818de8d7fSPeter Avalos int mm_answer_gss_userok(int, Buffer *); 15918de8d7fSPeter Avalos int mm_answer_gss_checkmic(int, Buffer *); 16018de8d7fSPeter Avalos #endif 16118de8d7fSPeter Avalos 16218de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 16318de8d7fSPeter Avalos int mm_answer_audit_event(int, Buffer *); 16418de8d7fSPeter Avalos int mm_answer_audit_command(int, Buffer *); 16518de8d7fSPeter Avalos #endif 16618de8d7fSPeter Avalos 1671c188a7fSPeter Avalos static int monitor_read_log(struct monitor *); 1681c188a7fSPeter Avalos 16918de8d7fSPeter Avalos static Authctxt *authctxt; 17036e94dc5SPeter Avalos 17118de8d7fSPeter Avalos /* local state for key verify */ 17218de8d7fSPeter Avalos static u_char *key_blob = NULL; 17318de8d7fSPeter Avalos static u_int key_bloblen = 0; 17418de8d7fSPeter Avalos static int key_blobtype = MM_NOKEY; 17518de8d7fSPeter Avalos static char *hostbased_cuser = NULL; 17618de8d7fSPeter Avalos static char *hostbased_chost = NULL; 17718de8d7fSPeter Avalos static char *auth_method = "unknown"; 17836e94dc5SPeter Avalos static char *auth_submethod = NULL; 17918de8d7fSPeter Avalos static u_int session_id2_len = 0; 18018de8d7fSPeter Avalos static u_char *session_id2 = NULL; 18118de8d7fSPeter Avalos static pid_t monitor_child_pid; 18218de8d7fSPeter Avalos 18318de8d7fSPeter Avalos struct mon_table { 18418de8d7fSPeter Avalos enum monitor_reqtype type; 18518de8d7fSPeter Avalos int flags; 18618de8d7fSPeter Avalos int (*f)(int, Buffer *); 18718de8d7fSPeter Avalos }; 18818de8d7fSPeter Avalos 18918de8d7fSPeter Avalos #define MON_ISAUTH 0x0004 /* Required for Authentication */ 19018de8d7fSPeter Avalos #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ 19118de8d7fSPeter Avalos #define MON_ONCE 0x0010 /* Disable after calling */ 19218de8d7fSPeter Avalos #define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ 19318de8d7fSPeter Avalos 19418de8d7fSPeter Avalos #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) 19518de8d7fSPeter Avalos 19618de8d7fSPeter Avalos #define MON_PERMIT 0x1000 /* Request is permitted */ 19718de8d7fSPeter Avalos 19818de8d7fSPeter Avalos struct mon_table mon_dispatch_proto20[] = { 19936e94dc5SPeter Avalos #ifdef WITH_OPENSSL 20018de8d7fSPeter Avalos {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 20136e94dc5SPeter Avalos #endif 20218de8d7fSPeter Avalos {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 20318de8d7fSPeter Avalos {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 20418de8d7fSPeter Avalos {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 20518de8d7fSPeter Avalos {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 20618de8d7fSPeter Avalos {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 20718de8d7fSPeter Avalos #ifdef USE_PAM 20818de8d7fSPeter Avalos {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 20918de8d7fSPeter Avalos {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 210*ce74bacaSMatthew Dillon {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx}, 211*ce74bacaSMatthew Dillon {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query}, 212*ce74bacaSMatthew Dillon {MONITOR_REQ_PAM_RESPOND, MON_ONCE, mm_answer_pam_respond}, 21318de8d7fSPeter Avalos {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 21418de8d7fSPeter Avalos #endif 21518de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 21618de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 21718de8d7fSPeter Avalos #endif 21818de8d7fSPeter Avalos #ifdef BSD_AUTH 21918de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 22018de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 22118de8d7fSPeter Avalos #endif 22218de8d7fSPeter Avalos #ifdef SKEY 22318de8d7fSPeter Avalos {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 22418de8d7fSPeter Avalos {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 22518de8d7fSPeter Avalos #endif 22618de8d7fSPeter Avalos {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, 22718de8d7fSPeter Avalos {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, 22818de8d7fSPeter Avalos #ifdef GSSAPI 22918de8d7fSPeter Avalos {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, 230*ce74bacaSMatthew Dillon {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, 231*ce74bacaSMatthew Dillon {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, 232*ce74bacaSMatthew Dillon {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, 23318de8d7fSPeter Avalos #endif 23418de8d7fSPeter Avalos {0, 0, NULL} 23518de8d7fSPeter Avalos }; 23618de8d7fSPeter Avalos 23718de8d7fSPeter Avalos struct mon_table mon_dispatch_postauth20[] = { 23836e94dc5SPeter Avalos #ifdef WITH_OPENSSL 23918de8d7fSPeter Avalos {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 24036e94dc5SPeter Avalos #endif 24118de8d7fSPeter Avalos {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 24218de8d7fSPeter Avalos {MONITOR_REQ_PTY, 0, mm_answer_pty}, 24318de8d7fSPeter Avalos {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 24418de8d7fSPeter Avalos {MONITOR_REQ_TERM, 0, mm_answer_term}, 24518de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 24618de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 24718de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 24818de8d7fSPeter Avalos #endif 24918de8d7fSPeter Avalos {0, 0, NULL} 25018de8d7fSPeter Avalos }; 25118de8d7fSPeter Avalos 25218de8d7fSPeter Avalos struct mon_table *mon_dispatch; 25318de8d7fSPeter Avalos 25418de8d7fSPeter Avalos /* Specifies if a certain message is allowed at the moment */ 25518de8d7fSPeter Avalos 25618de8d7fSPeter Avalos static void 25718de8d7fSPeter Avalos monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) 25818de8d7fSPeter Avalos { 25918de8d7fSPeter Avalos while (ent->f != NULL) { 26018de8d7fSPeter Avalos if (ent->type == type) { 26118de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 26218de8d7fSPeter Avalos ent->flags |= permit ? MON_PERMIT : 0; 26318de8d7fSPeter Avalos return; 26418de8d7fSPeter Avalos } 26518de8d7fSPeter Avalos ent++; 26618de8d7fSPeter Avalos } 26718de8d7fSPeter Avalos } 26818de8d7fSPeter Avalos 26918de8d7fSPeter Avalos static void 27018de8d7fSPeter Avalos monitor_permit_authentications(int permit) 27118de8d7fSPeter Avalos { 27218de8d7fSPeter Avalos struct mon_table *ent = mon_dispatch; 27318de8d7fSPeter Avalos 27418de8d7fSPeter Avalos while (ent->f != NULL) { 27518de8d7fSPeter Avalos if (ent->flags & MON_AUTH) { 27618de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 27718de8d7fSPeter Avalos ent->flags |= permit ? MON_PERMIT : 0; 27818de8d7fSPeter Avalos } 27918de8d7fSPeter Avalos ent++; 28018de8d7fSPeter Avalos } 28118de8d7fSPeter Avalos } 28218de8d7fSPeter Avalos 28318de8d7fSPeter Avalos void 28418de8d7fSPeter Avalos monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 28518de8d7fSPeter Avalos { 286*ce74bacaSMatthew Dillon struct ssh *ssh = active_state; /* XXX */ 28718de8d7fSPeter Avalos struct mon_table *ent; 28836e94dc5SPeter Avalos int authenticated = 0, partial = 0; 28918de8d7fSPeter Avalos 29018de8d7fSPeter Avalos debug3("preauth child monitor started"); 29118de8d7fSPeter Avalos 2921c188a7fSPeter Avalos close(pmonitor->m_recvfd); 2931c188a7fSPeter Avalos close(pmonitor->m_log_sendfd); 2941c188a7fSPeter Avalos pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; 2951c188a7fSPeter Avalos 29618de8d7fSPeter Avalos authctxt = _authctxt; 29718de8d7fSPeter Avalos memset(authctxt, 0, sizeof(*authctxt)); 29818de8d7fSPeter Avalos 29918de8d7fSPeter Avalos authctxt->loginmsg = &loginmsg; 30018de8d7fSPeter Avalos 30118de8d7fSPeter Avalos mon_dispatch = mon_dispatch_proto20; 30218de8d7fSPeter Avalos /* Permit requests for moduli and signatures */ 30318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 30418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 30518de8d7fSPeter Avalos 30618de8d7fSPeter Avalos /* The first few requests do not require asynchronous access */ 30718de8d7fSPeter Avalos while (!authenticated) { 30836e94dc5SPeter Avalos partial = 0; 30918de8d7fSPeter Avalos auth_method = "unknown"; 31036e94dc5SPeter Avalos auth_submethod = NULL; 311*ce74bacaSMatthew Dillon auth2_authctxt_reset_info(authctxt); 312*ce74bacaSMatthew Dillon 31318de8d7fSPeter Avalos authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); 31436e94dc5SPeter Avalos 31536e94dc5SPeter Avalos /* Special handling for multiple required authentications */ 31636e94dc5SPeter Avalos if (options.num_auth_methods != 0) { 31736e94dc5SPeter Avalos if (authenticated && 31836e94dc5SPeter Avalos !auth2_update_methods_lists(authctxt, 31936e94dc5SPeter Avalos auth_method, auth_submethod)) { 32036e94dc5SPeter Avalos debug3("%s: method %s: partial", __func__, 32136e94dc5SPeter Avalos auth_method); 32236e94dc5SPeter Avalos authenticated = 0; 32336e94dc5SPeter Avalos partial = 1; 32436e94dc5SPeter Avalos } 32536e94dc5SPeter Avalos } 32636e94dc5SPeter Avalos 32718de8d7fSPeter Avalos if (authenticated) { 32818de8d7fSPeter Avalos if (!(ent->flags & MON_AUTHDECIDE)) 32918de8d7fSPeter Avalos fatal("%s: unexpected authentication from %d", 33018de8d7fSPeter Avalos __func__, ent->type); 33118de8d7fSPeter Avalos if (authctxt->pw->pw_uid == 0 && 33218de8d7fSPeter Avalos !auth_root_allowed(auth_method)) 33318de8d7fSPeter Avalos authenticated = 0; 33418de8d7fSPeter Avalos #ifdef USE_PAM 33518de8d7fSPeter Avalos /* PAM needs to perform account checks after auth */ 33618de8d7fSPeter Avalos if (options.use_pam && authenticated) { 33718de8d7fSPeter Avalos Buffer m; 33818de8d7fSPeter Avalos 33918de8d7fSPeter Avalos buffer_init(&m); 34018de8d7fSPeter Avalos mm_request_receive_expect(pmonitor->m_sendfd, 34118de8d7fSPeter Avalos MONITOR_REQ_PAM_ACCOUNT, &m); 34218de8d7fSPeter Avalos authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m); 34318de8d7fSPeter Avalos buffer_free(&m); 34418de8d7fSPeter Avalos } 34518de8d7fSPeter Avalos #endif 34618de8d7fSPeter Avalos } 34718de8d7fSPeter Avalos if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { 34836e94dc5SPeter Avalos auth_log(authctxt, authenticated, partial, 34936e94dc5SPeter Avalos auth_method, auth_submethod); 350e9778795SPeter Avalos if (!partial && !authenticated) 35118de8d7fSPeter Avalos authctxt->failures++; 352*ce74bacaSMatthew Dillon if (authenticated || partial) { 353*ce74bacaSMatthew Dillon auth2_update_session_info(authctxt, 354*ce74bacaSMatthew Dillon auth_method, auth_submethod); 355*ce74bacaSMatthew Dillon } 35618de8d7fSPeter Avalos } 357cb5eb4f1SPeter Avalos } 3581c188a7fSPeter Avalos 35918de8d7fSPeter Avalos if (!authctxt->valid) 36018de8d7fSPeter Avalos fatal("%s: authenticated invalid user", __func__); 36118de8d7fSPeter Avalos if (strcmp(auth_method, "unknown") == 0) 36218de8d7fSPeter Avalos fatal("%s: authentication method name unknown", __func__); 36318de8d7fSPeter Avalos 36418de8d7fSPeter Avalos debug("%s: %s has been authenticated by privileged process", 36518de8d7fSPeter Avalos __func__, authctxt->user); 366*ce74bacaSMatthew Dillon ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); 36718de8d7fSPeter Avalos 36818de8d7fSPeter Avalos mm_get_keystate(pmonitor); 3691c188a7fSPeter Avalos 37036e94dc5SPeter Avalos /* Drain any buffered messages from the child */ 37136e94dc5SPeter Avalos while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) 37236e94dc5SPeter Avalos ; 37336e94dc5SPeter Avalos 3741c188a7fSPeter Avalos close(pmonitor->m_sendfd); 3751c188a7fSPeter Avalos close(pmonitor->m_log_recvfd); 3761c188a7fSPeter Avalos pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 37718de8d7fSPeter Avalos } 37818de8d7fSPeter Avalos 37918de8d7fSPeter Avalos static void 38018de8d7fSPeter Avalos monitor_set_child_handler(pid_t pid) 38118de8d7fSPeter Avalos { 38218de8d7fSPeter Avalos monitor_child_pid = pid; 38318de8d7fSPeter Avalos } 38418de8d7fSPeter Avalos 38518de8d7fSPeter Avalos static void 38618de8d7fSPeter Avalos monitor_child_handler(int sig) 38718de8d7fSPeter Avalos { 38818de8d7fSPeter Avalos kill(monitor_child_pid, sig); 38918de8d7fSPeter Avalos } 39018de8d7fSPeter Avalos 39118de8d7fSPeter Avalos void 39218de8d7fSPeter Avalos monitor_child_postauth(struct monitor *pmonitor) 39318de8d7fSPeter Avalos { 3941c188a7fSPeter Avalos close(pmonitor->m_recvfd); 3951c188a7fSPeter Avalos pmonitor->m_recvfd = -1; 3961c188a7fSPeter Avalos 39718de8d7fSPeter Avalos monitor_set_child_handler(pmonitor->m_pid); 39818de8d7fSPeter Avalos signal(SIGHUP, &monitor_child_handler); 39918de8d7fSPeter Avalos signal(SIGTERM, &monitor_child_handler); 40018de8d7fSPeter Avalos signal(SIGINT, &monitor_child_handler); 40136e94dc5SPeter Avalos #ifdef SIGXFSZ 40236e94dc5SPeter Avalos signal(SIGXFSZ, SIG_IGN); 40336e94dc5SPeter Avalos #endif 40418de8d7fSPeter Avalos 40518de8d7fSPeter Avalos mon_dispatch = mon_dispatch_postauth20; 40618de8d7fSPeter Avalos 40718de8d7fSPeter Avalos /* Permit requests for moduli and signatures */ 40818de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 40918de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 41018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 411*ce74bacaSMatthew Dillon 41218de8d7fSPeter Avalos if (!no_pty_flag) { 41318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 41418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 41518de8d7fSPeter Avalos } 41618de8d7fSPeter Avalos 41718de8d7fSPeter Avalos for (;;) 41818de8d7fSPeter Avalos monitor_read(pmonitor, mon_dispatch, NULL); 41918de8d7fSPeter Avalos } 42018de8d7fSPeter Avalos 4211c188a7fSPeter Avalos static int 4221c188a7fSPeter Avalos monitor_read_log(struct monitor *pmonitor) 4231c188a7fSPeter Avalos { 4241c188a7fSPeter Avalos Buffer logmsg; 4251c188a7fSPeter Avalos u_int len, level; 4261c188a7fSPeter Avalos char *msg; 4271c188a7fSPeter Avalos 4281c188a7fSPeter Avalos buffer_init(&logmsg); 4291c188a7fSPeter Avalos 4301c188a7fSPeter Avalos /* Read length */ 4311c188a7fSPeter Avalos buffer_append_space(&logmsg, 4); 4321c188a7fSPeter Avalos if (atomicio(read, pmonitor->m_log_recvfd, 4331c188a7fSPeter Avalos buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) { 4341c188a7fSPeter Avalos if (errno == EPIPE) { 43599e85e0dSPeter Avalos buffer_free(&logmsg); 4361c188a7fSPeter Avalos debug("%s: child log fd closed", __func__); 4371c188a7fSPeter Avalos close(pmonitor->m_log_recvfd); 4381c188a7fSPeter Avalos pmonitor->m_log_recvfd = -1; 4391c188a7fSPeter Avalos return -1; 4401c188a7fSPeter Avalos } 4411c188a7fSPeter Avalos fatal("%s: log fd read: %s", __func__, strerror(errno)); 4421c188a7fSPeter Avalos } 4431c188a7fSPeter Avalos len = buffer_get_int(&logmsg); 4441c188a7fSPeter Avalos if (len <= 4 || len > 8192) 4451c188a7fSPeter Avalos fatal("%s: invalid log message length %u", __func__, len); 4461c188a7fSPeter Avalos 4471c188a7fSPeter Avalos /* Read severity, message */ 4481c188a7fSPeter Avalos buffer_clear(&logmsg); 4491c188a7fSPeter Avalos buffer_append_space(&logmsg, len); 4501c188a7fSPeter Avalos if (atomicio(read, pmonitor->m_log_recvfd, 4511c188a7fSPeter Avalos buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) 4521c188a7fSPeter Avalos fatal("%s: log fd read: %s", __func__, strerror(errno)); 4531c188a7fSPeter Avalos 4541c188a7fSPeter Avalos /* Log it */ 4551c188a7fSPeter Avalos level = buffer_get_int(&logmsg); 4561c188a7fSPeter Avalos msg = buffer_get_string(&logmsg, NULL); 4571c188a7fSPeter Avalos if (log_level_name(level) == NULL) 4581c188a7fSPeter Avalos fatal("%s: invalid log level %u (corrupted message?)", 4591c188a7fSPeter Avalos __func__, level); 4601c188a7fSPeter Avalos do_log2(level, "%s [preauth]", msg); 4611c188a7fSPeter Avalos 4621c188a7fSPeter Avalos buffer_free(&logmsg); 46336e94dc5SPeter Avalos free(msg); 4641c188a7fSPeter Avalos 4651c188a7fSPeter Avalos return 0; 4661c188a7fSPeter Avalos } 4671c188a7fSPeter Avalos 46818de8d7fSPeter Avalos int 46918de8d7fSPeter Avalos monitor_read(struct monitor *pmonitor, struct mon_table *ent, 47018de8d7fSPeter Avalos struct mon_table **pent) 47118de8d7fSPeter Avalos { 47218de8d7fSPeter Avalos Buffer m; 47318de8d7fSPeter Avalos int ret; 47418de8d7fSPeter Avalos u_char type; 4751c188a7fSPeter Avalos struct pollfd pfd[2]; 4761c188a7fSPeter Avalos 4771c188a7fSPeter Avalos for (;;) { 47836e94dc5SPeter Avalos memset(&pfd, 0, sizeof(pfd)); 4791c188a7fSPeter Avalos pfd[0].fd = pmonitor->m_sendfd; 4801c188a7fSPeter Avalos pfd[0].events = POLLIN; 4811c188a7fSPeter Avalos pfd[1].fd = pmonitor->m_log_recvfd; 4821c188a7fSPeter Avalos pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; 4831c188a7fSPeter Avalos if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { 4841c188a7fSPeter Avalos if (errno == EINTR || errno == EAGAIN) 4851c188a7fSPeter Avalos continue; 4861c188a7fSPeter Avalos fatal("%s: poll: %s", __func__, strerror(errno)); 4871c188a7fSPeter Avalos } 4881c188a7fSPeter Avalos if (pfd[1].revents) { 4891c188a7fSPeter Avalos /* 4901c188a7fSPeter Avalos * Drain all log messages before processing next 4911c188a7fSPeter Avalos * monitor request. 4921c188a7fSPeter Avalos */ 4931c188a7fSPeter Avalos monitor_read_log(pmonitor); 4941c188a7fSPeter Avalos continue; 4951c188a7fSPeter Avalos } 4961c188a7fSPeter Avalos if (pfd[0].revents) 4971c188a7fSPeter Avalos break; /* Continues below */ 4981c188a7fSPeter Avalos } 49918de8d7fSPeter Avalos 50018de8d7fSPeter Avalos buffer_init(&m); 50118de8d7fSPeter Avalos 50218de8d7fSPeter Avalos mm_request_receive(pmonitor->m_sendfd, &m); 50318de8d7fSPeter Avalos type = buffer_get_char(&m); 50418de8d7fSPeter Avalos 50518de8d7fSPeter Avalos debug3("%s: checking request %d", __func__, type); 50618de8d7fSPeter Avalos 50718de8d7fSPeter Avalos while (ent->f != NULL) { 50818de8d7fSPeter Avalos if (ent->type == type) 50918de8d7fSPeter Avalos break; 51018de8d7fSPeter Avalos ent++; 51118de8d7fSPeter Avalos } 51218de8d7fSPeter Avalos 51318de8d7fSPeter Avalos if (ent->f != NULL) { 51418de8d7fSPeter Avalos if (!(ent->flags & MON_PERMIT)) 51518de8d7fSPeter Avalos fatal("%s: unpermitted request %d", __func__, 51618de8d7fSPeter Avalos type); 51718de8d7fSPeter Avalos ret = (*ent->f)(pmonitor->m_sendfd, &m); 51818de8d7fSPeter Avalos buffer_free(&m); 51918de8d7fSPeter Avalos 52018de8d7fSPeter Avalos /* The child may use this request only once, disable it */ 52118de8d7fSPeter Avalos if (ent->flags & MON_ONCE) { 52218de8d7fSPeter Avalos debug2("%s: %d used once, disabling now", __func__, 52318de8d7fSPeter Avalos type); 52418de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 52518de8d7fSPeter Avalos } 52618de8d7fSPeter Avalos 52718de8d7fSPeter Avalos if (pent != NULL) 52818de8d7fSPeter Avalos *pent = ent; 52918de8d7fSPeter Avalos 53018de8d7fSPeter Avalos return ret; 53118de8d7fSPeter Avalos } 53218de8d7fSPeter Avalos 53318de8d7fSPeter Avalos fatal("%s: unsupported request: %d", __func__, type); 53418de8d7fSPeter Avalos 53518de8d7fSPeter Avalos /* NOTREACHED */ 53618de8d7fSPeter Avalos return (-1); 53718de8d7fSPeter Avalos } 53818de8d7fSPeter Avalos 53918de8d7fSPeter Avalos /* allowed key state */ 54018de8d7fSPeter Avalos static int 54118de8d7fSPeter Avalos monitor_allowed_key(u_char *blob, u_int bloblen) 54218de8d7fSPeter Avalos { 54318de8d7fSPeter Avalos /* make sure key is allowed */ 54418de8d7fSPeter Avalos if (key_blob == NULL || key_bloblen != bloblen || 545856ea928SPeter Avalos timingsafe_bcmp(key_blob, blob, key_bloblen)) 54618de8d7fSPeter Avalos return (0); 54718de8d7fSPeter Avalos return (1); 54818de8d7fSPeter Avalos } 54918de8d7fSPeter Avalos 55018de8d7fSPeter Avalos static void 55118de8d7fSPeter Avalos monitor_reset_key_state(void) 55218de8d7fSPeter Avalos { 55318de8d7fSPeter Avalos /* reset state */ 55436e94dc5SPeter Avalos free(key_blob); 55536e94dc5SPeter Avalos free(hostbased_cuser); 55636e94dc5SPeter Avalos free(hostbased_chost); 55718de8d7fSPeter Avalos key_blob = NULL; 55818de8d7fSPeter Avalos key_bloblen = 0; 55918de8d7fSPeter Avalos key_blobtype = MM_NOKEY; 56018de8d7fSPeter Avalos hostbased_cuser = NULL; 56118de8d7fSPeter Avalos hostbased_chost = NULL; 56218de8d7fSPeter Avalos } 56318de8d7fSPeter Avalos 56436e94dc5SPeter Avalos #ifdef WITH_OPENSSL 56518de8d7fSPeter Avalos int 56618de8d7fSPeter Avalos mm_answer_moduli(int sock, Buffer *m) 56718de8d7fSPeter Avalos { 56818de8d7fSPeter Avalos DH *dh; 56918de8d7fSPeter Avalos int min, want, max; 57018de8d7fSPeter Avalos 57118de8d7fSPeter Avalos min = buffer_get_int(m); 57218de8d7fSPeter Avalos want = buffer_get_int(m); 57318de8d7fSPeter Avalos max = buffer_get_int(m); 57418de8d7fSPeter Avalos 57518de8d7fSPeter Avalos debug3("%s: got parameters: %d %d %d", 57618de8d7fSPeter Avalos __func__, min, want, max); 57718de8d7fSPeter Avalos /* We need to check here, too, in case the child got corrupted */ 57818de8d7fSPeter Avalos if (max < min || want < min || max < want) 57918de8d7fSPeter Avalos fatal("%s: bad parameters: %d %d %d", 58018de8d7fSPeter Avalos __func__, min, want, max); 58118de8d7fSPeter Avalos 58218de8d7fSPeter Avalos buffer_clear(m); 58318de8d7fSPeter Avalos 58418de8d7fSPeter Avalos dh = choose_dh(min, want, max); 58518de8d7fSPeter Avalos if (dh == NULL) { 58618de8d7fSPeter Avalos buffer_put_char(m, 0); 58718de8d7fSPeter Avalos return (0); 58818de8d7fSPeter Avalos } else { 58918de8d7fSPeter Avalos /* Send first bignum */ 59018de8d7fSPeter Avalos buffer_put_char(m, 1); 59118de8d7fSPeter Avalos buffer_put_bignum2(m, dh->p); 59218de8d7fSPeter Avalos buffer_put_bignum2(m, dh->g); 59318de8d7fSPeter Avalos 59418de8d7fSPeter Avalos DH_free(dh); 59518de8d7fSPeter Avalos } 59618de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_MODULI, m); 59718de8d7fSPeter Avalos return (0); 59818de8d7fSPeter Avalos } 59936e94dc5SPeter Avalos #endif 60036e94dc5SPeter Avalos 60118de8d7fSPeter Avalos int 60218de8d7fSPeter Avalos mm_answer_sign(int sock, Buffer *m) 60318de8d7fSPeter Avalos { 604e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 605e9778795SPeter Avalos extern int auth_sock; /* XXX move to state struct? */ 606e9778795SPeter Avalos struct sshkey *key; 607e9778795SPeter Avalos struct sshbuf *sigbuf = NULL; 608e9778795SPeter Avalos u_char *p = NULL, *signature = NULL; 609e9778795SPeter Avalos char *alg = NULL; 610e9778795SPeter Avalos size_t datlen, siglen, alglen; 611e9778795SPeter Avalos int r, is_proof = 0; 612e9778795SPeter Avalos u_int keyid; 613e9778795SPeter Avalos const char proof_req[] = "hostkeys-prove-00@openssh.com"; 61418de8d7fSPeter Avalos 61518de8d7fSPeter Avalos debug3("%s", __func__); 61618de8d7fSPeter Avalos 617e9778795SPeter Avalos if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 618e9778795SPeter Avalos (r = sshbuf_get_string(m, &p, &datlen)) != 0 || 619e9778795SPeter Avalos (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0) 620e9778795SPeter Avalos fatal("%s: buffer error: %s", __func__, ssh_err(r)); 621e9778795SPeter Avalos if (keyid > INT_MAX) 622e9778795SPeter Avalos fatal("%s: invalid key ID", __func__); 62318de8d7fSPeter Avalos 62418de8d7fSPeter Avalos /* 6259f304aafSPeter Avalos * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), 6269f304aafSPeter Avalos * SHA384 (48 bytes) and SHA512 (64 bytes). 627e9778795SPeter Avalos * 628e9778795SPeter Avalos * Otherwise, verify the signature request is for a hostkey 629e9778795SPeter Avalos * proof. 630e9778795SPeter Avalos * 631e9778795SPeter Avalos * XXX perform similar check for KEX signature requests too? 632e9778795SPeter Avalos * it's not trivial, since what is signed is the hash, rather 633e9778795SPeter Avalos * than the full kex structure... 63418de8d7fSPeter Avalos */ 635e9778795SPeter Avalos if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { 636e9778795SPeter Avalos /* 637e9778795SPeter Avalos * Construct expected hostkey proof and compare it to what 638e9778795SPeter Avalos * the client sent us. 639e9778795SPeter Avalos */ 640e9778795SPeter Avalos if (session_id2_len == 0) /* hostkeys is never first */ 641e9778795SPeter Avalos fatal("%s: bad data length: %zu", __func__, datlen); 642e9778795SPeter Avalos if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) 643e9778795SPeter Avalos fatal("%s: no hostkey for index %d", __func__, keyid); 644e9778795SPeter Avalos if ((sigbuf = sshbuf_new()) == NULL) 645e9778795SPeter Avalos fatal("%s: sshbuf_new", __func__); 646e9778795SPeter Avalos if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || 647e9778795SPeter Avalos (r = sshbuf_put_string(sigbuf, session_id2, 648e9778795SPeter Avalos session_id2_len)) != 0 || 649e9778795SPeter Avalos (r = sshkey_puts(key, sigbuf)) != 0) 650e9778795SPeter Avalos fatal("%s: couldn't prepare private key " 651e9778795SPeter Avalos "proof buffer: %s", __func__, ssh_err(r)); 652e9778795SPeter Avalos if (datlen != sshbuf_len(sigbuf) || 653e9778795SPeter Avalos memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) 654e9778795SPeter Avalos fatal("%s: bad data length: %zu, hostkey proof len %zu", 655e9778795SPeter Avalos __func__, datlen, sshbuf_len(sigbuf)); 656e9778795SPeter Avalos sshbuf_free(sigbuf); 657e9778795SPeter Avalos is_proof = 1; 658e9778795SPeter Avalos } 65918de8d7fSPeter Avalos 66018de8d7fSPeter Avalos /* save session id, it will be passed on the first call */ 66118de8d7fSPeter Avalos if (session_id2_len == 0) { 66218de8d7fSPeter Avalos session_id2_len = datlen; 66318de8d7fSPeter Avalos session_id2 = xmalloc(session_id2_len); 66418de8d7fSPeter Avalos memcpy(session_id2, p, session_id2_len); 66518de8d7fSPeter Avalos } 66618de8d7fSPeter Avalos 66736e94dc5SPeter Avalos if ((key = get_hostkey_by_index(keyid)) != NULL) { 668e9778795SPeter Avalos if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, 669e9778795SPeter Avalos datafellows)) != 0) 670e9778795SPeter Avalos fatal("%s: sshkey_sign failed: %s", 671e9778795SPeter Avalos __func__, ssh_err(r)); 672e9778795SPeter Avalos } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 673e9778795SPeter Avalos auth_sock > 0) { 674e9778795SPeter Avalos if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 675e9778795SPeter Avalos p, datlen, alg, datafellows)) != 0) { 676e9778795SPeter Avalos fatal("%s: ssh_agent_sign failed: %s", 677e9778795SPeter Avalos __func__, ssh_err(r)); 678e9778795SPeter Avalos } 67936e94dc5SPeter Avalos } else 68036e94dc5SPeter Avalos fatal("%s: no hostkey from index %d", __func__, keyid); 68118de8d7fSPeter Avalos 682e9778795SPeter Avalos debug3("%s: %s signature %p(%zu)", __func__, 683e9778795SPeter Avalos is_proof ? "KEX" : "hostkey proof", signature, siglen); 68418de8d7fSPeter Avalos 685e9778795SPeter Avalos sshbuf_reset(m); 686e9778795SPeter Avalos if ((r = sshbuf_put_string(m, signature, siglen)) != 0) 687e9778795SPeter Avalos fatal("%s: buffer error: %s", __func__, ssh_err(r)); 68818de8d7fSPeter Avalos 689e9778795SPeter Avalos free(alg); 69036e94dc5SPeter Avalos free(p); 69136e94dc5SPeter Avalos free(signature); 69218de8d7fSPeter Avalos 69318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SIGN, m); 69418de8d7fSPeter Avalos 69518de8d7fSPeter Avalos /* Turn on permissions for getpwnam */ 69618de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 69718de8d7fSPeter Avalos 69818de8d7fSPeter Avalos return (0); 69918de8d7fSPeter Avalos } 70018de8d7fSPeter Avalos 70118de8d7fSPeter Avalos /* Retrieves the password entry and also checks if the user is permitted */ 70218de8d7fSPeter Avalos 70318de8d7fSPeter Avalos int 70418de8d7fSPeter Avalos mm_answer_pwnamallow(int sock, Buffer *m) 70518de8d7fSPeter Avalos { 706*ce74bacaSMatthew Dillon struct ssh *ssh = active_state; /* XXX */ 70718de8d7fSPeter Avalos char *username; 70818de8d7fSPeter Avalos struct passwd *pwent; 70918de8d7fSPeter Avalos int allowed = 0; 7101c188a7fSPeter Avalos u_int i; 71118de8d7fSPeter Avalos 71218de8d7fSPeter Avalos debug3("%s", __func__); 71318de8d7fSPeter Avalos 71418de8d7fSPeter Avalos if (authctxt->attempt++ != 0) 71518de8d7fSPeter Avalos fatal("%s: multiple attempts for getpwnam", __func__); 71618de8d7fSPeter Avalos 71718de8d7fSPeter Avalos username = buffer_get_string(m, NULL); 71818de8d7fSPeter Avalos 71918de8d7fSPeter Avalos pwent = getpwnamallow(username); 72018de8d7fSPeter Avalos 72118de8d7fSPeter Avalos authctxt->user = xstrdup(username); 72218de8d7fSPeter Avalos setproctitle("%s [priv]", pwent ? username : "unknown"); 72336e94dc5SPeter Avalos free(username); 72418de8d7fSPeter Avalos 72518de8d7fSPeter Avalos buffer_clear(m); 72618de8d7fSPeter Avalos 72718de8d7fSPeter Avalos if (pwent == NULL) { 72818de8d7fSPeter Avalos buffer_put_char(m, 0); 72918de8d7fSPeter Avalos authctxt->pw = fakepw(); 73018de8d7fSPeter Avalos goto out; 73118de8d7fSPeter Avalos } 73218de8d7fSPeter Avalos 73318de8d7fSPeter Avalos allowed = 1; 73418de8d7fSPeter Avalos authctxt->pw = pwent; 73518de8d7fSPeter Avalos authctxt->valid = 1; 73618de8d7fSPeter Avalos 73718de8d7fSPeter Avalos buffer_put_char(m, 1); 73818de8d7fSPeter Avalos buffer_put_string(m, pwent, sizeof(struct passwd)); 73918de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_name); 74018de8d7fSPeter Avalos buffer_put_cstring(m, "*"); 74136e94dc5SPeter Avalos #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 74218de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_gecos); 74336e94dc5SPeter Avalos #endif 74436e94dc5SPeter Avalos #ifdef HAVE_STRUCT_PASSWD_PW_CLASS 74518de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_class); 74618de8d7fSPeter Avalos #endif 74718de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_dir); 74818de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_shell); 74918de8d7fSPeter Avalos 75018de8d7fSPeter Avalos out: 751*ce74bacaSMatthew Dillon ssh_packet_set_log_preamble(ssh, "%suser %s", 752*ce74bacaSMatthew Dillon authctxt->valid ? "authenticating" : "invalid ", authctxt->user); 75318de8d7fSPeter Avalos buffer_put_string(m, &options, sizeof(options)); 7541c188a7fSPeter Avalos 7551c188a7fSPeter Avalos #define M_CP_STROPT(x) do { \ 7561c188a7fSPeter Avalos if (options.x != NULL) \ 7571c188a7fSPeter Avalos buffer_put_cstring(m, options.x); \ 7581c188a7fSPeter Avalos } while (0) 7591c188a7fSPeter Avalos #define M_CP_STRARRAYOPT(x, nx) do { \ 7601c188a7fSPeter Avalos for (i = 0; i < options.nx; i++) \ 7611c188a7fSPeter Avalos buffer_put_cstring(m, options.x[i]); \ 7621c188a7fSPeter Avalos } while (0) 763*ce74bacaSMatthew Dillon #define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx) 7641c188a7fSPeter Avalos /* See comment in servconf.h */ 7651c188a7fSPeter Avalos COPY_MATCH_STRING_OPTS(); 7661c188a7fSPeter Avalos #undef M_CP_STROPT 7671c188a7fSPeter Avalos #undef M_CP_STRARRAYOPT 768*ce74bacaSMatthew Dillon #undef M_CP_STRARRAYOPT_ALLOC 7691c188a7fSPeter Avalos 77036e94dc5SPeter Avalos /* Create valid auth method lists */ 771*ce74bacaSMatthew Dillon if (auth2_setup_methods_lists(authctxt) != 0) { 77236e94dc5SPeter Avalos /* 77336e94dc5SPeter Avalos * The monitor will continue long enough to let the child 77436e94dc5SPeter Avalos * run to it's packet_disconnect(), but it must not allow any 77536e94dc5SPeter Avalos * authentication to succeed. 77636e94dc5SPeter Avalos */ 77736e94dc5SPeter Avalos debug("%s: no valid authentication method lists", __func__); 77836e94dc5SPeter Avalos } 77936e94dc5SPeter Avalos 78018de8d7fSPeter Avalos debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); 78118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PWNAM, m); 78218de8d7fSPeter Avalos 78318de8d7fSPeter Avalos /* Allow service/style information on the auth context */ 78418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 78518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 786*ce74bacaSMatthew Dillon 78718de8d7fSPeter Avalos #ifdef USE_PAM 78818de8d7fSPeter Avalos if (options.use_pam) 78918de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); 79018de8d7fSPeter Avalos #endif 79118de8d7fSPeter Avalos 79218de8d7fSPeter Avalos return (0); 79318de8d7fSPeter Avalos } 79418de8d7fSPeter Avalos 79518de8d7fSPeter Avalos int mm_answer_auth2_read_banner(int sock, Buffer *m) 79618de8d7fSPeter Avalos { 79718de8d7fSPeter Avalos char *banner; 79818de8d7fSPeter Avalos 79918de8d7fSPeter Avalos buffer_clear(m); 80018de8d7fSPeter Avalos banner = auth2_read_banner(); 80118de8d7fSPeter Avalos buffer_put_cstring(m, banner != NULL ? banner : ""); 80218de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); 80336e94dc5SPeter Avalos free(banner); 80418de8d7fSPeter Avalos 80518de8d7fSPeter Avalos return (0); 80618de8d7fSPeter Avalos } 80718de8d7fSPeter Avalos 80818de8d7fSPeter Avalos int 80918de8d7fSPeter Avalos mm_answer_authserv(int sock, Buffer *m) 81018de8d7fSPeter Avalos { 81118de8d7fSPeter Avalos monitor_permit_authentications(1); 81218de8d7fSPeter Avalos 81318de8d7fSPeter Avalos authctxt->service = buffer_get_string(m, NULL); 81418de8d7fSPeter Avalos authctxt->style = buffer_get_string(m, NULL); 81518de8d7fSPeter Avalos debug3("%s: service=%s, style=%s", 81618de8d7fSPeter Avalos __func__, authctxt->service, authctxt->style); 81718de8d7fSPeter Avalos 81818de8d7fSPeter Avalos if (strlen(authctxt->style) == 0) { 81936e94dc5SPeter Avalos free(authctxt->style); 82018de8d7fSPeter Avalos authctxt->style = NULL; 82118de8d7fSPeter Avalos } 82218de8d7fSPeter Avalos 82318de8d7fSPeter Avalos return (0); 82418de8d7fSPeter Avalos } 82518de8d7fSPeter Avalos 82618de8d7fSPeter Avalos int 82718de8d7fSPeter Avalos mm_answer_authpassword(int sock, Buffer *m) 82818de8d7fSPeter Avalos { 82918de8d7fSPeter Avalos static int call_count; 83018de8d7fSPeter Avalos char *passwd; 83118de8d7fSPeter Avalos int authenticated; 83218de8d7fSPeter Avalos u_int plen; 83318de8d7fSPeter Avalos 834*ce74bacaSMatthew Dillon if (!options.password_authentication) 835*ce74bacaSMatthew Dillon fatal("%s: password authentication not enabled", __func__); 83618de8d7fSPeter Avalos passwd = buffer_get_string(m, &plen); 83718de8d7fSPeter Avalos /* Only authenticate if the context is valid */ 83818de8d7fSPeter Avalos authenticated = options.password_authentication && 83918de8d7fSPeter Avalos auth_password(authctxt, passwd); 84036e94dc5SPeter Avalos explicit_bzero(passwd, strlen(passwd)); 84136e94dc5SPeter Avalos free(passwd); 84218de8d7fSPeter Avalos 84318de8d7fSPeter Avalos buffer_clear(m); 84418de8d7fSPeter Avalos buffer_put_int(m, authenticated); 845e9778795SPeter Avalos #ifdef USE_PAM 846e9778795SPeter Avalos buffer_put_int(m, sshpam_get_maxtries_reached()); 847e9778795SPeter Avalos #endif 84818de8d7fSPeter Avalos 84918de8d7fSPeter Avalos debug3("%s: sending result %d", __func__, authenticated); 85018de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); 85118de8d7fSPeter Avalos 85218de8d7fSPeter Avalos call_count++; 85318de8d7fSPeter Avalos if (plen == 0 && call_count == 1) 85418de8d7fSPeter Avalos auth_method = "none"; 85518de8d7fSPeter Avalos else 85618de8d7fSPeter Avalos auth_method = "password"; 85718de8d7fSPeter Avalos 85818de8d7fSPeter Avalos /* Causes monitor loop to terminate if authenticated */ 85918de8d7fSPeter Avalos return (authenticated); 86018de8d7fSPeter Avalos } 86118de8d7fSPeter Avalos 86218de8d7fSPeter Avalos #ifdef BSD_AUTH 86318de8d7fSPeter Avalos int 86418de8d7fSPeter Avalos mm_answer_bsdauthquery(int sock, Buffer *m) 86518de8d7fSPeter Avalos { 86618de8d7fSPeter Avalos char *name, *infotxt; 86718de8d7fSPeter Avalos u_int numprompts; 86818de8d7fSPeter Avalos u_int *echo_on; 86918de8d7fSPeter Avalos char **prompts; 87018de8d7fSPeter Avalos u_int success; 87118de8d7fSPeter Avalos 872*ce74bacaSMatthew Dillon if (!options.kbd_interactive_authentication) 873*ce74bacaSMatthew Dillon fatal("%s: kbd-int authentication not enabled", __func__); 87418de8d7fSPeter Avalos success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 87518de8d7fSPeter Avalos &prompts, &echo_on) < 0 ? 0 : 1; 87618de8d7fSPeter Avalos 87718de8d7fSPeter Avalos buffer_clear(m); 87818de8d7fSPeter Avalos buffer_put_int(m, success); 87918de8d7fSPeter Avalos if (success) 88018de8d7fSPeter Avalos buffer_put_cstring(m, prompts[0]); 88118de8d7fSPeter Avalos 88218de8d7fSPeter Avalos debug3("%s: sending challenge success: %u", __func__, success); 88318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); 88418de8d7fSPeter Avalos 88518de8d7fSPeter Avalos if (success) { 88636e94dc5SPeter Avalos free(name); 88736e94dc5SPeter Avalos free(infotxt); 88836e94dc5SPeter Avalos free(prompts); 88936e94dc5SPeter Avalos free(echo_on); 89018de8d7fSPeter Avalos } 89118de8d7fSPeter Avalos 89218de8d7fSPeter Avalos return (0); 89318de8d7fSPeter Avalos } 89418de8d7fSPeter Avalos 89518de8d7fSPeter Avalos int 89618de8d7fSPeter Avalos mm_answer_bsdauthrespond(int sock, Buffer *m) 89718de8d7fSPeter Avalos { 89818de8d7fSPeter Avalos char *response; 89918de8d7fSPeter Avalos int authok; 90018de8d7fSPeter Avalos 901*ce74bacaSMatthew Dillon if (!options.kbd_interactive_authentication) 902*ce74bacaSMatthew Dillon fatal("%s: kbd-int authentication not enabled", __func__); 903e9778795SPeter Avalos if (authctxt->as == NULL) 90418de8d7fSPeter Avalos fatal("%s: no bsd auth session", __func__); 90518de8d7fSPeter Avalos 90618de8d7fSPeter Avalos response = buffer_get_string(m, NULL); 90718de8d7fSPeter Avalos authok = options.challenge_response_authentication && 90818de8d7fSPeter Avalos auth_userresponse(authctxt->as, response, 0); 90918de8d7fSPeter Avalos authctxt->as = NULL; 91018de8d7fSPeter Avalos debug3("%s: <%s> = <%d>", __func__, response, authok); 91136e94dc5SPeter Avalos free(response); 91218de8d7fSPeter Avalos 91318de8d7fSPeter Avalos buffer_clear(m); 91418de8d7fSPeter Avalos buffer_put_int(m, authok); 91518de8d7fSPeter Avalos 91618de8d7fSPeter Avalos debug3("%s: sending authenticated: %d", __func__, authok); 91718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); 91818de8d7fSPeter Avalos 91936e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 92036e94dc5SPeter Avalos auth_submethod = "bsdauth"; 92118de8d7fSPeter Avalos 92218de8d7fSPeter Avalos return (authok != 0); 92318de8d7fSPeter Avalos } 92418de8d7fSPeter Avalos #endif 92518de8d7fSPeter Avalos 92618de8d7fSPeter Avalos #ifdef SKEY 92718de8d7fSPeter Avalos int 92818de8d7fSPeter Avalos mm_answer_skeyquery(int sock, Buffer *m) 92918de8d7fSPeter Avalos { 93018de8d7fSPeter Avalos struct skey skey; 93118de8d7fSPeter Avalos char challenge[1024]; 93218de8d7fSPeter Avalos u_int success; 93318de8d7fSPeter Avalos 93418de8d7fSPeter Avalos success = _compat_skeychallenge(&skey, authctxt->user, challenge, 93518de8d7fSPeter Avalos sizeof(challenge)) < 0 ? 0 : 1; 93618de8d7fSPeter Avalos 93718de8d7fSPeter Avalos buffer_clear(m); 93818de8d7fSPeter Avalos buffer_put_int(m, success); 93918de8d7fSPeter Avalos if (success) 94018de8d7fSPeter Avalos buffer_put_cstring(m, challenge); 94118de8d7fSPeter Avalos 94218de8d7fSPeter Avalos debug3("%s: sending challenge success: %u", __func__, success); 94318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m); 94418de8d7fSPeter Avalos 94518de8d7fSPeter Avalos return (0); 94618de8d7fSPeter Avalos } 94718de8d7fSPeter Avalos 94818de8d7fSPeter Avalos int 94918de8d7fSPeter Avalos mm_answer_skeyrespond(int sock, Buffer *m) 95018de8d7fSPeter Avalos { 95118de8d7fSPeter Avalos char *response; 95218de8d7fSPeter Avalos int authok; 95318de8d7fSPeter Avalos 95418de8d7fSPeter Avalos response = buffer_get_string(m, NULL); 95518de8d7fSPeter Avalos 95618de8d7fSPeter Avalos authok = (options.challenge_response_authentication && 95718de8d7fSPeter Avalos authctxt->valid && 95818de8d7fSPeter Avalos skey_haskey(authctxt->pw->pw_name) == 0 && 95918de8d7fSPeter Avalos skey_passcheck(authctxt->pw->pw_name, response) != -1); 96018de8d7fSPeter Avalos 96136e94dc5SPeter Avalos free(response); 96218de8d7fSPeter Avalos 96318de8d7fSPeter Avalos buffer_clear(m); 96418de8d7fSPeter Avalos buffer_put_int(m, authok); 96518de8d7fSPeter Avalos 96618de8d7fSPeter Avalos debug3("%s: sending authenticated: %d", __func__, authok); 96718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); 96818de8d7fSPeter Avalos 969e9778795SPeter Avalos auth_method = "keyboard-interactive"; 970e9778795SPeter Avalos auth_submethod = "skey"; 97118de8d7fSPeter Avalos 97218de8d7fSPeter Avalos return (authok != 0); 97318de8d7fSPeter Avalos } 97418de8d7fSPeter Avalos #endif 97518de8d7fSPeter Avalos 97618de8d7fSPeter Avalos #ifdef USE_PAM 97718de8d7fSPeter Avalos int 97818de8d7fSPeter Avalos mm_answer_pam_start(int sock, Buffer *m) 97918de8d7fSPeter Avalos { 98018de8d7fSPeter Avalos if (!options.use_pam) 98118de8d7fSPeter Avalos fatal("UsePAM not set, but ended up in %s anyway", __func__); 98218de8d7fSPeter Avalos 98318de8d7fSPeter Avalos start_pam(authctxt); 98418de8d7fSPeter Avalos 98518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); 986*ce74bacaSMatthew Dillon if (options.kbd_interactive_authentication) 987*ce74bacaSMatthew Dillon monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1); 98818de8d7fSPeter Avalos 98918de8d7fSPeter Avalos return (0); 99018de8d7fSPeter Avalos } 99118de8d7fSPeter Avalos 99218de8d7fSPeter Avalos int 99318de8d7fSPeter Avalos mm_answer_pam_account(int sock, Buffer *m) 99418de8d7fSPeter Avalos { 99518de8d7fSPeter Avalos u_int ret; 99618de8d7fSPeter Avalos 99718de8d7fSPeter Avalos if (!options.use_pam) 998*ce74bacaSMatthew Dillon fatal("%s: PAM not enabled", __func__); 99918de8d7fSPeter Avalos 100018de8d7fSPeter Avalos ret = do_pam_account(); 100118de8d7fSPeter Avalos 100218de8d7fSPeter Avalos buffer_put_int(m, ret); 100318de8d7fSPeter Avalos buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 100418de8d7fSPeter Avalos 100518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); 100618de8d7fSPeter Avalos 100718de8d7fSPeter Avalos return (ret); 100818de8d7fSPeter Avalos } 100918de8d7fSPeter Avalos 101018de8d7fSPeter Avalos static void *sshpam_ctxt, *sshpam_authok; 101118de8d7fSPeter Avalos extern KbdintDevice sshpam_device; 101218de8d7fSPeter Avalos 101318de8d7fSPeter Avalos int 101418de8d7fSPeter Avalos mm_answer_pam_init_ctx(int sock, Buffer *m) 101518de8d7fSPeter Avalos { 101618de8d7fSPeter Avalos debug3("%s", __func__); 1017*ce74bacaSMatthew Dillon if (!options.kbd_interactive_authentication) 1018*ce74bacaSMatthew Dillon fatal("%s: kbd-int authentication not enabled", __func__); 1019*ce74bacaSMatthew Dillon if (sshpam_ctxt != NULL) 1020*ce74bacaSMatthew Dillon fatal("%s: already called", __func__); 102118de8d7fSPeter Avalos sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); 102218de8d7fSPeter Avalos sshpam_authok = NULL; 102318de8d7fSPeter Avalos buffer_clear(m); 102418de8d7fSPeter Avalos if (sshpam_ctxt != NULL) { 102518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 1026*ce74bacaSMatthew Dillon monitor_permit(mon_dispatch, MONITOR_REQ_PAM_QUERY, 1); 102718de8d7fSPeter Avalos buffer_put_int(m, 1); 102818de8d7fSPeter Avalos } else { 102918de8d7fSPeter Avalos buffer_put_int(m, 0); 103018de8d7fSPeter Avalos } 103118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); 103218de8d7fSPeter Avalos return (0); 103318de8d7fSPeter Avalos } 103418de8d7fSPeter Avalos 103518de8d7fSPeter Avalos int 103618de8d7fSPeter Avalos mm_answer_pam_query(int sock, Buffer *m) 103718de8d7fSPeter Avalos { 1038856ea928SPeter Avalos char *name = NULL, *info = NULL, **prompts = NULL; 1039856ea928SPeter Avalos u_int i, num = 0, *echo_on = 0; 104018de8d7fSPeter Avalos int ret; 104118de8d7fSPeter Avalos 104218de8d7fSPeter Avalos debug3("%s", __func__); 104318de8d7fSPeter Avalos sshpam_authok = NULL; 1044*ce74bacaSMatthew Dillon if (sshpam_ctxt == NULL) 1045*ce74bacaSMatthew Dillon fatal("%s: no context", __func__); 1046*ce74bacaSMatthew Dillon ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, 1047*ce74bacaSMatthew Dillon &num, &prompts, &echo_on); 104818de8d7fSPeter Avalos if (ret == 0 && num == 0) 104918de8d7fSPeter Avalos sshpam_authok = sshpam_ctxt; 105018de8d7fSPeter Avalos if (num > 1 || name == NULL || info == NULL) 1051*ce74bacaSMatthew Dillon fatal("sshpam_device.query failed"); 1052*ce74bacaSMatthew Dillon monitor_permit(mon_dispatch, MONITOR_REQ_PAM_RESPOND, 1); 105318de8d7fSPeter Avalos buffer_clear(m); 105418de8d7fSPeter Avalos buffer_put_int(m, ret); 105518de8d7fSPeter Avalos buffer_put_cstring(m, name); 105636e94dc5SPeter Avalos free(name); 105718de8d7fSPeter Avalos buffer_put_cstring(m, info); 105836e94dc5SPeter Avalos free(info); 1059e9778795SPeter Avalos buffer_put_int(m, sshpam_get_maxtries_reached()); 106018de8d7fSPeter Avalos buffer_put_int(m, num); 106118de8d7fSPeter Avalos for (i = 0; i < num; ++i) { 106218de8d7fSPeter Avalos buffer_put_cstring(m, prompts[i]); 106336e94dc5SPeter Avalos free(prompts[i]); 106418de8d7fSPeter Avalos buffer_put_int(m, echo_on[i]); 106518de8d7fSPeter Avalos } 106636e94dc5SPeter Avalos free(prompts); 106736e94dc5SPeter Avalos free(echo_on); 106836e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 106936e94dc5SPeter Avalos auth_submethod = "pam"; 107018de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); 107118de8d7fSPeter Avalos return (0); 107218de8d7fSPeter Avalos } 107318de8d7fSPeter Avalos 107418de8d7fSPeter Avalos int 107518de8d7fSPeter Avalos mm_answer_pam_respond(int sock, Buffer *m) 107618de8d7fSPeter Avalos { 107718de8d7fSPeter Avalos char **resp; 107818de8d7fSPeter Avalos u_int i, num; 107918de8d7fSPeter Avalos int ret; 108018de8d7fSPeter Avalos 108118de8d7fSPeter Avalos debug3("%s", __func__); 1082*ce74bacaSMatthew Dillon if (sshpam_ctxt == NULL) 1083*ce74bacaSMatthew Dillon fatal("%s: no context", __func__); 108418de8d7fSPeter Avalos sshpam_authok = NULL; 108518de8d7fSPeter Avalos num = buffer_get_int(m); 108618de8d7fSPeter Avalos if (num > 0) { 108718de8d7fSPeter Avalos resp = xcalloc(num, sizeof(char *)); 108818de8d7fSPeter Avalos for (i = 0; i < num; ++i) 108918de8d7fSPeter Avalos resp[i] = buffer_get_string(m, NULL); 109018de8d7fSPeter Avalos ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); 109118de8d7fSPeter Avalos for (i = 0; i < num; ++i) 109236e94dc5SPeter Avalos free(resp[i]); 109336e94dc5SPeter Avalos free(resp); 109418de8d7fSPeter Avalos } else { 109518de8d7fSPeter Avalos ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); 109618de8d7fSPeter Avalos } 109718de8d7fSPeter Avalos buffer_clear(m); 109818de8d7fSPeter Avalos buffer_put_int(m, ret); 109918de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); 110036e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 110136e94dc5SPeter Avalos auth_submethod = "pam"; 110218de8d7fSPeter Avalos if (ret == 0) 110318de8d7fSPeter Avalos sshpam_authok = sshpam_ctxt; 110418de8d7fSPeter Avalos return (0); 110518de8d7fSPeter Avalos } 110618de8d7fSPeter Avalos 110718de8d7fSPeter Avalos int 110818de8d7fSPeter Avalos mm_answer_pam_free_ctx(int sock, Buffer *m) 110918de8d7fSPeter Avalos { 1110e9778795SPeter Avalos int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; 111118de8d7fSPeter Avalos 111218de8d7fSPeter Avalos debug3("%s", __func__); 1113*ce74bacaSMatthew Dillon if (sshpam_ctxt == NULL) 1114*ce74bacaSMatthew Dillon fatal("%s: no context", __func__); 111518de8d7fSPeter Avalos (sshpam_device.free_ctx)(sshpam_ctxt); 1116e9778795SPeter Avalos sshpam_ctxt = sshpam_authok = NULL; 111718de8d7fSPeter Avalos buffer_clear(m); 111818de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); 1119*ce74bacaSMatthew Dillon /* Allow another attempt */ 1120*ce74bacaSMatthew Dillon monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1); 112136e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 112236e94dc5SPeter Avalos auth_submethod = "pam"; 1123e9778795SPeter Avalos return r; 112418de8d7fSPeter Avalos } 112518de8d7fSPeter Avalos #endif 112618de8d7fSPeter Avalos 112718de8d7fSPeter Avalos int 112818de8d7fSPeter Avalos mm_answer_keyallowed(int sock, Buffer *m) 112918de8d7fSPeter Avalos { 1130*ce74bacaSMatthew Dillon struct sshkey *key; 113118de8d7fSPeter Avalos char *cuser, *chost; 113218de8d7fSPeter Avalos u_char *blob; 1133e9778795SPeter Avalos u_int bloblen, pubkey_auth_attempt; 113418de8d7fSPeter Avalos enum mm_keytype type = 0; 113518de8d7fSPeter Avalos int allowed = 0; 113618de8d7fSPeter Avalos 113718de8d7fSPeter Avalos debug3("%s entering", __func__); 113818de8d7fSPeter Avalos 113918de8d7fSPeter Avalos type = buffer_get_int(m); 114018de8d7fSPeter Avalos cuser = buffer_get_string(m, NULL); 114118de8d7fSPeter Avalos chost = buffer_get_string(m, NULL); 114218de8d7fSPeter Avalos blob = buffer_get_string(m, &bloblen); 1143e9778795SPeter Avalos pubkey_auth_attempt = buffer_get_int(m); 114418de8d7fSPeter Avalos 114518de8d7fSPeter Avalos key = key_from_blob(blob, bloblen); 114618de8d7fSPeter Avalos 114718de8d7fSPeter Avalos debug3("%s: key_from_blob: %p", __func__, key); 114818de8d7fSPeter Avalos 114918de8d7fSPeter Avalos if (key != NULL && authctxt->valid) { 1150e9778795SPeter Avalos /* These should not make it past the privsep child */ 1151e9778795SPeter Avalos if (key_type_plain(key->type) == KEY_RSA && 1152e9778795SPeter Avalos (datafellows & SSH_BUG_RSASIGMD5) != 0) 1153e9778795SPeter Avalos fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); 1154e9778795SPeter Avalos 115518de8d7fSPeter Avalos switch (type) { 115618de8d7fSPeter Avalos case MM_USERKEY: 115718de8d7fSPeter Avalos allowed = options.pubkey_authentication && 1158*ce74bacaSMatthew Dillon !auth2_key_already_used(authctxt, key) && 1159e9778795SPeter Avalos match_pattern_list(sshkey_ssh_name(key), 1160e9778795SPeter Avalos options.pubkey_key_types, 0) == 1 && 1161e9778795SPeter Avalos user_key_allowed(authctxt->pw, key, 1162e9778795SPeter Avalos pubkey_auth_attempt); 116318de8d7fSPeter Avalos auth_method = "publickey"; 1164e9778795SPeter Avalos if (options.pubkey_authentication && 1165e9778795SPeter Avalos (!pubkey_auth_attempt || allowed != 1)) 116618de8d7fSPeter Avalos auth_clear_options(); 116718de8d7fSPeter Avalos break; 116818de8d7fSPeter Avalos case MM_HOSTKEY: 116918de8d7fSPeter Avalos allowed = options.hostbased_authentication && 1170*ce74bacaSMatthew Dillon !auth2_key_already_used(authctxt, key) && 1171e9778795SPeter Avalos match_pattern_list(sshkey_ssh_name(key), 1172e9778795SPeter Avalos options.hostbased_key_types, 0) == 1 && 117318de8d7fSPeter Avalos hostbased_key_allowed(authctxt->pw, 117418de8d7fSPeter Avalos cuser, chost, key); 1175*ce74bacaSMatthew Dillon auth2_record_info(authctxt, 117636e94dc5SPeter Avalos "client user \"%.100s\", client host \"%.100s\"", 117736e94dc5SPeter Avalos cuser, chost); 117818de8d7fSPeter Avalos auth_method = "hostbased"; 117918de8d7fSPeter Avalos break; 118018de8d7fSPeter Avalos default: 118118de8d7fSPeter Avalos fatal("%s: unknown key type %d", __func__, type); 118218de8d7fSPeter Avalos break; 118318de8d7fSPeter Avalos } 118418de8d7fSPeter Avalos } 1185e9778795SPeter Avalos 1186*ce74bacaSMatthew Dillon debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); 1187e9778795SPeter Avalos 1188*ce74bacaSMatthew Dillon auth2_record_key(authctxt, 0, key); 1189*ce74bacaSMatthew Dillon sshkey_free(key); 119018de8d7fSPeter Avalos 119118de8d7fSPeter Avalos /* clear temporarily storage (used by verify) */ 119218de8d7fSPeter Avalos monitor_reset_key_state(); 119318de8d7fSPeter Avalos 119418de8d7fSPeter Avalos if (allowed) { 119518de8d7fSPeter Avalos /* Save temporarily for comparison in verify */ 119618de8d7fSPeter Avalos key_blob = blob; 119718de8d7fSPeter Avalos key_bloblen = bloblen; 119818de8d7fSPeter Avalos key_blobtype = type; 119918de8d7fSPeter Avalos hostbased_cuser = cuser; 120018de8d7fSPeter Avalos hostbased_chost = chost; 120118de8d7fSPeter Avalos } else { 120218de8d7fSPeter Avalos /* Log failed attempt */ 120336e94dc5SPeter Avalos auth_log(authctxt, 0, 0, auth_method, NULL); 120436e94dc5SPeter Avalos free(blob); 120536e94dc5SPeter Avalos free(cuser); 120636e94dc5SPeter Avalos free(chost); 120718de8d7fSPeter Avalos } 120818de8d7fSPeter Avalos 120918de8d7fSPeter Avalos buffer_clear(m); 121018de8d7fSPeter Avalos buffer_put_int(m, allowed); 121118de8d7fSPeter Avalos buffer_put_int(m, forced_command != NULL); 121218de8d7fSPeter Avalos 121318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); 121418de8d7fSPeter Avalos 121518de8d7fSPeter Avalos return (0); 121618de8d7fSPeter Avalos } 121718de8d7fSPeter Avalos 121818de8d7fSPeter Avalos static int 121918de8d7fSPeter Avalos monitor_valid_userblob(u_char *data, u_int datalen) 122018de8d7fSPeter Avalos { 122118de8d7fSPeter Avalos Buffer b; 1222e9778795SPeter Avalos u_char *p; 1223e9778795SPeter Avalos char *userstyle, *cp; 122418de8d7fSPeter Avalos u_int len; 122518de8d7fSPeter Avalos int fail = 0; 122618de8d7fSPeter Avalos 122718de8d7fSPeter Avalos buffer_init(&b); 122818de8d7fSPeter Avalos buffer_append(&b, data, datalen); 122918de8d7fSPeter Avalos 123018de8d7fSPeter Avalos if (datafellows & SSH_OLD_SESSIONID) { 123118de8d7fSPeter Avalos p = buffer_ptr(&b); 123218de8d7fSPeter Avalos len = buffer_len(&b); 123318de8d7fSPeter Avalos if ((session_id2 == NULL) || 123418de8d7fSPeter Avalos (len < session_id2_len) || 1235856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 123618de8d7fSPeter Avalos fail++; 123718de8d7fSPeter Avalos buffer_consume(&b, session_id2_len); 123818de8d7fSPeter Avalos } else { 123918de8d7fSPeter Avalos p = buffer_get_string(&b, &len); 124018de8d7fSPeter Avalos if ((session_id2 == NULL) || 124118de8d7fSPeter Avalos (len != session_id2_len) || 1242856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 124318de8d7fSPeter Avalos fail++; 124436e94dc5SPeter Avalos free(p); 124518de8d7fSPeter Avalos } 124618de8d7fSPeter Avalos if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 124718de8d7fSPeter Avalos fail++; 1248e9778795SPeter Avalos cp = buffer_get_cstring(&b, NULL); 124936e94dc5SPeter Avalos xasprintf(&userstyle, "%s%s%s", authctxt->user, 125036e94dc5SPeter Avalos authctxt->style ? ":" : "", 125136e94dc5SPeter Avalos authctxt->style ? authctxt->style : ""); 1252e9778795SPeter Avalos if (strcmp(userstyle, cp) != 0) { 1253e9778795SPeter Avalos logit("wrong user name passed to monitor: " 1254e9778795SPeter Avalos "expected %s != %.100s", userstyle, cp); 125518de8d7fSPeter Avalos fail++; 125618de8d7fSPeter Avalos } 125736e94dc5SPeter Avalos free(userstyle); 1258e9778795SPeter Avalos free(cp); 125918de8d7fSPeter Avalos buffer_skip_string(&b); 126018de8d7fSPeter Avalos if (datafellows & SSH_BUG_PKAUTH) { 126118de8d7fSPeter Avalos if (!buffer_get_char(&b)) 126218de8d7fSPeter Avalos fail++; 126318de8d7fSPeter Avalos } else { 1264e9778795SPeter Avalos cp = buffer_get_cstring(&b, NULL); 1265e9778795SPeter Avalos if (strcmp("publickey", cp) != 0) 126618de8d7fSPeter Avalos fail++; 1267e9778795SPeter Avalos free(cp); 126818de8d7fSPeter Avalos if (!buffer_get_char(&b)) 126918de8d7fSPeter Avalos fail++; 127018de8d7fSPeter Avalos buffer_skip_string(&b); 127118de8d7fSPeter Avalos } 127218de8d7fSPeter Avalos buffer_skip_string(&b); 127318de8d7fSPeter Avalos if (buffer_len(&b) != 0) 127418de8d7fSPeter Avalos fail++; 127518de8d7fSPeter Avalos buffer_free(&b); 127618de8d7fSPeter Avalos return (fail == 0); 127718de8d7fSPeter Avalos } 127818de8d7fSPeter Avalos 127918de8d7fSPeter Avalos static int 128018de8d7fSPeter Avalos monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 128118de8d7fSPeter Avalos char *chost) 128218de8d7fSPeter Avalos { 128318de8d7fSPeter Avalos Buffer b; 128436e94dc5SPeter Avalos char *p, *userstyle; 128518de8d7fSPeter Avalos u_int len; 128618de8d7fSPeter Avalos int fail = 0; 128718de8d7fSPeter Avalos 128818de8d7fSPeter Avalos buffer_init(&b); 128918de8d7fSPeter Avalos buffer_append(&b, data, datalen); 129018de8d7fSPeter Avalos 129118de8d7fSPeter Avalos p = buffer_get_string(&b, &len); 129218de8d7fSPeter Avalos if ((session_id2 == NULL) || 129318de8d7fSPeter Avalos (len != session_id2_len) || 1294856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 129518de8d7fSPeter Avalos fail++; 129636e94dc5SPeter Avalos free(p); 129718de8d7fSPeter Avalos 129818de8d7fSPeter Avalos if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 129918de8d7fSPeter Avalos fail++; 130036e94dc5SPeter Avalos p = buffer_get_cstring(&b, NULL); 130136e94dc5SPeter Avalos xasprintf(&userstyle, "%s%s%s", authctxt->user, 130236e94dc5SPeter Avalos authctxt->style ? ":" : "", 130336e94dc5SPeter Avalos authctxt->style ? authctxt->style : ""); 130436e94dc5SPeter Avalos if (strcmp(userstyle, p) != 0) { 130518de8d7fSPeter Avalos logit("wrong user name passed to monitor: expected %s != %.100s", 130636e94dc5SPeter Avalos userstyle, p); 130718de8d7fSPeter Avalos fail++; 130818de8d7fSPeter Avalos } 130936e94dc5SPeter Avalos free(userstyle); 131036e94dc5SPeter Avalos free(p); 131118de8d7fSPeter Avalos buffer_skip_string(&b); /* service */ 131236e94dc5SPeter Avalos p = buffer_get_cstring(&b, NULL); 131318de8d7fSPeter Avalos if (strcmp(p, "hostbased") != 0) 131418de8d7fSPeter Avalos fail++; 131536e94dc5SPeter Avalos free(p); 131618de8d7fSPeter Avalos buffer_skip_string(&b); /* pkalg */ 131718de8d7fSPeter Avalos buffer_skip_string(&b); /* pkblob */ 131818de8d7fSPeter Avalos 131918de8d7fSPeter Avalos /* verify client host, strip trailing dot if necessary */ 132018de8d7fSPeter Avalos p = buffer_get_string(&b, NULL); 132118de8d7fSPeter Avalos if (((len = strlen(p)) > 0) && p[len - 1] == '.') 132218de8d7fSPeter Avalos p[len - 1] = '\0'; 132318de8d7fSPeter Avalos if (strcmp(p, chost) != 0) 132418de8d7fSPeter Avalos fail++; 132536e94dc5SPeter Avalos free(p); 132618de8d7fSPeter Avalos 132718de8d7fSPeter Avalos /* verify client user */ 132818de8d7fSPeter Avalos p = buffer_get_string(&b, NULL); 132918de8d7fSPeter Avalos if (strcmp(p, cuser) != 0) 133018de8d7fSPeter Avalos fail++; 133136e94dc5SPeter Avalos free(p); 133218de8d7fSPeter Avalos 133318de8d7fSPeter Avalos if (buffer_len(&b) != 0) 133418de8d7fSPeter Avalos fail++; 133518de8d7fSPeter Avalos buffer_free(&b); 133618de8d7fSPeter Avalos return (fail == 0); 133718de8d7fSPeter Avalos } 133818de8d7fSPeter Avalos 133918de8d7fSPeter Avalos int 1340*ce74bacaSMatthew Dillon mm_answer_keyverify(int sock, struct sshbuf *m) 134118de8d7fSPeter Avalos { 1342*ce74bacaSMatthew Dillon struct sshkey *key; 134318de8d7fSPeter Avalos u_char *signature, *data, *blob; 1344*ce74bacaSMatthew Dillon size_t signaturelen, datalen, bloblen; 1345*ce74bacaSMatthew Dillon int r, ret, valid_data = 0, encoded_ret; 134618de8d7fSPeter Avalos 1347*ce74bacaSMatthew Dillon if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || 1348*ce74bacaSMatthew Dillon (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || 1349*ce74bacaSMatthew Dillon (r = sshbuf_get_string(m, &data, &datalen)) != 0) 1350*ce74bacaSMatthew Dillon fatal("%s: buffer error: %s", __func__, ssh_err(r)); 135118de8d7fSPeter Avalos 135218de8d7fSPeter Avalos if (hostbased_cuser == NULL || hostbased_chost == NULL || 135318de8d7fSPeter Avalos !monitor_allowed_key(blob, bloblen)) 135418de8d7fSPeter Avalos fatal("%s: bad key, not previously allowed", __func__); 135518de8d7fSPeter Avalos 1356*ce74bacaSMatthew Dillon /* XXX use sshkey_froms here; need to change key_blob, etc. */ 1357*ce74bacaSMatthew Dillon if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) 1358*ce74bacaSMatthew Dillon fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); 135918de8d7fSPeter Avalos 136018de8d7fSPeter Avalos switch (key_blobtype) { 136118de8d7fSPeter Avalos case MM_USERKEY: 136218de8d7fSPeter Avalos valid_data = monitor_valid_userblob(data, datalen); 1363*ce74bacaSMatthew Dillon auth_method = "publickey"; 136418de8d7fSPeter Avalos break; 136518de8d7fSPeter Avalos case MM_HOSTKEY: 136618de8d7fSPeter Avalos valid_data = monitor_valid_hostbasedblob(data, datalen, 136718de8d7fSPeter Avalos hostbased_cuser, hostbased_chost); 1368*ce74bacaSMatthew Dillon auth_method = "hostbased"; 136918de8d7fSPeter Avalos break; 137018de8d7fSPeter Avalos default: 137118de8d7fSPeter Avalos valid_data = 0; 137218de8d7fSPeter Avalos break; 137318de8d7fSPeter Avalos } 137418de8d7fSPeter Avalos if (!valid_data) 137518de8d7fSPeter Avalos fatal("%s: bad signature data blob", __func__); 137618de8d7fSPeter Avalos 1377*ce74bacaSMatthew Dillon ret = sshkey_verify(key, signature, signaturelen, data, datalen, 1378*ce74bacaSMatthew Dillon active_state->compat); 1379*ce74bacaSMatthew Dillon debug3("%s: %s %p signature %s", __func__, auth_method, key, 1380*ce74bacaSMatthew Dillon (ret == 0) ? "verified" : "unverified"); 1381*ce74bacaSMatthew Dillon auth2_record_key(authctxt, ret == 0, key); 1382e9778795SPeter Avalos 138336e94dc5SPeter Avalos free(blob); 138436e94dc5SPeter Avalos free(signature); 138536e94dc5SPeter Avalos free(data); 138618de8d7fSPeter Avalos 138718de8d7fSPeter Avalos monitor_reset_key_state(); 138818de8d7fSPeter Avalos 1389*ce74bacaSMatthew Dillon sshkey_free(key); 1390*ce74bacaSMatthew Dillon sshbuf_reset(m); 1391*ce74bacaSMatthew Dillon 1392*ce74bacaSMatthew Dillon /* encode ret != 0 as positive integer, since we're sending u32 */ 1393*ce74bacaSMatthew Dillon encoded_ret = (ret != 0); 1394*ce74bacaSMatthew Dillon if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) 1395*ce74bacaSMatthew Dillon fatal("%s: buffer error: %s", __func__, ssh_err(r)); 139618de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 139718de8d7fSPeter Avalos 1398*ce74bacaSMatthew Dillon return ret == 0; 139918de8d7fSPeter Avalos } 140018de8d7fSPeter Avalos 140118de8d7fSPeter Avalos static void 140218de8d7fSPeter Avalos mm_record_login(Session *s, struct passwd *pw) 140318de8d7fSPeter Avalos { 1404e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 140518de8d7fSPeter Avalos socklen_t fromlen; 140618de8d7fSPeter Avalos struct sockaddr_storage from; 140718de8d7fSPeter Avalos 140818de8d7fSPeter Avalos /* 140918de8d7fSPeter Avalos * Get IP address of client. If the connection is not a socket, let 141018de8d7fSPeter Avalos * the address be 0.0.0.0. 141118de8d7fSPeter Avalos */ 141218de8d7fSPeter Avalos memset(&from, 0, sizeof(from)); 141318de8d7fSPeter Avalos fromlen = sizeof(from); 141418de8d7fSPeter Avalos if (packet_connection_is_on_socket()) { 141518de8d7fSPeter Avalos if (getpeername(packet_get_connection_in(), 141618de8d7fSPeter Avalos (struct sockaddr *)&from, &fromlen) < 0) { 141718de8d7fSPeter Avalos debug("getpeername: %.100s", strerror(errno)); 141818de8d7fSPeter Avalos cleanup_exit(255); 141918de8d7fSPeter Avalos } 142018de8d7fSPeter Avalos } 142118de8d7fSPeter Avalos /* Record that there was a login on that tty from the remote host. */ 142218de8d7fSPeter Avalos record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 1423e9778795SPeter Avalos session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), 142418de8d7fSPeter Avalos (struct sockaddr *)&from, fromlen); 142518de8d7fSPeter Avalos } 142618de8d7fSPeter Avalos 142718de8d7fSPeter Avalos static void 142818de8d7fSPeter Avalos mm_session_close(Session *s) 142918de8d7fSPeter Avalos { 143018de8d7fSPeter Avalos debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); 143118de8d7fSPeter Avalos if (s->ttyfd != -1) { 143218de8d7fSPeter Avalos debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); 143318de8d7fSPeter Avalos session_pty_cleanup2(s); 143418de8d7fSPeter Avalos } 143518de8d7fSPeter Avalos session_unused(s->self); 143618de8d7fSPeter Avalos } 143718de8d7fSPeter Avalos 143818de8d7fSPeter Avalos int 143918de8d7fSPeter Avalos mm_answer_pty(int sock, Buffer *m) 144018de8d7fSPeter Avalos { 144118de8d7fSPeter Avalos extern struct monitor *pmonitor; 144218de8d7fSPeter Avalos Session *s; 144318de8d7fSPeter Avalos int res, fd0; 144418de8d7fSPeter Avalos 144518de8d7fSPeter Avalos debug3("%s entering", __func__); 144618de8d7fSPeter Avalos 144718de8d7fSPeter Avalos buffer_clear(m); 144818de8d7fSPeter Avalos s = session_new(); 144918de8d7fSPeter Avalos if (s == NULL) 145018de8d7fSPeter Avalos goto error; 145118de8d7fSPeter Avalos s->authctxt = authctxt; 145218de8d7fSPeter Avalos s->pw = authctxt->pw; 145318de8d7fSPeter Avalos s->pid = pmonitor->m_pid; 145418de8d7fSPeter Avalos res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 145518de8d7fSPeter Avalos if (res == 0) 145618de8d7fSPeter Avalos goto error; 145718de8d7fSPeter Avalos pty_setowner(authctxt->pw, s->tty); 145818de8d7fSPeter Avalos 145918de8d7fSPeter Avalos buffer_put_int(m, 1); 146018de8d7fSPeter Avalos buffer_put_cstring(m, s->tty); 146118de8d7fSPeter Avalos 146218de8d7fSPeter Avalos /* We need to trick ttyslot */ 146318de8d7fSPeter Avalos if (dup2(s->ttyfd, 0) == -1) 146418de8d7fSPeter Avalos fatal("%s: dup2", __func__); 146518de8d7fSPeter Avalos 146618de8d7fSPeter Avalos mm_record_login(s, authctxt->pw); 146718de8d7fSPeter Avalos 146818de8d7fSPeter Avalos /* Now we can close the file descriptor again */ 146918de8d7fSPeter Avalos close(0); 147018de8d7fSPeter Avalos 147118de8d7fSPeter Avalos /* send messages generated by record_login */ 147218de8d7fSPeter Avalos buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 147318de8d7fSPeter Avalos buffer_clear(&loginmsg); 147418de8d7fSPeter Avalos 147518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PTY, m); 147618de8d7fSPeter Avalos 147718de8d7fSPeter Avalos if (mm_send_fd(sock, s->ptyfd) == -1 || 147818de8d7fSPeter Avalos mm_send_fd(sock, s->ttyfd) == -1) 147918de8d7fSPeter Avalos fatal("%s: send fds failed", __func__); 148018de8d7fSPeter Avalos 148118de8d7fSPeter Avalos /* make sure nothing uses fd 0 */ 148218de8d7fSPeter Avalos if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 148318de8d7fSPeter Avalos fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); 148418de8d7fSPeter Avalos if (fd0 != 0) 148518de8d7fSPeter Avalos error("%s: fd0 %d != 0", __func__, fd0); 148618de8d7fSPeter Avalos 148718de8d7fSPeter Avalos /* slave is not needed */ 148818de8d7fSPeter Avalos close(s->ttyfd); 148918de8d7fSPeter Avalos s->ttyfd = s->ptyfd; 149018de8d7fSPeter Avalos /* no need to dup() because nobody closes ptyfd */ 149118de8d7fSPeter Avalos s->ptymaster = s->ptyfd; 149218de8d7fSPeter Avalos 149318de8d7fSPeter Avalos debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); 149418de8d7fSPeter Avalos 149518de8d7fSPeter Avalos return (0); 149618de8d7fSPeter Avalos 149718de8d7fSPeter Avalos error: 149818de8d7fSPeter Avalos if (s != NULL) 149918de8d7fSPeter Avalos mm_session_close(s); 150018de8d7fSPeter Avalos buffer_put_int(m, 0); 150118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PTY, m); 150218de8d7fSPeter Avalos return (0); 150318de8d7fSPeter Avalos } 150418de8d7fSPeter Avalos 150518de8d7fSPeter Avalos int 150618de8d7fSPeter Avalos mm_answer_pty_cleanup(int sock, Buffer *m) 150718de8d7fSPeter Avalos { 150818de8d7fSPeter Avalos Session *s; 150918de8d7fSPeter Avalos char *tty; 151018de8d7fSPeter Avalos 151118de8d7fSPeter Avalos debug3("%s entering", __func__); 151218de8d7fSPeter Avalos 151318de8d7fSPeter Avalos tty = buffer_get_string(m, NULL); 151418de8d7fSPeter Avalos if ((s = session_by_tty(tty)) != NULL) 151518de8d7fSPeter Avalos mm_session_close(s); 151618de8d7fSPeter Avalos buffer_clear(m); 151736e94dc5SPeter Avalos free(tty); 151818de8d7fSPeter Avalos return (0); 151918de8d7fSPeter Avalos } 152018de8d7fSPeter Avalos 152118de8d7fSPeter Avalos int 152218de8d7fSPeter Avalos mm_answer_term(int sock, Buffer *req) 152318de8d7fSPeter Avalos { 1524*ce74bacaSMatthew Dillon struct ssh *ssh = active_state; /* XXX */ 152518de8d7fSPeter Avalos extern struct monitor *pmonitor; 152618de8d7fSPeter Avalos int res, status; 152718de8d7fSPeter Avalos 152818de8d7fSPeter Avalos debug3("%s: tearing down sessions", __func__); 152918de8d7fSPeter Avalos 153018de8d7fSPeter Avalos /* The child is terminating */ 1531*ce74bacaSMatthew Dillon session_destroy_all(ssh, &mm_session_close); 153218de8d7fSPeter Avalos 153318de8d7fSPeter Avalos #ifdef USE_PAM 153418de8d7fSPeter Avalos if (options.use_pam) 153518de8d7fSPeter Avalos sshpam_cleanup(); 153618de8d7fSPeter Avalos #endif 153718de8d7fSPeter Avalos 153818de8d7fSPeter Avalos while (waitpid(pmonitor->m_pid, &status, 0) == -1) 153918de8d7fSPeter Avalos if (errno != EINTR) 154018de8d7fSPeter Avalos exit(1); 154118de8d7fSPeter Avalos 154218de8d7fSPeter Avalos res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 154318de8d7fSPeter Avalos 154418de8d7fSPeter Avalos /* Terminate process */ 154518de8d7fSPeter Avalos exit(res); 154618de8d7fSPeter Avalos } 154718de8d7fSPeter Avalos 154818de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 154918de8d7fSPeter Avalos /* Report that an audit event occurred */ 155018de8d7fSPeter Avalos int 155118de8d7fSPeter Avalos mm_answer_audit_event(int socket, Buffer *m) 155218de8d7fSPeter Avalos { 155318de8d7fSPeter Avalos ssh_audit_event_t event; 155418de8d7fSPeter Avalos 155518de8d7fSPeter Avalos debug3("%s entering", __func__); 155618de8d7fSPeter Avalos 155718de8d7fSPeter Avalos event = buffer_get_int(m); 155818de8d7fSPeter Avalos switch(event) { 155918de8d7fSPeter Avalos case SSH_AUTH_FAIL_PUBKEY: 156018de8d7fSPeter Avalos case SSH_AUTH_FAIL_HOSTBASED: 156118de8d7fSPeter Avalos case SSH_AUTH_FAIL_GSSAPI: 156218de8d7fSPeter Avalos case SSH_LOGIN_EXCEED_MAXTRIES: 156318de8d7fSPeter Avalos case SSH_LOGIN_ROOT_DENIED: 156418de8d7fSPeter Avalos case SSH_CONNECTION_CLOSE: 156518de8d7fSPeter Avalos case SSH_INVALID_USER: 156618de8d7fSPeter Avalos audit_event(event); 156718de8d7fSPeter Avalos break; 156818de8d7fSPeter Avalos default: 156918de8d7fSPeter Avalos fatal("Audit event type %d not permitted", event); 157018de8d7fSPeter Avalos } 157118de8d7fSPeter Avalos 157218de8d7fSPeter Avalos return (0); 157318de8d7fSPeter Avalos } 157418de8d7fSPeter Avalos 157518de8d7fSPeter Avalos int 157618de8d7fSPeter Avalos mm_answer_audit_command(int socket, Buffer *m) 157718de8d7fSPeter Avalos { 157818de8d7fSPeter Avalos u_int len; 157918de8d7fSPeter Avalos char *cmd; 158018de8d7fSPeter Avalos 158118de8d7fSPeter Avalos debug3("%s entering", __func__); 158218de8d7fSPeter Avalos cmd = buffer_get_string(m, &len); 158318de8d7fSPeter Avalos /* sanity check command, if so how? */ 158418de8d7fSPeter Avalos audit_run_command(cmd); 158536e94dc5SPeter Avalos free(cmd); 158618de8d7fSPeter Avalos return (0); 158718de8d7fSPeter Avalos } 158818de8d7fSPeter Avalos #endif /* SSH_AUDIT_EVENTS */ 158918de8d7fSPeter Avalos 159018de8d7fSPeter Avalos void 1591*ce74bacaSMatthew Dillon monitor_clear_keystate(struct monitor *pmonitor) 1592*ce74bacaSMatthew Dillon { 1593*ce74bacaSMatthew Dillon struct ssh *ssh = active_state; /* XXX */ 1594*ce74bacaSMatthew Dillon 1595*ce74bacaSMatthew Dillon ssh_clear_newkeys(ssh, MODE_IN); 1596*ce74bacaSMatthew Dillon ssh_clear_newkeys(ssh, MODE_OUT); 1597*ce74bacaSMatthew Dillon sshbuf_free(child_state); 1598*ce74bacaSMatthew Dillon child_state = NULL; 1599*ce74bacaSMatthew Dillon } 1600*ce74bacaSMatthew Dillon 1601*ce74bacaSMatthew Dillon void 160218de8d7fSPeter Avalos monitor_apply_keystate(struct monitor *pmonitor) 160318de8d7fSPeter Avalos { 1604e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 1605e9778795SPeter Avalos struct kex *kex; 1606e9778795SPeter Avalos int r; 160718de8d7fSPeter Avalos 1608e9778795SPeter Avalos debug3("%s: packet_set_state", __func__); 1609e9778795SPeter Avalos if ((r = ssh_packet_set_state(ssh, child_state)) != 0) 1610e9778795SPeter Avalos fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); 1611e9778795SPeter Avalos sshbuf_free(child_state); 1612e9778795SPeter Avalos child_state = NULL; 161318de8d7fSPeter Avalos 1614e9778795SPeter Avalos if ((kex = ssh->kex) != NULL) { 1615e9778795SPeter Avalos /* XXX set callbacks */ 161636e94dc5SPeter Avalos #ifdef WITH_OPENSSL 161718de8d7fSPeter Avalos kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 161818de8d7fSPeter Avalos kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1619e9778795SPeter Avalos kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 1620e9778795SPeter Avalos kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 1621e9778795SPeter Avalos kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 162218de8d7fSPeter Avalos kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 162318de8d7fSPeter Avalos kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1624e9778795SPeter Avalos # ifdef OPENSSL_HAS_ECC 16259f304aafSPeter Avalos kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 162636e94dc5SPeter Avalos # endif 1627e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 162836e94dc5SPeter Avalos kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1629856ea928SPeter Avalos kex->load_host_public_key=&get_hostkey_public_by_type; 1630856ea928SPeter Avalos kex->load_host_private_key=&get_hostkey_private_by_type; 163118de8d7fSPeter Avalos kex->host_key_index=&get_hostkey_index; 163236e94dc5SPeter Avalos kex->sign = sshd_hostkey_sign; 1633e9778795SPeter Avalos } 163418de8d7fSPeter Avalos } 163518de8d7fSPeter Avalos 163618de8d7fSPeter Avalos /* This function requries careful sanity checking */ 163718de8d7fSPeter Avalos 163818de8d7fSPeter Avalos void 163918de8d7fSPeter Avalos mm_get_keystate(struct monitor *pmonitor) 164018de8d7fSPeter Avalos { 164118de8d7fSPeter Avalos debug3("%s: Waiting for new keys", __func__); 164218de8d7fSPeter Avalos 1643e9778795SPeter Avalos if ((child_state = sshbuf_new()) == NULL) 1644e9778795SPeter Avalos fatal("%s: sshbuf_new failed", __func__); 1645e9778795SPeter Avalos mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, 1646e9778795SPeter Avalos child_state); 1647e9778795SPeter Avalos debug3("%s: GOT new keys", __func__); 164818de8d7fSPeter Avalos } 164918de8d7fSPeter Avalos 165018de8d7fSPeter Avalos 165118de8d7fSPeter Avalos /* XXX */ 165218de8d7fSPeter Avalos 165318de8d7fSPeter Avalos #define FD_CLOSEONEXEC(x) do { \ 16541c188a7fSPeter Avalos if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ 165518de8d7fSPeter Avalos fatal("fcntl(%d, F_SETFD)", x); \ 165618de8d7fSPeter Avalos } while (0) 165718de8d7fSPeter Avalos 165818de8d7fSPeter Avalos static void 16591c188a7fSPeter Avalos monitor_openfds(struct monitor *mon, int do_logfds) 166018de8d7fSPeter Avalos { 16611c188a7fSPeter Avalos int pair[2]; 1662*ce74bacaSMatthew Dillon #ifdef SO_ZEROIZE 1663*ce74bacaSMatthew Dillon int on = 1; 1664*ce74bacaSMatthew Dillon #endif 16651c188a7fSPeter Avalos 166618de8d7fSPeter Avalos if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 16671c188a7fSPeter Avalos fatal("%s: socketpair: %s", __func__, strerror(errno)); 1668*ce74bacaSMatthew Dillon #ifdef SO_ZEROIZE 1669*ce74bacaSMatthew Dillon if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) 1670*ce74bacaSMatthew Dillon error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); 1671*ce74bacaSMatthew Dillon if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) 1672*ce74bacaSMatthew Dillon error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); 1673*ce74bacaSMatthew Dillon #endif 167418de8d7fSPeter Avalos FD_CLOSEONEXEC(pair[0]); 167518de8d7fSPeter Avalos FD_CLOSEONEXEC(pair[1]); 16761c188a7fSPeter Avalos mon->m_recvfd = pair[0]; 16771c188a7fSPeter Avalos mon->m_sendfd = pair[1]; 16781c188a7fSPeter Avalos 16791c188a7fSPeter Avalos if (do_logfds) { 16801c188a7fSPeter Avalos if (pipe(pair) == -1) 16811c188a7fSPeter Avalos fatal("%s: pipe: %s", __func__, strerror(errno)); 16821c188a7fSPeter Avalos FD_CLOSEONEXEC(pair[0]); 16831c188a7fSPeter Avalos FD_CLOSEONEXEC(pair[1]); 16841c188a7fSPeter Avalos mon->m_log_recvfd = pair[0]; 16851c188a7fSPeter Avalos mon->m_log_sendfd = pair[1]; 16861c188a7fSPeter Avalos } else 16871c188a7fSPeter Avalos mon->m_log_recvfd = mon->m_log_sendfd = -1; 168818de8d7fSPeter Avalos } 168918de8d7fSPeter Avalos 169018de8d7fSPeter Avalos #define MM_MEMSIZE 65536 169118de8d7fSPeter Avalos 169218de8d7fSPeter Avalos struct monitor * 169318de8d7fSPeter Avalos monitor_init(void) 169418de8d7fSPeter Avalos { 169518de8d7fSPeter Avalos struct monitor *mon; 169618de8d7fSPeter Avalos 169718de8d7fSPeter Avalos mon = xcalloc(1, sizeof(*mon)); 16981c188a7fSPeter Avalos monitor_openfds(mon, 1); 169918de8d7fSPeter Avalos 170018de8d7fSPeter Avalos return mon; 170118de8d7fSPeter Avalos } 170218de8d7fSPeter Avalos 170318de8d7fSPeter Avalos void 170418de8d7fSPeter Avalos monitor_reinit(struct monitor *mon) 170518de8d7fSPeter Avalos { 17061c188a7fSPeter Avalos monitor_openfds(mon, 0); 170718de8d7fSPeter Avalos } 170818de8d7fSPeter Avalos 170918de8d7fSPeter Avalos #ifdef GSSAPI 171018de8d7fSPeter Avalos int 171118de8d7fSPeter Avalos mm_answer_gss_setup_ctx(int sock, Buffer *m) 171218de8d7fSPeter Avalos { 171318de8d7fSPeter Avalos gss_OID_desc goid; 171418de8d7fSPeter Avalos OM_uint32 major; 171518de8d7fSPeter Avalos u_int len; 171618de8d7fSPeter Avalos 1717*ce74bacaSMatthew Dillon if (!options.gss_authentication) 1718*ce74bacaSMatthew Dillon fatal("%s: GSSAPI authentication not enabled", __func__); 1719*ce74bacaSMatthew Dillon 172018de8d7fSPeter Avalos goid.elements = buffer_get_string(m, &len); 172118de8d7fSPeter Avalos goid.length = len; 172218de8d7fSPeter Avalos 172318de8d7fSPeter Avalos major = ssh_gssapi_server_ctx(&gsscontext, &goid); 172418de8d7fSPeter Avalos 172536e94dc5SPeter Avalos free(goid.elements); 172618de8d7fSPeter Avalos 172718de8d7fSPeter Avalos buffer_clear(m); 172818de8d7fSPeter Avalos buffer_put_int(m, major); 172918de8d7fSPeter Avalos 173018de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); 173118de8d7fSPeter Avalos 173218de8d7fSPeter Avalos /* Now we have a context, enable the step */ 173318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); 173418de8d7fSPeter Avalos 173518de8d7fSPeter Avalos return (0); 173618de8d7fSPeter Avalos } 173718de8d7fSPeter Avalos 173818de8d7fSPeter Avalos int 173918de8d7fSPeter Avalos mm_answer_gss_accept_ctx(int sock, Buffer *m) 174018de8d7fSPeter Avalos { 174118de8d7fSPeter Avalos gss_buffer_desc in; 174218de8d7fSPeter Avalos gss_buffer_desc out = GSS_C_EMPTY_BUFFER; 174318de8d7fSPeter Avalos OM_uint32 major, minor; 174418de8d7fSPeter Avalos OM_uint32 flags = 0; /* GSI needs this */ 174518de8d7fSPeter Avalos u_int len; 174618de8d7fSPeter Avalos 1747*ce74bacaSMatthew Dillon if (!options.gss_authentication) 1748*ce74bacaSMatthew Dillon fatal("%s: GSSAPI authentication not enabled", __func__); 1749*ce74bacaSMatthew Dillon 175018de8d7fSPeter Avalos in.value = buffer_get_string(m, &len); 175118de8d7fSPeter Avalos in.length = len; 175218de8d7fSPeter Avalos major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 175336e94dc5SPeter Avalos free(in.value); 175418de8d7fSPeter Avalos 175518de8d7fSPeter Avalos buffer_clear(m); 175618de8d7fSPeter Avalos buffer_put_int(m, major); 175718de8d7fSPeter Avalos buffer_put_string(m, out.value, out.length); 175818de8d7fSPeter Avalos buffer_put_int(m, flags); 175918de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); 176018de8d7fSPeter Avalos 176118de8d7fSPeter Avalos gss_release_buffer(&minor, &out); 176218de8d7fSPeter Avalos 176318de8d7fSPeter Avalos if (major == GSS_S_COMPLETE) { 176418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 176518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 176618de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 176718de8d7fSPeter Avalos } 176818de8d7fSPeter Avalos return (0); 176918de8d7fSPeter Avalos } 177018de8d7fSPeter Avalos 177118de8d7fSPeter Avalos int 177218de8d7fSPeter Avalos mm_answer_gss_checkmic(int sock, Buffer *m) 177318de8d7fSPeter Avalos { 177418de8d7fSPeter Avalos gss_buffer_desc gssbuf, mic; 177518de8d7fSPeter Avalos OM_uint32 ret; 177618de8d7fSPeter Avalos u_int len; 177718de8d7fSPeter Avalos 1778*ce74bacaSMatthew Dillon if (!options.gss_authentication) 1779*ce74bacaSMatthew Dillon fatal("%s: GSSAPI authentication not enabled", __func__); 1780*ce74bacaSMatthew Dillon 178118de8d7fSPeter Avalos gssbuf.value = buffer_get_string(m, &len); 178218de8d7fSPeter Avalos gssbuf.length = len; 178318de8d7fSPeter Avalos mic.value = buffer_get_string(m, &len); 178418de8d7fSPeter Avalos mic.length = len; 178518de8d7fSPeter Avalos 178618de8d7fSPeter Avalos ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); 178718de8d7fSPeter Avalos 178836e94dc5SPeter Avalos free(gssbuf.value); 178936e94dc5SPeter Avalos free(mic.value); 179018de8d7fSPeter Avalos 179118de8d7fSPeter Avalos buffer_clear(m); 179218de8d7fSPeter Avalos buffer_put_int(m, ret); 179318de8d7fSPeter Avalos 179418de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); 179518de8d7fSPeter Avalos 179618de8d7fSPeter Avalos if (!GSS_ERROR(ret)) 179718de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 179818de8d7fSPeter Avalos 179918de8d7fSPeter Avalos return (0); 180018de8d7fSPeter Avalos } 180118de8d7fSPeter Avalos 180218de8d7fSPeter Avalos int 180318de8d7fSPeter Avalos mm_answer_gss_userok(int sock, Buffer *m) 180418de8d7fSPeter Avalos { 180518de8d7fSPeter Avalos int authenticated; 1806*ce74bacaSMatthew Dillon const char *displayname; 1807*ce74bacaSMatthew Dillon 1808*ce74bacaSMatthew Dillon if (!options.gss_authentication) 1809*ce74bacaSMatthew Dillon fatal("%s: GSSAPI authentication not enabled", __func__); 181018de8d7fSPeter Avalos 181118de8d7fSPeter Avalos authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 181218de8d7fSPeter Avalos 181318de8d7fSPeter Avalos buffer_clear(m); 181418de8d7fSPeter Avalos buffer_put_int(m, authenticated); 181518de8d7fSPeter Avalos 181618de8d7fSPeter Avalos debug3("%s: sending result %d", __func__, authenticated); 181718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); 181818de8d7fSPeter Avalos 181918de8d7fSPeter Avalos auth_method = "gssapi-with-mic"; 182018de8d7fSPeter Avalos 1821*ce74bacaSMatthew Dillon if ((displayname = ssh_gssapi_displayname()) != NULL) 1822*ce74bacaSMatthew Dillon auth2_record_info(authctxt, "%s", displayname); 1823*ce74bacaSMatthew Dillon 182418de8d7fSPeter Avalos /* Monitor loop will terminate if authenticated */ 182518de8d7fSPeter Avalos return (authenticated); 182618de8d7fSPeter Avalos } 182718de8d7fSPeter Avalos #endif /* GSSAPI */ 1828cb5eb4f1SPeter Avalos 1829