1*190cef3dSDag-Erling Smørgrav /* $OpenBSD: monitor.c,v 1.186 2018/07/20 03:46:34 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> 37076ad2f8SDag-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 59a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 60333ee039SDag-Erling Smørgrav #include <openssl/dh.h> 61a0ee8cc6SDag-Erling Smørgrav #endif 62333ee039SDag-Erling Smørgrav 63d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h" 64e146993eSDag-Erling Smørgrav #include "atomicio.h" 65333ee039SDag-Erling Smørgrav #include "xmalloc.h" 66545d5ecaSDag-Erling Smørgrav #include "ssh.h" 67*190cef3dSDag-Erling Smørgrav #include "sshkey.h" 68*190cef3dSDag-Erling Smørgrav #include "sshbuf.h" 69333ee039SDag-Erling Smørgrav #include "hostfile.h" 70545d5ecaSDag-Erling Smørgrav #include "auth.h" 71333ee039SDag-Erling Smørgrav #include "cipher.h" 72545d5ecaSDag-Erling Smørgrav #include "kex.h" 73545d5ecaSDag-Erling Smørgrav #include "dh.h" 74076ad2f8SDag-Erling Smørgrav #include "auth-pam.h" 75545d5ecaSDag-Erling Smørgrav #include "packet.h" 76545d5ecaSDag-Erling Smørgrav #include "auth-options.h" 77545d5ecaSDag-Erling Smørgrav #include "sshpty.h" 78545d5ecaSDag-Erling Smørgrav #include "channels.h" 79545d5ecaSDag-Erling Smørgrav #include "session.h" 80545d5ecaSDag-Erling Smørgrav #include "sshlogin.h" 81545d5ecaSDag-Erling Smørgrav #include "canohost.h" 82545d5ecaSDag-Erling Smørgrav #include "log.h" 83a0ee8cc6SDag-Erling Smørgrav #include "misc.h" 84545d5ecaSDag-Erling Smørgrav #include "servconf.h" 85545d5ecaSDag-Erling Smørgrav #include "monitor.h" 86333ee039SDag-Erling Smørgrav #ifdef GSSAPI 87333ee039SDag-Erling Smørgrav #include "ssh-gss.h" 88333ee039SDag-Erling Smørgrav #endif 89545d5ecaSDag-Erling Smørgrav #include "monitor_wrap.h" 90545d5ecaSDag-Erling Smørgrav #include "monitor_fdpass.h" 91545d5ecaSDag-Erling Smørgrav #include "compat.h" 92545d5ecaSDag-Erling Smørgrav #include "ssh2.h" 93e4a9863fSDag-Erling Smørgrav #include "authfd.h" 94bc5531deSDag-Erling Smørgrav #include "match.h" 95bc5531deSDag-Erling Smørgrav #include "ssherr.h" 96545d5ecaSDag-Erling Smørgrav 97cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 98cf2b5f3bSDag-Erling Smørgrav static Gssctxt *gsscontext = NULL; 99cf2b5f3bSDag-Erling Smørgrav #endif 100cf2b5f3bSDag-Erling Smørgrav 101545d5ecaSDag-Erling Smørgrav /* Imports */ 102545d5ecaSDag-Erling Smørgrav extern ServerOptions options; 103545d5ecaSDag-Erling Smørgrav extern u_int utmp_len; 104545d5ecaSDag-Erling Smørgrav extern u_char session_id[]; 105*190cef3dSDag-Erling Smørgrav extern struct sshbuf *loginmsg; 10647dd1d1bSDag-Erling Smørgrav extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ 107545d5ecaSDag-Erling Smørgrav 108545d5ecaSDag-Erling Smørgrav /* State exported from the child */ 109bc5531deSDag-Erling Smørgrav static struct sshbuf *child_state; 110545d5ecaSDag-Erling Smørgrav 111cf2b5f3bSDag-Erling Smørgrav /* Functions on the monitor that answer unprivileged requests */ 112545d5ecaSDag-Erling Smørgrav 113*190cef3dSDag-Erling Smørgrav int mm_answer_moduli(int, struct sshbuf *); 114*190cef3dSDag-Erling Smørgrav int mm_answer_sign(int, struct sshbuf *); 115*190cef3dSDag-Erling Smørgrav int mm_answer_pwnamallow(int, struct sshbuf *); 116*190cef3dSDag-Erling Smørgrav int mm_answer_auth2_read_banner(int, struct sshbuf *); 117*190cef3dSDag-Erling Smørgrav int mm_answer_authserv(int, struct sshbuf *); 118*190cef3dSDag-Erling Smørgrav int mm_answer_authpassword(int, struct sshbuf *); 119*190cef3dSDag-Erling Smørgrav int mm_answer_bsdauthquery(int, struct sshbuf *); 120*190cef3dSDag-Erling Smørgrav int mm_answer_bsdauthrespond(int, struct sshbuf *); 121*190cef3dSDag-Erling Smørgrav int mm_answer_keyallowed(int, struct sshbuf *); 122*190cef3dSDag-Erling Smørgrav int mm_answer_keyverify(int, struct sshbuf *); 123*190cef3dSDag-Erling Smørgrav int mm_answer_pty(int, struct sshbuf *); 124*190cef3dSDag-Erling Smørgrav int mm_answer_pty_cleanup(int, struct sshbuf *); 125*190cef3dSDag-Erling Smørgrav int mm_answer_term(int, struct sshbuf *); 126*190cef3dSDag-Erling Smørgrav int mm_answer_rsa_keyallowed(int, struct sshbuf *); 127*190cef3dSDag-Erling Smørgrav int mm_answer_rsa_challenge(int, struct sshbuf *); 128*190cef3dSDag-Erling Smørgrav int mm_answer_rsa_response(int, struct sshbuf *); 129*190cef3dSDag-Erling Smørgrav int mm_answer_sesskey(int, struct sshbuf *); 130*190cef3dSDag-Erling Smørgrav int mm_answer_sessid(int, struct sshbuf *); 131545d5ecaSDag-Erling Smørgrav 132989dd127SDag-Erling Smørgrav #ifdef USE_PAM 133*190cef3dSDag-Erling Smørgrav int mm_answer_pam_start(int, struct sshbuf *); 134*190cef3dSDag-Erling Smørgrav int mm_answer_pam_account(int, struct sshbuf *); 135*190cef3dSDag-Erling Smørgrav int mm_answer_pam_init_ctx(int, struct sshbuf *); 136*190cef3dSDag-Erling Smørgrav int mm_answer_pam_query(int, struct sshbuf *); 137*190cef3dSDag-Erling Smørgrav int mm_answer_pam_respond(int, struct sshbuf *); 138*190cef3dSDag-Erling Smørgrav int mm_answer_pam_free_ctx(int, struct sshbuf *); 139989dd127SDag-Erling Smørgrav #endif 140989dd127SDag-Erling Smørgrav 141cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 142*190cef3dSDag-Erling Smørgrav int mm_answer_gss_setup_ctx(int, struct sshbuf *); 143*190cef3dSDag-Erling Smørgrav int mm_answer_gss_accept_ctx(int, struct sshbuf *); 144*190cef3dSDag-Erling Smørgrav int mm_answer_gss_userok(int, struct sshbuf *); 145*190cef3dSDag-Erling Smørgrav int mm_answer_gss_checkmic(int, struct sshbuf *); 146f388f5efSDag-Erling Smørgrav #endif 147f388f5efSDag-Erling Smørgrav 148aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 149*190cef3dSDag-Erling Smørgrav int mm_answer_audit_event(int, struct sshbuf *); 150*190cef3dSDag-Erling Smørgrav int mm_answer_audit_command(int, struct sshbuf *); 151aa49c926SDag-Erling Smørgrav #endif 152aa49c926SDag-Erling Smørgrav 153e146993eSDag-Erling Smørgrav static int monitor_read_log(struct monitor *); 154e146993eSDag-Erling Smørgrav 155545d5ecaSDag-Erling Smørgrav static Authctxt *authctxt; 156a0ee8cc6SDag-Erling Smørgrav 157545d5ecaSDag-Erling Smørgrav /* local state for key verify */ 158545d5ecaSDag-Erling Smørgrav static u_char *key_blob = NULL; 159*190cef3dSDag-Erling Smørgrav static size_t key_bloblen = 0; 160545d5ecaSDag-Erling Smørgrav static int key_blobtype = MM_NOKEY; 16147dd1d1bSDag-Erling Smørgrav static struct sshauthopt *key_opts = NULL; 162f388f5efSDag-Erling Smørgrav static char *hostbased_cuser = NULL; 163f388f5efSDag-Erling Smørgrav static char *hostbased_chost = NULL; 164545d5ecaSDag-Erling Smørgrav static char *auth_method = "unknown"; 1656888a9beSDag-Erling Smørgrav static char *auth_submethod = NULL; 166cf2b5f3bSDag-Erling Smørgrav static u_int session_id2_len = 0; 167545d5ecaSDag-Erling Smørgrav static u_char *session_id2 = NULL; 168cf2b5f3bSDag-Erling Smørgrav static pid_t monitor_child_pid; 169545d5ecaSDag-Erling Smørgrav 170545d5ecaSDag-Erling Smørgrav struct mon_table { 171545d5ecaSDag-Erling Smørgrav enum monitor_reqtype type; 172545d5ecaSDag-Erling Smørgrav int flags; 173*190cef3dSDag-Erling Smørgrav int (*f)(int, struct sshbuf *); 174545d5ecaSDag-Erling Smørgrav }; 175545d5ecaSDag-Erling Smørgrav 176545d5ecaSDag-Erling Smørgrav #define MON_ISAUTH 0x0004 /* Required for Authentication */ 177545d5ecaSDag-Erling Smørgrav #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ 178545d5ecaSDag-Erling Smørgrav #define MON_ONCE 0x0010 /* Disable after calling */ 179333ee039SDag-Erling Smørgrav #define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ 180545d5ecaSDag-Erling Smørgrav 181545d5ecaSDag-Erling Smørgrav #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) 182545d5ecaSDag-Erling Smørgrav 183545d5ecaSDag-Erling Smørgrav #define MON_PERMIT 0x1000 /* Request is permitted */ 184545d5ecaSDag-Erling Smørgrav 185545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_proto20[] = { 186a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 187545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 188a0ee8cc6SDag-Erling Smørgrav #endif 189545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 190545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 191545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 192545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 193545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 194989dd127SDag-Erling Smørgrav #ifdef USE_PAM 195989dd127SDag-Erling Smørgrav {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, 196cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, 197ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx}, 198ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query}, 199ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_PAM_RESPOND, MON_ONCE, mm_answer_pam_respond}, 200382d19eeSDag-Erling Smørgrav {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, 201989dd127SDag-Erling Smørgrav #endif 202aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 203aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 204aa49c926SDag-Erling Smørgrav #endif 205545d5ecaSDag-Erling Smørgrav #ifdef BSD_AUTH 206545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, 207545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, 208545d5ecaSDag-Erling Smørgrav #endif 209545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, 210545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, 211cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 212cf2b5f3bSDag-Erling Smørgrav {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, 213ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, 214ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, 215ca86bcf2SDag-Erling Smørgrav {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, 216cf2b5f3bSDag-Erling Smørgrav #endif 217545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 218545d5ecaSDag-Erling Smørgrav }; 219545d5ecaSDag-Erling Smørgrav 220545d5ecaSDag-Erling Smørgrav struct mon_table mon_dispatch_postauth20[] = { 221a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 222545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 223a0ee8cc6SDag-Erling Smørgrav #endif 224545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 225545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTY, 0, mm_answer_pty}, 226545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 227545d5ecaSDag-Erling Smørgrav {MONITOR_REQ_TERM, 0, mm_answer_term}, 228aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 229aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 230aa49c926SDag-Erling Smørgrav {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 231aa49c926SDag-Erling Smørgrav #endif 232545d5ecaSDag-Erling Smørgrav {0, 0, NULL} 233545d5ecaSDag-Erling Smørgrav }; 234545d5ecaSDag-Erling Smørgrav 235545d5ecaSDag-Erling Smørgrav struct mon_table *mon_dispatch; 236545d5ecaSDag-Erling Smørgrav 237545d5ecaSDag-Erling Smørgrav /* Specifies if a certain message is allowed at the moment */ 238545d5ecaSDag-Erling Smørgrav static void 239545d5ecaSDag-Erling Smørgrav monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) 240545d5ecaSDag-Erling Smørgrav { 241545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 242545d5ecaSDag-Erling Smørgrav if (ent->type == type) { 243545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 244545d5ecaSDag-Erling Smørgrav ent->flags |= permit ? MON_PERMIT : 0; 245545d5ecaSDag-Erling Smørgrav return; 246545d5ecaSDag-Erling Smørgrav } 247545d5ecaSDag-Erling Smørgrav ent++; 248545d5ecaSDag-Erling Smørgrav } 249545d5ecaSDag-Erling Smørgrav } 250545d5ecaSDag-Erling Smørgrav 251545d5ecaSDag-Erling Smørgrav static void 252545d5ecaSDag-Erling Smørgrav monitor_permit_authentications(int permit) 253545d5ecaSDag-Erling Smørgrav { 254545d5ecaSDag-Erling Smørgrav struct mon_table *ent = mon_dispatch; 255545d5ecaSDag-Erling Smørgrav 256545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 257545d5ecaSDag-Erling Smørgrav if (ent->flags & MON_AUTH) { 258545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 259545d5ecaSDag-Erling Smørgrav ent->flags |= permit ? MON_PERMIT : 0; 260545d5ecaSDag-Erling Smørgrav } 261545d5ecaSDag-Erling Smørgrav ent++; 262545d5ecaSDag-Erling Smørgrav } 263545d5ecaSDag-Erling Smørgrav } 264545d5ecaSDag-Erling Smørgrav 2651ec0d754SDag-Erling Smørgrav void 2661ec0d754SDag-Erling Smørgrav monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 267545d5ecaSDag-Erling Smørgrav { 268d93a896eSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 269545d5ecaSDag-Erling Smørgrav struct mon_table *ent; 2706888a9beSDag-Erling Smørgrav int authenticated = 0, partial = 0; 271545d5ecaSDag-Erling Smørgrav 272545d5ecaSDag-Erling Smørgrav debug3("preauth child monitor started"); 273545d5ecaSDag-Erling Smørgrav 27447dd1d1bSDag-Erling Smørgrav if (pmonitor->m_recvfd >= 0) 275e146993eSDag-Erling Smørgrav close(pmonitor->m_recvfd); 27647dd1d1bSDag-Erling Smørgrav if (pmonitor->m_log_sendfd >= 0) 277e146993eSDag-Erling Smørgrav close(pmonitor->m_log_sendfd); 278e146993eSDag-Erling Smørgrav pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; 279e146993eSDag-Erling Smørgrav 2801ec0d754SDag-Erling Smørgrav authctxt = _authctxt; 2811ec0d754SDag-Erling Smørgrav memset(authctxt, 0, sizeof(*authctxt)); 28247dd1d1bSDag-Erling Smørgrav ssh->authctxt = authctxt; 2831ec0d754SDag-Erling Smørgrav 284*190cef3dSDag-Erling Smørgrav authctxt->loginmsg = loginmsg; 285aa49c926SDag-Erling Smørgrav 286545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_proto20; 287545d5ecaSDag-Erling Smørgrav /* Permit requests for moduli and signatures */ 288545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 289545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 290545d5ecaSDag-Erling Smørgrav 291545d5ecaSDag-Erling Smørgrav /* The first few requests do not require asynchronous access */ 292545d5ecaSDag-Erling Smørgrav while (!authenticated) { 2936888a9beSDag-Erling Smørgrav partial = 0; 294333ee039SDag-Erling Smørgrav auth_method = "unknown"; 2956888a9beSDag-Erling Smørgrav auth_submethod = NULL; 2964f52dfbbSDag-Erling Smørgrav auth2_authctxt_reset_info(authctxt); 2974f52dfbbSDag-Erling Smørgrav 29862efe23aSDag-Erling Smørgrav authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); 2996888a9beSDag-Erling Smørgrav 3006888a9beSDag-Erling Smørgrav /* Special handling for multiple required authentications */ 3016888a9beSDag-Erling Smørgrav if (options.num_auth_methods != 0) { 3026888a9beSDag-Erling Smørgrav if (authenticated && 3036888a9beSDag-Erling Smørgrav !auth2_update_methods_lists(authctxt, 304e4a9863fSDag-Erling Smørgrav auth_method, auth_submethod)) { 3056888a9beSDag-Erling Smørgrav debug3("%s: method %s: partial", __func__, 3066888a9beSDag-Erling Smørgrav auth_method); 3076888a9beSDag-Erling Smørgrav authenticated = 0; 3086888a9beSDag-Erling Smørgrav partial = 1; 3096888a9beSDag-Erling Smørgrav } 3106888a9beSDag-Erling Smørgrav } 3116888a9beSDag-Erling Smørgrav 312545d5ecaSDag-Erling Smørgrav if (authenticated) { 313545d5ecaSDag-Erling Smørgrav if (!(ent->flags & MON_AUTHDECIDE)) 314545d5ecaSDag-Erling Smørgrav fatal("%s: unexpected authentication from %d", 315545d5ecaSDag-Erling Smørgrav __func__, ent->type); 316545d5ecaSDag-Erling Smørgrav if (authctxt->pw->pw_uid == 0 && 31747dd1d1bSDag-Erling Smørgrav !auth_root_allowed(ssh, auth_method)) 318545d5ecaSDag-Erling Smørgrav authenticated = 0; 319cf2b5f3bSDag-Erling Smørgrav #ifdef USE_PAM 320cf2b5f3bSDag-Erling Smørgrav /* PAM needs to perform account checks after auth */ 3211ec0d754SDag-Erling Smørgrav if (options.use_pam && authenticated) { 322*190cef3dSDag-Erling Smørgrav struct sshbuf *m; 323cf2b5f3bSDag-Erling Smørgrav 324*190cef3dSDag-Erling Smørgrav if ((m = sshbuf_new()) == NULL) 325*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new failed", 326*190cef3dSDag-Erling Smørgrav __func__); 327cf2b5f3bSDag-Erling Smørgrav mm_request_receive_expect(pmonitor->m_sendfd, 328*190cef3dSDag-Erling Smørgrav MONITOR_REQ_PAM_ACCOUNT, m); 329*190cef3dSDag-Erling Smørgrav authenticated = mm_answer_pam_account( 330*190cef3dSDag-Erling Smørgrav pmonitor->m_sendfd, m); 331*190cef3dSDag-Erling Smørgrav sshbuf_free(m); 332cf2b5f3bSDag-Erling Smørgrav } 333cf2b5f3bSDag-Erling Smørgrav #endif 334545d5ecaSDag-Erling Smørgrav } 335333ee039SDag-Erling Smørgrav if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { 3366888a9beSDag-Erling Smørgrav auth_log(authctxt, authenticated, partial, 337e4a9863fSDag-Erling Smørgrav auth_method, auth_submethod); 338557f75e5SDag-Erling Smørgrav if (!partial && !authenticated) 339545d5ecaSDag-Erling Smørgrav authctxt->failures++; 3404f52dfbbSDag-Erling Smørgrav if (authenticated || partial) { 3414f52dfbbSDag-Erling Smørgrav auth2_update_session_info(authctxt, 3424f52dfbbSDag-Erling Smørgrav auth_method, auth_submethod); 3434f52dfbbSDag-Erling Smørgrav } 344545d5ecaSDag-Erling Smørgrav } 345545d5ecaSDag-Erling Smørgrav } 346545d5ecaSDag-Erling Smørgrav 347545d5ecaSDag-Erling Smørgrav if (!authctxt->valid) 348545d5ecaSDag-Erling Smørgrav fatal("%s: authenticated invalid user", __func__); 349333ee039SDag-Erling Smørgrav if (strcmp(auth_method, "unknown") == 0) 350333ee039SDag-Erling Smørgrav fatal("%s: authentication method name unknown", __func__); 351545d5ecaSDag-Erling Smørgrav 352545d5ecaSDag-Erling Smørgrav debug("%s: %s has been authenticated by privileged process", 353545d5ecaSDag-Erling Smørgrav __func__, authctxt->user); 35447dd1d1bSDag-Erling Smørgrav ssh->authctxt = NULL; 355d93a896eSDag-Erling Smørgrav ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); 356545d5ecaSDag-Erling Smørgrav 357545d5ecaSDag-Erling Smørgrav mm_get_keystate(pmonitor); 358e146993eSDag-Erling Smørgrav 3596888a9beSDag-Erling Smørgrav /* Drain any buffered messages from the child */ 3606888a9beSDag-Erling Smørgrav while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) 3616888a9beSDag-Erling Smørgrav ; 3626888a9beSDag-Erling Smørgrav 36347dd1d1bSDag-Erling Smørgrav if (pmonitor->m_recvfd >= 0) 36447dd1d1bSDag-Erling Smørgrav close(pmonitor->m_recvfd); 36547dd1d1bSDag-Erling Smørgrav if (pmonitor->m_log_sendfd >= 0) 36647dd1d1bSDag-Erling Smørgrav close(pmonitor->m_log_sendfd); 367e146993eSDag-Erling Smørgrav pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 368545d5ecaSDag-Erling Smørgrav } 369545d5ecaSDag-Erling Smørgrav 370cf2b5f3bSDag-Erling Smørgrav static void 371cf2b5f3bSDag-Erling Smørgrav monitor_set_child_handler(pid_t pid) 372cf2b5f3bSDag-Erling Smørgrav { 373cf2b5f3bSDag-Erling Smørgrav monitor_child_pid = pid; 374cf2b5f3bSDag-Erling Smørgrav } 375cf2b5f3bSDag-Erling Smørgrav 376cf2b5f3bSDag-Erling Smørgrav static void 37721e764dfSDag-Erling Smørgrav monitor_child_handler(int sig) 378cf2b5f3bSDag-Erling Smørgrav { 37921e764dfSDag-Erling Smørgrav kill(monitor_child_pid, sig); 380cf2b5f3bSDag-Erling Smørgrav } 381cf2b5f3bSDag-Erling Smørgrav 382545d5ecaSDag-Erling Smørgrav void 383545d5ecaSDag-Erling Smørgrav monitor_child_postauth(struct monitor *pmonitor) 384545d5ecaSDag-Erling Smørgrav { 385e146993eSDag-Erling Smørgrav close(pmonitor->m_recvfd); 386e146993eSDag-Erling Smørgrav pmonitor->m_recvfd = -1; 387e146993eSDag-Erling Smørgrav 388cf2b5f3bSDag-Erling Smørgrav monitor_set_child_handler(pmonitor->m_pid); 389cf2b5f3bSDag-Erling Smørgrav signal(SIGHUP, &monitor_child_handler); 390cf2b5f3bSDag-Erling Smørgrav signal(SIGTERM, &monitor_child_handler); 391d4af9e69SDag-Erling Smørgrav signal(SIGINT, &monitor_child_handler); 392a0ee8cc6SDag-Erling Smørgrav #ifdef SIGXFSZ 393a0ee8cc6SDag-Erling Smørgrav signal(SIGXFSZ, SIG_IGN); 394a0ee8cc6SDag-Erling Smørgrav #endif 395cf2b5f3bSDag-Erling Smørgrav 396545d5ecaSDag-Erling Smørgrav mon_dispatch = mon_dispatch_postauth20; 397545d5ecaSDag-Erling Smørgrav 398545d5ecaSDag-Erling Smørgrav /* Permit requests for moduli and signatures */ 399545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 400545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 401545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 402ca86bcf2SDag-Erling Smørgrav 40347dd1d1bSDag-Erling Smørgrav if (auth_opts->permit_pty_flag) { 404545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 405545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 406545d5ecaSDag-Erling Smørgrav } 407545d5ecaSDag-Erling Smørgrav 408545d5ecaSDag-Erling Smørgrav for (;;) 409545d5ecaSDag-Erling Smørgrav monitor_read(pmonitor, mon_dispatch, NULL); 410545d5ecaSDag-Erling Smørgrav } 411545d5ecaSDag-Erling Smørgrav 412e146993eSDag-Erling Smørgrav static int 413e146993eSDag-Erling Smørgrav monitor_read_log(struct monitor *pmonitor) 414e146993eSDag-Erling Smørgrav { 415*190cef3dSDag-Erling Smørgrav struct sshbuf *logmsg; 416e146993eSDag-Erling Smørgrav u_int len, level; 417e146993eSDag-Erling Smørgrav char *msg; 418*190cef3dSDag-Erling Smørgrav u_char *p; 419*190cef3dSDag-Erling Smørgrav int r; 420e146993eSDag-Erling Smørgrav 421*190cef3dSDag-Erling Smørgrav if ((logmsg = sshbuf_new()) == NULL) 422*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 423e146993eSDag-Erling Smørgrav 424e146993eSDag-Erling Smørgrav /* Read length */ 425*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0) 426*190cef3dSDag-Erling Smørgrav fatal("%s: reserve: %s", __func__, ssh_err(r)); 427*190cef3dSDag-Erling Smørgrav if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) { 428e146993eSDag-Erling Smørgrav if (errno == EPIPE) { 429*190cef3dSDag-Erling Smørgrav sshbuf_free(logmsg); 430e146993eSDag-Erling Smørgrav debug("%s: child log fd closed", __func__); 431e146993eSDag-Erling Smørgrav close(pmonitor->m_log_recvfd); 432e146993eSDag-Erling Smørgrav pmonitor->m_log_recvfd = -1; 433e146993eSDag-Erling Smørgrav return -1; 434e146993eSDag-Erling Smørgrav } 435e146993eSDag-Erling Smørgrav fatal("%s: log fd read: %s", __func__, strerror(errno)); 436e146993eSDag-Erling Smørgrav } 437*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(logmsg, &len)) != 0) 438*190cef3dSDag-Erling Smørgrav fatal("%s: get len: %s", __func__, ssh_err(r)); 439e146993eSDag-Erling Smørgrav if (len <= 4 || len > 8192) 440e146993eSDag-Erling Smørgrav fatal("%s: invalid log message length %u", __func__, len); 441e146993eSDag-Erling Smørgrav 442e146993eSDag-Erling Smørgrav /* Read severity, message */ 443*190cef3dSDag-Erling Smørgrav sshbuf_reset(logmsg); 444*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_reserve(logmsg, len, &p)) != 0) 445*190cef3dSDag-Erling Smørgrav fatal("%s: reserve: %s", __func__, ssh_err(r)); 446*190cef3dSDag-Erling Smørgrav if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len) 447e146993eSDag-Erling Smørgrav fatal("%s: log fd read: %s", __func__, strerror(errno)); 448*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(logmsg, &level)) != 0 || 449*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) 450*190cef3dSDag-Erling Smørgrav fatal("%s: decode: %s", __func__, ssh_err(r)); 451e146993eSDag-Erling Smørgrav 452e146993eSDag-Erling Smørgrav /* Log it */ 453e146993eSDag-Erling Smørgrav if (log_level_name(level) == NULL) 454e146993eSDag-Erling Smørgrav fatal("%s: invalid log level %u (corrupted message?)", 455e146993eSDag-Erling Smørgrav __func__, level); 456e146993eSDag-Erling Smørgrav do_log2(level, "%s [preauth]", msg); 457e146993eSDag-Erling Smørgrav 458*190cef3dSDag-Erling Smørgrav sshbuf_free(logmsg); 459e4a9863fSDag-Erling Smørgrav free(msg); 460e146993eSDag-Erling Smørgrav 461e146993eSDag-Erling Smørgrav return 0; 462e146993eSDag-Erling Smørgrav } 463e146993eSDag-Erling Smørgrav 464545d5ecaSDag-Erling Smørgrav int 465545d5ecaSDag-Erling Smørgrav monitor_read(struct monitor *pmonitor, struct mon_table *ent, 466545d5ecaSDag-Erling Smørgrav struct mon_table **pent) 467545d5ecaSDag-Erling Smørgrav { 468*190cef3dSDag-Erling Smørgrav struct sshbuf *m; 469*190cef3dSDag-Erling Smørgrav int r, ret; 470545d5ecaSDag-Erling Smørgrav u_char type; 471e146993eSDag-Erling Smørgrav struct pollfd pfd[2]; 472e146993eSDag-Erling Smørgrav 473e146993eSDag-Erling Smørgrav for (;;) { 474b83788ffSDag-Erling Smørgrav memset(&pfd, 0, sizeof(pfd)); 475e146993eSDag-Erling Smørgrav pfd[0].fd = pmonitor->m_sendfd; 476e146993eSDag-Erling Smørgrav pfd[0].events = POLLIN; 477e146993eSDag-Erling Smørgrav pfd[1].fd = pmonitor->m_log_recvfd; 478e146993eSDag-Erling Smørgrav pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; 479e146993eSDag-Erling Smørgrav if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { 480e146993eSDag-Erling Smørgrav if (errno == EINTR || errno == EAGAIN) 481e146993eSDag-Erling Smørgrav continue; 482e146993eSDag-Erling Smørgrav fatal("%s: poll: %s", __func__, strerror(errno)); 483e146993eSDag-Erling Smørgrav } 484e146993eSDag-Erling Smørgrav if (pfd[1].revents) { 485e146993eSDag-Erling Smørgrav /* 486e146993eSDag-Erling Smørgrav * Drain all log messages before processing next 487e146993eSDag-Erling Smørgrav * monitor request. 488e146993eSDag-Erling Smørgrav */ 489e146993eSDag-Erling Smørgrav monitor_read_log(pmonitor); 490e146993eSDag-Erling Smørgrav continue; 491e146993eSDag-Erling Smørgrav } 492e146993eSDag-Erling Smørgrav if (pfd[0].revents) 493e146993eSDag-Erling Smørgrav break; /* Continues below */ 494e146993eSDag-Erling Smørgrav } 495545d5ecaSDag-Erling Smørgrav 496*190cef3dSDag-Erling Smørgrav if ((m = sshbuf_new()) == NULL) 497*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 498545d5ecaSDag-Erling Smørgrav 499*190cef3dSDag-Erling Smørgrav mm_request_receive(pmonitor->m_sendfd, m); 500*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(m, &type)) != 0) 501*190cef3dSDag-Erling Smørgrav fatal("%s: decode: %s", __func__, ssh_err(r)); 502545d5ecaSDag-Erling Smørgrav 503545d5ecaSDag-Erling Smørgrav debug3("%s: checking request %d", __func__, type); 504545d5ecaSDag-Erling Smørgrav 505545d5ecaSDag-Erling Smørgrav while (ent->f != NULL) { 506545d5ecaSDag-Erling Smørgrav if (ent->type == type) 507545d5ecaSDag-Erling Smørgrav break; 508545d5ecaSDag-Erling Smørgrav ent++; 509545d5ecaSDag-Erling Smørgrav } 510545d5ecaSDag-Erling Smørgrav 511545d5ecaSDag-Erling Smørgrav if (ent->f != NULL) { 512545d5ecaSDag-Erling Smørgrav if (!(ent->flags & MON_PERMIT)) 513545d5ecaSDag-Erling Smørgrav fatal("%s: unpermitted request %d", __func__, 514545d5ecaSDag-Erling Smørgrav type); 515*190cef3dSDag-Erling Smørgrav ret = (*ent->f)(pmonitor->m_sendfd, m); 516*190cef3dSDag-Erling Smørgrav sshbuf_free(m); 517545d5ecaSDag-Erling Smørgrav 518545d5ecaSDag-Erling Smørgrav /* The child may use this request only once, disable it */ 519545d5ecaSDag-Erling Smørgrav if (ent->flags & MON_ONCE) { 520545d5ecaSDag-Erling Smørgrav debug2("%s: %d used once, disabling now", __func__, 521545d5ecaSDag-Erling Smørgrav type); 522545d5ecaSDag-Erling Smørgrav ent->flags &= ~MON_PERMIT; 523545d5ecaSDag-Erling Smørgrav } 524545d5ecaSDag-Erling Smørgrav 525545d5ecaSDag-Erling Smørgrav if (pent != NULL) 526545d5ecaSDag-Erling Smørgrav *pent = ent; 527545d5ecaSDag-Erling Smørgrav 528545d5ecaSDag-Erling Smørgrav return ret; 529545d5ecaSDag-Erling Smørgrav } 530545d5ecaSDag-Erling Smørgrav 531545d5ecaSDag-Erling Smørgrav fatal("%s: unsupported request: %d", __func__, type); 532545d5ecaSDag-Erling Smørgrav 533545d5ecaSDag-Erling Smørgrav /* NOTREACHED */ 534545d5ecaSDag-Erling Smørgrav return (-1); 535545d5ecaSDag-Erling Smørgrav } 536545d5ecaSDag-Erling Smørgrav 537545d5ecaSDag-Erling Smørgrav /* allowed key state */ 538545d5ecaSDag-Erling Smørgrav static int 539545d5ecaSDag-Erling Smørgrav monitor_allowed_key(u_char *blob, u_int bloblen) 540545d5ecaSDag-Erling Smørgrav { 541545d5ecaSDag-Erling Smørgrav /* make sure key is allowed */ 542545d5ecaSDag-Erling Smørgrav if (key_blob == NULL || key_bloblen != bloblen || 543e2f6069cSDag-Erling Smørgrav timingsafe_bcmp(key_blob, blob, key_bloblen)) 544545d5ecaSDag-Erling Smørgrav return (0); 545545d5ecaSDag-Erling Smørgrav return (1); 546545d5ecaSDag-Erling Smørgrav } 547545d5ecaSDag-Erling Smørgrav 548545d5ecaSDag-Erling Smørgrav static void 549545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(void) 550545d5ecaSDag-Erling Smørgrav { 551545d5ecaSDag-Erling Smørgrav /* reset state */ 552e4a9863fSDag-Erling Smørgrav free(key_blob); 553e4a9863fSDag-Erling Smørgrav free(hostbased_cuser); 554e4a9863fSDag-Erling Smørgrav free(hostbased_chost); 55547dd1d1bSDag-Erling Smørgrav sshauthopt_free(key_opts); 556545d5ecaSDag-Erling Smørgrav key_blob = NULL; 557545d5ecaSDag-Erling Smørgrav key_bloblen = 0; 558545d5ecaSDag-Erling Smørgrav key_blobtype = MM_NOKEY; 55947dd1d1bSDag-Erling Smørgrav key_opts = NULL; 560545d5ecaSDag-Erling Smørgrav hostbased_cuser = NULL; 561545d5ecaSDag-Erling Smørgrav hostbased_chost = NULL; 562545d5ecaSDag-Erling Smørgrav } 563545d5ecaSDag-Erling Smørgrav 564a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 565545d5ecaSDag-Erling Smørgrav int 566*190cef3dSDag-Erling Smørgrav mm_answer_moduli(int sock, struct sshbuf *m) 567545d5ecaSDag-Erling Smørgrav { 568545d5ecaSDag-Erling Smørgrav DH *dh; 569*190cef3dSDag-Erling Smørgrav int r; 570*190cef3dSDag-Erling Smørgrav u_int min, want, max; 571545d5ecaSDag-Erling Smørgrav 572*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &min)) != 0 || 573*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_u32(m, &want)) != 0 || 574*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_u32(m, &max)) != 0) 575*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 576545d5ecaSDag-Erling Smørgrav 577545d5ecaSDag-Erling Smørgrav debug3("%s: got parameters: %d %d %d", 578545d5ecaSDag-Erling Smørgrav __func__, min, want, max); 579545d5ecaSDag-Erling Smørgrav /* We need to check here, too, in case the child got corrupted */ 580545d5ecaSDag-Erling Smørgrav if (max < min || want < min || max < want) 581545d5ecaSDag-Erling Smørgrav fatal("%s: bad parameters: %d %d %d", 582545d5ecaSDag-Erling Smørgrav __func__, min, want, max); 583545d5ecaSDag-Erling Smørgrav 584*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 585545d5ecaSDag-Erling Smørgrav 586545d5ecaSDag-Erling Smørgrav dh = choose_dh(min, want, max); 587545d5ecaSDag-Erling Smørgrav if (dh == NULL) { 588*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(m, 0)) != 0) 589*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 590545d5ecaSDag-Erling Smørgrav return (0); 591545d5ecaSDag-Erling Smørgrav } else { 592545d5ecaSDag-Erling Smørgrav /* Send first bignum */ 593*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(m, 1)) != 0 || 594*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_bignum2(m, dh->p)) != 0 || 595*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_bignum2(m, dh->g)) != 0) 596*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 597545d5ecaSDag-Erling Smørgrav 598545d5ecaSDag-Erling Smørgrav DH_free(dh); 599545d5ecaSDag-Erling Smørgrav } 60021e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_MODULI, m); 601545d5ecaSDag-Erling Smørgrav return (0); 602545d5ecaSDag-Erling Smørgrav } 603a0ee8cc6SDag-Erling Smørgrav #endif 604545d5ecaSDag-Erling Smørgrav 605545d5ecaSDag-Erling Smørgrav int 606*190cef3dSDag-Erling Smørgrav mm_answer_sign(int sock, struct sshbuf *m) 607545d5ecaSDag-Erling Smørgrav { 608bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 609bc5531deSDag-Erling Smørgrav extern int auth_sock; /* XXX move to state struct? */ 610bc5531deSDag-Erling Smørgrav struct sshkey *key; 611acc1a9efSDag-Erling Smørgrav struct sshbuf *sigbuf = NULL; 612acc1a9efSDag-Erling Smørgrav u_char *p = NULL, *signature = NULL; 613acc1a9efSDag-Erling Smørgrav char *alg = NULL; 614acc1a9efSDag-Erling Smørgrav size_t datlen, siglen, alglen; 615076ad2f8SDag-Erling Smørgrav int r, is_proof = 0; 616*190cef3dSDag-Erling Smørgrav u_int keyid, compat; 617bc5531deSDag-Erling Smørgrav const char proof_req[] = "hostkeys-prove-00@openssh.com"; 618545d5ecaSDag-Erling Smørgrav 619545d5ecaSDag-Erling Smørgrav debug3("%s", __func__); 620545d5ecaSDag-Erling Smørgrav 621bc5531deSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 622acc1a9efSDag-Erling Smørgrav (r = sshbuf_get_string(m, &p, &datlen)) != 0 || 623*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 || 624*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_u32(m, &compat)) != 0) 625bc5531deSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 626076ad2f8SDag-Erling Smørgrav if (keyid > INT_MAX) 627076ad2f8SDag-Erling Smørgrav fatal("%s: invalid key ID", __func__); 628545d5ecaSDag-Erling Smørgrav 629333ee039SDag-Erling Smørgrav /* 6304a421b63SDag-Erling Smørgrav * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), 6314a421b63SDag-Erling Smørgrav * SHA384 (48 bytes) and SHA512 (64 bytes). 632bc5531deSDag-Erling Smørgrav * 633bc5531deSDag-Erling Smørgrav * Otherwise, verify the signature request is for a hostkey 634bc5531deSDag-Erling Smørgrav * proof. 635bc5531deSDag-Erling Smørgrav * 636bc5531deSDag-Erling Smørgrav * XXX perform similar check for KEX signature requests too? 637bc5531deSDag-Erling Smørgrav * it's not trivial, since what is signed is the hash, rather 638bc5531deSDag-Erling Smørgrav * than the full kex structure... 639333ee039SDag-Erling Smørgrav */ 640bc5531deSDag-Erling Smørgrav if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { 641bc5531deSDag-Erling Smørgrav /* 642bc5531deSDag-Erling Smørgrav * Construct expected hostkey proof and compare it to what 643bc5531deSDag-Erling Smørgrav * the client sent us. 644bc5531deSDag-Erling Smørgrav */ 645bc5531deSDag-Erling Smørgrav if (session_id2_len == 0) /* hostkeys is never first */ 646bc5531deSDag-Erling Smørgrav fatal("%s: bad data length: %zu", __func__, datlen); 647bc5531deSDag-Erling Smørgrav if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) 648bc5531deSDag-Erling Smørgrav fatal("%s: no hostkey for index %d", __func__, keyid); 649bc5531deSDag-Erling Smørgrav if ((sigbuf = sshbuf_new()) == NULL) 650bc5531deSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 651bc5531deSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || 652bc5531deSDag-Erling Smørgrav (r = sshbuf_put_string(sigbuf, session_id2, 653acc1a9efSDag-Erling Smørgrav session_id2_len)) != 0 || 654bc5531deSDag-Erling Smørgrav (r = sshkey_puts(key, sigbuf)) != 0) 655bc5531deSDag-Erling Smørgrav fatal("%s: couldn't prepare private key " 656bc5531deSDag-Erling Smørgrav "proof buffer: %s", __func__, ssh_err(r)); 657bc5531deSDag-Erling Smørgrav if (datlen != sshbuf_len(sigbuf) || 658bc5531deSDag-Erling Smørgrav memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) 659bc5531deSDag-Erling Smørgrav fatal("%s: bad data length: %zu, hostkey proof len %zu", 660bc5531deSDag-Erling Smørgrav __func__, datlen, sshbuf_len(sigbuf)); 661bc5531deSDag-Erling Smørgrav sshbuf_free(sigbuf); 662bc5531deSDag-Erling Smørgrav is_proof = 1; 663bc5531deSDag-Erling Smørgrav } 664545d5ecaSDag-Erling Smørgrav 665545d5ecaSDag-Erling Smørgrav /* save session id, it will be passed on the first call */ 666545d5ecaSDag-Erling Smørgrav if (session_id2_len == 0) { 667545d5ecaSDag-Erling Smørgrav session_id2_len = datlen; 668545d5ecaSDag-Erling Smørgrav session_id2 = xmalloc(session_id2_len); 669545d5ecaSDag-Erling Smørgrav memcpy(session_id2, p, session_id2_len); 670545d5ecaSDag-Erling Smørgrav } 671545d5ecaSDag-Erling Smørgrav 672e4a9863fSDag-Erling Smørgrav if ((key = get_hostkey_by_index(keyid)) != NULL) { 673acc1a9efSDag-Erling Smørgrav if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, 674*190cef3dSDag-Erling Smørgrav compat)) != 0) 675bc5531deSDag-Erling Smørgrav fatal("%s: sshkey_sign failed: %s", 676bc5531deSDag-Erling Smørgrav __func__, ssh_err(r)); 677bc5531deSDag-Erling Smørgrav } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 678bc5531deSDag-Erling Smørgrav auth_sock > 0) { 679bc5531deSDag-Erling Smørgrav if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 680*190cef3dSDag-Erling Smørgrav p, datlen, alg, compat)) != 0) { 681bc5531deSDag-Erling Smørgrav fatal("%s: ssh_agent_sign failed: %s", 682bc5531deSDag-Erling Smørgrav __func__, ssh_err(r)); 683bc5531deSDag-Erling Smørgrav } 684e4a9863fSDag-Erling Smørgrav } else 685e4a9863fSDag-Erling Smørgrav fatal("%s: no hostkey from index %d", __func__, keyid); 686545d5ecaSDag-Erling Smørgrav 687bc5531deSDag-Erling Smørgrav debug3("%s: %s signature %p(%zu)", __func__, 688bc5531deSDag-Erling Smørgrav is_proof ? "KEX" : "hostkey proof", signature, siglen); 689545d5ecaSDag-Erling Smørgrav 690bc5531deSDag-Erling Smørgrav sshbuf_reset(m); 691bc5531deSDag-Erling Smørgrav if ((r = sshbuf_put_string(m, signature, siglen)) != 0) 692bc5531deSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 693545d5ecaSDag-Erling Smørgrav 694acc1a9efSDag-Erling Smørgrav free(alg); 695e4a9863fSDag-Erling Smørgrav free(p); 696e4a9863fSDag-Erling Smørgrav free(signature); 697545d5ecaSDag-Erling Smørgrav 69821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_SIGN, m); 699545d5ecaSDag-Erling Smørgrav 700545d5ecaSDag-Erling Smørgrav /* Turn on permissions for getpwnam */ 701545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 702545d5ecaSDag-Erling Smørgrav 703545d5ecaSDag-Erling Smørgrav return (0); 704545d5ecaSDag-Erling Smørgrav } 705545d5ecaSDag-Erling Smørgrav 706545d5ecaSDag-Erling Smørgrav /* Retrieves the password entry and also checks if the user is permitted */ 707545d5ecaSDag-Erling Smørgrav 708545d5ecaSDag-Erling Smørgrav int 709*190cef3dSDag-Erling Smørgrav mm_answer_pwnamallow(int sock, struct sshbuf *m) 710545d5ecaSDag-Erling Smørgrav { 711d93a896eSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 71221e764dfSDag-Erling Smørgrav char *username; 713545d5ecaSDag-Erling Smørgrav struct passwd *pwent; 714*190cef3dSDag-Erling Smørgrav int r, allowed = 0; 715e146993eSDag-Erling Smørgrav u_int i; 716545d5ecaSDag-Erling Smørgrav 717545d5ecaSDag-Erling Smørgrav debug3("%s", __func__); 718545d5ecaSDag-Erling Smørgrav 719545d5ecaSDag-Erling Smørgrav if (authctxt->attempt++ != 0) 720545d5ecaSDag-Erling Smørgrav fatal("%s: multiple attempts for getpwnam", __func__); 721545d5ecaSDag-Erling Smørgrav 722*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0) 723*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 724545d5ecaSDag-Erling Smørgrav 72521e764dfSDag-Erling Smørgrav pwent = getpwnamallow(username); 726545d5ecaSDag-Erling Smørgrav 72721e764dfSDag-Erling Smørgrav authctxt->user = xstrdup(username); 72821e764dfSDag-Erling Smørgrav setproctitle("%s [priv]", pwent ? username : "unknown"); 729e4a9863fSDag-Erling Smørgrav free(username); 730545d5ecaSDag-Erling Smørgrav 731*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 732545d5ecaSDag-Erling Smørgrav 733545d5ecaSDag-Erling Smørgrav if (pwent == NULL) { 734*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(m, 0)) != 0) 735*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 7361ec0d754SDag-Erling Smørgrav authctxt->pw = fakepw(); 737545d5ecaSDag-Erling Smørgrav goto out; 738545d5ecaSDag-Erling Smørgrav } 739545d5ecaSDag-Erling Smørgrav 740545d5ecaSDag-Erling Smørgrav allowed = 1; 741545d5ecaSDag-Erling Smørgrav authctxt->pw = pwent; 742545d5ecaSDag-Erling Smørgrav authctxt->valid = 1; 743545d5ecaSDag-Erling Smørgrav 744*190cef3dSDag-Erling Smørgrav /* XXX don't sent pwent to unpriv; send fake class/dir/shell too */ 745*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(m, 1)) != 0 || 746*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 || 747*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 || 748*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, "*")) != 0 || 749e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 750*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 || 751e4a9863fSDag-Erling Smørgrav #endif 752e4a9863fSDag-Erling Smørgrav #ifdef HAVE_STRUCT_PASSWD_PW_CLASS 753*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 || 754989dd127SDag-Erling Smørgrav #endif 755*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 || 756*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0) 757*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 758545d5ecaSDag-Erling Smørgrav 759545d5ecaSDag-Erling Smørgrav out: 760d93a896eSDag-Erling Smørgrav ssh_packet_set_log_preamble(ssh, "%suser %s", 761d93a896eSDag-Erling Smørgrav authctxt->valid ? "authenticating" : "invalid ", authctxt->user); 762*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) 763*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 764e146993eSDag-Erling Smørgrav 765e146993eSDag-Erling Smørgrav #define M_CP_STROPT(x) do { \ 766*190cef3dSDag-Erling Smørgrav if (options.x != NULL) { \ 767*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(m, options.x)) != 0) \ 768*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", \ 769*190cef3dSDag-Erling Smørgrav __func__, ssh_err(r)); \ 770*190cef3dSDag-Erling Smørgrav } \ 771e146993eSDag-Erling Smørgrav } while (0) 772e146993eSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(x, nx) do { \ 773*190cef3dSDag-Erling Smørgrav for (i = 0; i < options.nx; i++) { \ 774*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ 775*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", \ 776*190cef3dSDag-Erling Smørgrav __func__, ssh_err(r)); \ 777*190cef3dSDag-Erling Smørgrav } \ 778e146993eSDag-Erling Smørgrav } while (0) 779e146993eSDag-Erling Smørgrav /* See comment in servconf.h */ 780e146993eSDag-Erling Smørgrav COPY_MATCH_STRING_OPTS(); 781e146993eSDag-Erling Smørgrav #undef M_CP_STROPT 782e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT 783e146993eSDag-Erling Smørgrav 7846888a9beSDag-Erling Smørgrav /* Create valid auth method lists */ 785ca86bcf2SDag-Erling Smørgrav if (auth2_setup_methods_lists(authctxt) != 0) { 7866888a9beSDag-Erling Smørgrav /* 7876888a9beSDag-Erling Smørgrav * The monitor will continue long enough to let the child 7886888a9beSDag-Erling Smørgrav * run to it's packet_disconnect(), but it must not allow any 7896888a9beSDag-Erling Smørgrav * authentication to succeed. 7906888a9beSDag-Erling Smørgrav */ 7916888a9beSDag-Erling Smørgrav debug("%s: no valid authentication method lists", __func__); 7926888a9beSDag-Erling Smørgrav } 7936888a9beSDag-Erling Smørgrav 794545d5ecaSDag-Erling Smørgrav debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); 79521e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PWNAM, m); 796545d5ecaSDag-Erling Smørgrav 797545d5ecaSDag-Erling Smørgrav /* Allow service/style information on the auth context */ 798545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 799545d5ecaSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 800ca86bcf2SDag-Erling Smørgrav 801989dd127SDag-Erling Smørgrav #ifdef USE_PAM 802cf2b5f3bSDag-Erling Smørgrav if (options.use_pam) 803989dd127SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); 804989dd127SDag-Erling Smørgrav #endif 805545d5ecaSDag-Erling Smørgrav 806545d5ecaSDag-Erling Smørgrav return (0); 807545d5ecaSDag-Erling Smørgrav } 808545d5ecaSDag-Erling Smørgrav 809*190cef3dSDag-Erling Smørgrav int mm_answer_auth2_read_banner(int sock, struct sshbuf *m) 810545d5ecaSDag-Erling Smørgrav { 811545d5ecaSDag-Erling Smørgrav char *banner; 812*190cef3dSDag-Erling Smørgrav int r; 813545d5ecaSDag-Erling Smørgrav 814*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 815545d5ecaSDag-Erling Smørgrav banner = auth2_read_banner(); 816*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) 817*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 81821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); 819e4a9863fSDag-Erling Smørgrav free(banner); 820545d5ecaSDag-Erling Smørgrav 821545d5ecaSDag-Erling Smørgrav return (0); 822545d5ecaSDag-Erling Smørgrav } 823545d5ecaSDag-Erling Smørgrav 824545d5ecaSDag-Erling Smørgrav int 825*190cef3dSDag-Erling Smørgrav mm_answer_authserv(int sock, struct sshbuf *m) 826545d5ecaSDag-Erling Smørgrav { 827*190cef3dSDag-Erling Smørgrav int r; 828*190cef3dSDag-Erling Smørgrav 829545d5ecaSDag-Erling Smørgrav monitor_permit_authentications(1); 830545d5ecaSDag-Erling Smørgrav 831*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || 832*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0) 833*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 834545d5ecaSDag-Erling Smørgrav debug3("%s: service=%s, style=%s", 835545d5ecaSDag-Erling Smørgrav __func__, authctxt->service, authctxt->style); 836545d5ecaSDag-Erling Smørgrav 837545d5ecaSDag-Erling Smørgrav if (strlen(authctxt->style) == 0) { 838e4a9863fSDag-Erling Smørgrav free(authctxt->style); 839545d5ecaSDag-Erling Smørgrav authctxt->style = NULL; 840545d5ecaSDag-Erling Smørgrav } 841545d5ecaSDag-Erling Smørgrav 842545d5ecaSDag-Erling Smørgrav return (0); 843545d5ecaSDag-Erling Smørgrav } 844545d5ecaSDag-Erling Smørgrav 845545d5ecaSDag-Erling Smørgrav int 846*190cef3dSDag-Erling Smørgrav mm_answer_authpassword(int sock, struct sshbuf *m) 847545d5ecaSDag-Erling Smørgrav { 84847dd1d1bSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 849545d5ecaSDag-Erling Smørgrav static int call_count; 850545d5ecaSDag-Erling Smørgrav char *passwd; 851*190cef3dSDag-Erling Smørgrav int r, authenticated; 852*190cef3dSDag-Erling Smørgrav size_t plen; 853545d5ecaSDag-Erling Smørgrav 854ca86bcf2SDag-Erling Smørgrav if (!options.password_authentication) 855ca86bcf2SDag-Erling Smørgrav fatal("%s: password authentication not enabled", __func__); 856*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0) 857*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 858545d5ecaSDag-Erling Smørgrav /* Only authenticate if the context is valid */ 859545d5ecaSDag-Erling Smørgrav authenticated = options.password_authentication && 86047dd1d1bSDag-Erling Smørgrav auth_password(ssh, passwd); 861*190cef3dSDag-Erling Smørgrav explicit_bzero(passwd, plen); 862e4a9863fSDag-Erling Smørgrav free(passwd); 863545d5ecaSDag-Erling Smørgrav 864*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 865*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, authenticated)) != 0) 866*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 867076ad2f8SDag-Erling Smørgrav #ifdef USE_PAM 868*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0) 869*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 870076ad2f8SDag-Erling Smørgrav #endif 871545d5ecaSDag-Erling Smørgrav 872545d5ecaSDag-Erling Smørgrav debug3("%s: sending result %d", __func__, authenticated); 87321e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); 874545d5ecaSDag-Erling Smørgrav 875545d5ecaSDag-Erling Smørgrav call_count++; 876545d5ecaSDag-Erling Smørgrav if (plen == 0 && call_count == 1) 877545d5ecaSDag-Erling Smørgrav auth_method = "none"; 878545d5ecaSDag-Erling Smørgrav else 879545d5ecaSDag-Erling Smørgrav auth_method = "password"; 880545d5ecaSDag-Erling Smørgrav 881545d5ecaSDag-Erling Smørgrav /* Causes monitor loop to terminate if authenticated */ 882545d5ecaSDag-Erling Smørgrav return (authenticated); 883545d5ecaSDag-Erling Smørgrav } 884545d5ecaSDag-Erling Smørgrav 885545d5ecaSDag-Erling Smørgrav #ifdef BSD_AUTH 886545d5ecaSDag-Erling Smørgrav int 887*190cef3dSDag-Erling Smørgrav mm_answer_bsdauthquery(int sock, struct sshbuf *m) 888545d5ecaSDag-Erling Smørgrav { 889545d5ecaSDag-Erling Smørgrav char *name, *infotxt; 890*190cef3dSDag-Erling Smørgrav u_int numprompts, *echo_on, success; 891545d5ecaSDag-Erling Smørgrav char **prompts; 892*190cef3dSDag-Erling Smørgrav int r; 893545d5ecaSDag-Erling Smørgrav 894ca86bcf2SDag-Erling Smørgrav if (!options.kbd_interactive_authentication) 895ca86bcf2SDag-Erling Smørgrav fatal("%s: kbd-int authentication not enabled", __func__); 896e73e9afaSDag-Erling Smørgrav success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 897e73e9afaSDag-Erling Smørgrav &prompts, &echo_on) < 0 ? 0 : 1; 898545d5ecaSDag-Erling Smørgrav 899*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 900*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, success)) != 0) 901*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 902*190cef3dSDag-Erling Smørgrav if (success) { 903*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(m, prompts[0])) != 0) 904*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 905*190cef3dSDag-Erling Smørgrav } 906545d5ecaSDag-Erling Smørgrav 907e73e9afaSDag-Erling Smørgrav debug3("%s: sending challenge success: %u", __func__, success); 90821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); 909545d5ecaSDag-Erling Smørgrav 910e73e9afaSDag-Erling Smørgrav if (success) { 911e4a9863fSDag-Erling Smørgrav free(name); 912e4a9863fSDag-Erling Smørgrav free(infotxt); 913e4a9863fSDag-Erling Smørgrav free(prompts); 914e4a9863fSDag-Erling Smørgrav free(echo_on); 915545d5ecaSDag-Erling Smørgrav } 916545d5ecaSDag-Erling Smørgrav 917545d5ecaSDag-Erling Smørgrav return (0); 918545d5ecaSDag-Erling Smørgrav } 919545d5ecaSDag-Erling Smørgrav 920545d5ecaSDag-Erling Smørgrav int 921*190cef3dSDag-Erling Smørgrav mm_answer_bsdauthrespond(int sock, struct sshbuf *m) 922545d5ecaSDag-Erling Smørgrav { 923545d5ecaSDag-Erling Smørgrav char *response; 924*190cef3dSDag-Erling Smørgrav int r, authok; 925545d5ecaSDag-Erling Smørgrav 926ca86bcf2SDag-Erling Smørgrav if (!options.kbd_interactive_authentication) 927ca86bcf2SDag-Erling Smørgrav fatal("%s: kbd-int authentication not enabled", __func__); 928acc1a9efSDag-Erling Smørgrav if (authctxt->as == NULL) 929545d5ecaSDag-Erling Smørgrav fatal("%s: no bsd auth session", __func__); 930545d5ecaSDag-Erling Smørgrav 931*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) 932*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 933545d5ecaSDag-Erling Smørgrav authok = options.challenge_response_authentication && 934545d5ecaSDag-Erling Smørgrav auth_userresponse(authctxt->as, response, 0); 935545d5ecaSDag-Erling Smørgrav authctxt->as = NULL; 936545d5ecaSDag-Erling Smørgrav debug3("%s: <%s> = <%d>", __func__, response, authok); 937e4a9863fSDag-Erling Smørgrav free(response); 938545d5ecaSDag-Erling Smørgrav 939*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 940*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, authok)) != 0) 941*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 942545d5ecaSDag-Erling Smørgrav 943545d5ecaSDag-Erling Smørgrav debug3("%s: sending authenticated: %d", __func__, authok); 94421e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); 945545d5ecaSDag-Erling Smørgrav 946e4a9863fSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 947e4a9863fSDag-Erling Smørgrav auth_submethod = "bsdauth"; 948545d5ecaSDag-Erling Smørgrav 949545d5ecaSDag-Erling Smørgrav return (authok != 0); 950545d5ecaSDag-Erling Smørgrav } 951545d5ecaSDag-Erling Smørgrav #endif 952545d5ecaSDag-Erling Smørgrav 953989dd127SDag-Erling Smørgrav #ifdef USE_PAM 954989dd127SDag-Erling Smørgrav int 955*190cef3dSDag-Erling Smørgrav mm_answer_pam_start(int sock, struct sshbuf *m) 956989dd127SDag-Erling Smørgrav { 957cf2b5f3bSDag-Erling Smørgrav if (!options.use_pam) 958cf2b5f3bSDag-Erling Smørgrav fatal("UsePAM not set, but ended up in %s anyway", __func__); 959cf2b5f3bSDag-Erling Smørgrav 9605962c0e9SDag-Erling Smørgrav start_pam(authctxt); 961989dd127SDag-Erling Smørgrav 962cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); 963ca86bcf2SDag-Erling Smørgrav if (options.kbd_interactive_authentication) 964ca86bcf2SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1); 965cf2b5f3bSDag-Erling Smørgrav 966989dd127SDag-Erling Smørgrav return (0); 967989dd127SDag-Erling Smørgrav } 968382d19eeSDag-Erling Smørgrav 969cf2b5f3bSDag-Erling Smørgrav int 970*190cef3dSDag-Erling Smørgrav mm_answer_pam_account(int sock, struct sshbuf *m) 971cf2b5f3bSDag-Erling Smørgrav { 972cf2b5f3bSDag-Erling Smørgrav u_int ret; 973*190cef3dSDag-Erling Smørgrav int r; 974cf2b5f3bSDag-Erling Smørgrav 975cf2b5f3bSDag-Erling Smørgrav if (!options.use_pam) 976ca86bcf2SDag-Erling Smørgrav fatal("%s: PAM not enabled", __func__); 977cf2b5f3bSDag-Erling Smørgrav 978cf2b5f3bSDag-Erling Smørgrav ret = do_pam_account(); 979cf2b5f3bSDag-Erling Smørgrav 980*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, ret)) != 0 || 981*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_stringb(m, loginmsg)) != 0) 982*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 983cf2b5f3bSDag-Erling Smørgrav 98421e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); 985cf2b5f3bSDag-Erling Smørgrav 986cf2b5f3bSDag-Erling Smørgrav return (ret); 987cf2b5f3bSDag-Erling Smørgrav } 988cf2b5f3bSDag-Erling Smørgrav 989cf2b5f3bSDag-Erling Smørgrav static void *sshpam_ctxt, *sshpam_authok; 990cf2b5f3bSDag-Erling Smørgrav extern KbdintDevice sshpam_device; 991382d19eeSDag-Erling Smørgrav 992382d19eeSDag-Erling Smørgrav int 993*190cef3dSDag-Erling Smørgrav mm_answer_pam_init_ctx(int sock, struct sshbuf *m) 994382d19eeSDag-Erling Smørgrav { 995*190cef3dSDag-Erling Smørgrav u_int ok = 0; 996*190cef3dSDag-Erling Smørgrav int r; 997*190cef3dSDag-Erling Smørgrav 998382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 999ca86bcf2SDag-Erling Smørgrav if (!options.kbd_interactive_authentication) 1000ca86bcf2SDag-Erling Smørgrav fatal("%s: kbd-int authentication not enabled", __func__); 1001ca86bcf2SDag-Erling Smørgrav if (sshpam_ctxt != NULL) 1002ca86bcf2SDag-Erling Smørgrav fatal("%s: already called", __func__); 1003cf2b5f3bSDag-Erling Smørgrav sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); 1004cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1005*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1006cf2b5f3bSDag-Erling Smørgrav if (sshpam_ctxt != NULL) { 1007382d19eeSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 1008ca86bcf2SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_QUERY, 1); 1009*190cef3dSDag-Erling Smørgrav ok = 1; 1010382d19eeSDag-Erling Smørgrav } 1011*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, ok)) != 0) 1012*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 101321e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); 1014382d19eeSDag-Erling Smørgrav return (0); 1015382d19eeSDag-Erling Smørgrav } 1016382d19eeSDag-Erling Smørgrav 1017382d19eeSDag-Erling Smørgrav int 1018*190cef3dSDag-Erling Smørgrav mm_answer_pam_query(int sock, struct sshbuf *m) 1019382d19eeSDag-Erling Smørgrav { 1020e2f6069cSDag-Erling Smørgrav char *name = NULL, *info = NULL, **prompts = NULL; 1021e2f6069cSDag-Erling Smørgrav u_int i, num = 0, *echo_on = 0; 1022*190cef3dSDag-Erling Smørgrav int r, ret; 1023382d19eeSDag-Erling Smørgrav 1024382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1025cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1026ca86bcf2SDag-Erling Smørgrav if (sshpam_ctxt == NULL) 1027ca86bcf2SDag-Erling Smørgrav fatal("%s: no context", __func__); 1028ca86bcf2SDag-Erling Smørgrav ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, 1029ca86bcf2SDag-Erling Smørgrav &num, &prompts, &echo_on); 103007fd326cSDag-Erling Smørgrav if (ret == 0 && num == 0) 1031cf2b5f3bSDag-Erling Smørgrav sshpam_authok = sshpam_ctxt; 1032382d19eeSDag-Erling Smørgrav if (num > 1 || name == NULL || info == NULL) 1033ca86bcf2SDag-Erling Smørgrav fatal("sshpam_device.query failed"); 1034ca86bcf2SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_RESPOND, 1); 1035*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1036*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, ret)) != 0 || 1037*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, name)) != 0 || 1038*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, info)) != 0 || 1039*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0 || 1040*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(m, num)) != 0) 1041*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1042e4a9863fSDag-Erling Smørgrav free(name); 1043e4a9863fSDag-Erling Smørgrav free(info); 1044382d19eeSDag-Erling Smørgrav for (i = 0; i < num; ++i) { 1045*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 || 1046*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(m, echo_on[i])) != 0) 1047*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1048e4a9863fSDag-Erling Smørgrav free(prompts[i]); 1049382d19eeSDag-Erling Smørgrav } 1050e4a9863fSDag-Erling Smørgrav free(prompts); 1051e4a9863fSDag-Erling Smørgrav free(echo_on); 10526888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 10536888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 105421e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); 1055382d19eeSDag-Erling Smørgrav return (0); 1056382d19eeSDag-Erling Smørgrav } 1057382d19eeSDag-Erling Smørgrav 1058382d19eeSDag-Erling Smørgrav int 1059*190cef3dSDag-Erling Smørgrav mm_answer_pam_respond(int sock, struct sshbuf *m) 1060382d19eeSDag-Erling Smørgrav { 1061382d19eeSDag-Erling Smørgrav char **resp; 1062d4ecd108SDag-Erling Smørgrav u_int i, num; 1063*190cef3dSDag-Erling Smørgrav int r, ret; 1064382d19eeSDag-Erling Smørgrav 1065382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1066ca86bcf2SDag-Erling Smørgrav if (sshpam_ctxt == NULL) 1067ca86bcf2SDag-Erling Smørgrav fatal("%s: no context", __func__); 1068cf2b5f3bSDag-Erling Smørgrav sshpam_authok = NULL; 1069*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &num)) != 0) 1070*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1071382d19eeSDag-Erling Smørgrav if (num > 0) { 1072333ee039SDag-Erling Smørgrav resp = xcalloc(num, sizeof(char *)); 1073*190cef3dSDag-Erling Smørgrav for (i = 0; i < num; ++i) { 1074*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &(resp[i]), NULL)) != 0) 1075*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", 1076*190cef3dSDag-Erling Smørgrav __func__, ssh_err(r)); 1077*190cef3dSDag-Erling Smørgrav } 1078cf2b5f3bSDag-Erling Smørgrav ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); 1079382d19eeSDag-Erling Smørgrav for (i = 0; i < num; ++i) 1080e4a9863fSDag-Erling Smørgrav free(resp[i]); 1081e4a9863fSDag-Erling Smørgrav free(resp); 1082382d19eeSDag-Erling Smørgrav } else { 1083cf2b5f3bSDag-Erling Smørgrav ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); 1084382d19eeSDag-Erling Smørgrav } 1085*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1086*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, ret)) != 0) 1087*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 108821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); 10896888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 10906888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 1091382d19eeSDag-Erling Smørgrav if (ret == 0) 1092cf2b5f3bSDag-Erling Smørgrav sshpam_authok = sshpam_ctxt; 1093669e440eSDag-Erling Smørgrav return (0); 1094382d19eeSDag-Erling Smørgrav } 1095382d19eeSDag-Erling Smørgrav 1096382d19eeSDag-Erling Smørgrav int 1097*190cef3dSDag-Erling Smørgrav mm_answer_pam_free_ctx(int sock, struct sshbuf *m) 1098382d19eeSDag-Erling Smørgrav { 10991e415e29SXin LI int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; 1100382d19eeSDag-Erling Smørgrav 1101382d19eeSDag-Erling Smørgrav debug3("%s", __func__); 1102ca86bcf2SDag-Erling Smørgrav if (sshpam_ctxt == NULL) 1103ca86bcf2SDag-Erling Smørgrav fatal("%s: no context", __func__); 1104cf2b5f3bSDag-Erling Smørgrav (sshpam_device.free_ctx)(sshpam_ctxt); 11051e415e29SXin LI sshpam_ctxt = sshpam_authok = NULL; 1106*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 110721e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); 1108ca86bcf2SDag-Erling Smørgrav /* Allow another attempt */ 1109ca86bcf2SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1); 11106888a9beSDag-Erling Smørgrav auth_method = "keyboard-interactive"; 11116888a9beSDag-Erling Smørgrav auth_submethod = "pam"; 11121e415e29SXin LI return r; 1113382d19eeSDag-Erling Smørgrav } 1114989dd127SDag-Erling Smørgrav #endif 1115989dd127SDag-Erling Smørgrav 1116545d5ecaSDag-Erling Smørgrav int 1117*190cef3dSDag-Erling Smørgrav mm_answer_keyallowed(int sock, struct sshbuf *m) 1118545d5ecaSDag-Erling Smørgrav { 111947dd1d1bSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1120*190cef3dSDag-Erling Smørgrav struct sshkey *key = NULL; 1121f388f5efSDag-Erling Smørgrav char *cuser, *chost; 1122*190cef3dSDag-Erling Smørgrav u_int pubkey_auth_attempt; 1123545d5ecaSDag-Erling Smørgrav enum mm_keytype type = 0; 112447dd1d1bSDag-Erling Smørgrav int r, allowed = 0; 112547dd1d1bSDag-Erling Smørgrav struct sshauthopt *opts = NULL; 1126545d5ecaSDag-Erling Smørgrav 1127545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1128*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &type)) != 0 || 1129*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || 1130*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || 1131*190cef3dSDag-Erling Smørgrav (r = sshkey_froms(m, &key)) != 0 || 1132*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0) 1133*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1134545d5ecaSDag-Erling Smørgrav 1135545d5ecaSDag-Erling Smørgrav debug3("%s: key_from_blob: %p", __func__, key); 1136545d5ecaSDag-Erling Smørgrav 11371ec0d754SDag-Erling Smørgrav if (key != NULL && authctxt->valid) { 1138bc5531deSDag-Erling Smørgrav /* These should not make it past the privsep child */ 1139*190cef3dSDag-Erling Smørgrav if (sshkey_type_plain(key->type) == KEY_RSA && 1140bc5531deSDag-Erling Smørgrav (datafellows & SSH_BUG_RSASIGMD5) != 0) 1141bc5531deSDag-Erling Smørgrav fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); 1142bc5531deSDag-Erling Smørgrav 1143545d5ecaSDag-Erling Smørgrav switch (type) { 1144545d5ecaSDag-Erling Smørgrav case MM_USERKEY: 1145333ee039SDag-Erling Smørgrav auth_method = "publickey"; 114647dd1d1bSDag-Erling Smørgrav if (!options.pubkey_authentication) 114747dd1d1bSDag-Erling Smørgrav break; 114847dd1d1bSDag-Erling Smørgrav if (auth2_key_already_used(authctxt, key)) 114947dd1d1bSDag-Erling Smørgrav break; 115047dd1d1bSDag-Erling Smørgrav if (match_pattern_list(sshkey_ssh_name(key), 115147dd1d1bSDag-Erling Smørgrav options.pubkey_key_types, 0) != 1) 115247dd1d1bSDag-Erling Smørgrav break; 115347dd1d1bSDag-Erling Smørgrav allowed = user_key_allowed(ssh, authctxt->pw, key, 115447dd1d1bSDag-Erling Smørgrav pubkey_auth_attempt, &opts); 1155545d5ecaSDag-Erling Smørgrav break; 1156545d5ecaSDag-Erling Smørgrav case MM_HOSTKEY: 115747dd1d1bSDag-Erling Smørgrav auth_method = "hostbased"; 115847dd1d1bSDag-Erling Smørgrav if (!options.hostbased_authentication) 115947dd1d1bSDag-Erling Smørgrav break; 116047dd1d1bSDag-Erling Smørgrav if (auth2_key_already_used(authctxt, key)) 116147dd1d1bSDag-Erling Smørgrav break; 116247dd1d1bSDag-Erling Smørgrav if (match_pattern_list(sshkey_ssh_name(key), 116347dd1d1bSDag-Erling Smørgrav options.hostbased_key_types, 0) != 1) 116447dd1d1bSDag-Erling Smørgrav break; 116547dd1d1bSDag-Erling Smørgrav allowed = hostbased_key_allowed(authctxt->pw, 1166545d5ecaSDag-Erling Smørgrav cuser, chost, key); 11674f52dfbbSDag-Erling Smørgrav auth2_record_info(authctxt, 1168e4a9863fSDag-Erling Smørgrav "client user \"%.100s\", client host \"%.100s\"", 1169e4a9863fSDag-Erling Smørgrav cuser, chost); 1170545d5ecaSDag-Erling Smørgrav break; 1171545d5ecaSDag-Erling Smørgrav default: 1172545d5ecaSDag-Erling Smørgrav fatal("%s: unknown key type %d", __func__, type); 1173545d5ecaSDag-Erling Smørgrav break; 1174545d5ecaSDag-Erling Smørgrav } 1175545d5ecaSDag-Erling Smørgrav } 1176076ad2f8SDag-Erling Smørgrav 117747dd1d1bSDag-Erling Smørgrav debug3("%s: %s authentication%s: %s key is %s", __func__, 117847dd1d1bSDag-Erling Smørgrav auth_method, pubkey_auth_attempt ? "" : " test", 117947dd1d1bSDag-Erling Smørgrav (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), 118047dd1d1bSDag-Erling Smørgrav allowed ? "allowed" : "not allowed"); 1181076ad2f8SDag-Erling Smørgrav 11824f52dfbbSDag-Erling Smørgrav auth2_record_key(authctxt, 0, key); 1183545d5ecaSDag-Erling Smørgrav 1184545d5ecaSDag-Erling Smørgrav /* clear temporarily storage (used by verify) */ 1185545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1186545d5ecaSDag-Erling Smørgrav 1187545d5ecaSDag-Erling Smørgrav if (allowed) { 1188545d5ecaSDag-Erling Smørgrav /* Save temporarily for comparison in verify */ 1189*190cef3dSDag-Erling Smørgrav if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0) 1190*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1191545d5ecaSDag-Erling Smørgrav key_blobtype = type; 119247dd1d1bSDag-Erling Smørgrav key_opts = opts; 1193545d5ecaSDag-Erling Smørgrav hostbased_cuser = cuser; 1194545d5ecaSDag-Erling Smørgrav hostbased_chost = chost; 1195333ee039SDag-Erling Smørgrav } else { 1196333ee039SDag-Erling Smørgrav /* Log failed attempt */ 1197e4a9863fSDag-Erling Smørgrav auth_log(authctxt, 0, 0, auth_method, NULL); 1198e4a9863fSDag-Erling Smørgrav free(cuser); 1199e4a9863fSDag-Erling Smørgrav free(chost); 1200545d5ecaSDag-Erling Smørgrav } 1201*190cef3dSDag-Erling Smørgrav sshkey_free(key); 1202545d5ecaSDag-Erling Smørgrav 1203*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1204*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, allowed)) != 0) 1205*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 120647dd1d1bSDag-Erling Smørgrav if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) 120747dd1d1bSDag-Erling Smørgrav fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r)); 120821e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); 1209545d5ecaSDag-Erling Smørgrav 121047dd1d1bSDag-Erling Smørgrav if (!allowed) 121147dd1d1bSDag-Erling Smørgrav sshauthopt_free(opts); 121247dd1d1bSDag-Erling Smørgrav 1213545d5ecaSDag-Erling Smørgrav return (0); 1214545d5ecaSDag-Erling Smørgrav } 1215545d5ecaSDag-Erling Smørgrav 1216545d5ecaSDag-Erling Smørgrav static int 1217545d5ecaSDag-Erling Smørgrav monitor_valid_userblob(u_char *data, u_int datalen) 1218545d5ecaSDag-Erling Smørgrav { 1219*190cef3dSDag-Erling Smørgrav struct sshbuf *b; 1220*190cef3dSDag-Erling Smørgrav const u_char *p; 1221076ad2f8SDag-Erling Smørgrav char *userstyle, *cp; 1222*190cef3dSDag-Erling Smørgrav size_t len; 1223*190cef3dSDag-Erling Smørgrav u_char type; 1224*190cef3dSDag-Erling Smørgrav int r, fail = 0; 1225545d5ecaSDag-Erling Smørgrav 1226*190cef3dSDag-Erling Smørgrav if ((b = sshbuf_new()) == NULL) 1227*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 1228*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(b, data, datalen)) != 0) 1229*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1230545d5ecaSDag-Erling Smørgrav 1231545d5ecaSDag-Erling Smørgrav if (datafellows & SSH_OLD_SESSIONID) { 1232*190cef3dSDag-Erling Smørgrav p = sshbuf_ptr(b); 1233*190cef3dSDag-Erling Smørgrav len = sshbuf_len(b); 1234545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1235545d5ecaSDag-Erling Smørgrav (len < session_id2_len) || 1236e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1237545d5ecaSDag-Erling Smørgrav fail++; 1238*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_consume(b, session_id2_len)) != 0) 1239*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1240545d5ecaSDag-Erling Smørgrav } else { 1241*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) 1242*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1243545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1244545d5ecaSDag-Erling Smørgrav (len != session_id2_len) || 1245e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1246545d5ecaSDag-Erling Smørgrav fail++; 1247545d5ecaSDag-Erling Smørgrav } 1248*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(b, &type)) != 0) 1249*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1250*190cef3dSDag-Erling Smørgrav if (type != SSH2_MSG_USERAUTH_REQUEST) 1251545d5ecaSDag-Erling Smørgrav fail++; 1252*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1253*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1254e4a9863fSDag-Erling Smørgrav xasprintf(&userstyle, "%s%s%s", authctxt->user, 1255e4a9863fSDag-Erling Smørgrav authctxt->style ? ":" : "", 1256e4a9863fSDag-Erling Smørgrav authctxt->style ? authctxt->style : ""); 1257076ad2f8SDag-Erling Smørgrav if (strcmp(userstyle, cp) != 0) { 1258076ad2f8SDag-Erling Smørgrav logit("wrong user name passed to monitor: " 1259076ad2f8SDag-Erling Smørgrav "expected %s != %.100s", userstyle, cp); 1260545d5ecaSDag-Erling Smørgrav fail++; 1261545d5ecaSDag-Erling Smørgrav } 1262e4a9863fSDag-Erling Smørgrav free(userstyle); 1263076ad2f8SDag-Erling Smørgrav free(cp); 1264*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_skip_string(b)) != 0 || /* service */ 1265*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1266*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1267076ad2f8SDag-Erling Smørgrav if (strcmp("publickey", cp) != 0) 1268545d5ecaSDag-Erling Smørgrav fail++; 1269076ad2f8SDag-Erling Smørgrav free(cp); 1270*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(b, &type)) != 0) 1271*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1272*190cef3dSDag-Erling Smørgrav if (type == 0) 1273545d5ecaSDag-Erling Smørgrav fail++; 1274*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ 1275*190cef3dSDag-Erling Smørgrav (r = sshbuf_skip_string(b)) != 0) /* pkblob */ 1276*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1277*190cef3dSDag-Erling Smørgrav if (sshbuf_len(b) != 0) 1278545d5ecaSDag-Erling Smørgrav fail++; 1279*190cef3dSDag-Erling Smørgrav sshbuf_free(b); 1280545d5ecaSDag-Erling Smørgrav return (fail == 0); 1281545d5ecaSDag-Erling Smørgrav } 1282545d5ecaSDag-Erling Smørgrav 1283545d5ecaSDag-Erling Smørgrav static int 1284f388f5efSDag-Erling Smørgrav monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 1285f388f5efSDag-Erling Smørgrav char *chost) 1286545d5ecaSDag-Erling Smørgrav { 1287*190cef3dSDag-Erling Smørgrav struct sshbuf *b; 1288*190cef3dSDag-Erling Smørgrav const u_char *p; 1289*190cef3dSDag-Erling Smørgrav char *cp, *userstyle; 1290*190cef3dSDag-Erling Smørgrav size_t len; 1291*190cef3dSDag-Erling Smørgrav int r, fail = 0; 1292*190cef3dSDag-Erling Smørgrav u_char type; 1293545d5ecaSDag-Erling Smørgrav 1294*190cef3dSDag-Erling Smørgrav if ((b = sshbuf_new()) == NULL) 1295*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new", __func__); 1296*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(b, data, datalen)) != 0 || 1297*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_string_direct(b, &p, &len)) != 0) 1298*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1299545d5ecaSDag-Erling Smørgrav 1300545d5ecaSDag-Erling Smørgrav if ((session_id2 == NULL) || 1301545d5ecaSDag-Erling Smørgrav (len != session_id2_len) || 1302e2f6069cSDag-Erling Smørgrav (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) 1303545d5ecaSDag-Erling Smørgrav fail++; 1304545d5ecaSDag-Erling Smørgrav 1305*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(b, &type)) != 0) 1306*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1307*190cef3dSDag-Erling Smørgrav if (type != SSH2_MSG_USERAUTH_REQUEST) 1308545d5ecaSDag-Erling Smørgrav fail++; 1309*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1310*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1311e4a9863fSDag-Erling Smørgrav xasprintf(&userstyle, "%s%s%s", authctxt->user, 1312e4a9863fSDag-Erling Smørgrav authctxt->style ? ":" : "", 1313e4a9863fSDag-Erling Smørgrav authctxt->style ? authctxt->style : ""); 1314*190cef3dSDag-Erling Smørgrav if (strcmp(userstyle, cp) != 0) { 1315*190cef3dSDag-Erling Smørgrav logit("wrong user name passed to monitor: " 1316*190cef3dSDag-Erling Smørgrav "expected %s != %.100s", userstyle, cp); 1317545d5ecaSDag-Erling Smørgrav fail++; 1318545d5ecaSDag-Erling Smørgrav } 1319e4a9863fSDag-Erling Smørgrav free(userstyle); 1320*190cef3dSDag-Erling Smørgrav free(cp); 1321*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_skip_string(b)) != 0 || /* service */ 1322*190cef3dSDag-Erling Smørgrav (r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1323*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1324*190cef3dSDag-Erling Smørgrav if (strcmp(cp, "hostbased") != 0) 1325545d5ecaSDag-Erling Smørgrav fail++; 1326*190cef3dSDag-Erling Smørgrav free(cp); 1327*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ 1328*190cef3dSDag-Erling Smørgrav (r = sshbuf_skip_string(b)) != 0) /* pkblob */ 1329*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1330545d5ecaSDag-Erling Smørgrav 1331545d5ecaSDag-Erling Smørgrav /* verify client host, strip trailing dot if necessary */ 1332*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1333*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1334*190cef3dSDag-Erling Smørgrav if (((len = strlen(cp)) > 0) && cp[len - 1] == '.') 1335*190cef3dSDag-Erling Smørgrav cp[len - 1] = '\0'; 1336*190cef3dSDag-Erling Smørgrav if (strcmp(cp, chost) != 0) 1337545d5ecaSDag-Erling Smørgrav fail++; 1338*190cef3dSDag-Erling Smørgrav free(cp); 1339545d5ecaSDag-Erling Smørgrav 1340545d5ecaSDag-Erling Smørgrav /* verify client user */ 1341*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) 1342*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1343*190cef3dSDag-Erling Smørgrav if (strcmp(cp, cuser) != 0) 1344545d5ecaSDag-Erling Smørgrav fail++; 1345*190cef3dSDag-Erling Smørgrav free(cp); 1346545d5ecaSDag-Erling Smørgrav 1347*190cef3dSDag-Erling Smørgrav if (sshbuf_len(b) != 0) 1348545d5ecaSDag-Erling Smørgrav fail++; 1349*190cef3dSDag-Erling Smørgrav sshbuf_free(b); 1350545d5ecaSDag-Erling Smørgrav return (fail == 0); 1351545d5ecaSDag-Erling Smørgrav } 1352545d5ecaSDag-Erling Smørgrav 1353545d5ecaSDag-Erling Smørgrav int 13544f52dfbbSDag-Erling Smørgrav mm_answer_keyverify(int sock, struct sshbuf *m) 1355545d5ecaSDag-Erling Smørgrav { 135647dd1d1bSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 13574f52dfbbSDag-Erling Smørgrav struct sshkey *key; 1358545d5ecaSDag-Erling Smørgrav u_char *signature, *data, *blob; 135947dd1d1bSDag-Erling Smørgrav char *sigalg; 13604f52dfbbSDag-Erling Smørgrav size_t signaturelen, datalen, bloblen; 13614f52dfbbSDag-Erling Smørgrav int r, ret, valid_data = 0, encoded_ret; 1362545d5ecaSDag-Erling Smørgrav 13634f52dfbbSDag-Erling Smørgrav if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || 13644f52dfbbSDag-Erling Smørgrav (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || 136547dd1d1bSDag-Erling Smørgrav (r = sshbuf_get_string(m, &data, &datalen)) != 0 || 136647dd1d1bSDag-Erling Smørgrav (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) 13674f52dfbbSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1368545d5ecaSDag-Erling Smørgrav 1369545d5ecaSDag-Erling Smørgrav if (hostbased_cuser == NULL || hostbased_chost == NULL || 1370545d5ecaSDag-Erling Smørgrav !monitor_allowed_key(blob, bloblen)) 1371545d5ecaSDag-Erling Smørgrav fatal("%s: bad key, not previously allowed", __func__); 1372545d5ecaSDag-Erling Smørgrav 137347dd1d1bSDag-Erling Smørgrav /* Empty signature algorithm means NULL. */ 137447dd1d1bSDag-Erling Smørgrav if (*sigalg == '\0') { 137547dd1d1bSDag-Erling Smørgrav free(sigalg); 137647dd1d1bSDag-Erling Smørgrav sigalg = NULL; 137747dd1d1bSDag-Erling Smørgrav } 137847dd1d1bSDag-Erling Smørgrav 13794f52dfbbSDag-Erling Smørgrav /* XXX use sshkey_froms here; need to change key_blob, etc. */ 13804f52dfbbSDag-Erling Smørgrav if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) 13814f52dfbbSDag-Erling Smørgrav fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); 1382545d5ecaSDag-Erling Smørgrav 1383545d5ecaSDag-Erling Smørgrav switch (key_blobtype) { 1384545d5ecaSDag-Erling Smørgrav case MM_USERKEY: 1385545d5ecaSDag-Erling Smørgrav valid_data = monitor_valid_userblob(data, datalen); 13864f52dfbbSDag-Erling Smørgrav auth_method = "publickey"; 1387545d5ecaSDag-Erling Smørgrav break; 1388545d5ecaSDag-Erling Smørgrav case MM_HOSTKEY: 1389545d5ecaSDag-Erling Smørgrav valid_data = monitor_valid_hostbasedblob(data, datalen, 1390545d5ecaSDag-Erling Smørgrav hostbased_cuser, hostbased_chost); 13914f52dfbbSDag-Erling Smørgrav auth_method = "hostbased"; 1392545d5ecaSDag-Erling Smørgrav break; 1393545d5ecaSDag-Erling Smørgrav default: 1394545d5ecaSDag-Erling Smørgrav valid_data = 0; 1395545d5ecaSDag-Erling Smørgrav break; 1396545d5ecaSDag-Erling Smørgrav } 1397545d5ecaSDag-Erling Smørgrav if (!valid_data) 1398545d5ecaSDag-Erling Smørgrav fatal("%s: bad signature data blob", __func__); 1399545d5ecaSDag-Erling Smørgrav 14004f52dfbbSDag-Erling Smørgrav ret = sshkey_verify(key, signature, signaturelen, data, datalen, 140147dd1d1bSDag-Erling Smørgrav sigalg, active_state->compat); 14024f52dfbbSDag-Erling Smørgrav debug3("%s: %s %p signature %s", __func__, auth_method, key, 14034f52dfbbSDag-Erling Smørgrav (ret == 0) ? "verified" : "unverified"); 14044f52dfbbSDag-Erling Smørgrav auth2_record_key(authctxt, ret == 0, key); 1405bc5531deSDag-Erling Smørgrav 1406e4a9863fSDag-Erling Smørgrav free(blob); 1407e4a9863fSDag-Erling Smørgrav free(signature); 1408e4a9863fSDag-Erling Smørgrav free(data); 140947dd1d1bSDag-Erling Smørgrav free(sigalg); 1410545d5ecaSDag-Erling Smørgrav 141147dd1d1bSDag-Erling Smørgrav if (key_blobtype == MM_USERKEY) 141247dd1d1bSDag-Erling Smørgrav auth_activate_options(ssh, key_opts); 1413545d5ecaSDag-Erling Smørgrav monitor_reset_key_state(); 1414545d5ecaSDag-Erling Smørgrav 14154f52dfbbSDag-Erling Smørgrav sshkey_free(key); 14164f52dfbbSDag-Erling Smørgrav sshbuf_reset(m); 14174f52dfbbSDag-Erling Smørgrav 14184f52dfbbSDag-Erling Smørgrav /* encode ret != 0 as positive integer, since we're sending u32 */ 14194f52dfbbSDag-Erling Smørgrav encoded_ret = (ret != 0); 14204f52dfbbSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) 14214f52dfbbSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 142221e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 1423545d5ecaSDag-Erling Smørgrav 14244f52dfbbSDag-Erling Smørgrav return ret == 0; 1425545d5ecaSDag-Erling Smørgrav } 1426545d5ecaSDag-Erling Smørgrav 1427545d5ecaSDag-Erling Smørgrav static void 1428545d5ecaSDag-Erling Smørgrav mm_record_login(Session *s, struct passwd *pw) 1429545d5ecaSDag-Erling Smørgrav { 1430076ad2f8SDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1431545d5ecaSDag-Erling Smørgrav socklen_t fromlen; 1432545d5ecaSDag-Erling Smørgrav struct sockaddr_storage from; 1433545d5ecaSDag-Erling Smørgrav 1434545d5ecaSDag-Erling Smørgrav /* 1435545d5ecaSDag-Erling Smørgrav * Get IP address of client. If the connection is not a socket, let 1436545d5ecaSDag-Erling Smørgrav * the address be 0.0.0.0. 1437545d5ecaSDag-Erling Smørgrav */ 1438545d5ecaSDag-Erling Smørgrav memset(&from, 0, sizeof(from)); 1439545d5ecaSDag-Erling Smørgrav fromlen = sizeof(from); 14407ac32603SHajimu UMEMOTO if (packet_connection_is_on_socket()) { 1441545d5ecaSDag-Erling Smørgrav if (getpeername(packet_get_connection_in(), 1442545d5ecaSDag-Erling Smørgrav (struct sockaddr *)&from, &fromlen) < 0) { 1443545d5ecaSDag-Erling Smørgrav debug("getpeername: %.100s", strerror(errno)); 14441ec0d754SDag-Erling Smørgrav cleanup_exit(255); 1445545d5ecaSDag-Erling Smørgrav } 1446545d5ecaSDag-Erling Smørgrav } 1447545d5ecaSDag-Erling Smørgrav /* Record that there was a login on that tty from the remote host. */ 1448545d5ecaSDag-Erling Smørgrav record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 1449076ad2f8SDag-Erling Smørgrav session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), 14507ac32603SHajimu UMEMOTO (struct sockaddr *)&from, fromlen); 1451545d5ecaSDag-Erling Smørgrav } 1452545d5ecaSDag-Erling Smørgrav 1453545d5ecaSDag-Erling Smørgrav static void 1454545d5ecaSDag-Erling Smørgrav mm_session_close(Session *s) 1455545d5ecaSDag-Erling Smørgrav { 1456cf2b5f3bSDag-Erling Smørgrav debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); 1457545d5ecaSDag-Erling Smørgrav if (s->ttyfd != -1) { 1458545d5ecaSDag-Erling Smørgrav debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); 1459545d5ecaSDag-Erling Smørgrav session_pty_cleanup2(s); 1460545d5ecaSDag-Erling Smørgrav } 1461d4af9e69SDag-Erling Smørgrav session_unused(s->self); 1462545d5ecaSDag-Erling Smørgrav } 1463545d5ecaSDag-Erling Smørgrav 1464545d5ecaSDag-Erling Smørgrav int 1465*190cef3dSDag-Erling Smørgrav mm_answer_pty(int sock, struct sshbuf *m) 1466545d5ecaSDag-Erling Smørgrav { 1467545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor; 1468545d5ecaSDag-Erling Smørgrav Session *s; 1469*190cef3dSDag-Erling Smørgrav int r, res, fd0; 1470545d5ecaSDag-Erling Smørgrav 1471545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1472545d5ecaSDag-Erling Smørgrav 1473*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1474545d5ecaSDag-Erling Smørgrav s = session_new(); 1475545d5ecaSDag-Erling Smørgrav if (s == NULL) 1476545d5ecaSDag-Erling Smørgrav goto error; 1477545d5ecaSDag-Erling Smørgrav s->authctxt = authctxt; 1478545d5ecaSDag-Erling Smørgrav s->pw = authctxt->pw; 1479545d5ecaSDag-Erling Smørgrav s->pid = pmonitor->m_pid; 1480545d5ecaSDag-Erling Smørgrav res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 1481545d5ecaSDag-Erling Smørgrav if (res == 0) 1482545d5ecaSDag-Erling Smørgrav goto error; 1483545d5ecaSDag-Erling Smørgrav pty_setowner(authctxt->pw, s->tty); 1484545d5ecaSDag-Erling Smørgrav 1485*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, 1)) != 0 || 1486*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(m, s->tty)) != 0) 1487*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1488545d5ecaSDag-Erling Smørgrav 1489545d5ecaSDag-Erling Smørgrav /* We need to trick ttyslot */ 1490545d5ecaSDag-Erling Smørgrav if (dup2(s->ttyfd, 0) == -1) 1491545d5ecaSDag-Erling Smørgrav fatal("%s: dup2", __func__); 1492545d5ecaSDag-Erling Smørgrav 1493545d5ecaSDag-Erling Smørgrav mm_record_login(s, authctxt->pw); 1494545d5ecaSDag-Erling Smørgrav 1495545d5ecaSDag-Erling Smørgrav /* Now we can close the file descriptor again */ 1496545d5ecaSDag-Erling Smørgrav close(0); 1497545d5ecaSDag-Erling Smørgrav 149821e764dfSDag-Erling Smørgrav /* send messages generated by record_login */ 1499*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) 1500*190cef3dSDag-Erling Smørgrav fatal("%s: put login message: %s", __func__, ssh_err(r)); 1501*190cef3dSDag-Erling Smørgrav sshbuf_reset(loginmsg); 150221e764dfSDag-Erling Smørgrav 150321e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PTY, m); 150421e764dfSDag-Erling Smørgrav 1505d4af9e69SDag-Erling Smørgrav if (mm_send_fd(sock, s->ptyfd) == -1 || 1506d4af9e69SDag-Erling Smørgrav mm_send_fd(sock, s->ttyfd) == -1) 1507d4af9e69SDag-Erling Smørgrav fatal("%s: send fds failed", __func__); 150821e764dfSDag-Erling Smørgrav 1509545d5ecaSDag-Erling Smørgrav /* make sure nothing uses fd 0 */ 1510545d5ecaSDag-Erling Smørgrav if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 1511545d5ecaSDag-Erling Smørgrav fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); 1512545d5ecaSDag-Erling Smørgrav if (fd0 != 0) 1513545d5ecaSDag-Erling Smørgrav error("%s: fd0 %d != 0", __func__, fd0); 1514545d5ecaSDag-Erling Smørgrav 1515545d5ecaSDag-Erling Smørgrav /* slave is not needed */ 1516545d5ecaSDag-Erling Smørgrav close(s->ttyfd); 1517545d5ecaSDag-Erling Smørgrav s->ttyfd = s->ptyfd; 1518545d5ecaSDag-Erling Smørgrav /* no need to dup() because nobody closes ptyfd */ 1519545d5ecaSDag-Erling Smørgrav s->ptymaster = s->ptyfd; 1520545d5ecaSDag-Erling Smørgrav 1521545d5ecaSDag-Erling Smørgrav debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); 1522545d5ecaSDag-Erling Smørgrav 1523545d5ecaSDag-Erling Smørgrav return (0); 1524545d5ecaSDag-Erling Smørgrav 1525545d5ecaSDag-Erling Smørgrav error: 1526545d5ecaSDag-Erling Smørgrav if (s != NULL) 1527545d5ecaSDag-Erling Smørgrav mm_session_close(s); 1528*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, 0)) != 0) 1529*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 153021e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_PTY, m); 1531545d5ecaSDag-Erling Smørgrav return (0); 1532545d5ecaSDag-Erling Smørgrav } 1533545d5ecaSDag-Erling Smørgrav 1534545d5ecaSDag-Erling Smørgrav int 1535*190cef3dSDag-Erling Smørgrav mm_answer_pty_cleanup(int sock, struct sshbuf *m) 1536545d5ecaSDag-Erling Smørgrav { 1537545d5ecaSDag-Erling Smørgrav Session *s; 1538545d5ecaSDag-Erling Smørgrav char *tty; 1539*190cef3dSDag-Erling Smørgrav int r; 1540545d5ecaSDag-Erling Smørgrav 1541545d5ecaSDag-Erling Smørgrav debug3("%s entering", __func__); 1542545d5ecaSDag-Erling Smørgrav 1543*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) 1544*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1545545d5ecaSDag-Erling Smørgrav if ((s = session_by_tty(tty)) != NULL) 1546545d5ecaSDag-Erling Smørgrav mm_session_close(s); 1547*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1548e4a9863fSDag-Erling Smørgrav free(tty); 1549545d5ecaSDag-Erling Smørgrav return (0); 1550545d5ecaSDag-Erling Smørgrav } 1551545d5ecaSDag-Erling Smørgrav 1552545d5ecaSDag-Erling Smørgrav int 1553*190cef3dSDag-Erling Smørgrav mm_answer_term(int sock, struct sshbuf *req) 1554545d5ecaSDag-Erling Smørgrav { 15554f52dfbbSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1556545d5ecaSDag-Erling Smørgrav extern struct monitor *pmonitor; 1557545d5ecaSDag-Erling Smørgrav int res, status; 1558545d5ecaSDag-Erling Smørgrav 1559545d5ecaSDag-Erling Smørgrav debug3("%s: tearing down sessions", __func__); 1560545d5ecaSDag-Erling Smørgrav 1561545d5ecaSDag-Erling Smørgrav /* The child is terminating */ 15624f52dfbbSDag-Erling Smørgrav session_destroy_all(ssh, &mm_session_close); 1563545d5ecaSDag-Erling Smørgrav 1564d4af9e69SDag-Erling Smørgrav #ifdef USE_PAM 1565d4af9e69SDag-Erling Smørgrav if (options.use_pam) 1566d4af9e69SDag-Erling Smørgrav sshpam_cleanup(); 1567d4af9e69SDag-Erling Smørgrav #endif 1568d4af9e69SDag-Erling Smørgrav 1569545d5ecaSDag-Erling Smørgrav while (waitpid(pmonitor->m_pid, &status, 0) == -1) 1570545d5ecaSDag-Erling Smørgrav if (errno != EINTR) 1571545d5ecaSDag-Erling Smørgrav exit(1); 1572545d5ecaSDag-Erling Smørgrav 1573545d5ecaSDag-Erling Smørgrav res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 1574545d5ecaSDag-Erling Smørgrav 1575545d5ecaSDag-Erling Smørgrav /* Terminate process */ 1576545d5ecaSDag-Erling Smørgrav exit(res); 1577545d5ecaSDag-Erling Smørgrav } 1578545d5ecaSDag-Erling Smørgrav 1579aa49c926SDag-Erling Smørgrav #ifdef SSH_AUDIT_EVENTS 1580aa49c926SDag-Erling Smørgrav /* Report that an audit event occurred */ 1581aa49c926SDag-Erling Smørgrav int 1582*190cef3dSDag-Erling Smørgrav mm_answer_audit_event(int socket, struct sshbuf *m) 1583aa49c926SDag-Erling Smørgrav { 1584*190cef3dSDag-Erling Smørgrav u_int n; 1585aa49c926SDag-Erling Smørgrav ssh_audit_event_t event; 1586*190cef3dSDag-Erling Smørgrav int r; 1587aa49c926SDag-Erling Smørgrav 1588aa49c926SDag-Erling Smørgrav debug3("%s entering", __func__); 1589aa49c926SDag-Erling Smørgrav 1590*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(m, &n)) != 0) 1591*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1592*190cef3dSDag-Erling Smørgrav event = (ssh_audit_event_t)n; 1593aa49c926SDag-Erling Smørgrav switch (event) { 1594aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_PUBKEY: 1595aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_HOSTBASED: 1596aa49c926SDag-Erling Smørgrav case SSH_AUTH_FAIL_GSSAPI: 1597aa49c926SDag-Erling Smørgrav case SSH_LOGIN_EXCEED_MAXTRIES: 1598aa49c926SDag-Erling Smørgrav case SSH_LOGIN_ROOT_DENIED: 1599aa49c926SDag-Erling Smørgrav case SSH_CONNECTION_CLOSE: 1600aa49c926SDag-Erling Smørgrav case SSH_INVALID_USER: 1601aa49c926SDag-Erling Smørgrav audit_event(event); 1602aa49c926SDag-Erling Smørgrav break; 1603aa49c926SDag-Erling Smørgrav default: 1604aa49c926SDag-Erling Smørgrav fatal("Audit event type %d not permitted", event); 1605aa49c926SDag-Erling Smørgrav } 1606aa49c926SDag-Erling Smørgrav 1607aa49c926SDag-Erling Smørgrav return (0); 1608aa49c926SDag-Erling Smørgrav } 1609aa49c926SDag-Erling Smørgrav 1610aa49c926SDag-Erling Smørgrav int 1611*190cef3dSDag-Erling Smørgrav mm_answer_audit_command(int socket, struct sshbuf *m) 1612aa49c926SDag-Erling Smørgrav { 1613aa49c926SDag-Erling Smørgrav char *cmd; 1614*190cef3dSDag-Erling Smørgrav int r; 1615aa49c926SDag-Erling Smørgrav 1616aa49c926SDag-Erling Smørgrav debug3("%s entering", __func__); 1617*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) 1618*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1619aa49c926SDag-Erling Smørgrav /* sanity check command, if so how? */ 1620aa49c926SDag-Erling Smørgrav audit_run_command(cmd); 1621e4a9863fSDag-Erling Smørgrav free(cmd); 1622aa49c926SDag-Erling Smørgrav return (0); 1623aa49c926SDag-Erling Smørgrav } 1624aa49c926SDag-Erling Smørgrav #endif /* SSH_AUDIT_EVENTS */ 1625aa49c926SDag-Erling Smørgrav 1626545d5ecaSDag-Erling Smørgrav void 16274f52dfbbSDag-Erling Smørgrav monitor_clear_keystate(struct monitor *pmonitor) 16284f52dfbbSDag-Erling Smørgrav { 16294f52dfbbSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 16304f52dfbbSDag-Erling Smørgrav 16314f52dfbbSDag-Erling Smørgrav ssh_clear_newkeys(ssh, MODE_IN); 16324f52dfbbSDag-Erling Smørgrav ssh_clear_newkeys(ssh, MODE_OUT); 16334f52dfbbSDag-Erling Smørgrav sshbuf_free(child_state); 16344f52dfbbSDag-Erling Smørgrav child_state = NULL; 16354f52dfbbSDag-Erling Smørgrav } 16364f52dfbbSDag-Erling Smørgrav 16374f52dfbbSDag-Erling Smørgrav void 1638545d5ecaSDag-Erling Smørgrav monitor_apply_keystate(struct monitor *pmonitor) 1639545d5ecaSDag-Erling Smørgrav { 1640bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 1641bc5531deSDag-Erling Smørgrav struct kex *kex; 1642bc5531deSDag-Erling Smørgrav int r; 1643545d5ecaSDag-Erling Smørgrav 1644bc5531deSDag-Erling Smørgrav debug3("%s: packet_set_state", __func__); 1645bc5531deSDag-Erling Smørgrav if ((r = ssh_packet_set_state(ssh, child_state)) != 0) 1646bc5531deSDag-Erling Smørgrav fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); 1647bc5531deSDag-Erling Smørgrav sshbuf_free(child_state); 1648bc5531deSDag-Erling Smørgrav child_state = NULL; 1649545d5ecaSDag-Erling Smørgrav 1650acc1a9efSDag-Erling Smørgrav if ((kex = ssh->kex) != NULL) { 1651bc5531deSDag-Erling Smørgrav /* XXX set callbacks */ 1652a0ee8cc6SDag-Erling Smørgrav #ifdef WITH_OPENSSL 1653e73e9afaSDag-Erling Smørgrav kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 165421e764dfSDag-Erling Smørgrav kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1655076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 1656076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 1657076ad2f8SDag-Erling Smørgrav kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 1658e73e9afaSDag-Erling Smørgrav kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1659333ee039SDag-Erling Smørgrav kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1660bc5531deSDag-Erling Smørgrav # ifdef OPENSSL_HAS_ECC 16614a421b63SDag-Erling Smørgrav kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1662a0ee8cc6SDag-Erling Smørgrav # endif 1663bc5531deSDag-Erling Smørgrav #endif /* WITH_OPENSSL */ 1664f7167e0eSDag-Erling Smørgrav kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1665b15c8340SDag-Erling Smørgrav kex->load_host_public_key=&get_hostkey_public_by_type; 1666b15c8340SDag-Erling Smørgrav kex->load_host_private_key=&get_hostkey_private_by_type; 1667545d5ecaSDag-Erling Smørgrav kex->host_key_index=&get_hostkey_index; 1668e4a9863fSDag-Erling Smørgrav kex->sign = sshd_hostkey_sign; 1669bc5531deSDag-Erling Smørgrav } 1670545d5ecaSDag-Erling Smørgrav } 1671545d5ecaSDag-Erling Smørgrav 1672545d5ecaSDag-Erling Smørgrav /* This function requries careful sanity checking */ 1673545d5ecaSDag-Erling Smørgrav 1674545d5ecaSDag-Erling Smørgrav void 1675545d5ecaSDag-Erling Smørgrav mm_get_keystate(struct monitor *pmonitor) 1676545d5ecaSDag-Erling Smørgrav { 1677545d5ecaSDag-Erling Smørgrav debug3("%s: Waiting for new keys", __func__); 1678545d5ecaSDag-Erling Smørgrav 1679bc5531deSDag-Erling Smørgrav if ((child_state = sshbuf_new()) == NULL) 1680bc5531deSDag-Erling Smørgrav fatal("%s: sshbuf_new failed", __func__); 1681bc5531deSDag-Erling Smørgrav mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, 1682bc5531deSDag-Erling Smørgrav child_state); 1683bc5531deSDag-Erling Smørgrav debug3("%s: GOT new keys", __func__); 1684545d5ecaSDag-Erling Smørgrav } 1685545d5ecaSDag-Erling Smørgrav 1686545d5ecaSDag-Erling Smørgrav 1687545d5ecaSDag-Erling Smørgrav /* XXX */ 1688545d5ecaSDag-Erling Smørgrav 1689545d5ecaSDag-Erling Smørgrav #define FD_CLOSEONEXEC(x) do { \ 1690e146993eSDag-Erling Smørgrav if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ 1691545d5ecaSDag-Erling Smørgrav fatal("fcntl(%d, F_SETFD)", x); \ 1692545d5ecaSDag-Erling Smørgrav } while (0) 1693545d5ecaSDag-Erling Smørgrav 1694545d5ecaSDag-Erling Smørgrav static void 1695e146993eSDag-Erling Smørgrav monitor_openfds(struct monitor *mon, int do_logfds) 1696545d5ecaSDag-Erling Smørgrav { 1697e146993eSDag-Erling Smørgrav int pair[2]; 16984f52dfbbSDag-Erling Smørgrav #ifdef SO_ZEROIZE 16994f52dfbbSDag-Erling Smørgrav int on = 1; 17004f52dfbbSDag-Erling Smørgrav #endif 1701e146993eSDag-Erling Smørgrav 1702545d5ecaSDag-Erling Smørgrav if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 1703e146993eSDag-Erling Smørgrav fatal("%s: socketpair: %s", __func__, strerror(errno)); 17044f52dfbbSDag-Erling Smørgrav #ifdef SO_ZEROIZE 17054f52dfbbSDag-Erling Smørgrav if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) 17064f52dfbbSDag-Erling Smørgrav error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); 17074f52dfbbSDag-Erling Smørgrav if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) 17084f52dfbbSDag-Erling Smørgrav error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); 17094f52dfbbSDag-Erling Smørgrav #endif 1710545d5ecaSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[0]); 1711545d5ecaSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[1]); 1712e146993eSDag-Erling Smørgrav mon->m_recvfd = pair[0]; 1713e146993eSDag-Erling Smørgrav mon->m_sendfd = pair[1]; 1714e146993eSDag-Erling Smørgrav 1715e146993eSDag-Erling Smørgrav if (do_logfds) { 1716e146993eSDag-Erling Smørgrav if (pipe(pair) == -1) 1717e146993eSDag-Erling Smørgrav fatal("%s: pipe: %s", __func__, strerror(errno)); 1718e146993eSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[0]); 1719e146993eSDag-Erling Smørgrav FD_CLOSEONEXEC(pair[1]); 1720e146993eSDag-Erling Smørgrav mon->m_log_recvfd = pair[0]; 1721e146993eSDag-Erling Smørgrav mon->m_log_sendfd = pair[1]; 1722e146993eSDag-Erling Smørgrav } else 1723e146993eSDag-Erling Smørgrav mon->m_log_recvfd = mon->m_log_sendfd = -1; 1724545d5ecaSDag-Erling Smørgrav } 1725545d5ecaSDag-Erling Smørgrav 1726545d5ecaSDag-Erling Smørgrav #define MM_MEMSIZE 65536 1727545d5ecaSDag-Erling Smørgrav 1728545d5ecaSDag-Erling Smørgrav struct monitor * 1729545d5ecaSDag-Erling Smørgrav monitor_init(void) 1730545d5ecaSDag-Erling Smørgrav { 1731545d5ecaSDag-Erling Smørgrav struct monitor *mon; 1732545d5ecaSDag-Erling Smørgrav 1733333ee039SDag-Erling Smørgrav mon = xcalloc(1, sizeof(*mon)); 1734e146993eSDag-Erling Smørgrav monitor_openfds(mon, 1); 1735545d5ecaSDag-Erling Smørgrav 1736545d5ecaSDag-Erling Smørgrav return mon; 1737545d5ecaSDag-Erling Smørgrav } 1738545d5ecaSDag-Erling Smørgrav 1739545d5ecaSDag-Erling Smørgrav void 1740545d5ecaSDag-Erling Smørgrav monitor_reinit(struct monitor *mon) 1741545d5ecaSDag-Erling Smørgrav { 1742e146993eSDag-Erling Smørgrav monitor_openfds(mon, 0); 1743545d5ecaSDag-Erling Smørgrav } 1744cf2b5f3bSDag-Erling Smørgrav 1745cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 1746cf2b5f3bSDag-Erling Smørgrav int 1747*190cef3dSDag-Erling Smørgrav mm_answer_gss_setup_ctx(int sock, struct sshbuf *m) 1748cf2b5f3bSDag-Erling Smørgrav { 174921e764dfSDag-Erling Smørgrav gss_OID_desc goid; 1750cf2b5f3bSDag-Erling Smørgrav OM_uint32 major; 1751*190cef3dSDag-Erling Smørgrav size_t len; 1752*190cef3dSDag-Erling Smørgrav u_char *p; 1753*190cef3dSDag-Erling Smørgrav int r; 1754cf2b5f3bSDag-Erling Smørgrav 1755ca86bcf2SDag-Erling Smørgrav if (!options.gss_authentication) 1756ca86bcf2SDag-Erling Smørgrav fatal("%s: GSSAPI authentication not enabled", __func__); 1757ca86bcf2SDag-Erling Smørgrav 1758*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_string(m, &p, &len)) != 0) 1759*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1760*190cef3dSDag-Erling Smørgrav goid.elements = p; 176121e764dfSDag-Erling Smørgrav goid.length = len; 1762cf2b5f3bSDag-Erling Smørgrav 176321e764dfSDag-Erling Smørgrav major = ssh_gssapi_server_ctx(&gsscontext, &goid); 1764cf2b5f3bSDag-Erling Smørgrav 1765e4a9863fSDag-Erling Smørgrav free(goid.elements); 1766cf2b5f3bSDag-Erling Smørgrav 1767*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1768*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, major)) != 0) 1769*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1770cf2b5f3bSDag-Erling Smørgrav 177121e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); 1772cf2b5f3bSDag-Erling Smørgrav 1773cf2b5f3bSDag-Erling Smørgrav /* Now we have a context, enable the step */ 1774cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); 1775cf2b5f3bSDag-Erling Smørgrav 1776cf2b5f3bSDag-Erling Smørgrav return (0); 1777cf2b5f3bSDag-Erling Smørgrav } 1778cf2b5f3bSDag-Erling Smørgrav 1779cf2b5f3bSDag-Erling Smørgrav int 1780*190cef3dSDag-Erling Smørgrav mm_answer_gss_accept_ctx(int sock, struct sshbuf *m) 1781cf2b5f3bSDag-Erling Smørgrav { 1782cf2b5f3bSDag-Erling Smørgrav gss_buffer_desc in; 1783cf2b5f3bSDag-Erling Smørgrav gss_buffer_desc out = GSS_C_EMPTY_BUFFER; 1784cf2b5f3bSDag-Erling Smørgrav OM_uint32 major, minor; 1785cf2b5f3bSDag-Erling Smørgrav OM_uint32 flags = 0; /* GSI needs this */ 1786*190cef3dSDag-Erling Smørgrav int r; 1787cf2b5f3bSDag-Erling Smørgrav 1788ca86bcf2SDag-Erling Smørgrav if (!options.gss_authentication) 1789ca86bcf2SDag-Erling Smørgrav fatal("%s: GSSAPI authentication not enabled", __func__); 1790ca86bcf2SDag-Erling Smørgrav 1791*190cef3dSDag-Erling Smørgrav if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) 1792*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1793cf2b5f3bSDag-Erling Smørgrav major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 1794e4a9863fSDag-Erling Smørgrav free(in.value); 1795cf2b5f3bSDag-Erling Smørgrav 1796*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1797*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, major)) != 0 || 1798*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_string(m, out.value, out.length)) != 0 || 1799*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(m, flags)) != 0) 1800*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 180121e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); 1802cf2b5f3bSDag-Erling Smørgrav 1803cf2b5f3bSDag-Erling Smørgrav gss_release_buffer(&minor, &out); 1804cf2b5f3bSDag-Erling Smørgrav 1805cf2b5f3bSDag-Erling Smørgrav if (major == GSS_S_COMPLETE) { 1806cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 1807cf2b5f3bSDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 18081ec0d754SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 1809cf2b5f3bSDag-Erling Smørgrav } 1810cf2b5f3bSDag-Erling Smørgrav return (0); 1811cf2b5f3bSDag-Erling Smørgrav } 1812cf2b5f3bSDag-Erling Smørgrav 1813cf2b5f3bSDag-Erling Smørgrav int 1814*190cef3dSDag-Erling Smørgrav mm_answer_gss_checkmic(int sock, struct sshbuf *m) 18151ec0d754SDag-Erling Smørgrav { 18161ec0d754SDag-Erling Smørgrav gss_buffer_desc gssbuf, mic; 18171ec0d754SDag-Erling Smørgrav OM_uint32 ret; 1818*190cef3dSDag-Erling Smørgrav int r; 18191ec0d754SDag-Erling Smørgrav 1820ca86bcf2SDag-Erling Smørgrav if (!options.gss_authentication) 1821ca86bcf2SDag-Erling Smørgrav fatal("%s: GSSAPI authentication not enabled", __func__); 1822ca86bcf2SDag-Erling Smørgrav 1823*190cef3dSDag-Erling Smørgrav if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || 1824*190cef3dSDag-Erling Smørgrav (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) 1825*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 18261ec0d754SDag-Erling Smørgrav 18271ec0d754SDag-Erling Smørgrav ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); 18281ec0d754SDag-Erling Smørgrav 1829e4a9863fSDag-Erling Smørgrav free(gssbuf.value); 1830e4a9863fSDag-Erling Smørgrav free(mic.value); 18311ec0d754SDag-Erling Smørgrav 1832*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1833*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, ret)) != 0) 1834*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 18351ec0d754SDag-Erling Smørgrav 183621e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); 18371ec0d754SDag-Erling Smørgrav 18381ec0d754SDag-Erling Smørgrav if (!GSS_ERROR(ret)) 18391ec0d754SDag-Erling Smørgrav monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 18401ec0d754SDag-Erling Smørgrav 18411ec0d754SDag-Erling Smørgrav return (0); 18421ec0d754SDag-Erling Smørgrav } 18431ec0d754SDag-Erling Smørgrav 18441ec0d754SDag-Erling Smørgrav int 1845*190cef3dSDag-Erling Smørgrav mm_answer_gss_userok(int sock, struct sshbuf *m) 1846cf2b5f3bSDag-Erling Smørgrav { 1847*190cef3dSDag-Erling Smørgrav int r, authenticated; 18484f52dfbbSDag-Erling Smørgrav const char *displayname; 1849cf2b5f3bSDag-Erling Smørgrav 1850ca86bcf2SDag-Erling Smørgrav if (!options.gss_authentication) 1851ca86bcf2SDag-Erling Smørgrav fatal("%s: GSSAPI authentication not enabled", __func__); 1852ca86bcf2SDag-Erling Smørgrav 1853cf2b5f3bSDag-Erling Smørgrav authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 1854cf2b5f3bSDag-Erling Smørgrav 1855*190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 1856*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u32(m, authenticated)) != 0) 1857*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1858cf2b5f3bSDag-Erling Smørgrav 1859cf2b5f3bSDag-Erling Smørgrav debug3("%s: sending result %d", __func__, authenticated); 186021e764dfSDag-Erling Smørgrav mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); 1861cf2b5f3bSDag-Erling Smørgrav 18621ec0d754SDag-Erling Smørgrav auth_method = "gssapi-with-mic"; 1863cf2b5f3bSDag-Erling Smørgrav 18644f52dfbbSDag-Erling Smørgrav if ((displayname = ssh_gssapi_displayname()) != NULL) 18654f52dfbbSDag-Erling Smørgrav auth2_record_info(authctxt, "%s", displayname); 18664f52dfbbSDag-Erling Smørgrav 1867cf2b5f3bSDag-Erling Smørgrav /* Monitor loop will terminate if authenticated */ 1868cf2b5f3bSDag-Erling Smørgrav return (authenticated); 1869cf2b5f3bSDag-Erling Smørgrav } 1870cf2b5f3bSDag-Erling Smørgrav #endif /* GSSAPI */ 1871cce7d346SDag-Erling Smørgrav 1872