1*076ad2f8SDag-Erling Smørgrav /* $OpenBSD: monitor.c,v 1.161 2016/07/22 03:39:13 djm Exp $ */ 2545d5ecaSDag-Erling Smørgrav /* 3545d5ecaSDag-Erling Smørgrav * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4545d5ecaSDag-Erling Smørgrav * Copyright 2002 Markus Friedl <markus@openbsd.org> 5545d5ecaSDag-Erling Smørgrav * All rights reserved. 6545d5ecaSDag-Erling Smørgrav * 7545d5ecaSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 8545d5ecaSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 9545d5ecaSDag-Erling Smørgrav * are met: 10545d5ecaSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 11545d5ecaSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 12545d5ecaSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 13545d5ecaSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 14545d5ecaSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 15545d5ecaSDag-Erling Smørgrav * 16545d5ecaSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17545d5ecaSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18545d5ecaSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19545d5ecaSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20545d5ecaSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21545d5ecaSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22545d5ecaSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23545d5ecaSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24545d5ecaSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25545d5ecaSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26545d5ecaSDag-Erling Smørgrav */ 27545d5ecaSDag-Erling Smørgrav 28545d5ecaSDag-Erling Smørgrav #include "includes.h" 29545d5ecaSDag-Erling Smørgrav 30333ee039SDag-Erling Smørgrav #include <sys/types.h> 31333ee039SDag-Erling Smørgrav #include <sys/socket.h> 32333ee039SDag-Erling Smørgrav #include "openbsd-compat/sys-tree.h" 33333ee039SDag-Erling Smørgrav #include <sys/wait.h> 34333ee039SDag-Erling Smørgrav 35333ee039SDag-Erling Smørgrav #include <errno.h> 36333ee039SDag-Erling Smørgrav #include <fcntl.h> 37*076ad2f8SDag-Erling Smørgrav #include <limits.h> 38333ee039SDag-Erling Smørgrav #ifdef HAVE_PATHS_H 39333ee039SDag-Erling Smørgrav #include <paths.h> 40333ee039SDag-Erling Smørgrav #endif 41333ee039SDag-Erling Smørgrav #include <pwd.h> 42333ee039SDag-Erling Smørgrav #include <signal.h> 43bc5531deSDag-Erling Smørgrav #ifdef HAVE_STDINT_H 44bc5531deSDag-Erling Smørgrav #include <stdint.h> 45bc5531deSDag-Erling Smørgrav #endif 46333ee039SDag-Erling Smørgrav #include <stdlib.h> 47333ee039SDag-Erling Smørgrav #include <string.h> 48a0ee8cc6SDag-Erling Smørgrav #include <stdarg.h> 49a0ee8cc6SDag-Erling Smørgrav #include <stdio.h> 50333ee039SDag-Erling Smørgrav #include <unistd.h> 51e146993eSDag-Erling Smørgrav #ifdef HAVE_POLL_H 52e146993eSDag-Erling Smørgrav #include <poll.h> 53e146993eSDag-Erling Smørgrav #else 54e146993eSDag-Erling Smørgrav # ifdef HAVE_SYS_POLL_H 55e146993eSDag-Erling Smørgrav # include <sys/poll.h> 56e146993eSDag-Erling Smørgrav # endif 57e146993eSDag-Erling Smørgrav #endif 58545d5ecaSDag-Erling Smørgrav 59545d5ecaSDag-Erling Smørgrav #ifdef SKEY 60989dd127SDag-Erling Smørgrav #include <skey.h> 61545d5ecaSDag-Erling Smørgrav #endif 62545d5ecaSDag-Erling Smørgrav 63a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 64333ee039SDag-Erling Smørgrav #include <openssl/dh.h> 65a0ee8cc6SDag-Erling Smørgrav #endif 66333ee039SDag-Erling Smørgrav 67d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h" 68e146993eSDag-Erling Smørgrav #include "atomicio.h" 69333ee039SDag-Erling Smørgrav #include "xmalloc.h" 70545d5ecaSDag-Erling Smørgrav #include "ssh.h" 71333ee039SDag-Erling Smørgrav #include "key.h" 72333ee039SDag-Erling Smørgrav #include "buffer.h" 73333ee039SDag-Erling Smørgrav #include "hostfile.h" 74545d5ecaSDag-Erling Smørgrav #include "auth.h" 75333ee039SDag-Erling Smørgrav #include "cipher.h" 76545d5ecaSDag-Erling Smørgrav #include "kex.h" 77545d5ecaSDag-Erling Smørgrav #include "dh.h" 78*076ad2f8SDag-Erling Smørgrav #include "auth-pam.h" 795962c0e9SDag-Erling Smørgrav #ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */ 805962c0e9SDag-Erling Smørgrav #undef TARGET_OS_MAC 81545d5ecaSDag-Erling Smørgrav #include "zlib.h" 825962c0e9SDag-Erling Smørgrav #define TARGET_OS_MAC 1 835962c0e9SDag-Erling Smørgrav #else 845962c0e9SDag-Erling Smørgrav #include "zlib.h" 855962c0e9SDag-Erling Smørgrav #endif 86545d5ecaSDag-Erling Smørgrav #include "packet.h" 87545d5ecaSDag-Erling Smørgrav #include "auth-options.h" 88545d5ecaSDag-Erling Smørgrav #include "sshpty.h" 89545d5ecaSDag-Erling Smørgrav #include "channels.h" 90545d5ecaSDag-Erling Smørgrav #include "session.h" 91545d5ecaSDag-Erling Smørgrav #include "sshlogin.h" 92545d5ecaSDag-Erling Smørgrav #include "canohost.h" 93545d5ecaSDag-Erling Smørgrav #include "log.h" 94a0ee8cc6SDag-Erling Smørgrav #include "misc.h" 95545d5ecaSDag-Erling Smørgrav #include "servconf.h" 96545d5ecaSDag-Erling Smørgrav #include "monitor.h" 97545d5ecaSDag-Erling Smørgrav #include "monitor_mm.h" 98333ee039SDag-Erling Smørgrav #ifdef GSSAPI 99333ee039SDag-Erling Smørgrav #include "ssh-gss.h" 100333ee039SDag-Erling Smørgrav #endif 101545d5ecaSDag-Erling Smørgrav #include "monitor_wrap.h" 102545d5ecaSDag-Erling Smørgrav #include "monitor_fdpass.h" 103545d5ecaSDag-Erling Smørgrav #include "compat.h" 104545d5ecaSDag-Erling Smørgrav #include "ssh2.h" 105e4a9863fSDag-Erling Smørgrav #include "authfd.h" 106bc5531deSDag-Erling Smørgrav #include "match.h" 107bc5531deSDag-Erling Smørgrav #include "ssherr.h" 108545d5ecaSDag-Erling Smørgrav 109cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 110cf2b5f3bSDag-Erling Smørgrav static Gssctxt *gsscontext = NULL; 111cf2b5f3bSDag-Erling Smørgrav #endif 112cf2b5f3bSDag-Erling Smørgrav 113545d5ecaSDag-Erling Smørgrav /* Imports */ 114545d5ecaSDag-Erling Smørgrav extern ServerOptions options; 115545d5ecaSDag-Erling Smørgrav extern u_int utmp_len; 116545d5ecaSDag-Erling Smørgrav extern u_char session_id[]; 117545d5ecaSDag-Erling Smørgrav extern Buffer auth_debug; 118545d5ecaSDag-Erling Smørgrav extern int auth_debug_init; 11921e764dfSDag-Erling Smørgrav extern Buffer loginmsg; 120545d5ecaSDag-Erling Smørgrav 121545d5ecaSDag-Erling Smørgrav /* State exported from the child */ 122bc5531deSDag-Erling Smørgrav static struct sshbuf *child_state; 123545d5ecaSDag-Erling Smørgrav 124cf2b5f3bSDag-Erling Smørgrav /* Functions on the monitor that answer unprivileged requests */ 125545d5ecaSDag-Erling Smørgrav 126545d5ecaSDag-Erling Smørgrav int mm_answer_moduli(int, Buffer *); 127545d5ecaSDag-Erling Smørgrav int mm_answer_sign(int, Buffer *); 128545d5ecaSDag-Erling Smørgrav int mm_answer_pwnamallow(int, Buffer *); 129545d5ecaSDag-Erling Smørgrav int mm_answer_auth2_read_banner(int, Buffer *); 130545d5ecaSDag-Erling Smørgrav int mm_answer_authserv(int, Buffer *); 131545d5ecaSDag-Erling Smørgrav int mm_answer_authpassword(int, Buffer *); 132545d5ecaSDag-Erling Smørgrav int mm_answer_bsdauthquery(int, Buffer *); 133545d5ecaSDag-Erling Smørgrav int mm_answer_bsdauthrespond(int, Buffer *); 134545d5ecaSDag-Erling Smørgrav int mm_answer_skeyquery(int, Buffer *); 135545d5ecaSDag-Erling Smørgrav int mm_answer_skeyrespond(int, Buffer *); 136545d5ecaSDag-Erling Smørgrav int mm_answer_keyallowed(int, Buffer *); 137545d5ecaSDag-Erling Smørgrav int mm_answer_keyverify(int, Buffer *); 138545d5ecaSDag-Erling Smørgrav int mm_answer_pty(int, Buffer *); 139545d5ecaSDag-Erling Smørgrav int mm_answer_pty_cleanup(int, Buffer *); 140545d5ecaSDag-Erling Smørgrav int mm_answer_term(int, Buffer *); 141545d5ecaSDag-Erling Smørgrav int mm_answer_rsa_keyallowed(int, Buffer *); 142545d5ecaSDag-Erling Smørgrav int mm_answer_rsa_challenge(int, Buffer *); 143545d5ecaSDag-Erling Smørgrav int mm_answer_rsa_response(int, Buffer *); 144545d5ecaSDag-Erling Smørgrav int mm_answer_sesskey(int, Buffer *); 145545d5ecaSDag-Erling Smørgrav int mm_answer_sessid(int, Buffer *); 146545d5ecaSDag-Erling Smørgrav 147989dd127SDag-Erling Smørgrav #ifdef USE_PAM 148989dd127SDag-Erling Smørgrav int mm_answer_pam_start(int, Buffer *); 149cf2b5f3bSDag-Erling Smørgrav int mm_answer_pam_account(int, Buffer *); 150382d19eeSDag-Erling Smørgrav int mm_answer_pam_init_ctx(int, Buffer *); 151382d19eeSDag-Erling Smørgrav int mm_answer_pam_query(int, Buffer *); 152382d19eeSDag-Erling Smørgrav int mm_answer_pam_respond(int, Buffer *); 153382d19eeSDag-Erling Smørgrav int mm_answer_pam_free_ctx(int, Buffer *); 154989dd127SDag-Erling Smørgrav #endif 155989dd127SDag-Erling Smørgrav 156cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 157cf2b5f3bSDag-Erling Smørgrav int mm_answer_gss_setup_ctx(int, Buffer *); 158cf2b5f3bSDag-Erling Smørgrav int mm_answer_gss_accept_ctx(int, Buffer *); 159cf2b5f3bSDag-Erling Smørgrav int mm_answer_gss_userok(int, Buffer *); 1601ec0d754SDag-Erling Smørgrav int mm_answer_gss_checkmic(int, Buffer *); 161f388f5efSDag-Erling Smørgrav #endif 162f388f5efSDag-Erling Smørgrav 163aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 164aa49c926SDag-Erling Smørgrav int mm_answer_audit_event(int, Buffer *); 165aa49c926SDag-Erling Smørgrav int mm_answer_audit_command(int, Buffer *); 166aa49c926SDag-Erling Smørgrav #endif 167aa49c926SDag-Erling Smørgrav 168e146993eSDag-Erling Smørgrav static int monitor_read_log(struct monitor *); 169e146993eSDag-Erling Smørgrav 170545d5ecaSDag-Erling Smørgrav static Authctxt *authctxt; 171a0ee8cc6SDag-Erling Smørgrav 172a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_SSH1 173545d5ecaSDag-Erling Smørgrav static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 174a0ee8cc6SDag-Erling Smørgrav #endif 175545d5ecaSDag-Erling Smørgrav 176545d5ecaSDag-Erling Smørgrav /* local state for key verify */ 177545d5ecaSDag-Erling Smørgrav static u_char *key_blob = NULL; 178545d5ecaSDag-Erling Smørgrav static u_int key_bloblen = 0; 179545d5ecaSDag-Erling Smørgrav static int key_blobtype = MM_NOKEY; 180f388f5efSDag-Erling Smørgrav static char *hostbased_cuser = NULL; 181f388f5efSDag-Erling Smørgrav static char *hostbased_chost = NULL; 182545d5ecaSDag-Erling Smørgrav static char *auth_method = "unknown"; 1836888a9beSDag-Erling Smørgrav static char *auth_submethod = NULL; 184cf2b5f3bSDag-Erling Smørgrav static u_int session_id2_len = 0; 185545d5ecaSDag-Erling Smørgrav static u_char *session_id2 = NULL; 186cf2b5f3bSDag-Erling Smørgrav static pid_t monitor_child_pid; 187545d5ecaSDag-Erling Smørgrav 188545d5ecaSDag-Erling Smørgrav struct mon_table { 189545d5ecaSDag-Erling Smørgrav enum monitor_reqtype type; 190545d5ecaSDag-Erling Smørgrav int flags; 191545d5ecaSDag-Erling Smørgrav int (*f)(int, Buffer *); 192545d5ecaSDag-Erling Smørgrav }; 193545d5ecaSDag-Erling Smørgrav 194545d5ecaSDag-Erling Smørgrav #define MON_ISAUTH 0x0004 /* Required for Authentication */ 195545d5ecaSDag-Erling Smørgrav #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ 196545d5ecaSDag-Erling Smørgrav #define MON_ONCE 0x0010 /* Disable after calling */ 197333ee039SDag-Erling Smørgrav #define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ 198545d5ecaSDag-Erling Smørgrav 199545d5ecaSDag-Erling Smørgrav #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) 200545d5ecaSDag-Erling Smørgrav 201545d5ecaSDag-Erling Smørgrav #define MON_PERMIT 0x1000 /* Request is permitted */ 202545d5ecaSDag-Erling Smørgrav 203545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_proto20[] = { 204a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 205545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 206a0ee8cc6SDag-Erling Smørgrav #endif 207545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 208545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 209545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 210545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 211545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 212989dd127SDag-Erling Smørgrav #ifdef USE_PAM 213989dd127SDag-Erling Smørgrav {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 214cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 215382d19eeSDag-Erling Smørgrav {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 216382d19eeSDag-Erling Smørgrav {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 217382d19eeSDag-Erling Smørgrav {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 218382d19eeSDag-Erling Smørgrav {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 219989dd127SDag-Erling Smørgrav #endif 220aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 221aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 222aa49c926SDag-Erling Smørgrav #endif 223545d5ecaSDag-Erling Smørgrav #ifdef BSD_AUTH 224545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 225545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 226545d5ecaSDag-Erling Smørgrav #endif 227545d5ecaSDag-Erling Smørgrav #ifdef SKEY 228545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 229545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 230545d5ecaSDag-Erling Smørgrav #endif 231545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, 232545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, 233cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 234cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, 235cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, 236cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 2371ec0d754SDag-Erling Smørgrav {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 238cf2b5f3bSDag-Erling Smørgrav #endif 239545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 240545d5ecaSDag-Erling Smørgrav }; 241545d5ecaSDag-Erling Smørgrav 242545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_postauth20[] = { 243a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 244545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 245a0ee8cc6SDag-Erling Smørgrav #endif 246545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 247545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTY, 0, mm_answer_pty}, 248545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 249545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_TERM, 0, mm_answer_term}, 250aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 251aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 252aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 253aa49c926SDag-Erling Smørgrav #endif 254545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 255545d5ecaSDag-Erling Smørgrav }; 256545d5ecaSDag-Erling Smørgrav 257545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_proto15[] = { 258a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_SSH1 259545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 260545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, 261545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, 262545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 263333ee039SDag-Erling Smørgrav {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, 264333ee039SDag-Erling Smørgrav {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, 265545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, 266545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, 267545d5ecaSDag-Erling Smørgrav #ifdef BSD_AUTH 268545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 269545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 270545d5ecaSDag-Erling Smørgrav #endif 271545d5ecaSDag-Erling Smørgrav #ifdef SKEY 272545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, 273545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, 274545d5ecaSDag-Erling Smørgrav #endif 275a82e551fSDag-Erling Smørgrav #ifdef USE_PAM 276a82e551fSDag-Erling Smørgrav {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 277cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 278a82e551fSDag-Erling Smørgrav {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, 279a82e551fSDag-Erling Smørgrav {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, 280a82e551fSDag-Erling Smørgrav {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, 281a82e551fSDag-Erling Smørgrav {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 282a82e551fSDag-Erling Smørgrav #endif 283aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 284aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 285aa49c926SDag-Erling Smørgrav #endif 286a0ee8cc6SDag-Erling Smørgrav #endif /* WITH_SSH1 */ 287545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 288545d5ecaSDag-Erling Smørgrav }; 289545d5ecaSDag-Erling Smørgrav 290545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_postauth15[] = { 291a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_SSH1 292545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, 293545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, 294545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_TERM, 0, mm_answer_term}, 295aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 296aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 2979d2c6627SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, 298aa49c926SDag-Erling Smørgrav #endif 299a0ee8cc6SDag-Erling Smørgrav #endif /* WITH_SSH1 */ 300545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 301545d5ecaSDag-Erling Smørgrav }; 302545d5ecaSDag-Erling Smørgrav 303545d5ecaSDag-Erling Smørgrav struct mon_table *mon_dispatch; 304545d5ecaSDag-Erling Smørgrav 305545d5ecaSDag-Erling Smørgrav /* Specifies if a certain message is allowed at the moment */ 306545d5ecaSDag-Erling Smørgrav 307545d5ecaSDag-Erling Smørgrav static void 308545d5ecaSDag-Erling Smørgrav monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) 309545d5ecaSDag-Erling Smørgrav { 310545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 311545d5ecaSDag-Erling Smørgrav if (ent->type == type) { 312545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 313545d5ecaSDag-Erling Smørgrav ent->flags |= permit ? MON_PERMIT : 0; 314545d5ecaSDag-Erling Smørgrav return; 315545d5ecaSDag-Erling Smørgrav } 316545d5ecaSDag-Erling Smørgrav ent++; 317545d5ecaSDag-Erling Smørgrav } 318545d5ecaSDag-Erling Smørgrav } 319545d5ecaSDag-Erling Smørgrav 320545d5ecaSDag-Erling Smørgrav static void 321545d5ecaSDag-Erling Smørgrav monitor_permit_authentications(int permit) 322545d5ecaSDag-Erling Smørgrav { 323545d5ecaSDag-Erling Smørgrav struct mon_table *ent = mon_dispatch; 324545d5ecaSDag-Erling Smørgrav 325545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 326545d5ecaSDag-Erling Smørgrav if (ent->flags & MON_AUTH) { 327545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 328545d5ecaSDag-Erling Smørgrav ent->flags |= permit ? MON_PERMIT : 0; 329545d5ecaSDag-Erling Smørgrav } 330545d5ecaSDag-Erling Smørgrav ent++; 331545d5ecaSDag-Erling Smørgrav } 332545d5ecaSDag-Erling Smørgrav } 333545d5ecaSDag-Erling Smørgrav 3341ec0d754SDag-Erling Smørgrav void 3351ec0d754SDag-Erling Smørgrav monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 336545d5ecaSDag-Erling Smørgrav { 337545d5ecaSDag-Erling Smørgrav struct mon_table *ent; 3386888a9beSDag-Erling Smørgrav int authenticated = 0, partial = 0; 339545d5ecaSDag-Erling Smørgrav 340545d5ecaSDag-Erling Smørgrav debug3("preauth child monitor started"); 341545d5ecaSDag-Erling Smørgrav 342e146993eSDag-Erling Smørgrav close(pmonitor->m_recvfd); 343e146993eSDag-Erling Smørgrav close(pmonitor->m_log_sendfd); 344e146993eSDag-Erling Smørgrav pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; 345e146993eSDag-Erling Smørgrav 3461ec0d754SDag-Erling Smørgrav authctxt = _authctxt; 3471ec0d754SDag-Erling Smørgrav memset(authctxt, 0, sizeof(*authctxt)); 3481ec0d754SDag-Erling Smørgrav 349aa49c926SDag-Erling Smørgrav authctxt->loginmsg = &loginmsg; 350aa49c926SDag-Erling Smørgrav 351545d5ecaSDag-Erling Smørgrav if (compat20) { 352545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_proto20; 353545d5ecaSDag-Erling Smørgrav 354545d5ecaSDag-Erling Smørgrav /* Permit requests for moduli and signatures */ 355545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 356545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 357545d5ecaSDag-Erling Smørgrav } else { 358545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_proto15; 359545d5ecaSDag-Erling Smørgrav 360545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); 361545d5ecaSDag-Erling Smørgrav } 362545d5ecaSDag-Erling Smørgrav 363545d5ecaSDag-Erling Smørgrav /* The first few requests do not require asynchronous access */ 364545d5ecaSDag-Erling Smørgrav while (!authenticated) { 3656888a9beSDag-Erling Smørgrav partial = 0; 366333ee039SDag-Erling Smørgrav auth_method = "unknown"; 3676888a9beSDag-Erling Smørgrav auth_submethod = NULL; 36862efe23aSDag-Erling Smørgrav authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); 3696888a9beSDag-Erling Smørgrav 3706888a9beSDag-Erling Smørgrav /* Special handling for multiple required authentications */ 3716888a9beSDag-Erling Smørgrav if (options.num_auth_methods != 0) { 3726888a9beSDag-Erling Smørgrav if (!compat20) 3736888a9beSDag-Erling Smørgrav fatal("AuthenticationMethods is not supported" 3746888a9beSDag-Erling Smørgrav "with SSH protocol 1"); 3756888a9beSDag-Erling Smørgrav if (authenticated && 3766888a9beSDag-Erling Smørgrav !auth2_update_methods_lists(authctxt, 377e4a9863fSDag-Erling Smørgrav auth_method, auth_submethod)) { 3786888a9beSDag-Erling Smørgrav debug3("%s: method %s: partial", __func__, 3796888a9beSDag-Erling Smørgrav auth_method); 3806888a9beSDag-Erling Smørgrav authenticated = 0; 3816888a9beSDag-Erling Smørgrav partial = 1; 3826888a9beSDag-Erling Smørgrav } 3836888a9beSDag-Erling Smørgrav } 3846888a9beSDag-Erling Smørgrav 385545d5ecaSDag-Erling Smørgrav if (authenticated) { 386545d5ecaSDag-Erling Smørgrav if (!(ent->flags & MON_AUTHDECIDE)) 387545d5ecaSDag-Erling Smørgrav fatal("%s: unexpected authentication from %d", 388545d5ecaSDag-Erling Smørgrav __func__, ent->type); 389545d5ecaSDag-Erling Smørgrav if (authctxt->pw->pw_uid == 0 && 390545d5ecaSDag-Erling Smørgrav !auth_root_allowed(auth_method)) 391545d5ecaSDag-Erling Smørgrav authenticated = 0; 392cf2b5f3bSDag-Erling Smørgrav #ifdef USE_PAM 393cf2b5f3bSDag-Erling Smørgrav /* PAM needs to perform account checks after auth */ 3941ec0d754SDag-Erling Smørgrav if (options.use_pam && authenticated) { 395cf2b5f3bSDag-Erling Smørgrav Buffer m; 396cf2b5f3bSDag-Erling Smørgrav 397cf2b5f3bSDag-Erling Smørgrav buffer_init(&m); 398cf2b5f3bSDag-Erling Smørgrav mm_request_receive_expect(pmonitor->m_sendfd, 399cf2b5f3bSDag-Erling Smørgrav MONITOR_REQ_PAM_ACCOUNT, &m); 400cf2b5f3bSDag-Erling Smørgrav authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m); 401cf2b5f3bSDag-Erling Smørgrav buffer_free(&m); 402cf2b5f3bSDag-Erling Smørgrav } 403cf2b5f3bSDag-Erling Smørgrav #endif 404545d5ecaSDag-Erling Smørgrav } 405333ee039SDag-Erling Smørgrav if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { 4066888a9beSDag-Erling Smørgrav auth_log(authctxt, authenticated, partial, 407e4a9863fSDag-Erling Smørgrav auth_method, auth_submethod); 408557f75e5SDag-Erling Smørgrav if (!partial && !authenticated) 409545d5ecaSDag-Erling Smørgrav authctxt->failures++; 410545d5ecaSDag-Erling Smørgrav } 411545d5ecaSDag-Erling Smørgrav } 412545d5ecaSDag-Erling Smørgrav 413545d5ecaSDag-Erling Smørgrav if (!authctxt->valid) 414545d5ecaSDag-Erling Smørgrav fatal("%s: authenticated invalid user", __func__); 415333ee039SDag-Erling Smørgrav if (strcmp(auth_method, "unknown") == 0) 416333ee039SDag-Erling Smørgrav fatal("%s: authentication method name unknown", __func__); 417545d5ecaSDag-Erling Smørgrav 418545d5ecaSDag-Erling Smørgrav debug("%s: %s has been authenticated by privileged process", 419545d5ecaSDag-Erling Smørgrav __func__, authctxt->user); 420545d5ecaSDag-Erling Smørgrav 421545d5ecaSDag-Erling Smørgrav mm_get_keystate(pmonitor); 422e146993eSDag-Erling Smørgrav 4236888a9beSDag-Erling Smørgrav /* Drain any buffered messages from the child */ 4246888a9beSDag-Erling Smørgrav while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) 4256888a9beSDag-Erling Smørgrav ; 4266888a9beSDag-Erling Smørgrav 427e146993eSDag-Erling Smørgrav close(pmonitor->m_sendfd); 428e146993eSDag-Erling Smørgrav close(pmonitor->m_log_recvfd); 429e146993eSDag-Erling Smørgrav pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 430545d5ecaSDag-Erling Smørgrav } 431545d5ecaSDag-Erling Smørgrav 432cf2b5f3bSDag-Erling Smørgrav static void 433cf2b5f3bSDag-Erling Smørgrav monitor_set_child_handler(pid_t pid) 434cf2b5f3bSDag-Erling Smørgrav { 435cf2b5f3bSDag-Erling Smørgrav monitor_child_pid = pid; 436cf2b5f3bSDag-Erling Smørgrav } 437cf2b5f3bSDag-Erling Smørgrav 438cf2b5f3bSDag-Erling Smørgrav static void 43921e764dfSDag-Erling Smørgrav monitor_child_handler(int sig) 440cf2b5f3bSDag-Erling Smørgrav { 44121e764dfSDag-Erling Smørgrav kill(monitor_child_pid, sig); 442cf2b5f3bSDag-Erling Smørgrav } 443cf2b5f3bSDag-Erling Smørgrav 444545d5ecaSDag-Erling Smørgrav void 445545d5ecaSDag-Erling Smørgrav monitor_child_postauth(struct monitor *pmonitor) 446545d5ecaSDag-Erling Smørgrav { 447e146993eSDag-Erling Smørgrav close(pmonitor->m_recvfd); 448e146993eSDag-Erling Smørgrav pmonitor->m_recvfd = -1; 449e146993eSDag-Erling Smørgrav 450cf2b5f3bSDag-Erling Smørgrav monitor_set_child_handler(pmonitor->m_pid); 451cf2b5f3bSDag-Erling Smørgrav signal(SIGHUP, &monitor_child_handler); 452cf2b5f3bSDag-Erling Smørgrav signal(SIGTERM, &monitor_child_handler); 453d4af9e69SDag-Erling Smørgrav signal(SIGINT, &monitor_child_handler); 454a0ee8cc6SDag-Erling Smørgrav #ifdef SIGXFSZ 455a0ee8cc6SDag-Erling Smørgrav signal(SIGXFSZ, SIG_IGN); 456a0ee8cc6SDag-Erling Smørgrav #endif 457cf2b5f3bSDag-Erling Smørgrav 458545d5ecaSDag-Erling Smørgrav if (compat20) { 459545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_postauth20; 460545d5ecaSDag-Erling Smørgrav 461545d5ecaSDag-Erling Smørgrav /* Permit requests for moduli and signatures */ 462545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 463545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 464545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 465545d5ecaSDag-Erling Smørgrav } else { 466545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_postauth15; 467545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 468545d5ecaSDag-Erling Smørgrav } 469545d5ecaSDag-Erling Smørgrav if (!no_pty_flag) { 470545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 471545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 472545d5ecaSDag-Erling Smørgrav } 473545d5ecaSDag-Erling Smørgrav 474545d5ecaSDag-Erling Smørgrav for (;;) 475545d5ecaSDag-Erling Smørgrav monitor_read(pmonitor, mon_dispatch, NULL); 476545d5ecaSDag-Erling Smørgrav } 477545d5ecaSDag-Erling Smørgrav 478545d5ecaSDag-Erling Smørgrav void 479545d5ecaSDag-Erling Smørgrav monitor_sync(struct monitor *pmonitor) 480545d5ecaSDag-Erling Smørgrav { 481545d5ecaSDag-Erling Smørgrav if (options.compression) { 482545d5ecaSDag-Erling Smørgrav /* The member allocation is not visible, so sync it */ 483545d5ecaSDag-Erling Smørgrav mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); 484545d5ecaSDag-Erling Smørgrav } 485545d5ecaSDag-Erling Smørgrav } 486545d5ecaSDag-Erling Smørgrav 487bc5531deSDag-Erling Smørgrav /* Allocation functions for zlib */ 488bc5531deSDag-Erling Smørgrav static void * 489bc5531deSDag-Erling Smørgrav mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) 490bc5531deSDag-Erling Smørgrav { 491acc1a9efSDag-Erling Smørgrav if (size == 0 || ncount == 0 || ncount > SIZE_MAX / size) 492bc5531deSDag-Erling Smørgrav fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); 493bc5531deSDag-Erling Smørgrav 494acc1a9efSDag-Erling Smørgrav return mm_malloc(mm, size * ncount); 495bc5531deSDag-Erling Smørgrav } 496bc5531deSDag-Erling Smørgrav 497bc5531deSDag-Erling Smørgrav static void 498bc5531deSDag-Erling Smørgrav mm_zfree(struct mm_master *mm, void *address) 499bc5531deSDag-Erling Smørgrav { 500bc5531deSDag-Erling Smørgrav mm_free(mm, address); 501bc5531deSDag-Erling Smørgrav } 502bc5531deSDag-Erling Smørgrav 503e146993eSDag-Erling Smørgrav static int 504e146993eSDag-Erling Smørgrav monitor_read_log(struct monitor *pmonitor) 505e146993eSDag-Erling Smørgrav { 506e146993eSDag-Erling Smørgrav Buffer logmsg; 507e146993eSDag-Erling Smørgrav u_int len, level; 508e146993eSDag-Erling Smørgrav char *msg; 509e146993eSDag-Erling Smørgrav 510e146993eSDag-Erling Smørgrav buffer_init(&logmsg); 511e146993eSDag-Erling Smørgrav 512e146993eSDag-Erling Smørgrav /* Read length */ 513e146993eSDag-Erling Smørgrav buffer_append_space(&logmsg, 4); 514e146993eSDag-Erling Smørgrav if (atomicio(read, pmonitor->m_log_recvfd, 515e146993eSDag-Erling Smørgrav buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) { 516e146993eSDag-Erling Smørgrav if (errno == EPIPE) { 517462c32cbSDag-Erling Smørgrav buffer_free(&logmsg); 518e146993eSDag-Erling Smørgrav debug("%s: child log fd closed", __func__); 519e146993eSDag-Erling Smørgrav close(pmonitor->m_log_recvfd); 520e146993eSDag-Erling Smørgrav pmonitor->m_log_recvfd = -1; 521e146993eSDag-Erling Smørgrav return -1; 522e146993eSDag-Erling Smørgrav } 523e146993eSDag-Erling Smørgrav fatal("%s: log fd read: %s", __func__, strerror(errno)); 524e146993eSDag-Erling Smørgrav } 525e146993eSDag-Erling Smørgrav len = buffer_get_int(&logmsg); 526e146993eSDag-Erling Smørgrav if (len <= 4 || len > 8192) 527e146993eSDag-Erling Smørgrav fatal("%s: invalid log message length %u", __func__, len); 528e146993eSDag-Erling Smørgrav 529e146993eSDag-Erling Smørgrav /* Read severity, message */ 530e146993eSDag-Erling Smørgrav buffer_clear(&logmsg); 531e146993eSDag-Erling Smørgrav buffer_append_space(&logmsg, len); 532e146993eSDag-Erling Smørgrav if (atomicio(read, pmonitor->m_log_recvfd, 533e146993eSDag-Erling Smørgrav buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) 534e146993eSDag-Erling Smørgrav fatal("%s: log fd read: %s", __func__, strerror(errno)); 535e146993eSDag-Erling Smørgrav 536e146993eSDag-Erling Smørgrav /* Log it */ 537e146993eSDag-Erling Smørgrav level = buffer_get_int(&logmsg); 538e146993eSDag-Erling Smørgrav msg = buffer_get_string(&logmsg, NULL); 539e146993eSDag-Erling Smørgrav if (log_level_name(level) == NULL) 540e146993eSDag-Erling Smørgrav fatal("%s: invalid log level %u (corrupted message?)", 541e146993eSDag-Erling Smørgrav __func__, level); 542e146993eSDag-Erling Smørgrav do_log2(level, "%s [preauth]", msg); 543e146993eSDag-Erling Smørgrav 544e146993eSDag-Erling Smørgrav buffer_free(&logmsg); 545e4a9863fSDag-Erling Smørgrav free(msg); 546e146993eSDag-Erling Smørgrav 547e146993eSDag-Erling Smørgrav return 0; 548e146993eSDag-Erling Smørgrav } 549e146993eSDag-Erling Smørgrav 550545d5ecaSDag-Erling Smørgrav int 551545d5ecaSDag-Erling Smørgrav monitor_read(struct monitor *pmonitor, struct mon_table *ent, 552545d5ecaSDag-Erling Smørgrav struct mon_table **pent) 553545d5ecaSDag-Erling Smørgrav { 554545d5ecaSDag-Erling Smørgrav Buffer m; 555545d5ecaSDag-Erling Smørgrav int ret; 556545d5ecaSDag-Erling Smørgrav u_char type; 557e146993eSDag-Erling Smørgrav struct pollfd pfd[2]; 558e146993eSDag-Erling Smørgrav 559e146993eSDag-Erling Smørgrav for (;;) { 560b83788ffSDag-Erling Smørgrav memset(&pfd, 0, sizeof(pfd)); 561e146993eSDag-Erling Smørgrav pfd[0].fd = pmonitor->m_sendfd; 562e146993eSDag-Erling Smørgrav pfd[0].events = POLLIN; 563e146993eSDag-Erling Smørgrav pfd[1].fd = pmonitor->m_log_recvfd; 564e146993eSDag-Erling Smørgrav pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; 565e146993eSDag-Erling Smørgrav if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { 566e146993eSDag-Erling Smørgrav if (errno == EINTR || errno == EAGAIN) 567e146993eSDag-Erling Smørgrav continue; 568e146993eSDag-Erling Smørgrav fatal("%s: poll: %s", __func__, strerror(errno)); 569e146993eSDag-Erling Smørgrav } 570e146993eSDag-Erling Smørgrav if (pfd[1].revents) { 571e146993eSDag-Erling Smørgrav /* 572e146993eSDag-Erling Smørgrav * Drain all log messages before processing next 573e146993eSDag-Erling Smørgrav * monitor request. 574e146993eSDag-Erling Smørgrav */ 575e146993eSDag-Erling Smørgrav monitor_read_log(pmonitor); 576e146993eSDag-Erling Smørgrav continue; 577e146993eSDag-Erling Smørgrav } 578e146993eSDag-Erling Smørgrav if (pfd[0].revents) 579e146993eSDag-Erling Smørgrav break; /* Continues below */ 580e146993eSDag-Erling Smørgrav } 581545d5ecaSDag-Erling Smørgrav 582545d5ecaSDag-Erling Smørgrav buffer_init(&m); 583545d5ecaSDag-Erling Smørgrav 584545d5ecaSDag-Erling Smørgrav mm_request_receive(pmonitor->m_sendfd, &m); 585545d5ecaSDag-Erling Smørgrav type = buffer_get_char(&m); 586545d5ecaSDag-Erling Smørgrav 587545d5ecaSDag-Erling Smørgrav debug3("%s: checking request %d", __func__, type); 588545d5ecaSDag-Erling Smørgrav 589545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 590545d5ecaSDag-Erling Smørgrav if (ent->type == type) 591545d5ecaSDag-Erling Smørgrav break; 592545d5ecaSDag-Erling Smørgrav ent++; 593545d5ecaSDag-Erling Smørgrav } 594545d5ecaSDag-Erling Smørgrav 595545d5ecaSDag-Erling Smørgrav if (ent->f != NULL) { 596545d5ecaSDag-Erling Smørgrav if (!(ent->flags & MON_PERMIT)) 597545d5ecaSDag-Erling Smørgrav fatal("%s: unpermitted request %d", __func__, 598545d5ecaSDag-Erling Smørgrav type); 599545d5ecaSDag-Erling Smørgrav ret = (*ent->f)(pmonitor->m_sendfd, &m); 600545d5ecaSDag-Erling Smørgrav buffer_free(&m); 601545d5ecaSDag-Erling Smørgrav 602545d5ecaSDag-Erling Smørgrav /* The child may use this request only once, disable it */ 603545d5ecaSDag-Erling Smørgrav if (ent->flags & MON_ONCE) { 604545d5ecaSDag-Erling Smørgrav debug2("%s: %d used once, disabling now", __func__, 605545d5ecaSDag-Erling Smørgrav type); 606545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 607545d5ecaSDag-Erling Smørgrav } 608545d5ecaSDag-Erling Smørgrav 609545d5ecaSDag-Erling Smørgrav if (pent != NULL) 610545d5ecaSDag-Erling Smørgrav *pent = ent; 611545d5ecaSDag-Erling Smørgrav 612545d5ecaSDag-Erling Smørgrav return ret; 613545d5ecaSDag-Erling Smørgrav } 614545d5ecaSDag-Erling Smørgrav 615545d5ecaSDag-Erling Smørgrav fatal("%s: unsupported request: %d", __func__, type); 616545d5ecaSDag-Erling Smørgrav 617545d5ecaSDag-Erling Smørgrav /* NOTREACHED */ 618545d5ecaSDag-Erling Smørgrav return (-1); 619545d5ecaSDag-Erling Smørgrav } 620545d5ecaSDag-Erling Smørgrav 621545d5ecaSDag-Erling Smørgrav /* allowed key state */ 622545d5ecaSDag-Erling Smørgrav static int 623545d5ecaSDag-Erling Smørgrav monitor_allowed_key(u_char *blob, u_int bloblen) 624545d5ecaSDag-Erling Smørgrav { 625545d5ecaSDag-Erling Smørgrav /* make sure key is allowed */ 626545d5ecaSDag-Erling Smørgrav if (key_blob == NULL || key_bloblen != bloblen || 627e2f6069cSDag-Erling Smørgrav timingsafe_bcmp(key_blob, blob, key_bloblen)) 628545d5ecaSDag-Erling Smørgrav return (0); 629545d5ecaSDag-Erling Smørgrav return (1); 630545d5ecaSDag-Erling Smørgrav } 631545d5ecaSDag-Erling Smørgrav 632545d5ecaSDag-Erling Smørgrav static void 633545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(void) 634545d5ecaSDag-Erling Smørgrav { 635545d5ecaSDag-Erling Smørgrav /* reset state */ 636e4a9863fSDag-Erling Smørgrav free(key_blob); 637e4a9863fSDag-Erling Smørgrav free(hostbased_cuser); 638e4a9863fSDag-Erling Smørgrav free(hostbased_chost); 639545d5ecaSDag-Erling Smørgrav key_blob = NULL; 640545d5ecaSDag-Erling Smørgrav key_bloblen = 0; 641545d5ecaSDag-Erling Smørgrav key_blobtype = MM_NOKEY; 642545d5ecaSDag-Erling Smørgrav hostbased_cuser = NULL; 643545d5ecaSDag-Erling Smørgrav hostbased_chost = NULL; 644545d5ecaSDag-Erling Smørgrav } 645545d5ecaSDag-Erling Smørgrav 646a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 647545d5ecaSDag-Erling Smørgrav int 64821e764dfSDag-Erling Smørgrav mm_answer_moduli(int sock, Buffer *m) 649545d5ecaSDag-Erling Smørgrav { 650545d5ecaSDag-Erling Smørgrav DH *dh; 651545d5ecaSDag-Erling Smørgrav int min, want, max; 652545d5ecaSDag-Erling Smørgrav 653545d5ecaSDag-Erling Smørgrav min = buffer_get_int(m); 654545d5ecaSDag-Erling Smørgrav want = buffer_get_int(m); 655545d5ecaSDag-Erling Smørgrav max = buffer_get_int(m); 656545d5ecaSDag-Erling Smørgrav 657545d5ecaSDag-Erling Smørgrav debug3("%s: got parameters: %d %d %d", 658545d5ecaSDag-Erling Smørgrav __func__, min, want, max); 659545d5ecaSDag-Erling Smørgrav /* We need to check here, too, in case the child got corrupted */ 660545d5ecaSDag-Erling Smørgrav if (max < min || want < min || max < want) 661545d5ecaSDag-Erling Smørgrav fatal("%s: bad parameters: %d %d %d", 662545d5ecaSDag-Erling Smørgrav __func__, min, want, max); 663545d5ecaSDag-Erling Smørgrav 664545d5ecaSDag-Erling Smørgrav buffer_clear(m); 665545d5ecaSDag-Erling Smørgrav 666545d5ecaSDag-Erling Smørgrav dh = choose_dh(min, want, max); 667545d5ecaSDag-Erling Smørgrav if (dh == NULL) { 668545d5ecaSDag-Erling Smørgrav buffer_put_char(m, 0); 669545d5ecaSDag-Erling Smørgrav return (0); 670545d5ecaSDag-Erling Smørgrav } else { 671545d5ecaSDag-Erling Smørgrav /* Send first bignum */ 672545d5ecaSDag-Erling Smørgrav buffer_put_char(m, 1); 673545d5ecaSDag-Erling Smørgrav buffer_put_bignum2(m, dh->p); 674545d5ecaSDag-Erling Smørgrav buffer_put_bignum2(m, dh->g); 675545d5ecaSDag-Erling Smørgrav 676545d5ecaSDag-Erling Smørgrav DH_free(dh); 677545d5ecaSDag-Erling Smørgrav } 67821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_MODULI, m); 679545d5ecaSDag-Erling Smørgrav return (0); 680545d5ecaSDag-Erling Smørgrav } 681a0ee8cc6SDag-Erling Smørgrav #endif 682545d5ecaSDag-Erling Smørgrav 683545d5ecaSDag-Erling Smørgrav int 68421e764dfSDag-Erling Smørgrav mm_answer_sign(int sock, Buffer *m) 685545d5ecaSDag-Erling Smørgrav { 686bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 687bc5531deSDag-Erling Smørgrav extern int auth_sock; /* XXX move to state struct? */ 688bc5531deSDag-Erling Smørgrav struct sshkey *key; 689acc1a9efSDag-Erling Smørgrav struct sshbuf *sigbuf = NULL; 690acc1a9efSDag-Erling Smørgrav u_char *p = NULL, *signature = NULL; 691acc1a9efSDag-Erling Smørgrav char *alg = NULL; 692acc1a9efSDag-Erling Smørgrav size_t datlen, siglen, alglen; 693*076ad2f8SDag-Erling Smørgrav int r, is_proof = 0; 694*076ad2f8SDag-Erling Smørgrav u_int keyid; 695bc5531deSDag-Erling Smørgrav const char proof_req[] = "hostkeys-prove-00@openssh.com"; 696545d5ecaSDag-Erling Smørgrav 697545d5ecaSDag-Erling Smørgrav debug3("%s", __func__); 698545d5ecaSDag-Erling Smørgrav 699bc5531deSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 700acc1a9efSDag-Erling Smørgrav (r = sshbuf_get_string(m, &p, &datlen)) != 0 || 701acc1a9efSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0) 702bc5531deSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 703*076ad2f8SDag-Erling Smørgrav if (keyid > INT_MAX) 704*076ad2f8SDag-Erling Smørgrav fatal("%s: invalid key ID", __func__); 705545d5ecaSDag-Erling Smørgrav 706333ee039SDag-Erling Smørgrav /* 7074a421b63SDag-Erling Smørgrav * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), 7084a421b63SDag-Erling Smørgrav * SHA384 (48 bytes) and SHA512 (64 bytes). 709bc5531deSDag-Erling Smørgrav * 710bc5531deSDag-Erling Smørgrav * Otherwise, verify the signature request is for a hostkey 711bc5531deSDag-Erling Smørgrav * proof. 712bc5531deSDag-Erling Smørgrav * 713bc5531deSDag-Erling Smørgrav * XXX perform similar check for KEX signature requests too? 714bc5531deSDag-Erling Smørgrav * it's not trivial, since what is signed is the hash, rather 715bc5531deSDag-Erling Smørgrav * than the full kex structure... 716333ee039SDag-Erling Smørgrav */ 717bc5531deSDag-Erling Smørgrav if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { 718bc5531deSDag-Erling Smørgrav /* 719bc5531deSDag-Erling Smørgrav * Construct expected hostkey proof and compare it to what 720bc5531deSDag-Erling Smørgrav * the client sent us. 721bc5531deSDag-Erling Smørgrav */ 722bc5531deSDag-Erling Smørgrav if (session_id2_len == 0) /* hostkeys is never first */ 723bc5531deSDag-Erling Smørgrav fatal("%s: bad data length: %zu", __func__, datlen); 724bc5531deSDag-Erling Smørgrav if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) 725bc5531deSDag-Erling Smørgrav fatal("%s: no hostkey for index %d", __func__, keyid); 726bc5531deSDag-Erling Smørgrav if ((sigbuf = sshbuf_new()) == NULL) 727bc5531deSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 728bc5531deSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || 729bc5531deSDag-Erling Smørgrav (r = sshbuf_put_string(sigbuf, session_id2, 730acc1a9efSDag-Erling Smørgrav session_id2_len)) != 0 || 731bc5531deSDag-Erling Smørgrav (r = sshkey_puts(key, sigbuf)) != 0) 732bc5531deSDag-Erling Smørgrav fatal("%s: couldn't prepare private key " 733bc5531deSDag-Erling Smørgrav "proof buffer: %s", __func__, ssh_err(r)); 734bc5531deSDag-Erling Smørgrav if (datlen != sshbuf_len(sigbuf) || 735bc5531deSDag-Erling Smørgrav memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) 736bc5531deSDag-Erling Smørgrav fatal("%s: bad data length: %zu, hostkey proof len %zu", 737bc5531deSDag-Erling Smørgrav __func__, datlen, sshbuf_len(sigbuf)); 738bc5531deSDag-Erling Smørgrav sshbuf_free(sigbuf); 739bc5531deSDag-Erling Smørgrav is_proof = 1; 740bc5531deSDag-Erling Smørgrav } 741545d5ecaSDag-Erling Smørgrav 742545d5ecaSDag-Erling Smørgrav /* save session id, it will be passed on the first call */ 743545d5ecaSDag-Erling Smørgrav if (session_id2_len == 0) { 744545d5ecaSDag-Erling Smørgrav session_id2_len = datlen; 745545d5ecaSDag-Erling Smørgrav session_id2 = xmalloc(session_id2_len); 746545d5ecaSDag-Erling Smørgrav memcpy(session_id2, p, session_id2_len); 747545d5ecaSDag-Erling Smørgrav } 748545d5ecaSDag-Erling Smørgrav 749e4a9863fSDag-Erling Smørgrav if ((key = get_hostkey_by_index(keyid)) != NULL) { 750acc1a9efSDag-Erling Smørgrav if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, 751bc5531deSDag-Erling Smørgrav datafellows)) != 0) 752bc5531deSDag-Erling Smørgrav fatal("%s: sshkey_sign failed: %s", 753bc5531deSDag-Erling Smørgrav __func__, ssh_err(r)); 754bc5531deSDag-Erling Smørgrav } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 755bc5531deSDag-Erling Smørgrav auth_sock > 0) { 756bc5531deSDag-Erling Smørgrav if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 757acc1a9efSDag-Erling Smørgrav p, datlen, alg, datafellows)) != 0) { 758bc5531deSDag-Erling Smørgrav fatal("%s: ssh_agent_sign failed: %s", 759bc5531deSDag-Erling Smørgrav __func__, ssh_err(r)); 760bc5531deSDag-Erling Smørgrav } 761e4a9863fSDag-Erling Smørgrav } else 762e4a9863fSDag-Erling Smørgrav fatal("%s: no hostkey from index %d", __func__, keyid); 763545d5ecaSDag-Erling Smørgrav 764bc5531deSDag-Erling Smørgrav debug3("%s: %s signature %p(%zu)", __func__, 765bc5531deSDag-Erling Smørgrav is_proof ? "KEX" : "hostkey proof", signature, siglen); 766545d5ecaSDag-Erling Smørgrav 767bc5531deSDag-Erling Smørgrav sshbuf_reset(m); 768bc5531deSDag-Erling Smørgrav if ((r = sshbuf_put_string(m, signature, siglen)) != 0) 769bc5531deSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 770545d5ecaSDag-Erling Smørgrav 771acc1a9efSDag-Erling Smørgrav free(alg); 772e4a9863fSDag-Erling Smørgrav free(p); 773e4a9863fSDag-Erling Smørgrav free(signature); 774545d5ecaSDag-Erling Smørgrav 77521e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_SIGN, m); 776545d5ecaSDag-Erling Smørgrav 777545d5ecaSDag-Erling Smørgrav /* Turn on permissions for getpwnam */ 778545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 779545d5ecaSDag-Erling Smørgrav 780545d5ecaSDag-Erling Smørgrav return (0); 781545d5ecaSDag-Erling Smørgrav } 782545d5ecaSDag-Erling Smørgrav 783545d5ecaSDag-Erling Smørgrav /* Retrieves the password entry and also checks if the user is permitted */ 784545d5ecaSDag-Erling Smørgrav 785545d5ecaSDag-Erling Smørgrav int 78621e764dfSDag-Erling Smørgrav mm_answer_pwnamallow(int sock, Buffer *m) 787545d5ecaSDag-Erling Smørgrav { 78821e764dfSDag-Erling Smørgrav char *username; 789545d5ecaSDag-Erling Smørgrav struct passwd *pwent; 790545d5ecaSDag-Erling Smørgrav int allowed = 0; 791e146993eSDag-Erling Smørgrav u_int i; 792545d5ecaSDag-Erling Smørgrav 793545d5ecaSDag-Erling Smørgrav debug3("%s", __func__); 794545d5ecaSDag-Erling Smørgrav 795545d5ecaSDag-Erling Smørgrav if (authctxt->attempt++ != 0) 796545d5ecaSDag-Erling Smørgrav fatal("%s: multiple attempts for getpwnam", __func__); 797545d5ecaSDag-Erling Smørgrav 79821e764dfSDag-Erling Smørgrav username = buffer_get_string(m, NULL); 799545d5ecaSDag-Erling Smørgrav 80021e764dfSDag-Erling Smørgrav pwent = getpwnamallow(username); 801545d5ecaSDag-Erling Smørgrav 80221e764dfSDag-Erling Smørgrav authctxt->user = xstrdup(username); 80321e764dfSDag-Erling Smørgrav setproctitle("%s [priv]", pwent ? username : "unknown"); 804e4a9863fSDag-Erling Smørgrav free(username); 805545d5ecaSDag-Erling Smørgrav 806545d5ecaSDag-Erling Smørgrav buffer_clear(m); 807545d5ecaSDag-Erling Smørgrav 808545d5ecaSDag-Erling Smørgrav if (pwent == NULL) { 809545d5ecaSDag-Erling Smørgrav buffer_put_char(m, 0); 8101ec0d754SDag-Erling Smørgrav authctxt->pw = fakepw(); 811545d5ecaSDag-Erling Smørgrav goto out; 812545d5ecaSDag-Erling Smørgrav } 813545d5ecaSDag-Erling Smørgrav 814545d5ecaSDag-Erling Smørgrav allowed = 1; 815545d5ecaSDag-Erling Smørgrav authctxt->pw = pwent; 816545d5ecaSDag-Erling Smørgrav authctxt->valid = 1; 817545d5ecaSDag-Erling Smørgrav 818545d5ecaSDag-Erling Smørgrav buffer_put_char(m, 1); 819545d5ecaSDag-Erling Smørgrav buffer_put_string(m, pwent, sizeof(struct passwd)); 820545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, pwent->pw_name); 821545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, "*"); 822e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 823545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, pwent->pw_gecos); 824e4a9863fSDag-Erling Smørgrav #endif 825e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_CLASS 826545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, pwent->pw_class); 827989dd127SDag-Erling Smørgrav #endif 828545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, pwent->pw_dir); 829545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, pwent->pw_shell); 830545d5ecaSDag-Erling Smørgrav 831545d5ecaSDag-Erling Smørgrav out: 832d4af9e69SDag-Erling Smørgrav buffer_put_string(m, &options, sizeof(options)); 833e146993eSDag-Erling Smørgrav 834e146993eSDag-Erling Smørgrav #define M_CP_STROPT(x) do { \ 835e146993eSDag-Erling Smørgrav if (options.x != NULL) \ 836e146993eSDag-Erling Smørgrav buffer_put_cstring(m, options.x); \ 837e146993eSDag-Erling Smørgrav } while (0) 838e146993eSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(x, nx) do { \ 839e146993eSDag-Erling Smørgrav for (i = 0; i < options.nx; i++) \ 840e146993eSDag-Erling Smørgrav buffer_put_cstring(m, options.x[i]); \ 841e146993eSDag-Erling Smørgrav } while (0) 842e146993eSDag-Erling Smørgrav /* See comment in servconf.h */ 843e146993eSDag-Erling Smørgrav COPY_MATCH_STRING_OPTS(); 844e146993eSDag-Erling Smørgrav #undef M_CP_STROPT 845e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT 846e146993eSDag-Erling Smørgrav 8476888a9beSDag-Erling Smørgrav /* Create valid auth method lists */ 8486888a9beSDag-Erling Smørgrav if (compat20 && auth2_setup_methods_lists(authctxt) != 0) { 8496888a9beSDag-Erling Smørgrav /* 8506888a9beSDag-Erling Smørgrav * The monitor will continue long enough to let the child 8516888a9beSDag-Erling Smørgrav * run to it's packet_disconnect(), but it must not allow any 8526888a9beSDag-Erling Smørgrav * authentication to succeed. 8536888a9beSDag-Erling Smørgrav */ 8546888a9beSDag-Erling Smørgrav debug("%s: no valid authentication method lists", __func__); 8556888a9beSDag-Erling Smørgrav } 8566888a9beSDag-Erling Smørgrav 857545d5ecaSDag-Erling Smørgrav debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); 85821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PWNAM, m); 859545d5ecaSDag-Erling Smørgrav 860545d5ecaSDag-Erling Smørgrav /* For SSHv1 allow authentication now */ 861545d5ecaSDag-Erling Smørgrav if (!compat20) 862545d5ecaSDag-Erling Smørgrav monitor_permit_authentications(1); 863545d5ecaSDag-Erling Smørgrav else { 864545d5ecaSDag-Erling Smørgrav /* Allow service/style information on the auth context */ 865545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 866545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 867545d5ecaSDag-Erling Smørgrav } 868989dd127SDag-Erling Smørgrav #ifdef USE_PAM 869cf2b5f3bSDag-Erling Smørgrav if (options.use_pam) 870989dd127SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); 871989dd127SDag-Erling Smørgrav #endif 872545d5ecaSDag-Erling Smørgrav 873545d5ecaSDag-Erling Smørgrav return (0); 874545d5ecaSDag-Erling Smørgrav } 875545d5ecaSDag-Erling Smørgrav 87621e764dfSDag-Erling Smørgrav int mm_answer_auth2_read_banner(int sock, Buffer *m) 877545d5ecaSDag-Erling Smørgrav { 878545d5ecaSDag-Erling Smørgrav char *banner; 879545d5ecaSDag-Erling Smørgrav 880545d5ecaSDag-Erling Smørgrav buffer_clear(m); 881545d5ecaSDag-Erling Smørgrav banner = auth2_read_banner(); 882545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, banner != NULL ? banner : ""); 88321e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); 884e4a9863fSDag-Erling Smørgrav free(banner); 885545d5ecaSDag-Erling Smørgrav 886545d5ecaSDag-Erling Smørgrav return (0); 887545d5ecaSDag-Erling Smørgrav } 888545d5ecaSDag-Erling Smørgrav 889545d5ecaSDag-Erling Smørgrav int 89021e764dfSDag-Erling Smørgrav mm_answer_authserv(int sock, Buffer *m) 891545d5ecaSDag-Erling Smørgrav { 892545d5ecaSDag-Erling Smørgrav monitor_permit_authentications(1); 893545d5ecaSDag-Erling Smørgrav 894545d5ecaSDag-Erling Smørgrav authctxt->service = buffer_get_string(m, NULL); 895545d5ecaSDag-Erling Smørgrav authctxt->style = buffer_get_string(m, NULL); 896545d5ecaSDag-Erling Smørgrav debug3("%s: service=%s, style=%s", 897545d5ecaSDag-Erling Smørgrav __func__, authctxt->service, authctxt->style); 898545d5ecaSDag-Erling Smørgrav 899545d5ecaSDag-Erling Smørgrav if (strlen(authctxt->style) == 0) { 900e4a9863fSDag-Erling Smørgrav free(authctxt->style); 901545d5ecaSDag-Erling Smørgrav authctxt->style = NULL; 902545d5ecaSDag-Erling Smørgrav } 903545d5ecaSDag-Erling Smørgrav 904545d5ecaSDag-Erling Smørgrav return (0); 905545d5ecaSDag-Erling Smørgrav } 906545d5ecaSDag-Erling Smørgrav 907545d5ecaSDag-Erling Smørgrav int 90821e764dfSDag-Erling Smørgrav mm_answer_authpassword(int sock, Buffer *m) 909545d5ecaSDag-Erling Smørgrav { 910545d5ecaSDag-Erling Smørgrav static int call_count; 911545d5ecaSDag-Erling Smørgrav char *passwd; 912f388f5efSDag-Erling Smørgrav int authenticated; 913f388f5efSDag-Erling Smørgrav u_int plen; 914545d5ecaSDag-Erling Smørgrav 915545d5ecaSDag-Erling Smørgrav passwd = buffer_get_string(m, &plen); 916545d5ecaSDag-Erling Smørgrav /* Only authenticate if the context is valid */ 917545d5ecaSDag-Erling Smørgrav authenticated = options.password_authentication && 918cf2b5f3bSDag-Erling Smørgrav auth_password(authctxt, passwd); 919b83788ffSDag-Erling Smørgrav explicit_bzero(passwd, strlen(passwd)); 920e4a9863fSDag-Erling Smørgrav free(passwd); 921545d5ecaSDag-Erling Smørgrav 922545d5ecaSDag-Erling Smørgrav buffer_clear(m); 923545d5ecaSDag-Erling Smørgrav buffer_put_int(m, authenticated); 924*076ad2f8SDag-Erling Smørgrav #ifdef USE_PAM 925*076ad2f8SDag-Erling Smørgrav buffer_put_int(m, sshpam_get_maxtries_reached()); 926*076ad2f8SDag-Erling Smørgrav #endif 927545d5ecaSDag-Erling Smørgrav 928545d5ecaSDag-Erling Smørgrav debug3("%s: sending result %d", __func__, authenticated); 92921e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); 930545d5ecaSDag-Erling Smørgrav 931545d5ecaSDag-Erling Smørgrav call_count++; 932545d5ecaSDag-Erling Smørgrav if (plen == 0 && call_count == 1) 933545d5ecaSDag-Erling Smørgrav auth_method = "none"; 934545d5ecaSDag-Erling Smørgrav else 935545d5ecaSDag-Erling Smørgrav auth_method = "password"; 936545d5ecaSDag-Erling Smørgrav 937545d5ecaSDag-Erling Smørgrav /* Causes monitor loop to terminate if authenticated */ 938545d5ecaSDag-Erling Smørgrav return (authenticated); 939545d5ecaSDag-Erling Smørgrav } 940545d5ecaSDag-Erling Smørgrav 941545d5ecaSDag-Erling Smørgrav #ifdef BSD_AUTH 942545d5ecaSDag-Erling Smørgrav int 94321e764dfSDag-Erling Smørgrav mm_answer_bsdauthquery(int sock, Buffer *m) 944545d5ecaSDag-Erling Smørgrav { 945545d5ecaSDag-Erling Smørgrav char *name, *infotxt; 946545d5ecaSDag-Erling Smørgrav u_int numprompts; 947545d5ecaSDag-Erling Smørgrav u_int *echo_on; 948545d5ecaSDag-Erling Smørgrav char **prompts; 949e73e9afaSDag-Erling Smørgrav u_int success; 950545d5ecaSDag-Erling Smørgrav 951e73e9afaSDag-Erling Smørgrav success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 952e73e9afaSDag-Erling Smørgrav &prompts, &echo_on) < 0 ? 0 : 1; 953545d5ecaSDag-Erling Smørgrav 954545d5ecaSDag-Erling Smørgrav buffer_clear(m); 955e73e9afaSDag-Erling Smørgrav buffer_put_int(m, success); 956e73e9afaSDag-Erling Smørgrav if (success) 957545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, prompts[0]); 958545d5ecaSDag-Erling Smørgrav 959e73e9afaSDag-Erling Smørgrav debug3("%s: sending challenge success: %u", __func__, success); 96021e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); 961545d5ecaSDag-Erling Smørgrav 962e73e9afaSDag-Erling Smørgrav if (success) { 963e4a9863fSDag-Erling Smørgrav free(name); 964e4a9863fSDag-Erling Smørgrav free(infotxt); 965e4a9863fSDag-Erling Smørgrav free(prompts); 966e4a9863fSDag-Erling Smørgrav free(echo_on); 967545d5ecaSDag-Erling Smørgrav } 968545d5ecaSDag-Erling Smørgrav 969545d5ecaSDag-Erling Smørgrav return (0); 970545d5ecaSDag-Erling Smørgrav } 971545d5ecaSDag-Erling Smørgrav 972545d5ecaSDag-Erling Smørgrav int 97321e764dfSDag-Erling Smørgrav mm_answer_bsdauthrespond(int sock, Buffer *m) 974545d5ecaSDag-Erling Smørgrav { 975545d5ecaSDag-Erling Smørgrav char *response; 976545d5ecaSDag-Erling Smørgrav int authok; 977545d5ecaSDag-Erling Smørgrav 978acc1a9efSDag-Erling Smørgrav if (authctxt->as == NULL) 979545d5ecaSDag-Erling Smørgrav fatal("%s: no bsd auth session", __func__); 980545d5ecaSDag-Erling Smørgrav 981545d5ecaSDag-Erling Smørgrav response = buffer_get_string(m, NULL); 982545d5ecaSDag-Erling Smørgrav authok = options.challenge_response_authentication && 983545d5ecaSDag-Erling Smørgrav auth_userresponse(authctxt->as, response, 0); 984545d5ecaSDag-Erling Smørgrav authctxt->as = NULL; 985545d5ecaSDag-Erling Smørgrav debug3("%s: <%s> = <%d>", __func__, response, authok); 986e4a9863fSDag-Erling Smørgrav free(response); 987545d5ecaSDag-Erling Smørgrav 988545d5ecaSDag-Erling Smørgrav buffer_clear(m); 989545d5ecaSDag-Erling Smørgrav buffer_put_int(m, authok); 990545d5ecaSDag-Erling Smørgrav 991545d5ecaSDag-Erling Smørgrav debug3("%s: sending authenticated: %d", __func__, authok); 99221e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); 993545d5ecaSDag-Erling Smørgrav 994e4a9863fSDag-Erling Smørgrav if (compat20) { 995e4a9863fSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 996e4a9863fSDag-Erling Smørgrav auth_submethod = "bsdauth"; 997e4a9863fSDag-Erling Smørgrav } else 998545d5ecaSDag-Erling Smørgrav auth_method = "bsdauth"; 999545d5ecaSDag-Erling Smørgrav 1000545d5ecaSDag-Erling Smørgrav return (authok != 0); 1001545d5ecaSDag-Erling Smørgrav } 1002545d5ecaSDag-Erling Smørgrav #endif 1003545d5ecaSDag-Erling Smørgrav 1004545d5ecaSDag-Erling Smørgrav #ifdef SKEY 1005545d5ecaSDag-Erling Smørgrav int 100621e764dfSDag-Erling Smørgrav mm_answer_skeyquery(int sock, Buffer *m) 1007545d5ecaSDag-Erling Smørgrav { 1008989dd127SDag-Erling Smørgrav struct skey skey; 1009545d5ecaSDag-Erling Smørgrav char challenge[1024]; 1010e73e9afaSDag-Erling Smørgrav u_int success; 1011545d5ecaSDag-Erling Smørgrav 10125962c0e9SDag-Erling Smørgrav success = _compat_skeychallenge(&skey, authctxt->user, challenge, 10135962c0e9SDag-Erling Smørgrav sizeof(challenge)) < 0 ? 0 : 1; 1014545d5ecaSDag-Erling Smørgrav 1015545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1016e73e9afaSDag-Erling Smørgrav buffer_put_int(m, success); 1017e73e9afaSDag-Erling Smørgrav if (success) 1018545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, challenge); 1019545d5ecaSDag-Erling Smørgrav 1020e73e9afaSDag-Erling Smørgrav debug3("%s: sending challenge success: %u", __func__, success); 102121e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m); 1022545d5ecaSDag-Erling Smørgrav 1023545d5ecaSDag-Erling Smørgrav return (0); 1024545d5ecaSDag-Erling Smørgrav } 1025545d5ecaSDag-Erling Smørgrav 1026545d5ecaSDag-Erling Smørgrav int 102721e764dfSDag-Erling Smørgrav mm_answer_skeyrespond(int sock, Buffer *m) 1028545d5ecaSDag-Erling Smørgrav { 1029545d5ecaSDag-Erling Smørgrav char *response; 1030545d5ecaSDag-Erling Smørgrav int authok; 1031545d5ecaSDag-Erling Smørgrav 1032545d5ecaSDag-Erling Smørgrav response = buffer_get_string(m, NULL); 1033545d5ecaSDag-Erling Smørgrav 1034545d5ecaSDag-Erling Smørgrav authok = (options.challenge_response_authentication && 1035545d5ecaSDag-Erling Smørgrav authctxt->valid && 1036989dd127SDag-Erling Smørgrav skey_haskey(authctxt->pw->pw_name) == 0 && 1037989dd127SDag-Erling Smørgrav skey_passcheck(authctxt->pw->pw_name, response) != -1); 1038545d5ecaSDag-Erling Smørgrav 1039e4a9863fSDag-Erling Smørgrav free(response); 1040545d5ecaSDag-Erling Smørgrav 1041545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1042545d5ecaSDag-Erling Smørgrav buffer_put_int(m, authok); 1043545d5ecaSDag-Erling Smørgrav 1044545d5ecaSDag-Erling Smørgrav debug3("%s: sending authenticated: %d", __func__, authok); 104521e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); 1046545d5ecaSDag-Erling Smørgrav 1047acc1a9efSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 1048acc1a9efSDag-Erling Smørgrav auth_submethod = "skey"; 1049545d5ecaSDag-Erling Smørgrav 1050545d5ecaSDag-Erling Smørgrav return (authok != 0); 1051545d5ecaSDag-Erling Smørgrav } 1052545d5ecaSDag-Erling Smørgrav #endif 1053545d5ecaSDag-Erling Smørgrav 1054989dd127SDag-Erling Smørgrav #ifdef USE_PAM 1055989dd127SDag-Erling Smørgrav int 105621e764dfSDag-Erling Smørgrav mm_answer_pam_start(int sock, Buffer *m) 1057989dd127SDag-Erling Smørgrav { 1058cf2b5f3bSDag-Erling Smørgrav if (!options.use_pam) 1059cf2b5f3bSDag-Erling Smørgrav fatal("UsePAM not set, but ended up in %s anyway", __func__); 1060cf2b5f3bSDag-Erling Smørgrav 10615962c0e9SDag-Erling Smørgrav start_pam(authctxt); 1062989dd127SDag-Erling Smørgrav 1063cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); 1064cf2b5f3bSDag-Erling Smørgrav 1065989dd127SDag-Erling Smørgrav return (0); 1066989dd127SDag-Erling Smørgrav } 1067382d19eeSDag-Erling Smørgrav 1068cf2b5f3bSDag-Erling Smørgrav int 106921e764dfSDag-Erling Smørgrav mm_answer_pam_account(int sock, Buffer *m) 1070cf2b5f3bSDag-Erling Smørgrav { 1071cf2b5f3bSDag-Erling Smørgrav u_int ret; 1072cf2b5f3bSDag-Erling Smørgrav 1073cf2b5f3bSDag-Erling Smørgrav if (!options.use_pam) 1074cf2b5f3bSDag-Erling Smørgrav fatal("UsePAM not set, but ended up in %s anyway", __func__); 1075cf2b5f3bSDag-Erling Smørgrav 1076cf2b5f3bSDag-Erling Smørgrav ret = do_pam_account(); 1077cf2b5f3bSDag-Erling Smørgrav 1078cf2b5f3bSDag-Erling Smørgrav buffer_put_int(m, ret); 1079b74df5b2SDag-Erling Smørgrav buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 1080cf2b5f3bSDag-Erling Smørgrav 108121e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); 1082cf2b5f3bSDag-Erling Smørgrav 1083cf2b5f3bSDag-Erling Smørgrav return (ret); 1084cf2b5f3bSDag-Erling Smørgrav } 1085cf2b5f3bSDag-Erling Smørgrav 1086cf2b5f3bSDag-Erling Smørgrav static void *sshpam_ctxt, *sshpam_authok; 1087cf2b5f3bSDag-Erling Smørgrav extern KbdintDevice sshpam_device; 1088382d19eeSDag-Erling Smørgrav 1089382d19eeSDag-Erling Smørgrav int 109021e764dfSDag-Erling Smørgrav mm_answer_pam_init_ctx(int sock, Buffer *m) 1091382d19eeSDag-Erling Smørgrav { 1092382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1093cf2b5f3bSDag-Erling Smørgrav sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); 1094cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1095382d19eeSDag-Erling Smørgrav buffer_clear(m); 1096cf2b5f3bSDag-Erling Smørgrav if (sshpam_ctxt != NULL) { 1097382d19eeSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 1098382d19eeSDag-Erling Smørgrav buffer_put_int(m, 1); 1099382d19eeSDag-Erling Smørgrav } else { 1100382d19eeSDag-Erling Smørgrav buffer_put_int(m, 0); 1101382d19eeSDag-Erling Smørgrav } 110221e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); 1103382d19eeSDag-Erling Smørgrav return (0); 1104382d19eeSDag-Erling Smørgrav } 1105382d19eeSDag-Erling Smørgrav 1106382d19eeSDag-Erling Smørgrav int 110721e764dfSDag-Erling Smørgrav mm_answer_pam_query(int sock, Buffer *m) 1108382d19eeSDag-Erling Smørgrav { 1109e2f6069cSDag-Erling Smørgrav char *name = NULL, *info = NULL, **prompts = NULL; 1110e2f6069cSDag-Erling Smørgrav u_int i, num = 0, *echo_on = 0; 1111d4ecd108SDag-Erling Smørgrav int ret; 1112382d19eeSDag-Erling Smørgrav 1113382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1114cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1115cf2b5f3bSDag-Erling Smørgrav ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on); 111607fd326cSDag-Erling Smørgrav if (ret == 0 && num == 0) 1117cf2b5f3bSDag-Erling Smørgrav sshpam_authok = sshpam_ctxt; 1118382d19eeSDag-Erling Smørgrav if (num > 1 || name == NULL || info == NULL) 1119382d19eeSDag-Erling Smørgrav ret = -1; 1120645ca8e8SDag-Erling Smørgrav buffer_clear(m); 1121382d19eeSDag-Erling Smørgrav buffer_put_int(m, ret); 1122382d19eeSDag-Erling Smørgrav buffer_put_cstring(m, name); 1123e4a9863fSDag-Erling Smørgrav free(name); 1124382d19eeSDag-Erling Smørgrav buffer_put_cstring(m, info); 1125e4a9863fSDag-Erling Smørgrav free(info); 1126*076ad2f8SDag-Erling Smørgrav buffer_put_int(m, sshpam_get_maxtries_reached()); 1127382d19eeSDag-Erling Smørgrav buffer_put_int(m, num); 1128382d19eeSDag-Erling Smørgrav for (i = 0; i < num; ++i) { 1129382d19eeSDag-Erling Smørgrav buffer_put_cstring(m, prompts[i]); 1130e4a9863fSDag-Erling Smørgrav free(prompts[i]); 1131382d19eeSDag-Erling Smørgrav buffer_put_int(m, echo_on[i]); 1132382d19eeSDag-Erling Smørgrav } 1133e4a9863fSDag-Erling Smørgrav free(prompts); 1134e4a9863fSDag-Erling Smørgrav free(echo_on); 11356888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 11366888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 113721e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); 1138382d19eeSDag-Erling Smørgrav return (0); 1139382d19eeSDag-Erling Smørgrav } 1140382d19eeSDag-Erling Smørgrav 1141382d19eeSDag-Erling Smørgrav int 114221e764dfSDag-Erling Smørgrav mm_answer_pam_respond(int sock, Buffer *m) 1143382d19eeSDag-Erling Smørgrav { 1144382d19eeSDag-Erling Smørgrav char **resp; 1145d4ecd108SDag-Erling Smørgrav u_int i, num; 1146d4ecd108SDag-Erling Smørgrav int ret; 1147382d19eeSDag-Erling Smørgrav 1148382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1149cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1150382d19eeSDag-Erling Smørgrav num = buffer_get_int(m); 1151382d19eeSDag-Erling Smørgrav if (num > 0) { 1152333ee039SDag-Erling Smørgrav resp = xcalloc(num, sizeof(char *)); 1153382d19eeSDag-Erling Smørgrav for (i = 0; i < num; ++i) 1154382d19eeSDag-Erling Smørgrav resp[i] = buffer_get_string(m, NULL); 1155cf2b5f3bSDag-Erling Smørgrav ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); 1156382d19eeSDag-Erling Smørgrav for (i = 0; i < num; ++i) 1157e4a9863fSDag-Erling Smørgrav free(resp[i]); 1158e4a9863fSDag-Erling Smørgrav free(resp); 1159382d19eeSDag-Erling Smørgrav } else { 1160cf2b5f3bSDag-Erling Smørgrav ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); 1161382d19eeSDag-Erling Smørgrav } 1162382d19eeSDag-Erling Smørgrav buffer_clear(m); 1163382d19eeSDag-Erling Smørgrav buffer_put_int(m, ret); 116421e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); 11656888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 11666888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 1167382d19eeSDag-Erling Smørgrav if (ret == 0) 1168cf2b5f3bSDag-Erling Smørgrav sshpam_authok = sshpam_ctxt; 1169669e440eSDag-Erling Smørgrav return (0); 1170382d19eeSDag-Erling Smørgrav } 1171382d19eeSDag-Erling Smørgrav 1172382d19eeSDag-Erling Smørgrav int 117321e764dfSDag-Erling Smørgrav mm_answer_pam_free_ctx(int sock, Buffer *m) 1174382d19eeSDag-Erling Smørgrav { 11751e415e29SXin LI int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; 1176382d19eeSDag-Erling Smørgrav 1177382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1178cf2b5f3bSDag-Erling Smørgrav (sshpam_device.free_ctx)(sshpam_ctxt); 11791e415e29SXin LI sshpam_ctxt = sshpam_authok = NULL; 1180382d19eeSDag-Erling Smørgrav buffer_clear(m); 118121e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); 11826888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 11836888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 11841e415e29SXin LI return r; 1185382d19eeSDag-Erling Smørgrav } 1186989dd127SDag-Erling Smørgrav #endif 1187989dd127SDag-Erling Smørgrav 1188545d5ecaSDag-Erling Smørgrav int 118921e764dfSDag-Erling Smørgrav mm_answer_keyallowed(int sock, Buffer *m) 1190545d5ecaSDag-Erling Smørgrav { 1191545d5ecaSDag-Erling Smørgrav Key *key; 1192f388f5efSDag-Erling Smørgrav char *cuser, *chost; 1193f388f5efSDag-Erling Smørgrav u_char *blob; 1194557f75e5SDag-Erling Smørgrav u_int bloblen, pubkey_auth_attempt; 1195545d5ecaSDag-Erling Smørgrav enum mm_keytype type = 0; 1196545d5ecaSDag-Erling Smørgrav int allowed = 0; 1197545d5ecaSDag-Erling Smørgrav 1198545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1199545d5ecaSDag-Erling Smørgrav 1200545d5ecaSDag-Erling Smørgrav type = buffer_get_int(m); 1201545d5ecaSDag-Erling Smørgrav cuser = buffer_get_string(m, NULL); 1202545d5ecaSDag-Erling Smørgrav chost = buffer_get_string(m, NULL); 1203545d5ecaSDag-Erling Smørgrav blob = buffer_get_string(m, &bloblen); 1204557f75e5SDag-Erling Smørgrav pubkey_auth_attempt = buffer_get_int(m); 1205545d5ecaSDag-Erling Smørgrav 1206545d5ecaSDag-Erling Smørgrav key = key_from_blob(blob, bloblen); 1207545d5ecaSDag-Erling Smørgrav 1208545d5ecaSDag-Erling Smørgrav if ((compat20 && type == MM_RSAHOSTKEY) || 1209545d5ecaSDag-Erling Smørgrav (!compat20 && type != MM_RSAHOSTKEY)) 1210545d5ecaSDag-Erling Smørgrav fatal("%s: key type and protocol mismatch", __func__); 1211545d5ecaSDag-Erling Smørgrav 1212545d5ecaSDag-Erling Smørgrav debug3("%s: key_from_blob: %p", __func__, key); 1213545d5ecaSDag-Erling Smørgrav 12141ec0d754SDag-Erling Smørgrav if (key != NULL && authctxt->valid) { 1215bc5531deSDag-Erling Smørgrav /* These should not make it past the privsep child */ 1216bc5531deSDag-Erling Smørgrav if (key_type_plain(key->type) == KEY_RSA && 1217bc5531deSDag-Erling Smørgrav (datafellows & SSH_BUG_RSASIGMD5) != 0) 1218bc5531deSDag-Erling Smørgrav fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); 1219bc5531deSDag-Erling Smørgrav 1220545d5ecaSDag-Erling Smørgrav switch (type) { 1221545d5ecaSDag-Erling Smørgrav case MM_USERKEY: 1222545d5ecaSDag-Erling Smørgrav allowed = options.pubkey_authentication && 1223bc5531deSDag-Erling Smørgrav !auth2_userkey_already_used(authctxt, key) && 1224bc5531deSDag-Erling Smørgrav match_pattern_list(sshkey_ssh_name(key), 1225557f75e5SDag-Erling Smørgrav options.pubkey_key_types, 0) == 1 && 1226557f75e5SDag-Erling Smørgrav user_key_allowed(authctxt->pw, key, 1227557f75e5SDag-Erling Smørgrav pubkey_auth_attempt); 1228e4a9863fSDag-Erling Smørgrav pubkey_auth_info(authctxt, key, NULL); 1229333ee039SDag-Erling Smørgrav auth_method = "publickey"; 1230557f75e5SDag-Erling Smørgrav if (options.pubkey_authentication && 1231557f75e5SDag-Erling Smørgrav (!pubkey_auth_attempt || allowed != 1)) 1232d4af9e69SDag-Erling Smørgrav auth_clear_options(); 1233545d5ecaSDag-Erling Smørgrav break; 1234545d5ecaSDag-Erling Smørgrav case MM_HOSTKEY: 1235545d5ecaSDag-Erling Smørgrav allowed = options.hostbased_authentication && 1236bc5531deSDag-Erling Smørgrav match_pattern_list(sshkey_ssh_name(key), 1237557f75e5SDag-Erling Smørgrav options.hostbased_key_types, 0) == 1 && 1238545d5ecaSDag-Erling Smørgrav hostbased_key_allowed(authctxt->pw, 1239545d5ecaSDag-Erling Smørgrav cuser, chost, key); 1240e4a9863fSDag-Erling Smørgrav pubkey_auth_info(authctxt, key, 1241e4a9863fSDag-Erling Smørgrav "client user \"%.100s\", client host \"%.100s\"", 1242e4a9863fSDag-Erling Smørgrav cuser, chost); 1243333ee039SDag-Erling Smørgrav auth_method = "hostbased"; 1244545d5ecaSDag-Erling Smørgrav break; 1245a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_SSH1 1246545d5ecaSDag-Erling Smørgrav case MM_RSAHOSTKEY: 1247545d5ecaSDag-Erling Smørgrav key->type = KEY_RSA1; /* XXX */ 1248545d5ecaSDag-Erling Smørgrav allowed = options.rhosts_rsa_authentication && 1249545d5ecaSDag-Erling Smørgrav auth_rhosts_rsa_key_allowed(authctxt->pw, 1250545d5ecaSDag-Erling Smørgrav cuser, chost, key); 1251d4af9e69SDag-Erling Smørgrav if (options.rhosts_rsa_authentication && allowed != 1) 1252d4af9e69SDag-Erling Smørgrav auth_clear_options(); 1253333ee039SDag-Erling Smørgrav auth_method = "rsa"; 1254545d5ecaSDag-Erling Smørgrav break; 1255a0ee8cc6SDag-Erling Smørgrav #endif 1256545d5ecaSDag-Erling Smørgrav default: 1257545d5ecaSDag-Erling Smørgrav fatal("%s: unknown key type %d", __func__, type); 1258545d5ecaSDag-Erling Smørgrav break; 1259545d5ecaSDag-Erling Smørgrav } 1260545d5ecaSDag-Erling Smørgrav } 1261*076ad2f8SDag-Erling Smørgrav 1262*076ad2f8SDag-Erling Smørgrav debug3("%s: key %p is %s", 1263*076ad2f8SDag-Erling Smørgrav __func__, key, allowed ? "allowed" : "not allowed"); 1264*076ad2f8SDag-Erling Smørgrav 1265e73e9afaSDag-Erling Smørgrav if (key != NULL) 1266e73e9afaSDag-Erling Smørgrav key_free(key); 1267545d5ecaSDag-Erling Smørgrav 1268545d5ecaSDag-Erling Smørgrav /* clear temporarily storage (used by verify) */ 1269545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1270545d5ecaSDag-Erling Smørgrav 1271545d5ecaSDag-Erling Smørgrav if (allowed) { 1272545d5ecaSDag-Erling Smørgrav /* Save temporarily for comparison in verify */ 1273545d5ecaSDag-Erling Smørgrav key_blob = blob; 1274545d5ecaSDag-Erling Smørgrav key_bloblen = bloblen; 1275545d5ecaSDag-Erling Smørgrav key_blobtype = type; 1276545d5ecaSDag-Erling Smørgrav hostbased_cuser = cuser; 1277545d5ecaSDag-Erling Smørgrav hostbased_chost = chost; 1278333ee039SDag-Erling Smørgrav } else { 1279333ee039SDag-Erling Smørgrav /* Log failed attempt */ 1280e4a9863fSDag-Erling Smørgrav auth_log(authctxt, 0, 0, auth_method, NULL); 1281e4a9863fSDag-Erling Smørgrav free(blob); 1282e4a9863fSDag-Erling Smørgrav free(cuser); 1283e4a9863fSDag-Erling Smørgrav free(chost); 1284545d5ecaSDag-Erling Smørgrav } 1285545d5ecaSDag-Erling Smørgrav 1286545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1287545d5ecaSDag-Erling Smørgrav buffer_put_int(m, allowed); 1288e73e9afaSDag-Erling Smørgrav buffer_put_int(m, forced_command != NULL); 1289545d5ecaSDag-Erling Smørgrav 129021e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); 1291545d5ecaSDag-Erling Smørgrav 1292545d5ecaSDag-Erling Smørgrav if (type == MM_RSAHOSTKEY) 1293545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 1294545d5ecaSDag-Erling Smørgrav 1295545d5ecaSDag-Erling Smørgrav return (0); 1296545d5ecaSDag-Erling Smørgrav } 1297545d5ecaSDag-Erling Smørgrav 1298545d5ecaSDag-Erling Smørgrav static int 1299545d5ecaSDag-Erling Smørgrav monitor_valid_userblob(u_char *data, u_int datalen) 1300545d5ecaSDag-Erling Smørgrav { 1301545d5ecaSDag-Erling Smørgrav Buffer b; 1302*076ad2f8SDag-Erling Smørgrav u_char *p; 1303*076ad2f8SDag-Erling Smørgrav char *userstyle, *cp; 1304545d5ecaSDag-Erling Smørgrav u_int len; 1305545d5ecaSDag-Erling Smørgrav int fail = 0; 1306545d5ecaSDag-Erling Smørgrav 1307545d5ecaSDag-Erling Smørgrav buffer_init(&b); 1308545d5ecaSDag-Erling Smørgrav buffer_append(&b, data, datalen); 1309545d5ecaSDag-Erling Smørgrav 1310545d5ecaSDag-Erling Smørgrav if (datafellows & SSH_OLD_SESSIONID) { 1311545d5ecaSDag-Erling Smørgrav p = buffer_ptr(&b); 1312545d5ecaSDag-Erling Smørgrav len = buffer_len(&b); 1313545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1314545d5ecaSDag-Erling Smørgrav (len < session_id2_len) || 1315e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1316545d5ecaSDag-Erling Smørgrav fail++; 1317545d5ecaSDag-Erling Smørgrav buffer_consume(&b, session_id2_len); 1318545d5ecaSDag-Erling Smørgrav } else { 1319545d5ecaSDag-Erling Smørgrav p = buffer_get_string(&b, &len); 1320545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1321545d5ecaSDag-Erling Smørgrav (len != session_id2_len) || 1322e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1323545d5ecaSDag-Erling Smørgrav fail++; 1324e4a9863fSDag-Erling Smørgrav free(p); 1325545d5ecaSDag-Erling Smørgrav } 1326545d5ecaSDag-Erling Smørgrav if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 1327545d5ecaSDag-Erling Smørgrav fail++; 1328*076ad2f8SDag-Erling Smørgrav cp = buffer_get_cstring(&b, NULL); 1329e4a9863fSDag-Erling Smørgrav xasprintf(&userstyle, "%s%s%s", authctxt->user, 1330e4a9863fSDag-Erling Smørgrav authctxt->style ? ":" : "", 1331e4a9863fSDag-Erling Smørgrav authctxt->style ? authctxt->style : ""); 1332*076ad2f8SDag-Erling Smørgrav if (strcmp(userstyle, cp) != 0) { 1333*076ad2f8SDag-Erling Smørgrav logit("wrong user name passed to monitor: " 1334*076ad2f8SDag-Erling Smørgrav "expected %s != %.100s", userstyle, cp); 1335545d5ecaSDag-Erling Smørgrav fail++; 1336545d5ecaSDag-Erling Smørgrav } 1337e4a9863fSDag-Erling Smørgrav free(userstyle); 1338*076ad2f8SDag-Erling Smørgrav free(cp); 1339545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); 1340545d5ecaSDag-Erling Smørgrav if (datafellows & SSH_BUG_PKAUTH) { 1341545d5ecaSDag-Erling Smørgrav if (!buffer_get_char(&b)) 1342545d5ecaSDag-Erling Smørgrav fail++; 1343545d5ecaSDag-Erling Smørgrav } else { 1344*076ad2f8SDag-Erling Smørgrav cp = buffer_get_cstring(&b, NULL); 1345*076ad2f8SDag-Erling Smørgrav if (strcmp("publickey", cp) != 0) 1346545d5ecaSDag-Erling Smørgrav fail++; 1347*076ad2f8SDag-Erling Smørgrav free(cp); 1348545d5ecaSDag-Erling Smørgrav if (!buffer_get_char(&b)) 1349545d5ecaSDag-Erling Smørgrav fail++; 1350545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); 1351545d5ecaSDag-Erling Smørgrav } 1352545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); 1353545d5ecaSDag-Erling Smørgrav if (buffer_len(&b) != 0) 1354545d5ecaSDag-Erling Smørgrav fail++; 1355545d5ecaSDag-Erling Smørgrav buffer_free(&b); 1356545d5ecaSDag-Erling Smørgrav return (fail == 0); 1357545d5ecaSDag-Erling Smørgrav } 1358545d5ecaSDag-Erling Smørgrav 1359545d5ecaSDag-Erling Smørgrav static int 1360f388f5efSDag-Erling Smørgrav monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 1361f388f5efSDag-Erling Smørgrav char *chost) 1362545d5ecaSDag-Erling Smørgrav { 1363545d5ecaSDag-Erling Smørgrav Buffer b; 1364e4a9863fSDag-Erling Smørgrav char *p, *userstyle; 1365545d5ecaSDag-Erling Smørgrav u_int len; 1366545d5ecaSDag-Erling Smørgrav int fail = 0; 1367545d5ecaSDag-Erling Smørgrav 1368545d5ecaSDag-Erling Smørgrav buffer_init(&b); 1369545d5ecaSDag-Erling Smørgrav buffer_append(&b, data, datalen); 1370545d5ecaSDag-Erling Smørgrav 1371545d5ecaSDag-Erling Smørgrav p = buffer_get_string(&b, &len); 1372545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1373545d5ecaSDag-Erling Smørgrav (len != session_id2_len) || 1374e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1375545d5ecaSDag-Erling Smørgrav fail++; 1376e4a9863fSDag-Erling Smørgrav free(p); 1377545d5ecaSDag-Erling Smørgrav 1378545d5ecaSDag-Erling Smørgrav if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 1379545d5ecaSDag-Erling Smørgrav fail++; 1380e4a9863fSDag-Erling Smørgrav p = buffer_get_cstring(&b, NULL); 1381e4a9863fSDag-Erling Smørgrav xasprintf(&userstyle, "%s%s%s", authctxt->user, 1382e4a9863fSDag-Erling Smørgrav authctxt->style ? ":" : "", 1383e4a9863fSDag-Erling Smørgrav authctxt->style ? authctxt->style : ""); 1384e4a9863fSDag-Erling Smørgrav if (strcmp(userstyle, p) != 0) { 1385cf2b5f3bSDag-Erling Smørgrav logit("wrong user name passed to monitor: expected %s != %.100s", 1386e4a9863fSDag-Erling Smørgrav userstyle, p); 1387545d5ecaSDag-Erling Smørgrav fail++; 1388545d5ecaSDag-Erling Smørgrav } 1389e4a9863fSDag-Erling Smørgrav free(userstyle); 1390e4a9863fSDag-Erling Smørgrav free(p); 1391545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); /* service */ 1392e4a9863fSDag-Erling Smørgrav p = buffer_get_cstring(&b, NULL); 1393545d5ecaSDag-Erling Smørgrav if (strcmp(p, "hostbased") != 0) 1394545d5ecaSDag-Erling Smørgrav fail++; 1395e4a9863fSDag-Erling Smørgrav free(p); 1396545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); /* pkalg */ 1397545d5ecaSDag-Erling Smørgrav buffer_skip_string(&b); /* pkblob */ 1398545d5ecaSDag-Erling Smørgrav 1399545d5ecaSDag-Erling Smørgrav /* verify client host, strip trailing dot if necessary */ 1400545d5ecaSDag-Erling Smørgrav p = buffer_get_string(&b, NULL); 1401545d5ecaSDag-Erling Smørgrav if (((len = strlen(p)) > 0) && p[len - 1] == '.') 1402545d5ecaSDag-Erling Smørgrav p[len - 1] = '\0'; 1403545d5ecaSDag-Erling Smørgrav if (strcmp(p, chost) != 0) 1404545d5ecaSDag-Erling Smørgrav fail++; 1405e4a9863fSDag-Erling Smørgrav free(p); 1406545d5ecaSDag-Erling Smørgrav 1407545d5ecaSDag-Erling Smørgrav /* verify client user */ 1408545d5ecaSDag-Erling Smørgrav p = buffer_get_string(&b, NULL); 1409545d5ecaSDag-Erling Smørgrav if (strcmp(p, cuser) != 0) 1410545d5ecaSDag-Erling Smørgrav fail++; 1411e4a9863fSDag-Erling Smørgrav free(p); 1412545d5ecaSDag-Erling Smørgrav 1413545d5ecaSDag-Erling Smørgrav if (buffer_len(&b) != 0) 1414545d5ecaSDag-Erling Smørgrav fail++; 1415545d5ecaSDag-Erling Smørgrav buffer_free(&b); 1416545d5ecaSDag-Erling Smørgrav return (fail == 0); 1417545d5ecaSDag-Erling Smørgrav } 1418545d5ecaSDag-Erling Smørgrav 1419545d5ecaSDag-Erling Smørgrav int 142021e764dfSDag-Erling Smørgrav mm_answer_keyverify(int sock, Buffer *m) 1421545d5ecaSDag-Erling Smørgrav { 1422545d5ecaSDag-Erling Smørgrav Key *key; 1423545d5ecaSDag-Erling Smørgrav u_char *signature, *data, *blob; 1424545d5ecaSDag-Erling Smørgrav u_int signaturelen, datalen, bloblen; 1425545d5ecaSDag-Erling Smørgrav int verified = 0; 1426545d5ecaSDag-Erling Smørgrav int valid_data = 0; 1427545d5ecaSDag-Erling Smørgrav 1428545d5ecaSDag-Erling Smørgrav blob = buffer_get_string(m, &bloblen); 1429545d5ecaSDag-Erling Smørgrav signature = buffer_get_string(m, &signaturelen); 1430545d5ecaSDag-Erling Smørgrav data = buffer_get_string(m, &datalen); 1431545d5ecaSDag-Erling Smørgrav 1432545d5ecaSDag-Erling Smørgrav if (hostbased_cuser == NULL || hostbased_chost == NULL || 1433545d5ecaSDag-Erling Smørgrav !monitor_allowed_key(blob, bloblen)) 1434545d5ecaSDag-Erling Smørgrav fatal("%s: bad key, not previously allowed", __func__); 1435545d5ecaSDag-Erling Smørgrav 1436545d5ecaSDag-Erling Smørgrav key = key_from_blob(blob, bloblen); 1437545d5ecaSDag-Erling Smørgrav if (key == NULL) 1438545d5ecaSDag-Erling Smørgrav fatal("%s: bad public key blob", __func__); 1439545d5ecaSDag-Erling Smørgrav 1440545d5ecaSDag-Erling Smørgrav switch (key_blobtype) { 1441545d5ecaSDag-Erling Smørgrav case MM_USERKEY: 1442545d5ecaSDag-Erling Smørgrav valid_data = monitor_valid_userblob(data, datalen); 1443545d5ecaSDag-Erling Smørgrav break; 1444545d5ecaSDag-Erling Smørgrav case MM_HOSTKEY: 1445545d5ecaSDag-Erling Smørgrav valid_data = monitor_valid_hostbasedblob(data, datalen, 1446545d5ecaSDag-Erling Smørgrav hostbased_cuser, hostbased_chost); 1447545d5ecaSDag-Erling Smørgrav break; 1448545d5ecaSDag-Erling Smørgrav default: 1449545d5ecaSDag-Erling Smørgrav valid_data = 0; 1450545d5ecaSDag-Erling Smørgrav break; 1451545d5ecaSDag-Erling Smørgrav } 1452545d5ecaSDag-Erling Smørgrav if (!valid_data) 1453545d5ecaSDag-Erling Smørgrav fatal("%s: bad signature data blob", __func__); 1454545d5ecaSDag-Erling Smørgrav 1455545d5ecaSDag-Erling Smørgrav verified = key_verify(key, signature, signaturelen, data, datalen); 1456545d5ecaSDag-Erling Smørgrav debug3("%s: key %p signature %s", 145762efe23aSDag-Erling Smørgrav __func__, key, (verified == 1) ? "verified" : "unverified"); 1458545d5ecaSDag-Erling Smørgrav 1459bc5531deSDag-Erling Smørgrav /* If auth was successful then record key to ensure it isn't reused */ 1460acc1a9efSDag-Erling Smørgrav if (verified == 1 && key_blobtype == MM_USERKEY) 1461bc5531deSDag-Erling Smørgrav auth2_record_userkey(authctxt, key); 1462bc5531deSDag-Erling Smørgrav else 1463545d5ecaSDag-Erling Smørgrav key_free(key); 1464bc5531deSDag-Erling Smørgrav 1465e4a9863fSDag-Erling Smørgrav free(blob); 1466e4a9863fSDag-Erling Smørgrav free(signature); 1467e4a9863fSDag-Erling Smørgrav free(data); 1468545d5ecaSDag-Erling Smørgrav 1469a82e551fSDag-Erling Smørgrav auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; 1470a82e551fSDag-Erling Smørgrav 1471545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1472545d5ecaSDag-Erling Smørgrav 1473545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1474545d5ecaSDag-Erling Smørgrav buffer_put_int(m, verified); 147521e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 1476545d5ecaSDag-Erling Smørgrav 147762efe23aSDag-Erling Smørgrav return (verified == 1); 1478545d5ecaSDag-Erling Smørgrav } 1479545d5ecaSDag-Erling Smørgrav 1480545d5ecaSDag-Erling Smørgrav static void 1481545d5ecaSDag-Erling Smørgrav mm_record_login(Session *s, struct passwd *pw) 1482545d5ecaSDag-Erling Smørgrav { 1483*076ad2f8SDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1484545d5ecaSDag-Erling Smørgrav socklen_t fromlen; 1485545d5ecaSDag-Erling Smørgrav struct sockaddr_storage from; 1486545d5ecaSDag-Erling Smørgrav 1487557f75e5SDag-Erling Smørgrav if (options.use_login) 1488557f75e5SDag-Erling Smørgrav return; 1489557f75e5SDag-Erling Smørgrav 1490545d5ecaSDag-Erling Smørgrav /* 1491545d5ecaSDag-Erling Smørgrav * Get IP address of client. If the connection is not a socket, let 1492545d5ecaSDag-Erling Smørgrav * the address be 0.0.0.0. 1493545d5ecaSDag-Erling Smørgrav */ 1494545d5ecaSDag-Erling Smørgrav memset(&from, 0, sizeof(from)); 1495545d5ecaSDag-Erling Smørgrav fromlen = sizeof(from); 14967ac32603SHajimu UMEMOTO if (packet_connection_is_on_socket()) { 1497545d5ecaSDag-Erling Smørgrav if (getpeername(packet_get_connection_in(), 1498545d5ecaSDag-Erling Smørgrav (struct sockaddr *)&from, &fromlen) < 0) { 1499545d5ecaSDag-Erling Smørgrav debug("getpeername: %.100s", strerror(errno)); 15001ec0d754SDag-Erling Smørgrav cleanup_exit(255); 1501545d5ecaSDag-Erling Smørgrav } 1502545d5ecaSDag-Erling Smørgrav } 1503545d5ecaSDag-Erling Smørgrav /* Record that there was a login on that tty from the remote host. */ 1504545d5ecaSDag-Erling Smørgrav record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 1505*076ad2f8SDag-Erling Smørgrav session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), 15067ac32603SHajimu UMEMOTO (struct sockaddr *)&from, fromlen); 1507545d5ecaSDag-Erling Smørgrav } 1508545d5ecaSDag-Erling Smørgrav 1509545d5ecaSDag-Erling Smørgrav static void 1510545d5ecaSDag-Erling Smørgrav mm_session_close(Session *s) 1511545d5ecaSDag-Erling Smørgrav { 1512cf2b5f3bSDag-Erling Smørgrav debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); 1513545d5ecaSDag-Erling Smørgrav if (s->ttyfd != -1) { 1514545d5ecaSDag-Erling Smørgrav debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); 1515545d5ecaSDag-Erling Smørgrav session_pty_cleanup2(s); 1516545d5ecaSDag-Erling Smørgrav } 1517d4af9e69SDag-Erling Smørgrav session_unused(s->self); 1518545d5ecaSDag-Erling Smørgrav } 1519545d5ecaSDag-Erling Smørgrav 1520545d5ecaSDag-Erling Smørgrav int 152121e764dfSDag-Erling Smørgrav mm_answer_pty(int sock, Buffer *m) 1522545d5ecaSDag-Erling Smørgrav { 1523545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor; 1524545d5ecaSDag-Erling Smørgrav Session *s; 1525545d5ecaSDag-Erling Smørgrav int res, fd0; 1526545d5ecaSDag-Erling Smørgrav 1527545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1528545d5ecaSDag-Erling Smørgrav 1529545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1530545d5ecaSDag-Erling Smørgrav s = session_new(); 1531545d5ecaSDag-Erling Smørgrav if (s == NULL) 1532545d5ecaSDag-Erling Smørgrav goto error; 1533545d5ecaSDag-Erling Smørgrav s->authctxt = authctxt; 1534545d5ecaSDag-Erling Smørgrav s->pw = authctxt->pw; 1535545d5ecaSDag-Erling Smørgrav s->pid = pmonitor->m_pid; 1536545d5ecaSDag-Erling Smørgrav res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 1537545d5ecaSDag-Erling Smørgrav if (res == 0) 1538545d5ecaSDag-Erling Smørgrav goto error; 1539545d5ecaSDag-Erling Smørgrav pty_setowner(authctxt->pw, s->tty); 1540545d5ecaSDag-Erling Smørgrav 1541545d5ecaSDag-Erling Smørgrav buffer_put_int(m, 1); 1542545d5ecaSDag-Erling Smørgrav buffer_put_cstring(m, s->tty); 1543545d5ecaSDag-Erling Smørgrav 1544545d5ecaSDag-Erling Smørgrav /* We need to trick ttyslot */ 1545545d5ecaSDag-Erling Smørgrav if (dup2(s->ttyfd, 0) == -1) 1546545d5ecaSDag-Erling Smørgrav fatal("%s: dup2", __func__); 1547545d5ecaSDag-Erling Smørgrav 1548545d5ecaSDag-Erling Smørgrav mm_record_login(s, authctxt->pw); 1549545d5ecaSDag-Erling Smørgrav 1550545d5ecaSDag-Erling Smørgrav /* Now we can close the file descriptor again */ 1551545d5ecaSDag-Erling Smørgrav close(0); 1552545d5ecaSDag-Erling Smørgrav 155321e764dfSDag-Erling Smørgrav /* send messages generated by record_login */ 155421e764dfSDag-Erling Smørgrav buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); 155521e764dfSDag-Erling Smørgrav buffer_clear(&loginmsg); 155621e764dfSDag-Erling Smørgrav 155721e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PTY, m); 155821e764dfSDag-Erling Smørgrav 1559d4af9e69SDag-Erling Smørgrav if (mm_send_fd(sock, s->ptyfd) == -1 || 1560d4af9e69SDag-Erling Smørgrav mm_send_fd(sock, s->ttyfd) == -1) 1561d4af9e69SDag-Erling Smørgrav fatal("%s: send fds failed", __func__); 156221e764dfSDag-Erling Smørgrav 1563545d5ecaSDag-Erling Smørgrav /* make sure nothing uses fd 0 */ 1564545d5ecaSDag-Erling Smørgrav if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 1565545d5ecaSDag-Erling Smørgrav fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); 1566545d5ecaSDag-Erling Smørgrav if (fd0 != 0) 1567545d5ecaSDag-Erling Smørgrav error("%s: fd0 %d != 0", __func__, fd0); 1568545d5ecaSDag-Erling Smørgrav 1569545d5ecaSDag-Erling Smørgrav /* slave is not needed */ 1570545d5ecaSDag-Erling Smørgrav close(s->ttyfd); 1571545d5ecaSDag-Erling Smørgrav s->ttyfd = s->ptyfd; 1572545d5ecaSDag-Erling Smørgrav /* no need to dup() because nobody closes ptyfd */ 1573545d5ecaSDag-Erling Smørgrav s->ptymaster = s->ptyfd; 1574545d5ecaSDag-Erling Smørgrav 1575545d5ecaSDag-Erling Smørgrav debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); 1576545d5ecaSDag-Erling Smørgrav 1577545d5ecaSDag-Erling Smørgrav return (0); 1578545d5ecaSDag-Erling Smørgrav 1579545d5ecaSDag-Erling Smørgrav error: 1580545d5ecaSDag-Erling Smørgrav if (s != NULL) 1581545d5ecaSDag-Erling Smørgrav mm_session_close(s); 1582545d5ecaSDag-Erling Smørgrav buffer_put_int(m, 0); 158321e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PTY, m); 1584545d5ecaSDag-Erling Smørgrav return (0); 1585545d5ecaSDag-Erling Smørgrav } 1586545d5ecaSDag-Erling Smørgrav 1587545d5ecaSDag-Erling Smørgrav int 158821e764dfSDag-Erling Smørgrav mm_answer_pty_cleanup(int sock, Buffer *m) 1589545d5ecaSDag-Erling Smørgrav { 1590545d5ecaSDag-Erling Smørgrav Session *s; 1591545d5ecaSDag-Erling Smørgrav char *tty; 1592545d5ecaSDag-Erling Smørgrav 1593545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1594545d5ecaSDag-Erling Smørgrav 1595545d5ecaSDag-Erling Smørgrav tty = buffer_get_string(m, NULL); 1596545d5ecaSDag-Erling Smørgrav if ((s = session_by_tty(tty)) != NULL) 1597545d5ecaSDag-Erling Smørgrav mm_session_close(s); 1598545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1599e4a9863fSDag-Erling Smørgrav free(tty); 1600545d5ecaSDag-Erling Smørgrav return (0); 1601545d5ecaSDag-Erling Smørgrav } 1602545d5ecaSDag-Erling Smørgrav 1603a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_SSH1 1604545d5ecaSDag-Erling Smørgrav int 160521e764dfSDag-Erling Smørgrav mm_answer_sesskey(int sock, Buffer *m) 1606545d5ecaSDag-Erling Smørgrav { 1607545d5ecaSDag-Erling Smørgrav BIGNUM *p; 1608545d5ecaSDag-Erling Smørgrav int rsafail; 1609545d5ecaSDag-Erling Smørgrav 1610545d5ecaSDag-Erling Smørgrav /* Turn off permissions */ 1611aa49c926SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); 1612545d5ecaSDag-Erling Smørgrav 1613545d5ecaSDag-Erling Smørgrav if ((p = BN_new()) == NULL) 1614545d5ecaSDag-Erling Smørgrav fatal("%s: BN_new", __func__); 1615545d5ecaSDag-Erling Smørgrav 1616545d5ecaSDag-Erling Smørgrav buffer_get_bignum2(m, p); 1617545d5ecaSDag-Erling Smørgrav 1618545d5ecaSDag-Erling Smørgrav rsafail = ssh1_session_key(p); 1619545d5ecaSDag-Erling Smørgrav 1620545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1621545d5ecaSDag-Erling Smørgrav buffer_put_int(m, rsafail); 1622545d5ecaSDag-Erling Smørgrav buffer_put_bignum2(m, p); 1623545d5ecaSDag-Erling Smørgrav 1624545d5ecaSDag-Erling Smørgrav BN_clear_free(p); 1625545d5ecaSDag-Erling Smørgrav 162621e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_SESSKEY, m); 1627545d5ecaSDag-Erling Smørgrav 1628545d5ecaSDag-Erling Smørgrav /* Turn on permissions for sessid passing */ 1629545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); 1630545d5ecaSDag-Erling Smørgrav 1631545d5ecaSDag-Erling Smørgrav return (0); 1632545d5ecaSDag-Erling Smørgrav } 1633545d5ecaSDag-Erling Smørgrav 1634545d5ecaSDag-Erling Smørgrav int 163521e764dfSDag-Erling Smørgrav mm_answer_sessid(int sock, Buffer *m) 1636545d5ecaSDag-Erling Smørgrav { 1637545d5ecaSDag-Erling Smørgrav int i; 1638545d5ecaSDag-Erling Smørgrav 1639545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1640545d5ecaSDag-Erling Smørgrav 1641545d5ecaSDag-Erling Smørgrav if (buffer_len(m) != 16) 1642545d5ecaSDag-Erling Smørgrav fatal("%s: bad ssh1 session id", __func__); 1643545d5ecaSDag-Erling Smørgrav for (i = 0; i < 16; i++) 1644545d5ecaSDag-Erling Smørgrav session_id[i] = buffer_get_char(m); 1645545d5ecaSDag-Erling Smørgrav 1646545d5ecaSDag-Erling Smørgrav /* Turn on permissions for getpwnam */ 1647545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 1648545d5ecaSDag-Erling Smørgrav 1649545d5ecaSDag-Erling Smørgrav return (0); 1650545d5ecaSDag-Erling Smørgrav } 1651545d5ecaSDag-Erling Smørgrav 1652545d5ecaSDag-Erling Smørgrav int 165321e764dfSDag-Erling Smørgrav mm_answer_rsa_keyallowed(int sock, Buffer *m) 1654545d5ecaSDag-Erling Smørgrav { 1655545d5ecaSDag-Erling Smørgrav BIGNUM *client_n; 1656545d5ecaSDag-Erling Smørgrav Key *key = NULL; 1657545d5ecaSDag-Erling Smørgrav u_char *blob = NULL; 1658545d5ecaSDag-Erling Smørgrav u_int blen = 0; 1659545d5ecaSDag-Erling Smørgrav int allowed = 0; 1660545d5ecaSDag-Erling Smørgrav 1661545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1662545d5ecaSDag-Erling Smørgrav 1663333ee039SDag-Erling Smørgrav auth_method = "rsa"; 1664545d5ecaSDag-Erling Smørgrav if (options.rsa_authentication && authctxt->valid) { 1665545d5ecaSDag-Erling Smørgrav if ((client_n = BN_new()) == NULL) 1666545d5ecaSDag-Erling Smørgrav fatal("%s: BN_new", __func__); 1667545d5ecaSDag-Erling Smørgrav buffer_get_bignum2(m, client_n); 1668545d5ecaSDag-Erling Smørgrav allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); 1669545d5ecaSDag-Erling Smørgrav BN_clear_free(client_n); 1670545d5ecaSDag-Erling Smørgrav } 1671545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1672545d5ecaSDag-Erling Smørgrav buffer_put_int(m, allowed); 1673e73e9afaSDag-Erling Smørgrav buffer_put_int(m, forced_command != NULL); 1674545d5ecaSDag-Erling Smørgrav 1675545d5ecaSDag-Erling Smørgrav /* clear temporarily storage (used by generate challenge) */ 1676545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1677545d5ecaSDag-Erling Smørgrav 1678545d5ecaSDag-Erling Smørgrav if (allowed && key != NULL) { 1679545d5ecaSDag-Erling Smørgrav key->type = KEY_RSA; /* cheat for key_to_blob */ 1680545d5ecaSDag-Erling Smørgrav if (key_to_blob(key, &blob, &blen) == 0) 1681545d5ecaSDag-Erling Smørgrav fatal("%s: key_to_blob failed", __func__); 1682545d5ecaSDag-Erling Smørgrav buffer_put_string(m, blob, blen); 1683545d5ecaSDag-Erling Smørgrav 1684545d5ecaSDag-Erling Smørgrav /* Save temporarily for comparison in verify */ 1685545d5ecaSDag-Erling Smørgrav key_blob = blob; 1686545d5ecaSDag-Erling Smørgrav key_bloblen = blen; 1687545d5ecaSDag-Erling Smørgrav key_blobtype = MM_RSAUSERKEY; 1688545d5ecaSDag-Erling Smørgrav } 1689e73e9afaSDag-Erling Smørgrav if (key != NULL) 1690e73e9afaSDag-Erling Smørgrav key_free(key); 1691545d5ecaSDag-Erling Smørgrav 169221e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); 1693545d5ecaSDag-Erling Smørgrav 1694545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 1695545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); 1696545d5ecaSDag-Erling Smørgrav return (0); 1697545d5ecaSDag-Erling Smørgrav } 1698545d5ecaSDag-Erling Smørgrav 1699545d5ecaSDag-Erling Smørgrav int 170021e764dfSDag-Erling Smørgrav mm_answer_rsa_challenge(int sock, Buffer *m) 1701545d5ecaSDag-Erling Smørgrav { 1702545d5ecaSDag-Erling Smørgrav Key *key = NULL; 1703545d5ecaSDag-Erling Smørgrav u_char *blob; 1704545d5ecaSDag-Erling Smørgrav u_int blen; 1705545d5ecaSDag-Erling Smørgrav 1706545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1707545d5ecaSDag-Erling Smørgrav 1708545d5ecaSDag-Erling Smørgrav if (!authctxt->valid) 1709545d5ecaSDag-Erling Smørgrav fatal("%s: authctxt not valid", __func__); 1710545d5ecaSDag-Erling Smørgrav blob = buffer_get_string(m, &blen); 1711545d5ecaSDag-Erling Smørgrav if (!monitor_allowed_key(blob, blen)) 1712545d5ecaSDag-Erling Smørgrav fatal("%s: bad key, not previously allowed", __func__); 1713545d5ecaSDag-Erling Smørgrav if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 1714545d5ecaSDag-Erling Smørgrav fatal("%s: key type mismatch", __func__); 1715545d5ecaSDag-Erling Smørgrav if ((key = key_from_blob(blob, blen)) == NULL) 1716545d5ecaSDag-Erling Smørgrav fatal("%s: received bad key", __func__); 1717cce7d346SDag-Erling Smørgrav if (key->type != KEY_RSA) 1718cce7d346SDag-Erling Smørgrav fatal("%s: received bad key type %d", __func__, key->type); 1719cce7d346SDag-Erling Smørgrav key->type = KEY_RSA1; 1720545d5ecaSDag-Erling Smørgrav if (ssh1_challenge) 1721545d5ecaSDag-Erling Smørgrav BN_clear_free(ssh1_challenge); 1722545d5ecaSDag-Erling Smørgrav ssh1_challenge = auth_rsa_generate_challenge(key); 1723545d5ecaSDag-Erling Smørgrav 1724545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1725545d5ecaSDag-Erling Smørgrav buffer_put_bignum2(m, ssh1_challenge); 1726545d5ecaSDag-Erling Smørgrav 1727545d5ecaSDag-Erling Smørgrav debug3("%s sending reply", __func__); 172821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); 1729545d5ecaSDag-Erling Smørgrav 1730545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); 1731e73e9afaSDag-Erling Smørgrav 1732e4a9863fSDag-Erling Smørgrav free(blob); 1733e73e9afaSDag-Erling Smørgrav key_free(key); 1734545d5ecaSDag-Erling Smørgrav return (0); 1735545d5ecaSDag-Erling Smørgrav } 1736545d5ecaSDag-Erling Smørgrav 1737545d5ecaSDag-Erling Smørgrav int 173821e764dfSDag-Erling Smørgrav mm_answer_rsa_response(int sock, Buffer *m) 1739545d5ecaSDag-Erling Smørgrav { 1740545d5ecaSDag-Erling Smørgrav Key *key = NULL; 1741545d5ecaSDag-Erling Smørgrav u_char *blob, *response; 1742545d5ecaSDag-Erling Smørgrav u_int blen, len; 1743545d5ecaSDag-Erling Smørgrav int success; 1744545d5ecaSDag-Erling Smørgrav 1745545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1746545d5ecaSDag-Erling Smørgrav 1747545d5ecaSDag-Erling Smørgrav if (!authctxt->valid) 1748545d5ecaSDag-Erling Smørgrav fatal("%s: authctxt not valid", __func__); 1749545d5ecaSDag-Erling Smørgrav if (ssh1_challenge == NULL) 1750545d5ecaSDag-Erling Smørgrav fatal("%s: no ssh1_challenge", __func__); 1751545d5ecaSDag-Erling Smørgrav 1752545d5ecaSDag-Erling Smørgrav blob = buffer_get_string(m, &blen); 1753545d5ecaSDag-Erling Smørgrav if (!monitor_allowed_key(blob, blen)) 1754545d5ecaSDag-Erling Smørgrav fatal("%s: bad key, not previously allowed", __func__); 1755545d5ecaSDag-Erling Smørgrav if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 1756545d5ecaSDag-Erling Smørgrav fatal("%s: key type mismatch: %d", __func__, key_blobtype); 1757545d5ecaSDag-Erling Smørgrav if ((key = key_from_blob(blob, blen)) == NULL) 1758545d5ecaSDag-Erling Smørgrav fatal("%s: received bad key", __func__); 1759545d5ecaSDag-Erling Smørgrav response = buffer_get_string(m, &len); 1760545d5ecaSDag-Erling Smørgrav if (len != 16) 1761545d5ecaSDag-Erling Smørgrav fatal("%s: received bad response to challenge", __func__); 1762545d5ecaSDag-Erling Smørgrav success = auth_rsa_verify_response(key, ssh1_challenge, response); 1763545d5ecaSDag-Erling Smørgrav 1764e4a9863fSDag-Erling Smørgrav free(blob); 1765545d5ecaSDag-Erling Smørgrav key_free(key); 1766e4a9863fSDag-Erling Smørgrav free(response); 1767545d5ecaSDag-Erling Smørgrav 1768545d5ecaSDag-Erling Smørgrav auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; 1769545d5ecaSDag-Erling Smørgrav 1770545d5ecaSDag-Erling Smørgrav /* reset state */ 1771545d5ecaSDag-Erling Smørgrav BN_clear_free(ssh1_challenge); 1772545d5ecaSDag-Erling Smørgrav ssh1_challenge = NULL; 1773545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1774545d5ecaSDag-Erling Smørgrav 1775545d5ecaSDag-Erling Smørgrav buffer_clear(m); 1776545d5ecaSDag-Erling Smørgrav buffer_put_int(m, success); 177721e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); 1778545d5ecaSDag-Erling Smørgrav 1779545d5ecaSDag-Erling Smørgrav return (success); 1780545d5ecaSDag-Erling Smørgrav } 1781a0ee8cc6SDag-Erling Smørgrav #endif 1782545d5ecaSDag-Erling Smørgrav 1783545d5ecaSDag-Erling Smørgrav int 178421e764dfSDag-Erling Smørgrav mm_answer_term(int sock, Buffer *req) 1785545d5ecaSDag-Erling Smørgrav { 1786545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor; 1787545d5ecaSDag-Erling Smørgrav int res, status; 1788545d5ecaSDag-Erling Smørgrav 1789545d5ecaSDag-Erling Smørgrav debug3("%s: tearing down sessions", __func__); 1790545d5ecaSDag-Erling Smørgrav 1791545d5ecaSDag-Erling Smørgrav /* The child is terminating */ 1792545d5ecaSDag-Erling Smørgrav session_destroy_all(&mm_session_close); 1793545d5ecaSDag-Erling Smørgrav 1794d4af9e69SDag-Erling Smørgrav #ifdef USE_PAM 1795d4af9e69SDag-Erling Smørgrav if (options.use_pam) 1796d4af9e69SDag-Erling Smørgrav sshpam_cleanup(); 1797d4af9e69SDag-Erling Smørgrav #endif 1798d4af9e69SDag-Erling Smørgrav 1799545d5ecaSDag-Erling Smørgrav while (waitpid(pmonitor->m_pid, &status, 0) == -1) 1800545d5ecaSDag-Erling Smørgrav if (errno != EINTR) 1801545d5ecaSDag-Erling Smørgrav exit(1); 1802545d5ecaSDag-Erling Smørgrav 1803545d5ecaSDag-Erling Smørgrav res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 1804545d5ecaSDag-Erling Smørgrav 1805545d5ecaSDag-Erling Smørgrav /* Terminate process */ 1806545d5ecaSDag-Erling Smørgrav exit(res); 1807545d5ecaSDag-Erling Smørgrav } 1808545d5ecaSDag-Erling Smørgrav 1809aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 1810aa49c926SDag-Erling Smørgrav /* Report that an audit event occurred */ 1811aa49c926SDag-Erling Smørgrav int 1812aa49c926SDag-Erling Smørgrav mm_answer_audit_event(int socket, Buffer *m) 1813aa49c926SDag-Erling Smørgrav { 1814aa49c926SDag-Erling Smørgrav ssh_audit_event_t event; 1815aa49c926SDag-Erling Smørgrav 1816aa49c926SDag-Erling Smørgrav debug3("%s entering", __func__); 1817aa49c926SDag-Erling Smørgrav 1818aa49c926SDag-Erling Smørgrav event = buffer_get_int(m); 1819aa49c926SDag-Erling Smørgrav switch(event) { 1820aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_PUBKEY: 1821aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_HOSTBASED: 1822aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_GSSAPI: 1823aa49c926SDag-Erling Smørgrav case SSH_LOGIN_EXCEED_MAXTRIES: 1824aa49c926SDag-Erling Smørgrav case SSH_LOGIN_ROOT_DENIED: 1825aa49c926SDag-Erling Smørgrav case SSH_CONNECTION_CLOSE: 1826aa49c926SDag-Erling Smørgrav case SSH_INVALID_USER: 1827aa49c926SDag-Erling Smørgrav audit_event(event); 1828aa49c926SDag-Erling Smørgrav break; 1829aa49c926SDag-Erling Smørgrav default: 1830aa49c926SDag-Erling Smørgrav fatal("Audit event type %d not permitted", event); 1831aa49c926SDag-Erling Smørgrav } 1832aa49c926SDag-Erling Smørgrav 1833aa49c926SDag-Erling Smørgrav return (0); 1834aa49c926SDag-Erling Smørgrav } 1835aa49c926SDag-Erling Smørgrav 1836aa49c926SDag-Erling Smørgrav int 1837aa49c926SDag-Erling Smørgrav mm_answer_audit_command(int socket, Buffer *m) 1838aa49c926SDag-Erling Smørgrav { 1839aa49c926SDag-Erling Smørgrav u_int len; 1840aa49c926SDag-Erling Smørgrav char *cmd; 1841aa49c926SDag-Erling Smørgrav 1842aa49c926SDag-Erling Smørgrav debug3("%s entering", __func__); 1843aa49c926SDag-Erling Smørgrav cmd = buffer_get_string(m, &len); 1844aa49c926SDag-Erling Smørgrav /* sanity check command, if so how? */ 1845aa49c926SDag-Erling Smørgrav audit_run_command(cmd); 1846e4a9863fSDag-Erling Smørgrav free(cmd); 1847aa49c926SDag-Erling Smørgrav return (0); 1848aa49c926SDag-Erling Smørgrav } 1849aa49c926SDag-Erling Smørgrav #endif /* SSH_AUDIT_EVENTS */ 1850aa49c926SDag-Erling Smørgrav 1851545d5ecaSDag-Erling Smørgrav void 1852545d5ecaSDag-Erling Smørgrav monitor_apply_keystate(struct monitor *pmonitor) 1853545d5ecaSDag-Erling Smørgrav { 1854bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1855bc5531deSDag-Erling Smørgrav struct kex *kex; 1856bc5531deSDag-Erling Smørgrav int r; 1857545d5ecaSDag-Erling Smørgrav 1858bc5531deSDag-Erling Smørgrav debug3("%s: packet_set_state", __func__); 1859bc5531deSDag-Erling Smørgrav if ((r = ssh_packet_set_state(ssh, child_state)) != 0) 1860bc5531deSDag-Erling Smørgrav fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); 1861bc5531deSDag-Erling Smørgrav sshbuf_free(child_state); 1862bc5531deSDag-Erling Smørgrav child_state = NULL; 1863545d5ecaSDag-Erling Smørgrav 1864acc1a9efSDag-Erling Smørgrav if ((kex = ssh->kex) != NULL) { 1865bc5531deSDag-Erling Smørgrav /* XXX set callbacks */ 1866a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 1867e73e9afaSDag-Erling Smørgrav kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 186821e764dfSDag-Erling Smørgrav kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1869*076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 1870*076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 1871*076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 1872e73e9afaSDag-Erling Smørgrav kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1873333ee039SDag-Erling Smørgrav kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1874bc5531deSDag-Erling Smørgrav # ifdef OPENSSL_HAS_ECC 18754a421b63SDag-Erling Smørgrav kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1876a0ee8cc6SDag-Erling Smørgrav # endif 1877bc5531deSDag-Erling Smørgrav #endif /* WITH_OPENSSL */ 1878f7167e0eSDag-Erling Smørgrav kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1879b15c8340SDag-Erling Smørgrav kex->load_host_public_key=&get_hostkey_public_by_type; 1880b15c8340SDag-Erling Smørgrav kex->load_host_private_key=&get_hostkey_private_by_type; 1881545d5ecaSDag-Erling Smørgrav kex->host_key_index=&get_hostkey_index; 1882e4a9863fSDag-Erling Smørgrav kex->sign = sshd_hostkey_sign; 1883bc5531deSDag-Erling Smørgrav } 1884545d5ecaSDag-Erling Smørgrav 1885bc5531deSDag-Erling Smørgrav /* Update with new address */ 1886bc5531deSDag-Erling Smørgrav if (options.compression) { 1887bc5531deSDag-Erling Smørgrav ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, 1888bc5531deSDag-Erling Smørgrav (ssh_packet_comp_alloc_func *)mm_zalloc, 1889bc5531deSDag-Erling Smørgrav (ssh_packet_comp_free_func *)mm_zfree); 1890bc5531deSDag-Erling Smørgrav } 1891545d5ecaSDag-Erling Smørgrav } 1892545d5ecaSDag-Erling Smørgrav 1893545d5ecaSDag-Erling Smørgrav /* This function requries careful sanity checking */ 1894545d5ecaSDag-Erling Smørgrav 1895545d5ecaSDag-Erling Smørgrav void 1896545d5ecaSDag-Erling Smørgrav mm_get_keystate(struct monitor *pmonitor) 1897545d5ecaSDag-Erling Smørgrav { 1898545d5ecaSDag-Erling Smørgrav debug3("%s: Waiting for new keys", __func__); 1899545d5ecaSDag-Erling Smørgrav 1900bc5531deSDag-Erling Smørgrav if ((child_state = sshbuf_new()) == NULL) 1901bc5531deSDag-Erling Smørgrav fatal("%s: sshbuf_new failed", __func__); 1902bc5531deSDag-Erling Smørgrav mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, 1903bc5531deSDag-Erling Smørgrav child_state); 1904bc5531deSDag-Erling Smørgrav debug3("%s: GOT new keys", __func__); 1905545d5ecaSDag-Erling Smørgrav } 1906545d5ecaSDag-Erling Smørgrav 1907545d5ecaSDag-Erling Smørgrav 1908545d5ecaSDag-Erling Smørgrav /* XXX */ 1909545d5ecaSDag-Erling Smørgrav 1910545d5ecaSDag-Erling Smørgrav #define FD_CLOSEONEXEC(x) do { \ 1911e146993eSDag-Erling Smørgrav if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ 1912545d5ecaSDag-Erling Smørgrav fatal("fcntl(%d, F_SETFD)", x); \ 1913545d5ecaSDag-Erling Smørgrav } while (0) 1914545d5ecaSDag-Erling Smørgrav 1915545d5ecaSDag-Erling Smørgrav static void 1916e146993eSDag-Erling Smørgrav monitor_openfds(struct monitor *mon, int do_logfds) 1917545d5ecaSDag-Erling Smørgrav { 1918e146993eSDag-Erling Smørgrav int pair[2]; 1919e146993eSDag-Erling Smørgrav 1920545d5ecaSDag-Erling Smørgrav if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 1921e146993eSDag-Erling Smørgrav fatal("%s: socketpair: %s", __func__, strerror(errno)); 1922545d5ecaSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[0]); 1923545d5ecaSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[1]); 1924e146993eSDag-Erling Smørgrav mon->m_recvfd = pair[0]; 1925e146993eSDag-Erling Smørgrav mon->m_sendfd = pair[1]; 1926e146993eSDag-Erling Smørgrav 1927e146993eSDag-Erling Smørgrav if (do_logfds) { 1928e146993eSDag-Erling Smørgrav if (pipe(pair) == -1) 1929e146993eSDag-Erling Smørgrav fatal("%s: pipe: %s", __func__, strerror(errno)); 1930e146993eSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[0]); 1931e146993eSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[1]); 1932e146993eSDag-Erling Smørgrav mon->m_log_recvfd = pair[0]; 1933e146993eSDag-Erling Smørgrav mon->m_log_sendfd = pair[1]; 1934e146993eSDag-Erling Smørgrav } else 1935e146993eSDag-Erling Smørgrav mon->m_log_recvfd = mon->m_log_sendfd = -1; 1936545d5ecaSDag-Erling Smørgrav } 1937545d5ecaSDag-Erling Smørgrav 1938545d5ecaSDag-Erling Smørgrav #define MM_MEMSIZE 65536 1939545d5ecaSDag-Erling Smørgrav 1940545d5ecaSDag-Erling Smørgrav struct monitor * 1941545d5ecaSDag-Erling Smørgrav monitor_init(void) 1942545d5ecaSDag-Erling Smørgrav { 1943bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1944545d5ecaSDag-Erling Smørgrav struct monitor *mon; 1945545d5ecaSDag-Erling Smørgrav 1946333ee039SDag-Erling Smørgrav mon = xcalloc(1, sizeof(*mon)); 1947545d5ecaSDag-Erling Smørgrav 1948e146993eSDag-Erling Smørgrav monitor_openfds(mon, 1); 1949545d5ecaSDag-Erling Smørgrav 1950545d5ecaSDag-Erling Smørgrav /* Used to share zlib space across processes */ 1951545d5ecaSDag-Erling Smørgrav if (options.compression) { 1952545d5ecaSDag-Erling Smørgrav mon->m_zback = mm_create(NULL, MM_MEMSIZE); 1953545d5ecaSDag-Erling Smørgrav mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); 1954545d5ecaSDag-Erling Smørgrav 1955545d5ecaSDag-Erling Smørgrav /* Compression needs to share state across borders */ 1956bc5531deSDag-Erling Smørgrav ssh_packet_set_compress_hooks(ssh, mon->m_zlib, 1957bc5531deSDag-Erling Smørgrav (ssh_packet_comp_alloc_func *)mm_zalloc, 1958bc5531deSDag-Erling Smørgrav (ssh_packet_comp_free_func *)mm_zfree); 1959545d5ecaSDag-Erling Smørgrav } 1960545d5ecaSDag-Erling Smørgrav 1961545d5ecaSDag-Erling Smørgrav return mon; 1962545d5ecaSDag-Erling Smørgrav } 1963545d5ecaSDag-Erling Smørgrav 1964545d5ecaSDag-Erling Smørgrav void 1965545d5ecaSDag-Erling Smørgrav monitor_reinit(struct monitor *mon) 1966545d5ecaSDag-Erling Smørgrav { 1967e146993eSDag-Erling Smørgrav monitor_openfds(mon, 0); 1968545d5ecaSDag-Erling Smørgrav } 1969cf2b5f3bSDag-Erling Smørgrav 1970cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 1971cf2b5f3bSDag-Erling Smørgrav int 197221e764dfSDag-Erling Smørgrav mm_answer_gss_setup_ctx(int sock, Buffer *m) 1973cf2b5f3bSDag-Erling Smørgrav { 197421e764dfSDag-Erling Smørgrav gss_OID_desc goid; 1975cf2b5f3bSDag-Erling Smørgrav OM_uint32 major; 1976cf2b5f3bSDag-Erling Smørgrav u_int len; 1977cf2b5f3bSDag-Erling Smørgrav 197821e764dfSDag-Erling Smørgrav goid.elements = buffer_get_string(m, &len); 197921e764dfSDag-Erling Smørgrav goid.length = len; 1980cf2b5f3bSDag-Erling Smørgrav 198121e764dfSDag-Erling Smørgrav major = ssh_gssapi_server_ctx(&gsscontext, &goid); 1982cf2b5f3bSDag-Erling Smørgrav 1983e4a9863fSDag-Erling Smørgrav free(goid.elements); 1984cf2b5f3bSDag-Erling Smørgrav 1985cf2b5f3bSDag-Erling Smørgrav buffer_clear(m); 1986cf2b5f3bSDag-Erling Smørgrav buffer_put_int(m, major); 1987cf2b5f3bSDag-Erling Smørgrav 198821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); 1989cf2b5f3bSDag-Erling Smørgrav 1990cf2b5f3bSDag-Erling Smørgrav /* Now we have a context, enable the step */ 1991cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); 1992cf2b5f3bSDag-Erling Smørgrav 1993cf2b5f3bSDag-Erling Smørgrav return (0); 1994cf2b5f3bSDag-Erling Smørgrav } 1995cf2b5f3bSDag-Erling Smørgrav 1996cf2b5f3bSDag-Erling Smørgrav int 199721e764dfSDag-Erling Smørgrav mm_answer_gss_accept_ctx(int sock, Buffer *m) 1998cf2b5f3bSDag-Erling Smørgrav { 1999cf2b5f3bSDag-Erling Smørgrav gss_buffer_desc in; 2000cf2b5f3bSDag-Erling Smørgrav gss_buffer_desc out = GSS_C_EMPTY_BUFFER; 2001cf2b5f3bSDag-Erling Smørgrav OM_uint32 major, minor; 2002cf2b5f3bSDag-Erling Smørgrav OM_uint32 flags = 0; /* GSI needs this */ 2003cf2b5f3bSDag-Erling Smørgrav u_int len; 2004cf2b5f3bSDag-Erling Smørgrav 2005cf2b5f3bSDag-Erling Smørgrav in.value = buffer_get_string(m, &len); 2006cf2b5f3bSDag-Erling Smørgrav in.length = len; 2007cf2b5f3bSDag-Erling Smørgrav major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 2008e4a9863fSDag-Erling Smørgrav free(in.value); 2009cf2b5f3bSDag-Erling Smørgrav 2010cf2b5f3bSDag-Erling Smørgrav buffer_clear(m); 2011cf2b5f3bSDag-Erling Smørgrav buffer_put_int(m, major); 2012cf2b5f3bSDag-Erling Smørgrav buffer_put_string(m, out.value, out.length); 2013cf2b5f3bSDag-Erling Smørgrav buffer_put_int(m, flags); 201421e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); 2015cf2b5f3bSDag-Erling Smørgrav 2016cf2b5f3bSDag-Erling Smørgrav gss_release_buffer(&minor, &out); 2017cf2b5f3bSDag-Erling Smørgrav 2018cf2b5f3bSDag-Erling Smørgrav if (major == GSS_S_COMPLETE) { 2019cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 2020cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 20211ec0d754SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 2022cf2b5f3bSDag-Erling Smørgrav } 2023cf2b5f3bSDag-Erling Smørgrav return (0); 2024cf2b5f3bSDag-Erling Smørgrav } 2025cf2b5f3bSDag-Erling Smørgrav 2026cf2b5f3bSDag-Erling Smørgrav int 202721e764dfSDag-Erling Smørgrav mm_answer_gss_checkmic(int sock, Buffer *m) 20281ec0d754SDag-Erling Smørgrav { 20291ec0d754SDag-Erling Smørgrav gss_buffer_desc gssbuf, mic; 20301ec0d754SDag-Erling Smørgrav OM_uint32 ret; 20311ec0d754SDag-Erling Smørgrav u_int len; 20321ec0d754SDag-Erling Smørgrav 20331ec0d754SDag-Erling Smørgrav gssbuf.value = buffer_get_string(m, &len); 20341ec0d754SDag-Erling Smørgrav gssbuf.length = len; 20351ec0d754SDag-Erling Smørgrav mic.value = buffer_get_string(m, &len); 20361ec0d754SDag-Erling Smørgrav mic.length = len; 20371ec0d754SDag-Erling Smørgrav 20381ec0d754SDag-Erling Smørgrav ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); 20391ec0d754SDag-Erling Smørgrav 2040e4a9863fSDag-Erling Smørgrav free(gssbuf.value); 2041e4a9863fSDag-Erling Smørgrav free(mic.value); 20421ec0d754SDag-Erling Smørgrav 20431ec0d754SDag-Erling Smørgrav buffer_clear(m); 20441ec0d754SDag-Erling Smørgrav buffer_put_int(m, ret); 20451ec0d754SDag-Erling Smørgrav 204621e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); 20471ec0d754SDag-Erling Smørgrav 20481ec0d754SDag-Erling Smørgrav if (!GSS_ERROR(ret)) 20491ec0d754SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 20501ec0d754SDag-Erling Smørgrav 20511ec0d754SDag-Erling Smørgrav return (0); 20521ec0d754SDag-Erling Smørgrav } 20531ec0d754SDag-Erling Smørgrav 20541ec0d754SDag-Erling Smørgrav int 205521e764dfSDag-Erling Smørgrav mm_answer_gss_userok(int sock, Buffer *m) 2056cf2b5f3bSDag-Erling Smørgrav { 2057cf2b5f3bSDag-Erling Smørgrav int authenticated; 2058cf2b5f3bSDag-Erling Smørgrav 2059cf2b5f3bSDag-Erling Smørgrav authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 2060cf2b5f3bSDag-Erling Smørgrav 2061cf2b5f3bSDag-Erling Smørgrav buffer_clear(m); 2062cf2b5f3bSDag-Erling Smørgrav buffer_put_int(m, authenticated); 2063cf2b5f3bSDag-Erling Smørgrav 2064cf2b5f3bSDag-Erling Smørgrav debug3("%s: sending result %d", __func__, authenticated); 206521e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); 2066cf2b5f3bSDag-Erling Smørgrav 20671ec0d754SDag-Erling Smørgrav auth_method = "gssapi-with-mic"; 2068cf2b5f3bSDag-Erling Smørgrav 2069cf2b5f3bSDag-Erling Smørgrav /* Monitor loop will terminate if authenticated */ 2070cf2b5f3bSDag-Erling Smørgrav return (authenticated); 2071cf2b5f3bSDag-Erling Smørgrav } 2072cf2b5f3bSDag-Erling Smørgrav #endif /* GSSAPI */ 2073cce7d346SDag-Erling Smørgrav 2074