1*e9778795SPeter Avalos /* $OpenBSD: monitor.c,v 1.161 2016/07/22 03:39:13 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> 37*e9778795SPeter 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> 43*e9778795SPeter Avalos #ifdef HAVE_STDINT_H 44*e9778795SPeter Avalos #include <stdint.h> 45*e9778795SPeter 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" 78*e9778795SPeter 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 #include "monitor_mm.h" 9818de8d7fSPeter Avalos #ifdef GSSAPI 9918de8d7fSPeter Avalos #include "ssh-gss.h" 10018de8d7fSPeter Avalos #endif 10118de8d7fSPeter Avalos #include "monitor_wrap.h" 10218de8d7fSPeter Avalos #include "monitor_fdpass.h" 10318de8d7fSPeter Avalos #include "compat.h" 10418de8d7fSPeter Avalos #include "ssh2.h" 10536e94dc5SPeter Avalos #include "authfd.h" 106*e9778795SPeter Avalos #include "match.h" 107*e9778795SPeter Avalos #include "ssherr.h" 10818de8d7fSPeter Avalos 10918de8d7fSPeter Avalos #ifdef GSSAPI 11018de8d7fSPeter Avalos static Gssctxt *gsscontext = NULL; 11118de8d7fSPeter Avalos #endif 11218de8d7fSPeter Avalos 11318de8d7fSPeter Avalos /* Imports */ 11418de8d7fSPeter Avalos extern ServerOptions options; 11518de8d7fSPeter Avalos extern u_int utmp_len; 11618de8d7fSPeter Avalos extern u_char session_id[]; 11718de8d7fSPeter Avalos extern Buffer auth_debug; 11818de8d7fSPeter Avalos extern int auth_debug_init; 11918de8d7fSPeter Avalos extern Buffer loginmsg; 12018de8d7fSPeter Avalos 12118de8d7fSPeter Avalos /* State exported from the child */ 122*e9778795SPeter Avalos static struct sshbuf *child_state; 12318de8d7fSPeter Avalos 12418de8d7fSPeter Avalos /* Functions on the monitor that answer unprivileged requests */ 12518de8d7fSPeter Avalos 12618de8d7fSPeter Avalos int mm_answer_moduli(int, Buffer *); 12718de8d7fSPeter Avalos int mm_answer_sign(int, Buffer *); 12818de8d7fSPeter Avalos int mm_answer_pwnamallow(int, Buffer *); 12918de8d7fSPeter Avalos int mm_answer_auth2_read_banner(int, Buffer *); 13018de8d7fSPeter Avalos int mm_answer_authserv(int, Buffer *); 13118de8d7fSPeter Avalos int mm_answer_authpassword(int, Buffer *); 13218de8d7fSPeter Avalos int mm_answer_bsdauthquery(int, Buffer *); 13318de8d7fSPeter Avalos int mm_answer_bsdauthrespond(int, Buffer *); 13418de8d7fSPeter Avalos int mm_answer_skeyquery(int, Buffer *); 13518de8d7fSPeter Avalos int mm_answer_skeyrespond(int, Buffer *); 13618de8d7fSPeter Avalos int mm_answer_keyallowed(int, Buffer *); 13718de8d7fSPeter Avalos int mm_answer_keyverify(int, Buffer *); 13818de8d7fSPeter Avalos int mm_answer_pty(int, Buffer *); 13918de8d7fSPeter Avalos int mm_answer_pty_cleanup(int, Buffer *); 14018de8d7fSPeter Avalos int mm_answer_term(int, Buffer *); 14118de8d7fSPeter Avalos int mm_answer_rsa_keyallowed(int, Buffer *); 14218de8d7fSPeter Avalos int mm_answer_rsa_challenge(int, Buffer *); 14318de8d7fSPeter Avalos int mm_answer_rsa_response(int, Buffer *); 14418de8d7fSPeter Avalos int mm_answer_sesskey(int, Buffer *); 14518de8d7fSPeter Avalos int mm_answer_sessid(int, Buffer *); 14618de8d7fSPeter Avalos 14718de8d7fSPeter Avalos #ifdef USE_PAM 14818de8d7fSPeter Avalos int mm_answer_pam_start(int, Buffer *); 14918de8d7fSPeter Avalos int mm_answer_pam_account(int, Buffer *); 15018de8d7fSPeter Avalos int mm_answer_pam_init_ctx(int, Buffer *); 15118de8d7fSPeter Avalos int mm_answer_pam_query(int, Buffer *); 15218de8d7fSPeter Avalos int mm_answer_pam_respond(int, Buffer *); 15318de8d7fSPeter Avalos int mm_answer_pam_free_ctx(int, Buffer *); 15418de8d7fSPeter Avalos #endif 15518de8d7fSPeter Avalos 15618de8d7fSPeter Avalos #ifdef GSSAPI 15718de8d7fSPeter Avalos int mm_answer_gss_setup_ctx(int, Buffer *); 15818de8d7fSPeter Avalos int mm_answer_gss_accept_ctx(int, Buffer *); 15918de8d7fSPeter Avalos int mm_answer_gss_userok(int, Buffer *); 16018de8d7fSPeter Avalos int mm_answer_gss_checkmic(int, Buffer *); 16118de8d7fSPeter Avalos #endif 16218de8d7fSPeter Avalos 16318de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 16418de8d7fSPeter Avalos int mm_answer_audit_event(int, Buffer *); 16518de8d7fSPeter Avalos int mm_answer_audit_command(int, Buffer *); 16618de8d7fSPeter Avalos #endif 16718de8d7fSPeter Avalos 1681c188a7fSPeter Avalos static int monitor_read_log(struct monitor *); 1691c188a7fSPeter Avalos 17018de8d7fSPeter Avalos static Authctxt *authctxt; 17136e94dc5SPeter Avalos 17236e94dc5SPeter Avalos #ifdef WITH_SSH1 17318de8d7fSPeter Avalos static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 17436e94dc5SPeter Avalos #endif 17518de8d7fSPeter Avalos 17618de8d7fSPeter Avalos /* local state for key verify */ 17718de8d7fSPeter Avalos static u_char *key_blob = NULL; 17818de8d7fSPeter Avalos static u_int key_bloblen = 0; 17918de8d7fSPeter Avalos static int key_blobtype = MM_NOKEY; 18018de8d7fSPeter Avalos static char *hostbased_cuser = NULL; 18118de8d7fSPeter Avalos static char *hostbased_chost = NULL; 18218de8d7fSPeter Avalos static char *auth_method = "unknown"; 18336e94dc5SPeter Avalos static char *auth_submethod = NULL; 18418de8d7fSPeter Avalos static u_int session_id2_len = 0; 18518de8d7fSPeter Avalos static u_char *session_id2 = NULL; 18618de8d7fSPeter Avalos static pid_t monitor_child_pid; 18718de8d7fSPeter Avalos 18818de8d7fSPeter Avalos struct mon_table { 18918de8d7fSPeter Avalos enum monitor_reqtype type; 19018de8d7fSPeter Avalos int flags; 19118de8d7fSPeter Avalos int (*f)(int, Buffer *); 19218de8d7fSPeter Avalos }; 19318de8d7fSPeter Avalos 19418de8d7fSPeter Avalos #define MON_ISAUTH 0x0004 /* Required for Authentication */ 19518de8d7fSPeter Avalos #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ 19618de8d7fSPeter Avalos #define MON_ONCE 0x0010 /* Disable after calling */ 19718de8d7fSPeter Avalos #define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ 19818de8d7fSPeter Avalos 19918de8d7fSPeter Avalos #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) 20018de8d7fSPeter Avalos 20118de8d7fSPeter Avalos #define MON_PERMIT 0x1000 /* Request is permitted */ 20218de8d7fSPeter Avalos 20318de8d7fSPeter Avalos struct mon_table mon_dispatch_proto20[] = { 20436e94dc5SPeter Avalos #ifdef WITH_OPENSSL 20518de8d7fSPeter Avalos {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 20636e94dc5SPeter Avalos #endif 20718de8d7fSPeter Avalos {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 20818de8d7fSPeter Avalos {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 20918de8d7fSPeter Avalos {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 21018de8d7fSPeter Avalos {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 21118de8d7fSPeter Avalos {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 21218de8d7fSPeter Avalos #ifdef USE_PAM 21318de8d7fSPeter Avalos {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 21418de8d7fSPeter Avalos {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 21518de8d7fSPeter Avalos {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 21618de8d7fSPeter Avalos {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 21718de8d7fSPeter Avalos {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 21818de8d7fSPeter Avalos {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 21918de8d7fSPeter Avalos #endif 22018de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 22118de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 22218de8d7fSPeter Avalos #endif 22318de8d7fSPeter Avalos #ifdef BSD_AUTH 22418de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 22518de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 22618de8d7fSPeter Avalos #endif 22718de8d7fSPeter Avalos #ifdef SKEY 22818de8d7fSPeter Avalos {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 22918de8d7fSPeter Avalos {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 23018de8d7fSPeter Avalos #endif 23118de8d7fSPeter Avalos {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, 23218de8d7fSPeter Avalos {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, 23318de8d7fSPeter Avalos #ifdef GSSAPI 23418de8d7fSPeter Avalos {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, 23518de8d7fSPeter Avalos {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, 23618de8d7fSPeter Avalos {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 23718de8d7fSPeter Avalos {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 23818de8d7fSPeter Avalos #endif 23918de8d7fSPeter Avalos {0, 0, NULL} 24018de8d7fSPeter Avalos }; 24118de8d7fSPeter Avalos 24218de8d7fSPeter Avalos struct mon_table mon_dispatch_postauth20[] = { 24336e94dc5SPeter Avalos #ifdef WITH_OPENSSL 24418de8d7fSPeter Avalos {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 24536e94dc5SPeter Avalos #endif 24618de8d7fSPeter Avalos {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 24718de8d7fSPeter Avalos {MONITOR_REQ_PTY, 0, mm_answer_pty}, 24818de8d7fSPeter Avalos {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 24918de8d7fSPeter Avalos {MONITOR_REQ_TERM, 0, mm_answer_term}, 25018de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 25118de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 25218de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 25318de8d7fSPeter Avalos #endif 25418de8d7fSPeter Avalos {0, 0, NULL} 25518de8d7fSPeter Avalos }; 25618de8d7fSPeter Avalos 25718de8d7fSPeter Avalos struct mon_table mon_dispatch_proto15[] = { 25836e94dc5SPeter Avalos #ifdef WITH_SSH1 25918de8d7fSPeter Avalos {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 26018de8d7fSPeter Avalos {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, 26118de8d7fSPeter Avalos {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, 26218de8d7fSPeter Avalos {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 26318de8d7fSPeter Avalos {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, 26418de8d7fSPeter Avalos {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, 26518de8d7fSPeter Avalos {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, 26618de8d7fSPeter Avalos {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, 26718de8d7fSPeter Avalos #ifdef BSD_AUTH 26818de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 26918de8d7fSPeter Avalos {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 27018de8d7fSPeter Avalos #endif 27118de8d7fSPeter Avalos #ifdef SKEY 27218de8d7fSPeter Avalos {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 27318de8d7fSPeter Avalos {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 27418de8d7fSPeter Avalos #endif 27518de8d7fSPeter Avalos #ifdef USE_PAM 27618de8d7fSPeter Avalos {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 27718de8d7fSPeter Avalos {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 27818de8d7fSPeter Avalos {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 27918de8d7fSPeter Avalos {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 28018de8d7fSPeter Avalos {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 28118de8d7fSPeter Avalos {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 28218de8d7fSPeter Avalos #endif 28318de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 28418de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 28518de8d7fSPeter Avalos #endif 28636e94dc5SPeter Avalos #endif /* WITH_SSH1 */ 28718de8d7fSPeter Avalos {0, 0, NULL} 28818de8d7fSPeter Avalos }; 28918de8d7fSPeter Avalos 29018de8d7fSPeter Avalos struct mon_table mon_dispatch_postauth15[] = { 29136e94dc5SPeter Avalos #ifdef WITH_SSH1 29218de8d7fSPeter Avalos {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, 29318de8d7fSPeter Avalos {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, 29418de8d7fSPeter Avalos {MONITOR_REQ_TERM, 0, mm_answer_term}, 29518de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 29618de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 29718de8d7fSPeter Avalos {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, 29818de8d7fSPeter Avalos #endif 29936e94dc5SPeter Avalos #endif /* WITH_SSH1 */ 30018de8d7fSPeter Avalos {0, 0, NULL} 30118de8d7fSPeter Avalos }; 30218de8d7fSPeter Avalos 30318de8d7fSPeter Avalos struct mon_table *mon_dispatch; 30418de8d7fSPeter Avalos 30518de8d7fSPeter Avalos /* Specifies if a certain message is allowed at the moment */ 30618de8d7fSPeter Avalos 30718de8d7fSPeter Avalos static void 30818de8d7fSPeter Avalos monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) 30918de8d7fSPeter Avalos { 31018de8d7fSPeter Avalos while (ent->f != NULL) { 31118de8d7fSPeter Avalos if (ent->type == type) { 31218de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 31318de8d7fSPeter Avalos ent->flags |= permit ? MON_PERMIT : 0; 31418de8d7fSPeter Avalos return; 31518de8d7fSPeter Avalos } 31618de8d7fSPeter Avalos ent++; 31718de8d7fSPeter Avalos } 31818de8d7fSPeter Avalos } 31918de8d7fSPeter Avalos 32018de8d7fSPeter Avalos static void 32118de8d7fSPeter Avalos monitor_permit_authentications(int permit) 32218de8d7fSPeter Avalos { 32318de8d7fSPeter Avalos struct mon_table *ent = mon_dispatch; 32418de8d7fSPeter Avalos 32518de8d7fSPeter Avalos while (ent->f != NULL) { 32618de8d7fSPeter Avalos if (ent->flags & MON_AUTH) { 32718de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 32818de8d7fSPeter Avalos ent->flags |= permit ? MON_PERMIT : 0; 32918de8d7fSPeter Avalos } 33018de8d7fSPeter Avalos ent++; 33118de8d7fSPeter Avalos } 33218de8d7fSPeter Avalos } 33318de8d7fSPeter Avalos 33418de8d7fSPeter Avalos void 33518de8d7fSPeter Avalos monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 33618de8d7fSPeter Avalos { 33718de8d7fSPeter Avalos struct mon_table *ent; 33836e94dc5SPeter Avalos int authenticated = 0, partial = 0; 33918de8d7fSPeter Avalos 34018de8d7fSPeter Avalos debug3("preauth child monitor started"); 34118de8d7fSPeter Avalos 3421c188a7fSPeter Avalos close(pmonitor->m_recvfd); 3431c188a7fSPeter Avalos close(pmonitor->m_log_sendfd); 3441c188a7fSPeter Avalos pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; 3451c188a7fSPeter Avalos 34618de8d7fSPeter Avalos authctxt = _authctxt; 34718de8d7fSPeter Avalos memset(authctxt, 0, sizeof(*authctxt)); 34818de8d7fSPeter Avalos 34918de8d7fSPeter Avalos authctxt->loginmsg = &loginmsg; 35018de8d7fSPeter Avalos 35118de8d7fSPeter Avalos if (compat20) { 35218de8d7fSPeter Avalos mon_dispatch = mon_dispatch_proto20; 35318de8d7fSPeter Avalos 35418de8d7fSPeter Avalos /* Permit requests for moduli and signatures */ 35518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 35618de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 35718de8d7fSPeter Avalos } else { 35818de8d7fSPeter Avalos mon_dispatch = mon_dispatch_proto15; 35918de8d7fSPeter Avalos 36018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); 36118de8d7fSPeter Avalos } 36218de8d7fSPeter Avalos 36318de8d7fSPeter Avalos /* The first few requests do not require asynchronous access */ 36418de8d7fSPeter Avalos while (!authenticated) { 36536e94dc5SPeter Avalos partial = 0; 36618de8d7fSPeter Avalos auth_method = "unknown"; 36736e94dc5SPeter Avalos auth_submethod = NULL; 36818de8d7fSPeter Avalos authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); 36936e94dc5SPeter Avalos 37036e94dc5SPeter Avalos /* Special handling for multiple required authentications */ 37136e94dc5SPeter Avalos if (options.num_auth_methods != 0) { 37236e94dc5SPeter Avalos if (!compat20) 37336e94dc5SPeter Avalos fatal("AuthenticationMethods is not supported" 37436e94dc5SPeter Avalos "with SSH protocol 1"); 37536e94dc5SPeter Avalos if (authenticated && 37636e94dc5SPeter Avalos !auth2_update_methods_lists(authctxt, 37736e94dc5SPeter Avalos auth_method, auth_submethod)) { 37836e94dc5SPeter Avalos debug3("%s: method %s: partial", __func__, 37936e94dc5SPeter Avalos auth_method); 38036e94dc5SPeter Avalos authenticated = 0; 38136e94dc5SPeter Avalos partial = 1; 38236e94dc5SPeter Avalos } 38336e94dc5SPeter Avalos } 38436e94dc5SPeter Avalos 38518de8d7fSPeter Avalos if (authenticated) { 38618de8d7fSPeter Avalos if (!(ent->flags & MON_AUTHDECIDE)) 38718de8d7fSPeter Avalos fatal("%s: unexpected authentication from %d", 38818de8d7fSPeter Avalos __func__, ent->type); 38918de8d7fSPeter Avalos if (authctxt->pw->pw_uid == 0 && 39018de8d7fSPeter Avalos !auth_root_allowed(auth_method)) 39118de8d7fSPeter Avalos authenticated = 0; 39218de8d7fSPeter Avalos #ifdef USE_PAM 39318de8d7fSPeter Avalos /* PAM needs to perform account checks after auth */ 39418de8d7fSPeter Avalos if (options.use_pam && authenticated) { 39518de8d7fSPeter Avalos Buffer m; 39618de8d7fSPeter Avalos 39718de8d7fSPeter Avalos buffer_init(&m); 39818de8d7fSPeter Avalos mm_request_receive_expect(pmonitor->m_sendfd, 39918de8d7fSPeter Avalos MONITOR_REQ_PAM_ACCOUNT, &m); 40018de8d7fSPeter Avalos authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m); 40118de8d7fSPeter Avalos buffer_free(&m); 40218de8d7fSPeter Avalos } 40318de8d7fSPeter Avalos #endif 40418de8d7fSPeter Avalos } 40518de8d7fSPeter Avalos if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { 40636e94dc5SPeter Avalos auth_log(authctxt, authenticated, partial, 40736e94dc5SPeter Avalos auth_method, auth_submethod); 408*e9778795SPeter Avalos if (!partial && !authenticated) 40918de8d7fSPeter Avalos authctxt->failures++; 41018de8d7fSPeter Avalos } 411cb5eb4f1SPeter Avalos } 4121c188a7fSPeter Avalos 41318de8d7fSPeter Avalos if (!authctxt->valid) 41418de8d7fSPeter Avalos fatal("%s: authenticated invalid user", __func__); 41518de8d7fSPeter Avalos if (strcmp(auth_method, "unknown") == 0) 41618de8d7fSPeter Avalos fatal("%s: authentication method name unknown", __func__); 41718de8d7fSPeter Avalos 41818de8d7fSPeter Avalos debug("%s: %s has been authenticated by privileged process", 41918de8d7fSPeter Avalos __func__, authctxt->user); 42018de8d7fSPeter Avalos 42118de8d7fSPeter Avalos mm_get_keystate(pmonitor); 4221c188a7fSPeter Avalos 42336e94dc5SPeter Avalos /* Drain any buffered messages from the child */ 42436e94dc5SPeter Avalos while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) 42536e94dc5SPeter Avalos ; 42636e94dc5SPeter Avalos 4271c188a7fSPeter Avalos close(pmonitor->m_sendfd); 4281c188a7fSPeter Avalos close(pmonitor->m_log_recvfd); 4291c188a7fSPeter Avalos pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 43018de8d7fSPeter Avalos } 43118de8d7fSPeter Avalos 43218de8d7fSPeter Avalos static void 43318de8d7fSPeter Avalos monitor_set_child_handler(pid_t pid) 43418de8d7fSPeter Avalos { 43518de8d7fSPeter Avalos monitor_child_pid = pid; 43618de8d7fSPeter Avalos } 43718de8d7fSPeter Avalos 43818de8d7fSPeter Avalos static void 43918de8d7fSPeter Avalos monitor_child_handler(int sig) 44018de8d7fSPeter Avalos { 44118de8d7fSPeter Avalos kill(monitor_child_pid, sig); 44218de8d7fSPeter Avalos } 44318de8d7fSPeter Avalos 44418de8d7fSPeter Avalos void 44518de8d7fSPeter Avalos monitor_child_postauth(struct monitor *pmonitor) 44618de8d7fSPeter Avalos { 4471c188a7fSPeter Avalos close(pmonitor->m_recvfd); 4481c188a7fSPeter Avalos pmonitor->m_recvfd = -1; 4491c188a7fSPeter Avalos 45018de8d7fSPeter Avalos monitor_set_child_handler(pmonitor->m_pid); 45118de8d7fSPeter Avalos signal(SIGHUP, &monitor_child_handler); 45218de8d7fSPeter Avalos signal(SIGTERM, &monitor_child_handler); 45318de8d7fSPeter Avalos signal(SIGINT, &monitor_child_handler); 45436e94dc5SPeter Avalos #ifdef SIGXFSZ 45536e94dc5SPeter Avalos signal(SIGXFSZ, SIG_IGN); 45636e94dc5SPeter Avalos #endif 45718de8d7fSPeter Avalos 45818de8d7fSPeter Avalos if (compat20) { 45918de8d7fSPeter Avalos mon_dispatch = mon_dispatch_postauth20; 46018de8d7fSPeter Avalos 46118de8d7fSPeter Avalos /* Permit requests for moduli and signatures */ 46218de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 46318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 46418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 46518de8d7fSPeter Avalos } else { 46618de8d7fSPeter Avalos mon_dispatch = mon_dispatch_postauth15; 46718de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 46818de8d7fSPeter Avalos } 46918de8d7fSPeter Avalos if (!no_pty_flag) { 47018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 47118de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 47218de8d7fSPeter Avalos } 47318de8d7fSPeter Avalos 47418de8d7fSPeter Avalos for (;;) 47518de8d7fSPeter Avalos monitor_read(pmonitor, mon_dispatch, NULL); 47618de8d7fSPeter Avalos } 47718de8d7fSPeter Avalos 47818de8d7fSPeter Avalos void 47918de8d7fSPeter Avalos monitor_sync(struct monitor *pmonitor) 48018de8d7fSPeter Avalos { 48118de8d7fSPeter Avalos if (options.compression) { 48218de8d7fSPeter Avalos /* The member allocation is not visible, so sync it */ 48318de8d7fSPeter Avalos mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); 48418de8d7fSPeter Avalos } 48518de8d7fSPeter Avalos } 48618de8d7fSPeter Avalos 487*e9778795SPeter Avalos /* Allocation functions for zlib */ 488*e9778795SPeter Avalos static void * 489*e9778795SPeter Avalos mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) 490*e9778795SPeter Avalos { 491*e9778795SPeter Avalos if (size == 0 || ncount == 0 || ncount > SIZE_MAX / size) 492*e9778795SPeter Avalos fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); 493*e9778795SPeter Avalos 494*e9778795SPeter Avalos return mm_malloc(mm, size * ncount); 495*e9778795SPeter Avalos } 496*e9778795SPeter Avalos 497*e9778795SPeter Avalos static void 498*e9778795SPeter Avalos mm_zfree(struct mm_master *mm, void *address) 499*e9778795SPeter Avalos { 500*e9778795SPeter Avalos mm_free(mm, address); 501*e9778795SPeter Avalos } 502*e9778795SPeter Avalos 5031c188a7fSPeter Avalos static int 5041c188a7fSPeter Avalos monitor_read_log(struct monitor *pmonitor) 5051c188a7fSPeter Avalos { 5061c188a7fSPeter Avalos Buffer logmsg; 5071c188a7fSPeter Avalos u_int len, level; 5081c188a7fSPeter Avalos char *msg; 5091c188a7fSPeter Avalos 5101c188a7fSPeter Avalos buffer_init(&logmsg); 5111c188a7fSPeter Avalos 5121c188a7fSPeter Avalos /* Read length */ 5131c188a7fSPeter Avalos buffer_append_space(&logmsg, 4); 5141c188a7fSPeter Avalos if (atomicio(read, pmonitor->m_log_recvfd, 5151c188a7fSPeter Avalos buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) { 5161c188a7fSPeter Avalos if (errno == EPIPE) { 51799e85e0dSPeter Avalos buffer_free(&logmsg); 5181c188a7fSPeter Avalos debug("%s: child log fd closed", __func__); 5191c188a7fSPeter Avalos close(pmonitor->m_log_recvfd); 5201c188a7fSPeter Avalos pmonitor->m_log_recvfd = -1; 5211c188a7fSPeter Avalos return -1; 5221c188a7fSPeter Avalos } 5231c188a7fSPeter Avalos fatal("%s: log fd read: %s", __func__, strerror(errno)); 5241c188a7fSPeter Avalos } 5251c188a7fSPeter Avalos len = buffer_get_int(&logmsg); 5261c188a7fSPeter Avalos if (len <= 4 || len > 8192) 5271c188a7fSPeter Avalos fatal("%s: invalid log message length %u", __func__, len); 5281c188a7fSPeter Avalos 5291c188a7fSPeter Avalos /* Read severity, message */ 5301c188a7fSPeter Avalos buffer_clear(&logmsg); 5311c188a7fSPeter Avalos buffer_append_space(&logmsg, len); 5321c188a7fSPeter Avalos if (atomicio(read, pmonitor->m_log_recvfd, 5331c188a7fSPeter Avalos buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) 5341c188a7fSPeter Avalos fatal("%s: log fd read: %s", __func__, strerror(errno)); 5351c188a7fSPeter Avalos 5361c188a7fSPeter Avalos /* Log it */ 5371c188a7fSPeter Avalos level = buffer_get_int(&logmsg); 5381c188a7fSPeter Avalos msg = buffer_get_string(&logmsg, NULL); 5391c188a7fSPeter Avalos if (log_level_name(level) == NULL) 5401c188a7fSPeter Avalos fatal("%s: invalid log level %u (corrupted message?)", 5411c188a7fSPeter Avalos __func__, level); 5421c188a7fSPeter Avalos do_log2(level, "%s [preauth]", msg); 5431c188a7fSPeter Avalos 5441c188a7fSPeter Avalos buffer_free(&logmsg); 54536e94dc5SPeter Avalos free(msg); 5461c188a7fSPeter Avalos 5471c188a7fSPeter Avalos return 0; 5481c188a7fSPeter Avalos } 5491c188a7fSPeter Avalos 55018de8d7fSPeter Avalos int 55118de8d7fSPeter Avalos monitor_read(struct monitor *pmonitor, struct mon_table *ent, 55218de8d7fSPeter Avalos struct mon_table **pent) 55318de8d7fSPeter Avalos { 55418de8d7fSPeter Avalos Buffer m; 55518de8d7fSPeter Avalos int ret; 55618de8d7fSPeter Avalos u_char type; 5571c188a7fSPeter Avalos struct pollfd pfd[2]; 5581c188a7fSPeter Avalos 5591c188a7fSPeter Avalos for (;;) { 56036e94dc5SPeter Avalos memset(&pfd, 0, sizeof(pfd)); 5611c188a7fSPeter Avalos pfd[0].fd = pmonitor->m_sendfd; 5621c188a7fSPeter Avalos pfd[0].events = POLLIN; 5631c188a7fSPeter Avalos pfd[1].fd = pmonitor->m_log_recvfd; 5641c188a7fSPeter Avalos pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; 5651c188a7fSPeter Avalos if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { 5661c188a7fSPeter Avalos if (errno == EINTR || errno == EAGAIN) 5671c188a7fSPeter Avalos continue; 5681c188a7fSPeter Avalos fatal("%s: poll: %s", __func__, strerror(errno)); 5691c188a7fSPeter Avalos } 5701c188a7fSPeter Avalos if (pfd[1].revents) { 5711c188a7fSPeter Avalos /* 5721c188a7fSPeter Avalos * Drain all log messages before processing next 5731c188a7fSPeter Avalos * monitor request. 5741c188a7fSPeter Avalos */ 5751c188a7fSPeter Avalos monitor_read_log(pmonitor); 5761c188a7fSPeter Avalos continue; 5771c188a7fSPeter Avalos } 5781c188a7fSPeter Avalos if (pfd[0].revents) 5791c188a7fSPeter Avalos break; /* Continues below */ 5801c188a7fSPeter Avalos } 58118de8d7fSPeter Avalos 58218de8d7fSPeter Avalos buffer_init(&m); 58318de8d7fSPeter Avalos 58418de8d7fSPeter Avalos mm_request_receive(pmonitor->m_sendfd, &m); 58518de8d7fSPeter Avalos type = buffer_get_char(&m); 58618de8d7fSPeter Avalos 58718de8d7fSPeter Avalos debug3("%s: checking request %d", __func__, type); 58818de8d7fSPeter Avalos 58918de8d7fSPeter Avalos while (ent->f != NULL) { 59018de8d7fSPeter Avalos if (ent->type == type) 59118de8d7fSPeter Avalos break; 59218de8d7fSPeter Avalos ent++; 59318de8d7fSPeter Avalos } 59418de8d7fSPeter Avalos 59518de8d7fSPeter Avalos if (ent->f != NULL) { 59618de8d7fSPeter Avalos if (!(ent->flags & MON_PERMIT)) 59718de8d7fSPeter Avalos fatal("%s: unpermitted request %d", __func__, 59818de8d7fSPeter Avalos type); 59918de8d7fSPeter Avalos ret = (*ent->f)(pmonitor->m_sendfd, &m); 60018de8d7fSPeter Avalos buffer_free(&m); 60118de8d7fSPeter Avalos 60218de8d7fSPeter Avalos /* The child may use this request only once, disable it */ 60318de8d7fSPeter Avalos if (ent->flags & MON_ONCE) { 60418de8d7fSPeter Avalos debug2("%s: %d used once, disabling now", __func__, 60518de8d7fSPeter Avalos type); 60618de8d7fSPeter Avalos ent->flags &= ~MON_PERMIT; 60718de8d7fSPeter Avalos } 60818de8d7fSPeter Avalos 60918de8d7fSPeter Avalos if (pent != NULL) 61018de8d7fSPeter Avalos *pent = ent; 61118de8d7fSPeter Avalos 61218de8d7fSPeter Avalos return ret; 61318de8d7fSPeter Avalos } 61418de8d7fSPeter Avalos 61518de8d7fSPeter Avalos fatal("%s: unsupported request: %d", __func__, type); 61618de8d7fSPeter Avalos 61718de8d7fSPeter Avalos /* NOTREACHED */ 61818de8d7fSPeter Avalos return (-1); 61918de8d7fSPeter Avalos } 62018de8d7fSPeter Avalos 62118de8d7fSPeter Avalos /* allowed key state */ 62218de8d7fSPeter Avalos static int 62318de8d7fSPeter Avalos monitor_allowed_key(u_char *blob, u_int bloblen) 62418de8d7fSPeter Avalos { 62518de8d7fSPeter Avalos /* make sure key is allowed */ 62618de8d7fSPeter Avalos if (key_blob == NULL || key_bloblen != bloblen || 627856ea928SPeter Avalos timingsafe_bcmp(key_blob, blob, key_bloblen)) 62818de8d7fSPeter Avalos return (0); 62918de8d7fSPeter Avalos return (1); 63018de8d7fSPeter Avalos } 63118de8d7fSPeter Avalos 63218de8d7fSPeter Avalos static void 63318de8d7fSPeter Avalos monitor_reset_key_state(void) 63418de8d7fSPeter Avalos { 63518de8d7fSPeter Avalos /* reset state */ 63636e94dc5SPeter Avalos free(key_blob); 63736e94dc5SPeter Avalos free(hostbased_cuser); 63836e94dc5SPeter Avalos free(hostbased_chost); 63918de8d7fSPeter Avalos key_blob = NULL; 64018de8d7fSPeter Avalos key_bloblen = 0; 64118de8d7fSPeter Avalos key_blobtype = MM_NOKEY; 64218de8d7fSPeter Avalos hostbased_cuser = NULL; 64318de8d7fSPeter Avalos hostbased_chost = NULL; 64418de8d7fSPeter Avalos } 64518de8d7fSPeter Avalos 64636e94dc5SPeter Avalos #ifdef WITH_OPENSSL 64718de8d7fSPeter Avalos int 64818de8d7fSPeter Avalos mm_answer_moduli(int sock, Buffer *m) 64918de8d7fSPeter Avalos { 65018de8d7fSPeter Avalos DH *dh; 65118de8d7fSPeter Avalos int min, want, max; 65218de8d7fSPeter Avalos 65318de8d7fSPeter Avalos min = buffer_get_int(m); 65418de8d7fSPeter Avalos want = buffer_get_int(m); 65518de8d7fSPeter Avalos max = buffer_get_int(m); 65618de8d7fSPeter Avalos 65718de8d7fSPeter Avalos debug3("%s: got parameters: %d %d %d", 65818de8d7fSPeter Avalos __func__, min, want, max); 65918de8d7fSPeter Avalos /* We need to check here, too, in case the child got corrupted */ 66018de8d7fSPeter Avalos if (max < min || want < min || max < want) 66118de8d7fSPeter Avalos fatal("%s: bad parameters: %d %d %d", 66218de8d7fSPeter Avalos __func__, min, want, max); 66318de8d7fSPeter Avalos 66418de8d7fSPeter Avalos buffer_clear(m); 66518de8d7fSPeter Avalos 66618de8d7fSPeter Avalos dh = choose_dh(min, want, max); 66718de8d7fSPeter Avalos if (dh == NULL) { 66818de8d7fSPeter Avalos buffer_put_char(m, 0); 66918de8d7fSPeter Avalos return (0); 67018de8d7fSPeter Avalos } else { 67118de8d7fSPeter Avalos /* Send first bignum */ 67218de8d7fSPeter Avalos buffer_put_char(m, 1); 67318de8d7fSPeter Avalos buffer_put_bignum2(m, dh->p); 67418de8d7fSPeter Avalos buffer_put_bignum2(m, dh->g); 67518de8d7fSPeter Avalos 67618de8d7fSPeter Avalos DH_free(dh); 67718de8d7fSPeter Avalos } 67818de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_MODULI, m); 67918de8d7fSPeter Avalos return (0); 68018de8d7fSPeter Avalos } 68136e94dc5SPeter Avalos #endif 68236e94dc5SPeter Avalos 68318de8d7fSPeter Avalos int 68418de8d7fSPeter Avalos mm_answer_sign(int sock, Buffer *m) 68518de8d7fSPeter Avalos { 686*e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 687*e9778795SPeter Avalos extern int auth_sock; /* XXX move to state struct? */ 688*e9778795SPeter Avalos struct sshkey *key; 689*e9778795SPeter Avalos struct sshbuf *sigbuf = NULL; 690*e9778795SPeter Avalos u_char *p = NULL, *signature = NULL; 691*e9778795SPeter Avalos char *alg = NULL; 692*e9778795SPeter Avalos size_t datlen, siglen, alglen; 693*e9778795SPeter Avalos int r, is_proof = 0; 694*e9778795SPeter Avalos u_int keyid; 695*e9778795SPeter Avalos const char proof_req[] = "hostkeys-prove-00@openssh.com"; 69618de8d7fSPeter Avalos 69718de8d7fSPeter Avalos debug3("%s", __func__); 69818de8d7fSPeter Avalos 699*e9778795SPeter Avalos if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 700*e9778795SPeter Avalos (r = sshbuf_get_string(m, &p, &datlen)) != 0 || 701*e9778795SPeter Avalos (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0) 702*e9778795SPeter Avalos fatal("%s: buffer error: %s", __func__, ssh_err(r)); 703*e9778795SPeter Avalos if (keyid > INT_MAX) 704*e9778795SPeter Avalos fatal("%s: invalid key ID", __func__); 70518de8d7fSPeter Avalos 70618de8d7fSPeter Avalos /* 7079f304aafSPeter Avalos * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), 7089f304aafSPeter Avalos * SHA384 (48 bytes) and SHA512 (64 bytes). 709*e9778795SPeter Avalos * 710*e9778795SPeter Avalos * Otherwise, verify the signature request is for a hostkey 711*e9778795SPeter Avalos * proof. 712*e9778795SPeter Avalos * 713*e9778795SPeter Avalos * XXX perform similar check for KEX signature requests too? 714*e9778795SPeter Avalos * it's not trivial, since what is signed is the hash, rather 715*e9778795SPeter Avalos * than the full kex structure... 71618de8d7fSPeter Avalos */ 717*e9778795SPeter Avalos if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { 718*e9778795SPeter Avalos /* 719*e9778795SPeter Avalos * Construct expected hostkey proof and compare it to what 720*e9778795SPeter Avalos * the client sent us. 721*e9778795SPeter Avalos */ 722*e9778795SPeter Avalos if (session_id2_len == 0) /* hostkeys is never first */ 723*e9778795SPeter Avalos fatal("%s: bad data length: %zu", __func__, datlen); 724*e9778795SPeter Avalos if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) 725*e9778795SPeter Avalos fatal("%s: no hostkey for index %d", __func__, keyid); 726*e9778795SPeter Avalos if ((sigbuf = sshbuf_new()) == NULL) 727*e9778795SPeter Avalos fatal("%s: sshbuf_new", __func__); 728*e9778795SPeter Avalos if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || 729*e9778795SPeter Avalos (r = sshbuf_put_string(sigbuf, session_id2, 730*e9778795SPeter Avalos session_id2_len)) != 0 || 731*e9778795SPeter Avalos (r = sshkey_puts(key, sigbuf)) != 0) 732*e9778795SPeter Avalos fatal("%s: couldn't prepare private key " 733*e9778795SPeter Avalos "proof buffer: %s", __func__, ssh_err(r)); 734*e9778795SPeter Avalos if (datlen != sshbuf_len(sigbuf) || 735*e9778795SPeter Avalos memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) 736*e9778795SPeter Avalos fatal("%s: bad data length: %zu, hostkey proof len %zu", 737*e9778795SPeter Avalos __func__, datlen, sshbuf_len(sigbuf)); 738*e9778795SPeter Avalos sshbuf_free(sigbuf); 739*e9778795SPeter Avalos is_proof = 1; 740*e9778795SPeter Avalos } 74118de8d7fSPeter Avalos 74218de8d7fSPeter Avalos /* save session id, it will be passed on the first call */ 74318de8d7fSPeter Avalos if (session_id2_len == 0) { 74418de8d7fSPeter Avalos session_id2_len = datlen; 74518de8d7fSPeter Avalos session_id2 = xmalloc(session_id2_len); 74618de8d7fSPeter Avalos memcpy(session_id2, p, session_id2_len); 74718de8d7fSPeter Avalos } 74818de8d7fSPeter Avalos 74936e94dc5SPeter Avalos if ((key = get_hostkey_by_index(keyid)) != NULL) { 750*e9778795SPeter Avalos if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, 751*e9778795SPeter Avalos datafellows)) != 0) 752*e9778795SPeter Avalos fatal("%s: sshkey_sign failed: %s", 753*e9778795SPeter Avalos __func__, ssh_err(r)); 754*e9778795SPeter Avalos } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 755*e9778795SPeter Avalos auth_sock > 0) { 756*e9778795SPeter Avalos if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 757*e9778795SPeter Avalos p, datlen, alg, datafellows)) != 0) { 758*e9778795SPeter Avalos fatal("%s: ssh_agent_sign failed: %s", 759*e9778795SPeter Avalos __func__, ssh_err(r)); 760*e9778795SPeter Avalos } 76136e94dc5SPeter Avalos } else 76236e94dc5SPeter Avalos fatal("%s: no hostkey from index %d", __func__, keyid); 76318de8d7fSPeter Avalos 764*e9778795SPeter Avalos debug3("%s: %s signature %p(%zu)", __func__, 765*e9778795SPeter Avalos is_proof ? "KEX" : "hostkey proof", signature, siglen); 76618de8d7fSPeter Avalos 767*e9778795SPeter Avalos sshbuf_reset(m); 768*e9778795SPeter Avalos if ((r = sshbuf_put_string(m, signature, siglen)) != 0) 769*e9778795SPeter Avalos fatal("%s: buffer error: %s", __func__, ssh_err(r)); 77018de8d7fSPeter Avalos 771*e9778795SPeter Avalos free(alg); 77236e94dc5SPeter Avalos free(p); 77336e94dc5SPeter Avalos free(signature); 77418de8d7fSPeter Avalos 77518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SIGN, m); 77618de8d7fSPeter Avalos 77718de8d7fSPeter Avalos /* Turn on permissions for getpwnam */ 77818de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 77918de8d7fSPeter Avalos 78018de8d7fSPeter Avalos return (0); 78118de8d7fSPeter Avalos } 78218de8d7fSPeter Avalos 78318de8d7fSPeter Avalos /* Retrieves the password entry and also checks if the user is permitted */ 78418de8d7fSPeter Avalos 78518de8d7fSPeter Avalos int 78618de8d7fSPeter Avalos mm_answer_pwnamallow(int sock, Buffer *m) 78718de8d7fSPeter Avalos { 78818de8d7fSPeter Avalos char *username; 78918de8d7fSPeter Avalos struct passwd *pwent; 79018de8d7fSPeter Avalos int allowed = 0; 7911c188a7fSPeter Avalos u_int i; 79218de8d7fSPeter Avalos 79318de8d7fSPeter Avalos debug3("%s", __func__); 79418de8d7fSPeter Avalos 79518de8d7fSPeter Avalos if (authctxt->attempt++ != 0) 79618de8d7fSPeter Avalos fatal("%s: multiple attempts for getpwnam", __func__); 79718de8d7fSPeter Avalos 79818de8d7fSPeter Avalos username = buffer_get_string(m, NULL); 79918de8d7fSPeter Avalos 80018de8d7fSPeter Avalos pwent = getpwnamallow(username); 80118de8d7fSPeter Avalos 80218de8d7fSPeter Avalos authctxt->user = xstrdup(username); 80318de8d7fSPeter Avalos setproctitle("%s [priv]", pwent ? username : "unknown"); 80436e94dc5SPeter Avalos free(username); 80518de8d7fSPeter Avalos 80618de8d7fSPeter Avalos buffer_clear(m); 80718de8d7fSPeter Avalos 80818de8d7fSPeter Avalos if (pwent == NULL) { 80918de8d7fSPeter Avalos buffer_put_char(m, 0); 81018de8d7fSPeter Avalos authctxt->pw = fakepw(); 81118de8d7fSPeter Avalos goto out; 81218de8d7fSPeter Avalos } 81318de8d7fSPeter Avalos 81418de8d7fSPeter Avalos allowed = 1; 81518de8d7fSPeter Avalos authctxt->pw = pwent; 81618de8d7fSPeter Avalos authctxt->valid = 1; 81718de8d7fSPeter Avalos 81818de8d7fSPeter Avalos buffer_put_char(m, 1); 81918de8d7fSPeter Avalos buffer_put_string(m, pwent, sizeof(struct passwd)); 82018de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_name); 82118de8d7fSPeter Avalos buffer_put_cstring(m, "*"); 82236e94dc5SPeter Avalos #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 82318de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_gecos); 82436e94dc5SPeter Avalos #endif 82536e94dc5SPeter Avalos #ifdef HAVE_STRUCT_PASSWD_PW_CLASS 82618de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_class); 82718de8d7fSPeter Avalos #endif 82818de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_dir); 82918de8d7fSPeter Avalos buffer_put_cstring(m, pwent->pw_shell); 83018de8d7fSPeter Avalos 83118de8d7fSPeter Avalos out: 83218de8d7fSPeter Avalos buffer_put_string(m, &options, sizeof(options)); 8331c188a7fSPeter Avalos 8341c188a7fSPeter Avalos #define M_CP_STROPT(x) do { \ 8351c188a7fSPeter Avalos if (options.x != NULL) \ 8361c188a7fSPeter Avalos buffer_put_cstring(m, options.x); \ 8371c188a7fSPeter Avalos } while (0) 8381c188a7fSPeter Avalos #define M_CP_STRARRAYOPT(x, nx) do { \ 8391c188a7fSPeter Avalos for (i = 0; i < options.nx; i++) \ 8401c188a7fSPeter Avalos buffer_put_cstring(m, options.x[i]); \ 8411c188a7fSPeter Avalos } while (0) 8421c188a7fSPeter Avalos /* See comment in servconf.h */ 8431c188a7fSPeter Avalos COPY_MATCH_STRING_OPTS(); 8441c188a7fSPeter Avalos #undef M_CP_STROPT 8451c188a7fSPeter Avalos #undef M_CP_STRARRAYOPT 8461c188a7fSPeter Avalos 84736e94dc5SPeter Avalos /* Create valid auth method lists */ 84836e94dc5SPeter Avalos if (compat20 && auth2_setup_methods_lists(authctxt) != 0) { 84936e94dc5SPeter Avalos /* 85036e94dc5SPeter Avalos * The monitor will continue long enough to let the child 85136e94dc5SPeter Avalos * run to it's packet_disconnect(), but it must not allow any 85236e94dc5SPeter Avalos * authentication to succeed. 85336e94dc5SPeter Avalos */ 85436e94dc5SPeter Avalos debug("%s: no valid authentication method lists", __func__); 85536e94dc5SPeter Avalos } 85636e94dc5SPeter Avalos 85718de8d7fSPeter Avalos debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); 85818de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PWNAM, m); 85918de8d7fSPeter Avalos 86018de8d7fSPeter Avalos /* For SSHv1 allow authentication now */ 86118de8d7fSPeter Avalos if (!compat20) 86218de8d7fSPeter Avalos monitor_permit_authentications(1); 86318de8d7fSPeter Avalos else { 86418de8d7fSPeter Avalos /* Allow service/style information on the auth context */ 86518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 86618de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 86718de8d7fSPeter Avalos } 86818de8d7fSPeter Avalos #ifdef USE_PAM 86918de8d7fSPeter Avalos if (options.use_pam) 87018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); 87118de8d7fSPeter Avalos #endif 87218de8d7fSPeter Avalos 87318de8d7fSPeter Avalos return (0); 87418de8d7fSPeter Avalos } 87518de8d7fSPeter Avalos 87618de8d7fSPeter Avalos int mm_answer_auth2_read_banner(int sock, Buffer *m) 87718de8d7fSPeter Avalos { 87818de8d7fSPeter Avalos char *banner; 87918de8d7fSPeter Avalos 88018de8d7fSPeter Avalos buffer_clear(m); 88118de8d7fSPeter Avalos banner = auth2_read_banner(); 88218de8d7fSPeter Avalos buffer_put_cstring(m, banner != NULL ? banner : ""); 88318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); 88436e94dc5SPeter Avalos free(banner); 88518de8d7fSPeter Avalos 88618de8d7fSPeter Avalos return (0); 88718de8d7fSPeter Avalos } 88818de8d7fSPeter Avalos 88918de8d7fSPeter Avalos int 89018de8d7fSPeter Avalos mm_answer_authserv(int sock, Buffer *m) 89118de8d7fSPeter Avalos { 89218de8d7fSPeter Avalos monitor_permit_authentications(1); 89318de8d7fSPeter Avalos 89418de8d7fSPeter Avalos authctxt->service = buffer_get_string(m, NULL); 89518de8d7fSPeter Avalos authctxt->style = buffer_get_string(m, NULL); 89618de8d7fSPeter Avalos debug3("%s: service=%s, style=%s", 89718de8d7fSPeter Avalos __func__, authctxt->service, authctxt->style); 89818de8d7fSPeter Avalos 89918de8d7fSPeter Avalos if (strlen(authctxt->style) == 0) { 90036e94dc5SPeter Avalos free(authctxt->style); 90118de8d7fSPeter Avalos authctxt->style = NULL; 90218de8d7fSPeter Avalos } 90318de8d7fSPeter Avalos 90418de8d7fSPeter Avalos return (0); 90518de8d7fSPeter Avalos } 90618de8d7fSPeter Avalos 90718de8d7fSPeter Avalos int 90818de8d7fSPeter Avalos mm_answer_authpassword(int sock, Buffer *m) 90918de8d7fSPeter Avalos { 91018de8d7fSPeter Avalos static int call_count; 91118de8d7fSPeter Avalos char *passwd; 91218de8d7fSPeter Avalos int authenticated; 91318de8d7fSPeter Avalos u_int plen; 91418de8d7fSPeter Avalos 91518de8d7fSPeter Avalos passwd = buffer_get_string(m, &plen); 91618de8d7fSPeter Avalos /* Only authenticate if the context is valid */ 91718de8d7fSPeter Avalos authenticated = options.password_authentication && 91818de8d7fSPeter Avalos auth_password(authctxt, passwd); 91936e94dc5SPeter Avalos explicit_bzero(passwd, strlen(passwd)); 92036e94dc5SPeter Avalos free(passwd); 92118de8d7fSPeter Avalos 92218de8d7fSPeter Avalos buffer_clear(m); 92318de8d7fSPeter Avalos buffer_put_int(m, authenticated); 924*e9778795SPeter Avalos #ifdef USE_PAM 925*e9778795SPeter Avalos buffer_put_int(m, sshpam_get_maxtries_reached()); 926*e9778795SPeter Avalos #endif 92718de8d7fSPeter Avalos 92818de8d7fSPeter Avalos debug3("%s: sending result %d", __func__, authenticated); 92918de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); 93018de8d7fSPeter Avalos 93118de8d7fSPeter Avalos call_count++; 93218de8d7fSPeter Avalos if (plen == 0 && call_count == 1) 93318de8d7fSPeter Avalos auth_method = "none"; 93418de8d7fSPeter Avalos else 93518de8d7fSPeter Avalos auth_method = "password"; 93618de8d7fSPeter Avalos 93718de8d7fSPeter Avalos /* Causes monitor loop to terminate if authenticated */ 93818de8d7fSPeter Avalos return (authenticated); 93918de8d7fSPeter Avalos } 94018de8d7fSPeter Avalos 94118de8d7fSPeter Avalos #ifdef BSD_AUTH 94218de8d7fSPeter Avalos int 94318de8d7fSPeter Avalos mm_answer_bsdauthquery(int sock, Buffer *m) 94418de8d7fSPeter Avalos { 94518de8d7fSPeter Avalos char *name, *infotxt; 94618de8d7fSPeter Avalos u_int numprompts; 94718de8d7fSPeter Avalos u_int *echo_on; 94818de8d7fSPeter Avalos char **prompts; 94918de8d7fSPeter Avalos u_int success; 95018de8d7fSPeter Avalos 95118de8d7fSPeter Avalos success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 95218de8d7fSPeter Avalos &prompts, &echo_on) < 0 ? 0 : 1; 95318de8d7fSPeter Avalos 95418de8d7fSPeter Avalos buffer_clear(m); 95518de8d7fSPeter Avalos buffer_put_int(m, success); 95618de8d7fSPeter Avalos if (success) 95718de8d7fSPeter Avalos buffer_put_cstring(m, prompts[0]); 95818de8d7fSPeter Avalos 95918de8d7fSPeter Avalos debug3("%s: sending challenge success: %u", __func__, success); 96018de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); 96118de8d7fSPeter Avalos 96218de8d7fSPeter Avalos if (success) { 96336e94dc5SPeter Avalos free(name); 96436e94dc5SPeter Avalos free(infotxt); 96536e94dc5SPeter Avalos free(prompts); 96636e94dc5SPeter Avalos free(echo_on); 96718de8d7fSPeter Avalos } 96818de8d7fSPeter Avalos 96918de8d7fSPeter Avalos return (0); 97018de8d7fSPeter Avalos } 97118de8d7fSPeter Avalos 97218de8d7fSPeter Avalos int 97318de8d7fSPeter Avalos mm_answer_bsdauthrespond(int sock, Buffer *m) 97418de8d7fSPeter Avalos { 97518de8d7fSPeter Avalos char *response; 97618de8d7fSPeter Avalos int authok; 97718de8d7fSPeter Avalos 978*e9778795SPeter Avalos if (authctxt->as == NULL) 97918de8d7fSPeter Avalos fatal("%s: no bsd auth session", __func__); 98018de8d7fSPeter Avalos 98118de8d7fSPeter Avalos response = buffer_get_string(m, NULL); 98218de8d7fSPeter Avalos authok = options.challenge_response_authentication && 98318de8d7fSPeter Avalos auth_userresponse(authctxt->as, response, 0); 98418de8d7fSPeter Avalos authctxt->as = NULL; 98518de8d7fSPeter Avalos debug3("%s: <%s> = <%d>", __func__, response, authok); 98636e94dc5SPeter Avalos free(response); 98718de8d7fSPeter Avalos 98818de8d7fSPeter Avalos buffer_clear(m); 98918de8d7fSPeter Avalos buffer_put_int(m, authok); 99018de8d7fSPeter Avalos 99118de8d7fSPeter Avalos debug3("%s: sending authenticated: %d", __func__, authok); 99218de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); 99318de8d7fSPeter Avalos 99436e94dc5SPeter Avalos if (compat20) { 99536e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 99636e94dc5SPeter Avalos auth_submethod = "bsdauth"; 99736e94dc5SPeter Avalos } else 99818de8d7fSPeter Avalos auth_method = "bsdauth"; 99918de8d7fSPeter Avalos 100018de8d7fSPeter Avalos return (authok != 0); 100118de8d7fSPeter Avalos } 100218de8d7fSPeter Avalos #endif 100318de8d7fSPeter Avalos 100418de8d7fSPeter Avalos #ifdef SKEY 100518de8d7fSPeter Avalos int 100618de8d7fSPeter Avalos mm_answer_skeyquery(int sock, Buffer *m) 100718de8d7fSPeter Avalos { 100818de8d7fSPeter Avalos struct skey skey; 100918de8d7fSPeter Avalos char challenge[1024]; 101018de8d7fSPeter Avalos u_int success; 101118de8d7fSPeter Avalos 101218de8d7fSPeter Avalos success = _compat_skeychallenge(&skey, authctxt->user, challenge, 101318de8d7fSPeter Avalos sizeof(challenge)) < 0 ? 0 : 1; 101418de8d7fSPeter Avalos 101518de8d7fSPeter Avalos buffer_clear(m); 101618de8d7fSPeter Avalos buffer_put_int(m, success); 101718de8d7fSPeter Avalos if (success) 101818de8d7fSPeter Avalos buffer_put_cstring(m, challenge); 101918de8d7fSPeter Avalos 102018de8d7fSPeter Avalos debug3("%s: sending challenge success: %u", __func__, success); 102118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m); 102218de8d7fSPeter Avalos 102318de8d7fSPeter Avalos return (0); 102418de8d7fSPeter Avalos } 102518de8d7fSPeter Avalos 102618de8d7fSPeter Avalos int 102718de8d7fSPeter Avalos mm_answer_skeyrespond(int sock, Buffer *m) 102818de8d7fSPeter Avalos { 102918de8d7fSPeter Avalos char *response; 103018de8d7fSPeter Avalos int authok; 103118de8d7fSPeter Avalos 103218de8d7fSPeter Avalos response = buffer_get_string(m, NULL); 103318de8d7fSPeter Avalos 103418de8d7fSPeter Avalos authok = (options.challenge_response_authentication && 103518de8d7fSPeter Avalos authctxt->valid && 103618de8d7fSPeter Avalos skey_haskey(authctxt->pw->pw_name) == 0 && 103718de8d7fSPeter Avalos skey_passcheck(authctxt->pw->pw_name, response) != -1); 103818de8d7fSPeter Avalos 103936e94dc5SPeter Avalos free(response); 104018de8d7fSPeter Avalos 104118de8d7fSPeter Avalos buffer_clear(m); 104218de8d7fSPeter Avalos buffer_put_int(m, authok); 104318de8d7fSPeter Avalos 104418de8d7fSPeter Avalos debug3("%s: sending authenticated: %d", __func__, authok); 104518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); 104618de8d7fSPeter Avalos 1047*e9778795SPeter Avalos auth_method = "keyboard-interactive"; 1048*e9778795SPeter Avalos auth_submethod = "skey"; 104918de8d7fSPeter Avalos 105018de8d7fSPeter Avalos return (authok != 0); 105118de8d7fSPeter Avalos } 105218de8d7fSPeter Avalos #endif 105318de8d7fSPeter Avalos 105418de8d7fSPeter Avalos #ifdef USE_PAM 105518de8d7fSPeter Avalos int 105618de8d7fSPeter Avalos mm_answer_pam_start(int sock, Buffer *m) 105718de8d7fSPeter Avalos { 105818de8d7fSPeter Avalos if (!options.use_pam) 105918de8d7fSPeter Avalos fatal("UsePAM not set, but ended up in %s anyway", __func__); 106018de8d7fSPeter Avalos 106118de8d7fSPeter Avalos start_pam(authctxt); 106218de8d7fSPeter Avalos 106318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); 106418de8d7fSPeter Avalos 106518de8d7fSPeter Avalos return (0); 106618de8d7fSPeter Avalos } 106718de8d7fSPeter Avalos 106818de8d7fSPeter Avalos int 106918de8d7fSPeter Avalos mm_answer_pam_account(int sock, Buffer *m) 107018de8d7fSPeter Avalos { 107118de8d7fSPeter Avalos u_int ret; 107218de8d7fSPeter Avalos 107318de8d7fSPeter Avalos if (!options.use_pam) 107418de8d7fSPeter Avalos fatal("UsePAM not set, but ended up in %s anyway", __func__); 107518de8d7fSPeter Avalos 107618de8d7fSPeter Avalos ret = do_pam_account(); 107718de8d7fSPeter Avalos 107818de8d7fSPeter Avalos buffer_put_int(m, ret); 107918de8d7fSPeter Avalos buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 108018de8d7fSPeter Avalos 108118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); 108218de8d7fSPeter Avalos 108318de8d7fSPeter Avalos return (ret); 108418de8d7fSPeter Avalos } 108518de8d7fSPeter Avalos 108618de8d7fSPeter Avalos static void *sshpam_ctxt, *sshpam_authok; 108718de8d7fSPeter Avalos extern KbdintDevice sshpam_device; 108818de8d7fSPeter Avalos 108918de8d7fSPeter Avalos int 109018de8d7fSPeter Avalos mm_answer_pam_init_ctx(int sock, Buffer *m) 109118de8d7fSPeter Avalos { 109218de8d7fSPeter Avalos debug3("%s", __func__); 109318de8d7fSPeter Avalos sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); 109418de8d7fSPeter Avalos sshpam_authok = NULL; 109518de8d7fSPeter Avalos buffer_clear(m); 109618de8d7fSPeter Avalos if (sshpam_ctxt != NULL) { 109718de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 109818de8d7fSPeter Avalos buffer_put_int(m, 1); 109918de8d7fSPeter Avalos } else { 110018de8d7fSPeter Avalos buffer_put_int(m, 0); 110118de8d7fSPeter Avalos } 110218de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); 110318de8d7fSPeter Avalos return (0); 110418de8d7fSPeter Avalos } 110518de8d7fSPeter Avalos 110618de8d7fSPeter Avalos int 110718de8d7fSPeter Avalos mm_answer_pam_query(int sock, Buffer *m) 110818de8d7fSPeter Avalos { 1109856ea928SPeter Avalos char *name = NULL, *info = NULL, **prompts = NULL; 1110856ea928SPeter Avalos u_int i, num = 0, *echo_on = 0; 111118de8d7fSPeter Avalos int ret; 111218de8d7fSPeter Avalos 111318de8d7fSPeter Avalos debug3("%s", __func__); 111418de8d7fSPeter Avalos sshpam_authok = NULL; 111518de8d7fSPeter Avalos ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on); 111618de8d7fSPeter Avalos if (ret == 0 && num == 0) 111718de8d7fSPeter Avalos sshpam_authok = sshpam_ctxt; 111818de8d7fSPeter Avalos if (num > 1 || name == NULL || info == NULL) 111918de8d7fSPeter Avalos ret = -1; 112018de8d7fSPeter Avalos buffer_clear(m); 112118de8d7fSPeter Avalos buffer_put_int(m, ret); 112218de8d7fSPeter Avalos buffer_put_cstring(m, name); 112336e94dc5SPeter Avalos free(name); 112418de8d7fSPeter Avalos buffer_put_cstring(m, info); 112536e94dc5SPeter Avalos free(info); 1126*e9778795SPeter Avalos buffer_put_int(m, sshpam_get_maxtries_reached()); 112718de8d7fSPeter Avalos buffer_put_int(m, num); 112818de8d7fSPeter Avalos for (i = 0; i < num; ++i) { 112918de8d7fSPeter Avalos buffer_put_cstring(m, prompts[i]); 113036e94dc5SPeter Avalos free(prompts[i]); 113118de8d7fSPeter Avalos buffer_put_int(m, echo_on[i]); 113218de8d7fSPeter Avalos } 113336e94dc5SPeter Avalos free(prompts); 113436e94dc5SPeter Avalos free(echo_on); 113536e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 113636e94dc5SPeter Avalos auth_submethod = "pam"; 113718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); 113818de8d7fSPeter Avalos return (0); 113918de8d7fSPeter Avalos } 114018de8d7fSPeter Avalos 114118de8d7fSPeter Avalos int 114218de8d7fSPeter Avalos mm_answer_pam_respond(int sock, Buffer *m) 114318de8d7fSPeter Avalos { 114418de8d7fSPeter Avalos char **resp; 114518de8d7fSPeter Avalos u_int i, num; 114618de8d7fSPeter Avalos int ret; 114718de8d7fSPeter Avalos 114818de8d7fSPeter Avalos debug3("%s", __func__); 114918de8d7fSPeter Avalos sshpam_authok = NULL; 115018de8d7fSPeter Avalos num = buffer_get_int(m); 115118de8d7fSPeter Avalos if (num > 0) { 115218de8d7fSPeter Avalos resp = xcalloc(num, sizeof(char *)); 115318de8d7fSPeter Avalos for (i = 0; i < num; ++i) 115418de8d7fSPeter Avalos resp[i] = buffer_get_string(m, NULL); 115518de8d7fSPeter Avalos ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); 115618de8d7fSPeter Avalos for (i = 0; i < num; ++i) 115736e94dc5SPeter Avalos free(resp[i]); 115836e94dc5SPeter Avalos free(resp); 115918de8d7fSPeter Avalos } else { 116018de8d7fSPeter Avalos ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); 116118de8d7fSPeter Avalos } 116218de8d7fSPeter Avalos buffer_clear(m); 116318de8d7fSPeter Avalos buffer_put_int(m, ret); 116418de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); 116536e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 116636e94dc5SPeter Avalos auth_submethod = "pam"; 116718de8d7fSPeter Avalos if (ret == 0) 116818de8d7fSPeter Avalos sshpam_authok = sshpam_ctxt; 116918de8d7fSPeter Avalos return (0); 117018de8d7fSPeter Avalos } 117118de8d7fSPeter Avalos 117218de8d7fSPeter Avalos int 117318de8d7fSPeter Avalos mm_answer_pam_free_ctx(int sock, Buffer *m) 117418de8d7fSPeter Avalos { 1175*e9778795SPeter Avalos int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; 117618de8d7fSPeter Avalos 117718de8d7fSPeter Avalos debug3("%s", __func__); 117818de8d7fSPeter Avalos (sshpam_device.free_ctx)(sshpam_ctxt); 1179*e9778795SPeter Avalos sshpam_ctxt = sshpam_authok = NULL; 118018de8d7fSPeter Avalos buffer_clear(m); 118118de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); 118236e94dc5SPeter Avalos auth_method = "keyboard-interactive"; 118336e94dc5SPeter Avalos auth_submethod = "pam"; 1184*e9778795SPeter Avalos return r; 118518de8d7fSPeter Avalos } 118618de8d7fSPeter Avalos #endif 118718de8d7fSPeter Avalos 118818de8d7fSPeter Avalos int 118918de8d7fSPeter Avalos mm_answer_keyallowed(int sock, Buffer *m) 119018de8d7fSPeter Avalos { 119118de8d7fSPeter Avalos Key *key; 119218de8d7fSPeter Avalos char *cuser, *chost; 119318de8d7fSPeter Avalos u_char *blob; 1194*e9778795SPeter Avalos u_int bloblen, pubkey_auth_attempt; 119518de8d7fSPeter Avalos enum mm_keytype type = 0; 119618de8d7fSPeter Avalos int allowed = 0; 119718de8d7fSPeter Avalos 119818de8d7fSPeter Avalos debug3("%s entering", __func__); 119918de8d7fSPeter Avalos 120018de8d7fSPeter Avalos type = buffer_get_int(m); 120118de8d7fSPeter Avalos cuser = buffer_get_string(m, NULL); 120218de8d7fSPeter Avalos chost = buffer_get_string(m, NULL); 120318de8d7fSPeter Avalos blob = buffer_get_string(m, &bloblen); 1204*e9778795SPeter Avalos pubkey_auth_attempt = buffer_get_int(m); 120518de8d7fSPeter Avalos 120618de8d7fSPeter Avalos key = key_from_blob(blob, bloblen); 120718de8d7fSPeter Avalos 120818de8d7fSPeter Avalos if ((compat20 && type == MM_RSAHOSTKEY) || 120918de8d7fSPeter Avalos (!compat20 && type != MM_RSAHOSTKEY)) 121018de8d7fSPeter Avalos fatal("%s: key type and protocol mismatch", __func__); 121118de8d7fSPeter Avalos 121218de8d7fSPeter Avalos debug3("%s: key_from_blob: %p", __func__, key); 121318de8d7fSPeter Avalos 121418de8d7fSPeter Avalos if (key != NULL && authctxt->valid) { 1215*e9778795SPeter Avalos /* These should not make it past the privsep child */ 1216*e9778795SPeter Avalos if (key_type_plain(key->type) == KEY_RSA && 1217*e9778795SPeter Avalos (datafellows & SSH_BUG_RSASIGMD5) != 0) 1218*e9778795SPeter Avalos fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); 1219*e9778795SPeter Avalos 122018de8d7fSPeter Avalos switch (type) { 122118de8d7fSPeter Avalos case MM_USERKEY: 122218de8d7fSPeter Avalos allowed = options.pubkey_authentication && 1223*e9778795SPeter Avalos !auth2_userkey_already_used(authctxt, key) && 1224*e9778795SPeter Avalos match_pattern_list(sshkey_ssh_name(key), 1225*e9778795SPeter Avalos options.pubkey_key_types, 0) == 1 && 1226*e9778795SPeter Avalos user_key_allowed(authctxt->pw, key, 1227*e9778795SPeter Avalos pubkey_auth_attempt); 122836e94dc5SPeter Avalos pubkey_auth_info(authctxt, key, NULL); 122918de8d7fSPeter Avalos auth_method = "publickey"; 1230*e9778795SPeter Avalos if (options.pubkey_authentication && 1231*e9778795SPeter Avalos (!pubkey_auth_attempt || allowed != 1)) 123218de8d7fSPeter Avalos auth_clear_options(); 123318de8d7fSPeter Avalos break; 123418de8d7fSPeter Avalos case MM_HOSTKEY: 123518de8d7fSPeter Avalos allowed = options.hostbased_authentication && 1236*e9778795SPeter Avalos match_pattern_list(sshkey_ssh_name(key), 1237*e9778795SPeter Avalos options.hostbased_key_types, 0) == 1 && 123818de8d7fSPeter Avalos hostbased_key_allowed(authctxt->pw, 123918de8d7fSPeter Avalos cuser, chost, key); 124036e94dc5SPeter Avalos pubkey_auth_info(authctxt, key, 124136e94dc5SPeter Avalos "client user \"%.100s\", client host \"%.100s\"", 124236e94dc5SPeter Avalos cuser, chost); 124318de8d7fSPeter Avalos auth_method = "hostbased"; 124418de8d7fSPeter Avalos break; 124536e94dc5SPeter Avalos #ifdef WITH_SSH1 124618de8d7fSPeter Avalos case MM_RSAHOSTKEY: 124718de8d7fSPeter Avalos key->type = KEY_RSA1; /* XXX */ 124818de8d7fSPeter Avalos allowed = options.rhosts_rsa_authentication && 124918de8d7fSPeter Avalos auth_rhosts_rsa_key_allowed(authctxt->pw, 125018de8d7fSPeter Avalos cuser, chost, key); 125118de8d7fSPeter Avalos if (options.rhosts_rsa_authentication && allowed != 1) 125218de8d7fSPeter Avalos auth_clear_options(); 125318de8d7fSPeter Avalos auth_method = "rsa"; 125418de8d7fSPeter Avalos break; 125536e94dc5SPeter Avalos #endif 125618de8d7fSPeter Avalos default: 125718de8d7fSPeter Avalos fatal("%s: unknown key type %d", __func__, type); 125818de8d7fSPeter Avalos break; 125918de8d7fSPeter Avalos } 126018de8d7fSPeter Avalos } 1261*e9778795SPeter Avalos 1262*e9778795SPeter Avalos debug3("%s: key %p is %s", 1263*e9778795SPeter Avalos __func__, key, allowed ? "allowed" : "not allowed"); 1264*e9778795SPeter Avalos 126518de8d7fSPeter Avalos if (key != NULL) 126618de8d7fSPeter Avalos key_free(key); 126718de8d7fSPeter Avalos 126818de8d7fSPeter Avalos /* clear temporarily storage (used by verify) */ 126918de8d7fSPeter Avalos monitor_reset_key_state(); 127018de8d7fSPeter Avalos 127118de8d7fSPeter Avalos if (allowed) { 127218de8d7fSPeter Avalos /* Save temporarily for comparison in verify */ 127318de8d7fSPeter Avalos key_blob = blob; 127418de8d7fSPeter Avalos key_bloblen = bloblen; 127518de8d7fSPeter Avalos key_blobtype = type; 127618de8d7fSPeter Avalos hostbased_cuser = cuser; 127718de8d7fSPeter Avalos hostbased_chost = chost; 127818de8d7fSPeter Avalos } else { 127918de8d7fSPeter Avalos /* Log failed attempt */ 128036e94dc5SPeter Avalos auth_log(authctxt, 0, 0, auth_method, NULL); 128136e94dc5SPeter Avalos free(blob); 128236e94dc5SPeter Avalos free(cuser); 128336e94dc5SPeter Avalos free(chost); 128418de8d7fSPeter Avalos } 128518de8d7fSPeter Avalos 128618de8d7fSPeter Avalos buffer_clear(m); 128718de8d7fSPeter Avalos buffer_put_int(m, allowed); 128818de8d7fSPeter Avalos buffer_put_int(m, forced_command != NULL); 128918de8d7fSPeter Avalos 129018de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); 129118de8d7fSPeter Avalos 129218de8d7fSPeter Avalos if (type == MM_RSAHOSTKEY) 129318de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 129418de8d7fSPeter Avalos 129518de8d7fSPeter Avalos return (0); 129618de8d7fSPeter Avalos } 129718de8d7fSPeter Avalos 129818de8d7fSPeter Avalos static int 129918de8d7fSPeter Avalos monitor_valid_userblob(u_char *data, u_int datalen) 130018de8d7fSPeter Avalos { 130118de8d7fSPeter Avalos Buffer b; 1302*e9778795SPeter Avalos u_char *p; 1303*e9778795SPeter Avalos char *userstyle, *cp; 130418de8d7fSPeter Avalos u_int len; 130518de8d7fSPeter Avalos int fail = 0; 130618de8d7fSPeter Avalos 130718de8d7fSPeter Avalos buffer_init(&b); 130818de8d7fSPeter Avalos buffer_append(&b, data, datalen); 130918de8d7fSPeter Avalos 131018de8d7fSPeter Avalos if (datafellows & SSH_OLD_SESSIONID) { 131118de8d7fSPeter Avalos p = buffer_ptr(&b); 131218de8d7fSPeter Avalos len = buffer_len(&b); 131318de8d7fSPeter Avalos if ((session_id2 == NULL) || 131418de8d7fSPeter Avalos (len < session_id2_len) || 1315856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 131618de8d7fSPeter Avalos fail++; 131718de8d7fSPeter Avalos buffer_consume(&b, session_id2_len); 131818de8d7fSPeter Avalos } else { 131918de8d7fSPeter Avalos p = buffer_get_string(&b, &len); 132018de8d7fSPeter Avalos if ((session_id2 == NULL) || 132118de8d7fSPeter Avalos (len != session_id2_len) || 1322856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 132318de8d7fSPeter Avalos fail++; 132436e94dc5SPeter Avalos free(p); 132518de8d7fSPeter Avalos } 132618de8d7fSPeter Avalos if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 132718de8d7fSPeter Avalos fail++; 1328*e9778795SPeter Avalos cp = buffer_get_cstring(&b, NULL); 132936e94dc5SPeter Avalos xasprintf(&userstyle, "%s%s%s", authctxt->user, 133036e94dc5SPeter Avalos authctxt->style ? ":" : "", 133136e94dc5SPeter Avalos authctxt->style ? authctxt->style : ""); 1332*e9778795SPeter Avalos if (strcmp(userstyle, cp) != 0) { 1333*e9778795SPeter Avalos logit("wrong user name passed to monitor: " 1334*e9778795SPeter Avalos "expected %s != %.100s", userstyle, cp); 133518de8d7fSPeter Avalos fail++; 133618de8d7fSPeter Avalos } 133736e94dc5SPeter Avalos free(userstyle); 1338*e9778795SPeter Avalos free(cp); 133918de8d7fSPeter Avalos buffer_skip_string(&b); 134018de8d7fSPeter Avalos if (datafellows & SSH_BUG_PKAUTH) { 134118de8d7fSPeter Avalos if (!buffer_get_char(&b)) 134218de8d7fSPeter Avalos fail++; 134318de8d7fSPeter Avalos } else { 1344*e9778795SPeter Avalos cp = buffer_get_cstring(&b, NULL); 1345*e9778795SPeter Avalos if (strcmp("publickey", cp) != 0) 134618de8d7fSPeter Avalos fail++; 1347*e9778795SPeter Avalos free(cp); 134818de8d7fSPeter Avalos if (!buffer_get_char(&b)) 134918de8d7fSPeter Avalos fail++; 135018de8d7fSPeter Avalos buffer_skip_string(&b); 135118de8d7fSPeter Avalos } 135218de8d7fSPeter Avalos buffer_skip_string(&b); 135318de8d7fSPeter Avalos if (buffer_len(&b) != 0) 135418de8d7fSPeter Avalos fail++; 135518de8d7fSPeter Avalos buffer_free(&b); 135618de8d7fSPeter Avalos return (fail == 0); 135718de8d7fSPeter Avalos } 135818de8d7fSPeter Avalos 135918de8d7fSPeter Avalos static int 136018de8d7fSPeter Avalos monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 136118de8d7fSPeter Avalos char *chost) 136218de8d7fSPeter Avalos { 136318de8d7fSPeter Avalos Buffer b; 136436e94dc5SPeter Avalos char *p, *userstyle; 136518de8d7fSPeter Avalos u_int len; 136618de8d7fSPeter Avalos int fail = 0; 136718de8d7fSPeter Avalos 136818de8d7fSPeter Avalos buffer_init(&b); 136918de8d7fSPeter Avalos buffer_append(&b, data, datalen); 137018de8d7fSPeter Avalos 137118de8d7fSPeter Avalos p = buffer_get_string(&b, &len); 137218de8d7fSPeter Avalos if ((session_id2 == NULL) || 137318de8d7fSPeter Avalos (len != session_id2_len) || 1374856ea928SPeter Avalos (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 137518de8d7fSPeter Avalos fail++; 137636e94dc5SPeter Avalos free(p); 137718de8d7fSPeter Avalos 137818de8d7fSPeter Avalos if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 137918de8d7fSPeter Avalos fail++; 138036e94dc5SPeter Avalos p = buffer_get_cstring(&b, NULL); 138136e94dc5SPeter Avalos xasprintf(&userstyle, "%s%s%s", authctxt->user, 138236e94dc5SPeter Avalos authctxt->style ? ":" : "", 138336e94dc5SPeter Avalos authctxt->style ? authctxt->style : ""); 138436e94dc5SPeter Avalos if (strcmp(userstyle, p) != 0) { 138518de8d7fSPeter Avalos logit("wrong user name passed to monitor: expected %s != %.100s", 138636e94dc5SPeter Avalos userstyle, p); 138718de8d7fSPeter Avalos fail++; 138818de8d7fSPeter Avalos } 138936e94dc5SPeter Avalos free(userstyle); 139036e94dc5SPeter Avalos free(p); 139118de8d7fSPeter Avalos buffer_skip_string(&b); /* service */ 139236e94dc5SPeter Avalos p = buffer_get_cstring(&b, NULL); 139318de8d7fSPeter Avalos if (strcmp(p, "hostbased") != 0) 139418de8d7fSPeter Avalos fail++; 139536e94dc5SPeter Avalos free(p); 139618de8d7fSPeter Avalos buffer_skip_string(&b); /* pkalg */ 139718de8d7fSPeter Avalos buffer_skip_string(&b); /* pkblob */ 139818de8d7fSPeter Avalos 139918de8d7fSPeter Avalos /* verify client host, strip trailing dot if necessary */ 140018de8d7fSPeter Avalos p = buffer_get_string(&b, NULL); 140118de8d7fSPeter Avalos if (((len = strlen(p)) > 0) && p[len - 1] == '.') 140218de8d7fSPeter Avalos p[len - 1] = '\0'; 140318de8d7fSPeter Avalos if (strcmp(p, chost) != 0) 140418de8d7fSPeter Avalos fail++; 140536e94dc5SPeter Avalos free(p); 140618de8d7fSPeter Avalos 140718de8d7fSPeter Avalos /* verify client user */ 140818de8d7fSPeter Avalos p = buffer_get_string(&b, NULL); 140918de8d7fSPeter Avalos if (strcmp(p, cuser) != 0) 141018de8d7fSPeter Avalos fail++; 141136e94dc5SPeter Avalos free(p); 141218de8d7fSPeter Avalos 141318de8d7fSPeter Avalos if (buffer_len(&b) != 0) 141418de8d7fSPeter Avalos fail++; 141518de8d7fSPeter Avalos buffer_free(&b); 141618de8d7fSPeter Avalos return (fail == 0); 141718de8d7fSPeter Avalos } 141818de8d7fSPeter Avalos 141918de8d7fSPeter Avalos int 142018de8d7fSPeter Avalos mm_answer_keyverify(int sock, Buffer *m) 142118de8d7fSPeter Avalos { 142218de8d7fSPeter Avalos Key *key; 142318de8d7fSPeter Avalos u_char *signature, *data, *blob; 142418de8d7fSPeter Avalos u_int signaturelen, datalen, bloblen; 142518de8d7fSPeter Avalos int verified = 0; 142618de8d7fSPeter Avalos int valid_data = 0; 142718de8d7fSPeter Avalos 142818de8d7fSPeter Avalos blob = buffer_get_string(m, &bloblen); 142918de8d7fSPeter Avalos signature = buffer_get_string(m, &signaturelen); 143018de8d7fSPeter Avalos data = buffer_get_string(m, &datalen); 143118de8d7fSPeter Avalos 143218de8d7fSPeter Avalos if (hostbased_cuser == NULL || hostbased_chost == NULL || 143318de8d7fSPeter Avalos !monitor_allowed_key(blob, bloblen)) 143418de8d7fSPeter Avalos fatal("%s: bad key, not previously allowed", __func__); 143518de8d7fSPeter Avalos 143618de8d7fSPeter Avalos key = key_from_blob(blob, bloblen); 143718de8d7fSPeter Avalos if (key == NULL) 143818de8d7fSPeter Avalos fatal("%s: bad public key blob", __func__); 143918de8d7fSPeter Avalos 144018de8d7fSPeter Avalos switch (key_blobtype) { 144118de8d7fSPeter Avalos case MM_USERKEY: 144218de8d7fSPeter Avalos valid_data = monitor_valid_userblob(data, datalen); 144318de8d7fSPeter Avalos break; 144418de8d7fSPeter Avalos case MM_HOSTKEY: 144518de8d7fSPeter Avalos valid_data = monitor_valid_hostbasedblob(data, datalen, 144618de8d7fSPeter Avalos hostbased_cuser, hostbased_chost); 144718de8d7fSPeter Avalos break; 144818de8d7fSPeter Avalos default: 144918de8d7fSPeter Avalos valid_data = 0; 145018de8d7fSPeter Avalos break; 145118de8d7fSPeter Avalos } 145218de8d7fSPeter Avalos if (!valid_data) 145318de8d7fSPeter Avalos fatal("%s: bad signature data blob", __func__); 145418de8d7fSPeter Avalos 145518de8d7fSPeter Avalos verified = key_verify(key, signature, signaturelen, data, datalen); 145618de8d7fSPeter Avalos debug3("%s: key %p signature %s", 145718de8d7fSPeter Avalos __func__, key, (verified == 1) ? "verified" : "unverified"); 145818de8d7fSPeter Avalos 1459*e9778795SPeter Avalos /* If auth was successful then record key to ensure it isn't reused */ 1460*e9778795SPeter Avalos if (verified == 1 && key_blobtype == MM_USERKEY) 1461*e9778795SPeter Avalos auth2_record_userkey(authctxt, key); 1462*e9778795SPeter Avalos else 146318de8d7fSPeter Avalos key_free(key); 1464*e9778795SPeter Avalos 146536e94dc5SPeter Avalos free(blob); 146636e94dc5SPeter Avalos free(signature); 146736e94dc5SPeter Avalos free(data); 146818de8d7fSPeter Avalos 146918de8d7fSPeter Avalos auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; 147018de8d7fSPeter Avalos 147118de8d7fSPeter Avalos monitor_reset_key_state(); 147218de8d7fSPeter Avalos 147318de8d7fSPeter Avalos buffer_clear(m); 147418de8d7fSPeter Avalos buffer_put_int(m, verified); 147518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 147618de8d7fSPeter Avalos 147718de8d7fSPeter Avalos return (verified == 1); 147818de8d7fSPeter Avalos } 147918de8d7fSPeter Avalos 148018de8d7fSPeter Avalos static void 148118de8d7fSPeter Avalos mm_record_login(Session *s, struct passwd *pw) 148218de8d7fSPeter Avalos { 1483*e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 148418de8d7fSPeter Avalos socklen_t fromlen; 148518de8d7fSPeter Avalos struct sockaddr_storage from; 148618de8d7fSPeter Avalos 1487*e9778795SPeter Avalos if (options.use_login) 1488*e9778795SPeter Avalos return; 1489*e9778795SPeter Avalos 149018de8d7fSPeter Avalos /* 149118de8d7fSPeter Avalos * Get IP address of client. If the connection is not a socket, let 149218de8d7fSPeter Avalos * the address be 0.0.0.0. 149318de8d7fSPeter Avalos */ 149418de8d7fSPeter Avalos memset(&from, 0, sizeof(from)); 149518de8d7fSPeter Avalos fromlen = sizeof(from); 149618de8d7fSPeter Avalos if (packet_connection_is_on_socket()) { 149718de8d7fSPeter Avalos if (getpeername(packet_get_connection_in(), 149818de8d7fSPeter Avalos (struct sockaddr *)&from, &fromlen) < 0) { 149918de8d7fSPeter Avalos debug("getpeername: %.100s", strerror(errno)); 150018de8d7fSPeter Avalos cleanup_exit(255); 150118de8d7fSPeter Avalos } 150218de8d7fSPeter Avalos } 150318de8d7fSPeter Avalos /* Record that there was a login on that tty from the remote host. */ 150418de8d7fSPeter Avalos record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 1505*e9778795SPeter Avalos session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), 150618de8d7fSPeter Avalos (struct sockaddr *)&from, fromlen); 150718de8d7fSPeter Avalos } 150818de8d7fSPeter Avalos 150918de8d7fSPeter Avalos static void 151018de8d7fSPeter Avalos mm_session_close(Session *s) 151118de8d7fSPeter Avalos { 151218de8d7fSPeter Avalos debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); 151318de8d7fSPeter Avalos if (s->ttyfd != -1) { 151418de8d7fSPeter Avalos debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); 151518de8d7fSPeter Avalos session_pty_cleanup2(s); 151618de8d7fSPeter Avalos } 151718de8d7fSPeter Avalos session_unused(s->self); 151818de8d7fSPeter Avalos } 151918de8d7fSPeter Avalos 152018de8d7fSPeter Avalos int 152118de8d7fSPeter Avalos mm_answer_pty(int sock, Buffer *m) 152218de8d7fSPeter Avalos { 152318de8d7fSPeter Avalos extern struct monitor *pmonitor; 152418de8d7fSPeter Avalos Session *s; 152518de8d7fSPeter Avalos int res, fd0; 152618de8d7fSPeter Avalos 152718de8d7fSPeter Avalos debug3("%s entering", __func__); 152818de8d7fSPeter Avalos 152918de8d7fSPeter Avalos buffer_clear(m); 153018de8d7fSPeter Avalos s = session_new(); 153118de8d7fSPeter Avalos if (s == NULL) 153218de8d7fSPeter Avalos goto error; 153318de8d7fSPeter Avalos s->authctxt = authctxt; 153418de8d7fSPeter Avalos s->pw = authctxt->pw; 153518de8d7fSPeter Avalos s->pid = pmonitor->m_pid; 153618de8d7fSPeter Avalos res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 153718de8d7fSPeter Avalos if (res == 0) 153818de8d7fSPeter Avalos goto error; 153918de8d7fSPeter Avalos pty_setowner(authctxt->pw, s->tty); 154018de8d7fSPeter Avalos 154118de8d7fSPeter Avalos buffer_put_int(m, 1); 154218de8d7fSPeter Avalos buffer_put_cstring(m, s->tty); 154318de8d7fSPeter Avalos 154418de8d7fSPeter Avalos /* We need to trick ttyslot */ 154518de8d7fSPeter Avalos if (dup2(s->ttyfd, 0) == -1) 154618de8d7fSPeter Avalos fatal("%s: dup2", __func__); 154718de8d7fSPeter Avalos 154818de8d7fSPeter Avalos mm_record_login(s, authctxt->pw); 154918de8d7fSPeter Avalos 155018de8d7fSPeter Avalos /* Now we can close the file descriptor again */ 155118de8d7fSPeter Avalos close(0); 155218de8d7fSPeter Avalos 155318de8d7fSPeter Avalos /* send messages generated by record_login */ 155418de8d7fSPeter Avalos buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 155518de8d7fSPeter Avalos buffer_clear(&loginmsg); 155618de8d7fSPeter Avalos 155718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PTY, m); 155818de8d7fSPeter Avalos 155918de8d7fSPeter Avalos if (mm_send_fd(sock, s->ptyfd) == -1 || 156018de8d7fSPeter Avalos mm_send_fd(sock, s->ttyfd) == -1) 156118de8d7fSPeter Avalos fatal("%s: send fds failed", __func__); 156218de8d7fSPeter Avalos 156318de8d7fSPeter Avalos /* make sure nothing uses fd 0 */ 156418de8d7fSPeter Avalos if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 156518de8d7fSPeter Avalos fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); 156618de8d7fSPeter Avalos if (fd0 != 0) 156718de8d7fSPeter Avalos error("%s: fd0 %d != 0", __func__, fd0); 156818de8d7fSPeter Avalos 156918de8d7fSPeter Avalos /* slave is not needed */ 157018de8d7fSPeter Avalos close(s->ttyfd); 157118de8d7fSPeter Avalos s->ttyfd = s->ptyfd; 157218de8d7fSPeter Avalos /* no need to dup() because nobody closes ptyfd */ 157318de8d7fSPeter Avalos s->ptymaster = s->ptyfd; 157418de8d7fSPeter Avalos 157518de8d7fSPeter Avalos debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); 157618de8d7fSPeter Avalos 157718de8d7fSPeter Avalos return (0); 157818de8d7fSPeter Avalos 157918de8d7fSPeter Avalos error: 158018de8d7fSPeter Avalos if (s != NULL) 158118de8d7fSPeter Avalos mm_session_close(s); 158218de8d7fSPeter Avalos buffer_put_int(m, 0); 158318de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_PTY, m); 158418de8d7fSPeter Avalos return (0); 158518de8d7fSPeter Avalos } 158618de8d7fSPeter Avalos 158718de8d7fSPeter Avalos int 158818de8d7fSPeter Avalos mm_answer_pty_cleanup(int sock, Buffer *m) 158918de8d7fSPeter Avalos { 159018de8d7fSPeter Avalos Session *s; 159118de8d7fSPeter Avalos char *tty; 159218de8d7fSPeter Avalos 159318de8d7fSPeter Avalos debug3("%s entering", __func__); 159418de8d7fSPeter Avalos 159518de8d7fSPeter Avalos tty = buffer_get_string(m, NULL); 159618de8d7fSPeter Avalos if ((s = session_by_tty(tty)) != NULL) 159718de8d7fSPeter Avalos mm_session_close(s); 159818de8d7fSPeter Avalos buffer_clear(m); 159936e94dc5SPeter Avalos free(tty); 160018de8d7fSPeter Avalos return (0); 160118de8d7fSPeter Avalos } 160218de8d7fSPeter Avalos 160336e94dc5SPeter Avalos #ifdef WITH_SSH1 160418de8d7fSPeter Avalos int 160518de8d7fSPeter Avalos mm_answer_sesskey(int sock, Buffer *m) 160618de8d7fSPeter Avalos { 160718de8d7fSPeter Avalos BIGNUM *p; 160818de8d7fSPeter Avalos int rsafail; 160918de8d7fSPeter Avalos 161018de8d7fSPeter Avalos /* Turn off permissions */ 161118de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); 161218de8d7fSPeter Avalos 161318de8d7fSPeter Avalos if ((p = BN_new()) == NULL) 161418de8d7fSPeter Avalos fatal("%s: BN_new", __func__); 161518de8d7fSPeter Avalos 161618de8d7fSPeter Avalos buffer_get_bignum2(m, p); 161718de8d7fSPeter Avalos 161818de8d7fSPeter Avalos rsafail = ssh1_session_key(p); 161918de8d7fSPeter Avalos 162018de8d7fSPeter Avalos buffer_clear(m); 162118de8d7fSPeter Avalos buffer_put_int(m, rsafail); 162218de8d7fSPeter Avalos buffer_put_bignum2(m, p); 162318de8d7fSPeter Avalos 162418de8d7fSPeter Avalos BN_clear_free(p); 162518de8d7fSPeter Avalos 162618de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_SESSKEY, m); 162718de8d7fSPeter Avalos 162818de8d7fSPeter Avalos /* Turn on permissions for sessid passing */ 162918de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); 163018de8d7fSPeter Avalos 163118de8d7fSPeter Avalos return (0); 163218de8d7fSPeter Avalos } 163318de8d7fSPeter Avalos 163418de8d7fSPeter Avalos int 163518de8d7fSPeter Avalos mm_answer_sessid(int sock, Buffer *m) 163618de8d7fSPeter Avalos { 163718de8d7fSPeter Avalos int i; 163818de8d7fSPeter Avalos 163918de8d7fSPeter Avalos debug3("%s entering", __func__); 164018de8d7fSPeter Avalos 164118de8d7fSPeter Avalos if (buffer_len(m) != 16) 164218de8d7fSPeter Avalos fatal("%s: bad ssh1 session id", __func__); 164318de8d7fSPeter Avalos for (i = 0; i < 16; i++) 164418de8d7fSPeter Avalos session_id[i] = buffer_get_char(m); 164518de8d7fSPeter Avalos 164618de8d7fSPeter Avalos /* Turn on permissions for getpwnam */ 164718de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 164818de8d7fSPeter Avalos 164918de8d7fSPeter Avalos return (0); 165018de8d7fSPeter Avalos } 165118de8d7fSPeter Avalos 165218de8d7fSPeter Avalos int 165318de8d7fSPeter Avalos mm_answer_rsa_keyallowed(int sock, Buffer *m) 165418de8d7fSPeter Avalos { 165518de8d7fSPeter Avalos BIGNUM *client_n; 165618de8d7fSPeter Avalos Key *key = NULL; 165718de8d7fSPeter Avalos u_char *blob = NULL; 165818de8d7fSPeter Avalos u_int blen = 0; 165918de8d7fSPeter Avalos int allowed = 0; 166018de8d7fSPeter Avalos 166118de8d7fSPeter Avalos debug3("%s entering", __func__); 166218de8d7fSPeter Avalos 166318de8d7fSPeter Avalos auth_method = "rsa"; 166418de8d7fSPeter Avalos if (options.rsa_authentication && authctxt->valid) { 166518de8d7fSPeter Avalos if ((client_n = BN_new()) == NULL) 166618de8d7fSPeter Avalos fatal("%s: BN_new", __func__); 166718de8d7fSPeter Avalos buffer_get_bignum2(m, client_n); 166818de8d7fSPeter Avalos allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); 166918de8d7fSPeter Avalos BN_clear_free(client_n); 167018de8d7fSPeter Avalos } 167118de8d7fSPeter Avalos buffer_clear(m); 167218de8d7fSPeter Avalos buffer_put_int(m, allowed); 167318de8d7fSPeter Avalos buffer_put_int(m, forced_command != NULL); 167418de8d7fSPeter Avalos 167518de8d7fSPeter Avalos /* clear temporarily storage (used by generate challenge) */ 167618de8d7fSPeter Avalos monitor_reset_key_state(); 167718de8d7fSPeter Avalos 167818de8d7fSPeter Avalos if (allowed && key != NULL) { 167918de8d7fSPeter Avalos key->type = KEY_RSA; /* cheat for key_to_blob */ 168018de8d7fSPeter Avalos if (key_to_blob(key, &blob, &blen) == 0) 168118de8d7fSPeter Avalos fatal("%s: key_to_blob failed", __func__); 168218de8d7fSPeter Avalos buffer_put_string(m, blob, blen); 168318de8d7fSPeter Avalos 168418de8d7fSPeter Avalos /* Save temporarily for comparison in verify */ 168518de8d7fSPeter Avalos key_blob = blob; 168618de8d7fSPeter Avalos key_bloblen = blen; 168718de8d7fSPeter Avalos key_blobtype = MM_RSAUSERKEY; 168818de8d7fSPeter Avalos } 168918de8d7fSPeter Avalos if (key != NULL) 169018de8d7fSPeter Avalos key_free(key); 169118de8d7fSPeter Avalos 169218de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); 169318de8d7fSPeter Avalos 169418de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 169518de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); 169618de8d7fSPeter Avalos return (0); 169718de8d7fSPeter Avalos } 169818de8d7fSPeter Avalos 169918de8d7fSPeter Avalos int 170018de8d7fSPeter Avalos mm_answer_rsa_challenge(int sock, Buffer *m) 170118de8d7fSPeter Avalos { 170218de8d7fSPeter Avalos Key *key = NULL; 170318de8d7fSPeter Avalos u_char *blob; 170418de8d7fSPeter Avalos u_int blen; 170518de8d7fSPeter Avalos 170618de8d7fSPeter Avalos debug3("%s entering", __func__); 170718de8d7fSPeter Avalos 170818de8d7fSPeter Avalos if (!authctxt->valid) 170918de8d7fSPeter Avalos fatal("%s: authctxt not valid", __func__); 171018de8d7fSPeter Avalos blob = buffer_get_string(m, &blen); 171118de8d7fSPeter Avalos if (!monitor_allowed_key(blob, blen)) 171218de8d7fSPeter Avalos fatal("%s: bad key, not previously allowed", __func__); 171318de8d7fSPeter Avalos if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 171418de8d7fSPeter Avalos fatal("%s: key type mismatch", __func__); 171518de8d7fSPeter Avalos if ((key = key_from_blob(blob, blen)) == NULL) 171618de8d7fSPeter Avalos fatal("%s: received bad key", __func__); 1717cb5eb4f1SPeter Avalos if (key->type != KEY_RSA) 1718cb5eb4f1SPeter Avalos fatal("%s: received bad key type %d", __func__, key->type); 1719cb5eb4f1SPeter Avalos key->type = KEY_RSA1; 172018de8d7fSPeter Avalos if (ssh1_challenge) 172118de8d7fSPeter Avalos BN_clear_free(ssh1_challenge); 172218de8d7fSPeter Avalos ssh1_challenge = auth_rsa_generate_challenge(key); 172318de8d7fSPeter Avalos 172418de8d7fSPeter Avalos buffer_clear(m); 172518de8d7fSPeter Avalos buffer_put_bignum2(m, ssh1_challenge); 172618de8d7fSPeter Avalos 172718de8d7fSPeter Avalos debug3("%s sending reply", __func__); 172818de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); 172918de8d7fSPeter Avalos 173018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); 173118de8d7fSPeter Avalos 173236e94dc5SPeter Avalos free(blob); 173318de8d7fSPeter Avalos key_free(key); 173418de8d7fSPeter Avalos return (0); 173518de8d7fSPeter Avalos } 173618de8d7fSPeter Avalos 173718de8d7fSPeter Avalos int 173818de8d7fSPeter Avalos mm_answer_rsa_response(int sock, Buffer *m) 173918de8d7fSPeter Avalos { 174018de8d7fSPeter Avalos Key *key = NULL; 174118de8d7fSPeter Avalos u_char *blob, *response; 174218de8d7fSPeter Avalos u_int blen, len; 174318de8d7fSPeter Avalos int success; 174418de8d7fSPeter Avalos 174518de8d7fSPeter Avalos debug3("%s entering", __func__); 174618de8d7fSPeter Avalos 174718de8d7fSPeter Avalos if (!authctxt->valid) 174818de8d7fSPeter Avalos fatal("%s: authctxt not valid", __func__); 174918de8d7fSPeter Avalos if (ssh1_challenge == NULL) 175018de8d7fSPeter Avalos fatal("%s: no ssh1_challenge", __func__); 175118de8d7fSPeter Avalos 175218de8d7fSPeter Avalos blob = buffer_get_string(m, &blen); 175318de8d7fSPeter Avalos if (!monitor_allowed_key(blob, blen)) 175418de8d7fSPeter Avalos fatal("%s: bad key, not previously allowed", __func__); 175518de8d7fSPeter Avalos if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 175618de8d7fSPeter Avalos fatal("%s: key type mismatch: %d", __func__, key_blobtype); 175718de8d7fSPeter Avalos if ((key = key_from_blob(blob, blen)) == NULL) 175818de8d7fSPeter Avalos fatal("%s: received bad key", __func__); 175918de8d7fSPeter Avalos response = buffer_get_string(m, &len); 176018de8d7fSPeter Avalos if (len != 16) 176118de8d7fSPeter Avalos fatal("%s: received bad response to challenge", __func__); 176218de8d7fSPeter Avalos success = auth_rsa_verify_response(key, ssh1_challenge, response); 176318de8d7fSPeter Avalos 176436e94dc5SPeter Avalos free(blob); 176518de8d7fSPeter Avalos key_free(key); 176636e94dc5SPeter Avalos free(response); 176718de8d7fSPeter Avalos 176818de8d7fSPeter Avalos auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; 176918de8d7fSPeter Avalos 177018de8d7fSPeter Avalos /* reset state */ 177118de8d7fSPeter Avalos BN_clear_free(ssh1_challenge); 177218de8d7fSPeter Avalos ssh1_challenge = NULL; 177318de8d7fSPeter Avalos monitor_reset_key_state(); 177418de8d7fSPeter Avalos 177518de8d7fSPeter Avalos buffer_clear(m); 177618de8d7fSPeter Avalos buffer_put_int(m, success); 177718de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); 177818de8d7fSPeter Avalos 177918de8d7fSPeter Avalos return (success); 178018de8d7fSPeter Avalos } 178136e94dc5SPeter Avalos #endif 178218de8d7fSPeter Avalos 178318de8d7fSPeter Avalos int 178418de8d7fSPeter Avalos mm_answer_term(int sock, Buffer *req) 178518de8d7fSPeter Avalos { 178618de8d7fSPeter Avalos extern struct monitor *pmonitor; 178718de8d7fSPeter Avalos int res, status; 178818de8d7fSPeter Avalos 178918de8d7fSPeter Avalos debug3("%s: tearing down sessions", __func__); 179018de8d7fSPeter Avalos 179118de8d7fSPeter Avalos /* The child is terminating */ 179218de8d7fSPeter Avalos session_destroy_all(&mm_session_close); 179318de8d7fSPeter Avalos 179418de8d7fSPeter Avalos #ifdef USE_PAM 179518de8d7fSPeter Avalos if (options.use_pam) 179618de8d7fSPeter Avalos sshpam_cleanup(); 179718de8d7fSPeter Avalos #endif 179818de8d7fSPeter Avalos 179918de8d7fSPeter Avalos while (waitpid(pmonitor->m_pid, &status, 0) == -1) 180018de8d7fSPeter Avalos if (errno != EINTR) 180118de8d7fSPeter Avalos exit(1); 180218de8d7fSPeter Avalos 180318de8d7fSPeter Avalos res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 180418de8d7fSPeter Avalos 180518de8d7fSPeter Avalos /* Terminate process */ 180618de8d7fSPeter Avalos exit(res); 180718de8d7fSPeter Avalos } 180818de8d7fSPeter Avalos 180918de8d7fSPeter Avalos #ifdef SSH_AUDIT_EVENTS 181018de8d7fSPeter Avalos /* Report that an audit event occurred */ 181118de8d7fSPeter Avalos int 181218de8d7fSPeter Avalos mm_answer_audit_event(int socket, Buffer *m) 181318de8d7fSPeter Avalos { 181418de8d7fSPeter Avalos ssh_audit_event_t event; 181518de8d7fSPeter Avalos 181618de8d7fSPeter Avalos debug3("%s entering", __func__); 181718de8d7fSPeter Avalos 181818de8d7fSPeter Avalos event = buffer_get_int(m); 181918de8d7fSPeter Avalos switch(event) { 182018de8d7fSPeter Avalos case SSH_AUTH_FAIL_PUBKEY: 182118de8d7fSPeter Avalos case SSH_AUTH_FAIL_HOSTBASED: 182218de8d7fSPeter Avalos case SSH_AUTH_FAIL_GSSAPI: 182318de8d7fSPeter Avalos case SSH_LOGIN_EXCEED_MAXTRIES: 182418de8d7fSPeter Avalos case SSH_LOGIN_ROOT_DENIED: 182518de8d7fSPeter Avalos case SSH_CONNECTION_CLOSE: 182618de8d7fSPeter Avalos case SSH_INVALID_USER: 182718de8d7fSPeter Avalos audit_event(event); 182818de8d7fSPeter Avalos break; 182918de8d7fSPeter Avalos default: 183018de8d7fSPeter Avalos fatal("Audit event type %d not permitted", event); 183118de8d7fSPeter Avalos } 183218de8d7fSPeter Avalos 183318de8d7fSPeter Avalos return (0); 183418de8d7fSPeter Avalos } 183518de8d7fSPeter Avalos 183618de8d7fSPeter Avalos int 183718de8d7fSPeter Avalos mm_answer_audit_command(int socket, Buffer *m) 183818de8d7fSPeter Avalos { 183918de8d7fSPeter Avalos u_int len; 184018de8d7fSPeter Avalos char *cmd; 184118de8d7fSPeter Avalos 184218de8d7fSPeter Avalos debug3("%s entering", __func__); 184318de8d7fSPeter Avalos cmd = buffer_get_string(m, &len); 184418de8d7fSPeter Avalos /* sanity check command, if so how? */ 184518de8d7fSPeter Avalos audit_run_command(cmd); 184636e94dc5SPeter Avalos free(cmd); 184718de8d7fSPeter Avalos return (0); 184818de8d7fSPeter Avalos } 184918de8d7fSPeter Avalos #endif /* SSH_AUDIT_EVENTS */ 185018de8d7fSPeter Avalos 185118de8d7fSPeter Avalos void 185218de8d7fSPeter Avalos monitor_apply_keystate(struct monitor *pmonitor) 185318de8d7fSPeter Avalos { 1854*e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 1855*e9778795SPeter Avalos struct kex *kex; 1856*e9778795SPeter Avalos int r; 185718de8d7fSPeter Avalos 1858*e9778795SPeter Avalos debug3("%s: packet_set_state", __func__); 1859*e9778795SPeter Avalos if ((r = ssh_packet_set_state(ssh, child_state)) != 0) 1860*e9778795SPeter Avalos fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); 1861*e9778795SPeter Avalos sshbuf_free(child_state); 1862*e9778795SPeter Avalos child_state = NULL; 186318de8d7fSPeter Avalos 1864*e9778795SPeter Avalos if ((kex = ssh->kex) != NULL) { 1865*e9778795SPeter Avalos /* XXX set callbacks */ 186636e94dc5SPeter Avalos #ifdef WITH_OPENSSL 186718de8d7fSPeter Avalos kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 186818de8d7fSPeter Avalos kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1869*e9778795SPeter Avalos kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 1870*e9778795SPeter Avalos kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 1871*e9778795SPeter Avalos kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 187218de8d7fSPeter Avalos kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 187318de8d7fSPeter Avalos kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1874*e9778795SPeter Avalos # ifdef OPENSSL_HAS_ECC 18759f304aafSPeter Avalos kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 187636e94dc5SPeter Avalos # endif 1877*e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 187836e94dc5SPeter Avalos kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1879856ea928SPeter Avalos kex->load_host_public_key=&get_hostkey_public_by_type; 1880856ea928SPeter Avalos kex->load_host_private_key=&get_hostkey_private_by_type; 188118de8d7fSPeter Avalos kex->host_key_index=&get_hostkey_index; 188236e94dc5SPeter Avalos kex->sign = sshd_hostkey_sign; 1883*e9778795SPeter Avalos } 188418de8d7fSPeter Avalos 1885*e9778795SPeter Avalos /* Update with new address */ 1886*e9778795SPeter Avalos if (options.compression) { 1887*e9778795SPeter Avalos ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, 1888*e9778795SPeter Avalos (ssh_packet_comp_alloc_func *)mm_zalloc, 1889*e9778795SPeter Avalos (ssh_packet_comp_free_func *)mm_zfree); 1890*e9778795SPeter Avalos } 189118de8d7fSPeter Avalos } 189218de8d7fSPeter Avalos 189318de8d7fSPeter Avalos /* This function requries careful sanity checking */ 189418de8d7fSPeter Avalos 189518de8d7fSPeter Avalos void 189618de8d7fSPeter Avalos mm_get_keystate(struct monitor *pmonitor) 189718de8d7fSPeter Avalos { 189818de8d7fSPeter Avalos debug3("%s: Waiting for new keys", __func__); 189918de8d7fSPeter Avalos 1900*e9778795SPeter Avalos if ((child_state = sshbuf_new()) == NULL) 1901*e9778795SPeter Avalos fatal("%s: sshbuf_new failed", __func__); 1902*e9778795SPeter Avalos mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, 1903*e9778795SPeter Avalos child_state); 1904*e9778795SPeter Avalos debug3("%s: GOT new keys", __func__); 190518de8d7fSPeter Avalos } 190618de8d7fSPeter Avalos 190718de8d7fSPeter Avalos 190818de8d7fSPeter Avalos /* XXX */ 190918de8d7fSPeter Avalos 191018de8d7fSPeter Avalos #define FD_CLOSEONEXEC(x) do { \ 19111c188a7fSPeter Avalos if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ 191218de8d7fSPeter Avalos fatal("fcntl(%d, F_SETFD)", x); \ 191318de8d7fSPeter Avalos } while (0) 191418de8d7fSPeter Avalos 191518de8d7fSPeter Avalos static void 19161c188a7fSPeter Avalos monitor_openfds(struct monitor *mon, int do_logfds) 191718de8d7fSPeter Avalos { 19181c188a7fSPeter Avalos int pair[2]; 19191c188a7fSPeter Avalos 192018de8d7fSPeter Avalos if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 19211c188a7fSPeter Avalos fatal("%s: socketpair: %s", __func__, strerror(errno)); 192218de8d7fSPeter Avalos FD_CLOSEONEXEC(pair[0]); 192318de8d7fSPeter Avalos FD_CLOSEONEXEC(pair[1]); 19241c188a7fSPeter Avalos mon->m_recvfd = pair[0]; 19251c188a7fSPeter Avalos mon->m_sendfd = pair[1]; 19261c188a7fSPeter Avalos 19271c188a7fSPeter Avalos if (do_logfds) { 19281c188a7fSPeter Avalos if (pipe(pair) == -1) 19291c188a7fSPeter Avalos fatal("%s: pipe: %s", __func__, strerror(errno)); 19301c188a7fSPeter Avalos FD_CLOSEONEXEC(pair[0]); 19311c188a7fSPeter Avalos FD_CLOSEONEXEC(pair[1]); 19321c188a7fSPeter Avalos mon->m_log_recvfd = pair[0]; 19331c188a7fSPeter Avalos mon->m_log_sendfd = pair[1]; 19341c188a7fSPeter Avalos } else 19351c188a7fSPeter Avalos mon->m_log_recvfd = mon->m_log_sendfd = -1; 193618de8d7fSPeter Avalos } 193718de8d7fSPeter Avalos 193818de8d7fSPeter Avalos #define MM_MEMSIZE 65536 193918de8d7fSPeter Avalos 194018de8d7fSPeter Avalos struct monitor * 194118de8d7fSPeter Avalos monitor_init(void) 194218de8d7fSPeter Avalos { 1943*e9778795SPeter Avalos struct ssh *ssh = active_state; /* XXX */ 194418de8d7fSPeter Avalos struct monitor *mon; 194518de8d7fSPeter Avalos 194618de8d7fSPeter Avalos mon = xcalloc(1, sizeof(*mon)); 194718de8d7fSPeter Avalos 19481c188a7fSPeter Avalos monitor_openfds(mon, 1); 194918de8d7fSPeter Avalos 195018de8d7fSPeter Avalos /* Used to share zlib space across processes */ 195118de8d7fSPeter Avalos if (options.compression) { 195218de8d7fSPeter Avalos mon->m_zback = mm_create(NULL, MM_MEMSIZE); 195318de8d7fSPeter Avalos mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); 195418de8d7fSPeter Avalos 195518de8d7fSPeter Avalos /* Compression needs to share state across borders */ 1956*e9778795SPeter Avalos ssh_packet_set_compress_hooks(ssh, mon->m_zlib, 1957*e9778795SPeter Avalos (ssh_packet_comp_alloc_func *)mm_zalloc, 1958*e9778795SPeter Avalos (ssh_packet_comp_free_func *)mm_zfree); 195918de8d7fSPeter Avalos } 196018de8d7fSPeter Avalos 196118de8d7fSPeter Avalos return mon; 196218de8d7fSPeter Avalos } 196318de8d7fSPeter Avalos 196418de8d7fSPeter Avalos void 196518de8d7fSPeter Avalos monitor_reinit(struct monitor *mon) 196618de8d7fSPeter Avalos { 19671c188a7fSPeter Avalos monitor_openfds(mon, 0); 196818de8d7fSPeter Avalos } 196918de8d7fSPeter Avalos 197018de8d7fSPeter Avalos #ifdef GSSAPI 197118de8d7fSPeter Avalos int 197218de8d7fSPeter Avalos mm_answer_gss_setup_ctx(int sock, Buffer *m) 197318de8d7fSPeter Avalos { 197418de8d7fSPeter Avalos gss_OID_desc goid; 197518de8d7fSPeter Avalos OM_uint32 major; 197618de8d7fSPeter Avalos u_int len; 197718de8d7fSPeter Avalos 197818de8d7fSPeter Avalos goid.elements = buffer_get_string(m, &len); 197918de8d7fSPeter Avalos goid.length = len; 198018de8d7fSPeter Avalos 198118de8d7fSPeter Avalos major = ssh_gssapi_server_ctx(&gsscontext, &goid); 198218de8d7fSPeter Avalos 198336e94dc5SPeter Avalos free(goid.elements); 198418de8d7fSPeter Avalos 198518de8d7fSPeter Avalos buffer_clear(m); 198618de8d7fSPeter Avalos buffer_put_int(m, major); 198718de8d7fSPeter Avalos 198818de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); 198918de8d7fSPeter Avalos 199018de8d7fSPeter Avalos /* Now we have a context, enable the step */ 199118de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); 199218de8d7fSPeter Avalos 199318de8d7fSPeter Avalos return (0); 199418de8d7fSPeter Avalos } 199518de8d7fSPeter Avalos 199618de8d7fSPeter Avalos int 199718de8d7fSPeter Avalos mm_answer_gss_accept_ctx(int sock, Buffer *m) 199818de8d7fSPeter Avalos { 199918de8d7fSPeter Avalos gss_buffer_desc in; 200018de8d7fSPeter Avalos gss_buffer_desc out = GSS_C_EMPTY_BUFFER; 200118de8d7fSPeter Avalos OM_uint32 major, minor; 200218de8d7fSPeter Avalos OM_uint32 flags = 0; /* GSI needs this */ 200318de8d7fSPeter Avalos u_int len; 200418de8d7fSPeter Avalos 200518de8d7fSPeter Avalos in.value = buffer_get_string(m, &len); 200618de8d7fSPeter Avalos in.length = len; 200718de8d7fSPeter Avalos major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 200836e94dc5SPeter Avalos free(in.value); 200918de8d7fSPeter Avalos 201018de8d7fSPeter Avalos buffer_clear(m); 201118de8d7fSPeter Avalos buffer_put_int(m, major); 201218de8d7fSPeter Avalos buffer_put_string(m, out.value, out.length); 201318de8d7fSPeter Avalos buffer_put_int(m, flags); 201418de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); 201518de8d7fSPeter Avalos 201618de8d7fSPeter Avalos gss_release_buffer(&minor, &out); 201718de8d7fSPeter Avalos 201818de8d7fSPeter Avalos if (major == GSS_S_COMPLETE) { 201918de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 202018de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 202118de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 202218de8d7fSPeter Avalos } 202318de8d7fSPeter Avalos return (0); 202418de8d7fSPeter Avalos } 202518de8d7fSPeter Avalos 202618de8d7fSPeter Avalos int 202718de8d7fSPeter Avalos mm_answer_gss_checkmic(int sock, Buffer *m) 202818de8d7fSPeter Avalos { 202918de8d7fSPeter Avalos gss_buffer_desc gssbuf, mic; 203018de8d7fSPeter Avalos OM_uint32 ret; 203118de8d7fSPeter Avalos u_int len; 203218de8d7fSPeter Avalos 203318de8d7fSPeter Avalos gssbuf.value = buffer_get_string(m, &len); 203418de8d7fSPeter Avalos gssbuf.length = len; 203518de8d7fSPeter Avalos mic.value = buffer_get_string(m, &len); 203618de8d7fSPeter Avalos mic.length = len; 203718de8d7fSPeter Avalos 203818de8d7fSPeter Avalos ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); 203918de8d7fSPeter Avalos 204036e94dc5SPeter Avalos free(gssbuf.value); 204136e94dc5SPeter Avalos free(mic.value); 204218de8d7fSPeter Avalos 204318de8d7fSPeter Avalos buffer_clear(m); 204418de8d7fSPeter Avalos buffer_put_int(m, ret); 204518de8d7fSPeter Avalos 204618de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); 204718de8d7fSPeter Avalos 204818de8d7fSPeter Avalos if (!GSS_ERROR(ret)) 204918de8d7fSPeter Avalos monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 205018de8d7fSPeter Avalos 205118de8d7fSPeter Avalos return (0); 205218de8d7fSPeter Avalos } 205318de8d7fSPeter Avalos 205418de8d7fSPeter Avalos int 205518de8d7fSPeter Avalos mm_answer_gss_userok(int sock, Buffer *m) 205618de8d7fSPeter Avalos { 205718de8d7fSPeter Avalos int authenticated; 205818de8d7fSPeter Avalos 205918de8d7fSPeter Avalos authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 206018de8d7fSPeter Avalos 206118de8d7fSPeter Avalos buffer_clear(m); 206218de8d7fSPeter Avalos buffer_put_int(m, authenticated); 206318de8d7fSPeter Avalos 206418de8d7fSPeter Avalos debug3("%s: sending result %d", __func__, authenticated); 206518de8d7fSPeter Avalos mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); 206618de8d7fSPeter Avalos 206718de8d7fSPeter Avalos auth_method = "gssapi-with-mic"; 206818de8d7fSPeter Avalos 206918de8d7fSPeter Avalos /* Monitor loop will terminate if authenticated */ 207018de8d7fSPeter Avalos return (authenticated); 207118de8d7fSPeter Avalos } 207218de8d7fSPeter Avalos #endif /* GSSAPI */ 2073cb5eb4f1SPeter Avalos 2074