1264377Sdes/* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm Exp $ */ 298675Sdes/* 398675Sdes * Copyright 2002 Niels Provos <provos@citi.umich.edu> 498675Sdes * Copyright 2002 Markus Friedl <markus@openbsd.org> 598675Sdes * All rights reserved. 698675Sdes * 798675Sdes * Redistribution and use in source and binary forms, with or without 898675Sdes * modification, are permitted provided that the following conditions 998675Sdes * are met: 1098675Sdes * 1. Redistributions of source code must retain the above copyright 1198675Sdes * notice, this list of conditions and the following disclaimer. 1298675Sdes * 2. Redistributions in binary form must reproduce the above copyright 1398675Sdes * notice, this list of conditions and the following disclaimer in the 1498675Sdes * documentation and/or other materials provided with the distribution. 1598675Sdes * 1698675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1798675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1898675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1998675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2098675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2198675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2298675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2398675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2498675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2598675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2698675Sdes */ 2798675Sdes 2898675Sdes#include "includes.h" 2998675Sdes 30162856Sdes#include <sys/types.h> 31162856Sdes#include <sys/uio.h> 32162856Sdes 33162856Sdes#include <errno.h> 34162856Sdes#include <pwd.h> 35162856Sdes#include <signal.h> 36162856Sdes#include <stdarg.h> 37162856Sdes#include <stdio.h> 38162856Sdes#include <string.h> 39162856Sdes#include <unistd.h> 40162856Sdes 4198675Sdes#include <openssl/bn.h> 4298675Sdes#include <openssl/dh.h> 43192595Sdes#include <openssl/evp.h> 4498675Sdes 45181111Sdes#include "openbsd-compat/sys-queue.h" 46162856Sdes#include "xmalloc.h" 4798675Sdes#include "ssh.h" 4898675Sdes#include "dh.h" 49162856Sdes#include "buffer.h" 50162856Sdes#include "key.h" 51162856Sdes#include "cipher.h" 5298675Sdes#include "kex.h" 53162856Sdes#include "hostfile.h" 5498675Sdes#include "auth.h" 55113911Sdes#include "auth-options.h" 5698675Sdes#include "packet.h" 5798675Sdes#include "mac.h" 5898675Sdes#include "log.h" 59128460Sdes#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */ 60128460Sdes#undef TARGET_OS_MAC 6198675Sdes#include "zlib.h" 62128460Sdes#define TARGET_OS_MAC 1 63128460Sdes#else 64128460Sdes#include "zlib.h" 65128460Sdes#endif 6698675Sdes#include "monitor.h" 67162856Sdes#ifdef GSSAPI 68162856Sdes#include "ssh-gss.h" 69162856Sdes#endif 7098675Sdes#include "monitor_wrap.h" 7198675Sdes#include "atomicio.h" 7298675Sdes#include "monitor_fdpass.h" 73162856Sdes#include "misc.h" 74221420Sdes#include "uuencode.h" 7598675Sdes 7698675Sdes#include "channels.h" 7798675Sdes#include "session.h" 78181111Sdes#include "servconf.h" 79197679Sdes#include "roaming.h" 8098675Sdes 8198675Sdes/* Imports */ 8298675Sdesextern int compat20; 8398675Sdesextern z_stream incoming_stream; 8498675Sdesextern z_stream outgoing_stream; 8598675Sdesextern struct monitor *pmonitor; 86137019Sdesextern Buffer loginmsg; 87124211Sdesextern ServerOptions options; 8898675Sdes 89226046Sdesvoid 90226046Sdesmm_log_handler(LogLevel level, const char *msg, void *ctx) 91226046Sdes{ 92226046Sdes Buffer log_msg; 93226046Sdes struct monitor *mon = (struct monitor *)ctx; 94226046Sdes 95226046Sdes if (mon->m_log_sendfd == -1) 96226046Sdes fatal("%s: no log channel", __func__); 97226046Sdes 98226046Sdes buffer_init(&log_msg); 99226046Sdes /* 100226046Sdes * Placeholder for packet length. Will be filled in with the actual 101226046Sdes * packet length once the packet has been constucted. This saves 102226046Sdes * fragile math. 103226046Sdes */ 104226046Sdes buffer_put_int(&log_msg, 0); 105226046Sdes 106226046Sdes buffer_put_int(&log_msg, level); 107226046Sdes buffer_put_cstring(&log_msg, msg); 108226046Sdes put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4); 109226046Sdes if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg), 110226046Sdes buffer_len(&log_msg)) != buffer_len(&log_msg)) 111226046Sdes fatal("%s: write: %s", __func__, strerror(errno)); 112226046Sdes buffer_free(&log_msg); 113226046Sdes} 114226046Sdes 115126277Sdesint 116126277Sdesmm_is_monitor(void) 117126277Sdes{ 118126277Sdes /* 119126277Sdes * m_pid is only set in the privileged part, and 120126277Sdes * points to the unprivileged child. 121126277Sdes */ 122126277Sdes return (pmonitor && pmonitor->m_pid > 0); 123126277Sdes} 124126277Sdes 12598675Sdesvoid 126137019Sdesmm_request_send(int sock, enum monitor_reqtype type, Buffer *m) 12798675Sdes{ 128106130Sdes u_int mlen = buffer_len(m); 12998675Sdes u_char buf[5]; 13098675Sdes 13198675Sdes debug3("%s entering: type %d", __func__, type); 13298675Sdes 133162856Sdes put_u32(buf, mlen + 1); 13498675Sdes buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ 135137019Sdes if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf)) 136149753Sdes fatal("%s: write: %s", __func__, strerror(errno)); 137137019Sdes if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen) 138149753Sdes fatal("%s: write: %s", __func__, strerror(errno)); 13998675Sdes} 14098675Sdes 14198675Sdesvoid 142137019Sdesmm_request_receive(int sock, Buffer *m) 14398675Sdes{ 14498675Sdes u_char buf[4]; 145106130Sdes u_int msg_len; 14698675Sdes 14798675Sdes debug3("%s entering", __func__); 14898675Sdes 149149753Sdes if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) { 150149753Sdes if (errno == EPIPE) 151126277Sdes cleanup_exit(255); 152149753Sdes fatal("%s: read: %s", __func__, strerror(errno)); 15398675Sdes } 154162856Sdes msg_len = get_u32(buf); 15598675Sdes if (msg_len > 256 * 1024) 15698675Sdes fatal("%s: read: bad msg_len %d", __func__, msg_len); 15798675Sdes buffer_clear(m); 15898675Sdes buffer_append_space(m, msg_len); 159149753Sdes if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len) 160149753Sdes fatal("%s: read: %s", __func__, strerror(errno)); 16198675Sdes} 16298675Sdes 16398675Sdesvoid 164137019Sdesmm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m) 16598675Sdes{ 16698675Sdes u_char rtype; 16798675Sdes 16898675Sdes debug3("%s entering: type %d", __func__, type); 16998675Sdes 170137019Sdes mm_request_receive(sock, m); 17198675Sdes rtype = buffer_get_char(m); 17298675Sdes if (rtype != type) 17398675Sdes fatal("%s: read: rtype %d != type %d", __func__, 17498675Sdes rtype, type); 17598675Sdes} 17698675Sdes 17798675SdesDH * 17898675Sdesmm_choose_dh(int min, int nbits, int max) 17998675Sdes{ 18098675Sdes BIGNUM *p, *g; 18198675Sdes int success = 0; 18298675Sdes Buffer m; 18398675Sdes 18498675Sdes buffer_init(&m); 18598675Sdes buffer_put_int(&m, min); 18698675Sdes buffer_put_int(&m, nbits); 18798675Sdes buffer_put_int(&m, max); 18898675Sdes 18998675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); 19098675Sdes 19198675Sdes debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); 19298675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); 19398675Sdes 19498675Sdes success = buffer_get_char(&m); 19598675Sdes if (success == 0) 19698675Sdes fatal("%s: MONITOR_ANS_MODULI failed", __func__); 19798675Sdes 19898675Sdes if ((p = BN_new()) == NULL) 19998675Sdes fatal("%s: BN_new failed", __func__); 20098675Sdes if ((g = BN_new()) == NULL) 20198675Sdes fatal("%s: BN_new failed", __func__); 20298675Sdes buffer_get_bignum2(&m, p); 20398675Sdes buffer_get_bignum2(&m, g); 20498675Sdes 20598675Sdes debug3("%s: remaining %d", __func__, buffer_len(&m)); 20698675Sdes buffer_free(&m); 20798675Sdes 20898675Sdes return (dh_new_group(g, p)); 20998675Sdes} 21098675Sdes 21198675Sdesint 21298675Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) 21398675Sdes{ 21498675Sdes Kex *kex = *pmonitor->m_pkex; 21598675Sdes Buffer m; 21698675Sdes 21798675Sdes debug3("%s entering", __func__); 21898675Sdes 21998675Sdes buffer_init(&m); 22098675Sdes buffer_put_int(&m, kex->host_key_index(key)); 22198675Sdes buffer_put_string(&m, data, datalen); 22298675Sdes 22398675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); 22498675Sdes 22598675Sdes debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); 22698675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m); 22798675Sdes *sigp = buffer_get_string(&m, lenp); 22898675Sdes buffer_free(&m); 22998675Sdes 23098675Sdes return (0); 23198675Sdes} 23298675Sdes 23398675Sdesstruct passwd * 234137019Sdesmm_getpwnamallow(const char *username) 23598675Sdes{ 23698675Sdes Buffer m; 23798675Sdes struct passwd *pw; 238226046Sdes u_int len, i; 239181111Sdes ServerOptions *newopts; 24098675Sdes 24198675Sdes debug3("%s entering", __func__); 24298675Sdes 24398675Sdes buffer_init(&m); 244137019Sdes buffer_put_cstring(&m, username); 24598675Sdes 24698675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); 24798675Sdes 24898675Sdes debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); 24998675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); 25098675Sdes 25198675Sdes if (buffer_get_char(&m) == 0) { 252181111Sdes pw = NULL; 253181111Sdes goto out; 25498675Sdes } 255181111Sdes pw = buffer_get_string(&m, &len); 256181111Sdes if (len != sizeof(struct passwd)) 25798675Sdes fatal("%s: struct passwd size mismatch", __func__); 25898675Sdes pw->pw_name = buffer_get_string(&m, NULL); 25998675Sdes pw->pw_passwd = buffer_get_string(&m, NULL); 260255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS 26198675Sdes pw->pw_gecos = buffer_get_string(&m, NULL); 262255767Sdes#endif 263255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS 26498675Sdes pw->pw_class = buffer_get_string(&m, NULL); 26598937Sdes#endif 26698675Sdes pw->pw_dir = buffer_get_string(&m, NULL); 26798675Sdes pw->pw_shell = buffer_get_string(&m, NULL); 268181111Sdes 269181111Sdesout: 270181111Sdes /* copy options block as a Match directive may have changed some */ 271181111Sdes newopts = buffer_get_string(&m, &len); 272181111Sdes if (len != sizeof(*newopts)) 273181111Sdes fatal("%s: option block size mismatch", __func__); 274226046Sdes 275226046Sdes#define M_CP_STROPT(x) do { \ 276226046Sdes if (newopts->x != NULL) \ 277226046Sdes newopts->x = buffer_get_string(&m, NULL); \ 278226046Sdes } while (0) 279226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \ 280226046Sdes for (i = 0; i < newopts->nx; i++) \ 281226046Sdes newopts->x[i] = buffer_get_string(&m, NULL); \ 282226046Sdes } while (0) 283226046Sdes /* See comment in servconf.h */ 284226046Sdes COPY_MATCH_STRING_OPTS(); 285226046Sdes#undef M_CP_STROPT 286226046Sdes#undef M_CP_STRARRAYOPT 287226046Sdes 288181111Sdes copy_set_server_options(&options, newopts, 1); 289255767Sdes free(newopts); 290181111Sdes 29198675Sdes buffer_free(&m); 29298675Sdes 29398675Sdes return (pw); 29498675Sdes} 29598675Sdes 296126277Sdeschar * 297126277Sdesmm_auth2_read_banner(void) 29898675Sdes{ 29998675Sdes Buffer m; 30098675Sdes char *banner; 30198675Sdes 30298675Sdes debug3("%s entering", __func__); 30398675Sdes 30498675Sdes buffer_init(&m); 30598675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m); 30698675Sdes buffer_clear(&m); 30798675Sdes 308126277Sdes mm_request_receive_expect(pmonitor->m_recvfd, 309126277Sdes MONITOR_ANS_AUTH2_READ_BANNER, &m); 31098675Sdes banner = buffer_get_string(&m, NULL); 31198675Sdes buffer_free(&m); 31298675Sdes 313126277Sdes /* treat empty banner as missing banner */ 314126277Sdes if (strlen(banner) == 0) { 315255767Sdes free(banner); 316126277Sdes banner = NULL; 317126277Sdes } 31898675Sdes return (banner); 31998675Sdes} 32098675Sdes 32198675Sdes/* Inform the privileged process about service and style */ 32298675Sdes 32398675Sdesvoid 32498675Sdesmm_inform_authserv(char *service, char *style) 32598675Sdes{ 32698675Sdes Buffer m; 32798675Sdes 32898675Sdes debug3("%s entering", __func__); 32998675Sdes 33098675Sdes buffer_init(&m); 33198675Sdes buffer_put_cstring(&m, service); 33298675Sdes buffer_put_cstring(&m, style ? style : ""); 33398675Sdes 33498675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m); 33598675Sdes 33698675Sdes buffer_free(&m); 33798675Sdes} 33898675Sdes 33998675Sdes/* Do the password authentication */ 34098675Sdesint 34198675Sdesmm_auth_password(Authctxt *authctxt, char *password) 34298675Sdes{ 34398675Sdes Buffer m; 34498675Sdes int authenticated = 0; 34598675Sdes 34698675Sdes debug3("%s entering", __func__); 34798675Sdes 34898675Sdes buffer_init(&m); 34998675Sdes buffer_put_cstring(&m, password); 35098675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); 35198675Sdes 35298675Sdes debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); 35398675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); 35498675Sdes 35598675Sdes authenticated = buffer_get_int(&m); 35698675Sdes 35798675Sdes buffer_free(&m); 35898675Sdes 35998675Sdes debug3("%s: user %sauthenticated", 36098675Sdes __func__, authenticated ? "" : "not "); 36198675Sdes return (authenticated); 36298675Sdes} 36398675Sdes 36498675Sdesint 36598675Sdesmm_user_key_allowed(struct passwd *pw, Key *key) 36698675Sdes{ 36798675Sdes return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); 36898675Sdes} 36998675Sdes 37098675Sdesint 37198675Sdesmm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, 37298675Sdes Key *key) 37398675Sdes{ 37498675Sdes return (mm_key_allowed(MM_HOSTKEY, user, host, key)); 37598675Sdes} 37698675Sdes 37798675Sdesint 37898675Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, 37998675Sdes char *host, Key *key) 38098675Sdes{ 38198675Sdes int ret; 38298675Sdes 38398675Sdes key->type = KEY_RSA; /* XXX hack for key_to_blob */ 38498675Sdes ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); 38598675Sdes key->type = KEY_RSA1; 38698675Sdes return (ret); 38798675Sdes} 38898675Sdes 38998675Sdesint 39098675Sdesmm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) 39198675Sdes{ 39298675Sdes Buffer m; 39398675Sdes u_char *blob; 39498675Sdes u_int len; 395113911Sdes int allowed = 0, have_forced = 0; 39698675Sdes 39798675Sdes debug3("%s entering", __func__); 39898675Sdes 39998675Sdes /* Convert the key to a blob and the pass it over */ 40098675Sdes if (!key_to_blob(key, &blob, &len)) 40198675Sdes return (0); 40298675Sdes 40398675Sdes buffer_init(&m); 40498675Sdes buffer_put_int(&m, type); 40598675Sdes buffer_put_cstring(&m, user ? user : ""); 40698675Sdes buffer_put_cstring(&m, host ? host : ""); 40798675Sdes buffer_put_string(&m, blob, len); 408255767Sdes free(blob); 40998675Sdes 41098675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); 41198675Sdes 41298675Sdes debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); 41398675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m); 41498675Sdes 41598675Sdes allowed = buffer_get_int(&m); 41698675Sdes 417113911Sdes /* fake forced command */ 418113911Sdes auth_clear_options(); 419113911Sdes have_forced = buffer_get_int(&m); 420113911Sdes forced_command = have_forced ? xstrdup("true") : NULL; 421113911Sdes 42298675Sdes buffer_free(&m); 42398675Sdes 42498675Sdes return (allowed); 42598675Sdes} 42698675Sdes 42798675Sdes/* 42898675Sdes * This key verify needs to send the key type along, because the 42998675Sdes * privileged parent makes the decision if the key is allowed 43098675Sdes * for authentication. 43198675Sdes */ 43298675Sdes 43398675Sdesint 43498675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) 43598675Sdes{ 43698675Sdes Buffer m; 43798675Sdes u_char *blob; 43898675Sdes u_int len; 43998675Sdes int verified = 0; 44098675Sdes 44198675Sdes debug3("%s entering", __func__); 44298675Sdes 44398675Sdes /* Convert the key to a blob and the pass it over */ 44498675Sdes if (!key_to_blob(key, &blob, &len)) 44598675Sdes return (0); 44698675Sdes 44798675Sdes buffer_init(&m); 44898675Sdes buffer_put_string(&m, blob, len); 44998675Sdes buffer_put_string(&m, sig, siglen); 45098675Sdes buffer_put_string(&m, data, datalen); 451255767Sdes free(blob); 45298675Sdes 45398675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m); 45498675Sdes 45598675Sdes debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); 45698675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); 45798675Sdes 45898675Sdes verified = buffer_get_int(&m); 45998675Sdes 46098675Sdes buffer_free(&m); 46198675Sdes 46298675Sdes return (verified); 46398675Sdes} 46498675Sdes 46598675Sdes/* Export key state after authentication */ 46698675SdesNewkeys * 46798675Sdesmm_newkeys_from_blob(u_char *blob, int blen) 46898675Sdes{ 46998675Sdes Buffer b; 47098675Sdes u_int len; 47198675Sdes Newkeys *newkey = NULL; 47298675Sdes Enc *enc; 47398675Sdes Mac *mac; 47498675Sdes Comp *comp; 47598675Sdes 47698675Sdes debug3("%s: %p(%d)", __func__, blob, blen); 47798675Sdes#ifdef DEBUG_PK 47898675Sdes dump_base64(stderr, blob, blen); 47998675Sdes#endif 48098675Sdes buffer_init(&b); 48198675Sdes buffer_append(&b, blob, blen); 48298675Sdes 483258335Sdes newkey = xcalloc(1, sizeof(*newkey)); 48498675Sdes enc = &newkey->enc; 48598675Sdes mac = &newkey->mac; 48698675Sdes comp = &newkey->comp; 48798675Sdes 48898675Sdes /* Enc structure */ 48998675Sdes enc->name = buffer_get_string(&b, NULL); 49098675Sdes buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); 49198675Sdes enc->enabled = buffer_get_int(&b); 49298675Sdes enc->block_size = buffer_get_int(&b); 49398675Sdes enc->key = buffer_get_string(&b, &enc->key_len); 494248619Sdes enc->iv = buffer_get_string(&b, &enc->iv_len); 49598675Sdes 49698675Sdes if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) 49798675Sdes fatal("%s: bad cipher name %s or pointer %p", __func__, 49898675Sdes enc->name, enc->cipher); 49998675Sdes 50098675Sdes /* Mac structure */ 501248619Sdes if (cipher_authlen(enc->cipher) == 0) { 502248619Sdes mac->name = buffer_get_string(&b, NULL); 503248619Sdes if (mac->name == NULL || mac_setup(mac, mac->name) == -1) 504248619Sdes fatal("%s: can not setup mac %s", __func__, mac->name); 505248619Sdes mac->enabled = buffer_get_int(&b); 506248619Sdes mac->key = buffer_get_string(&b, &len); 507248619Sdes if (len > mac->key_len) 508248619Sdes fatal("%s: bad mac key length: %u > %d", __func__, len, 509248619Sdes mac->key_len); 510248619Sdes mac->key_len = len; 511248619Sdes } 51298675Sdes 51398675Sdes /* Comp structure */ 51498675Sdes comp->type = buffer_get_int(&b); 51598675Sdes comp->enabled = buffer_get_int(&b); 51698675Sdes comp->name = buffer_get_string(&b, NULL); 51798675Sdes 51898675Sdes len = buffer_len(&b); 51998675Sdes if (len != 0) 520106130Sdes error("newkeys_from_blob: remaining bytes in blob %u", len); 52198675Sdes buffer_free(&b); 52298675Sdes return (newkey); 52398675Sdes} 52498675Sdes 52598675Sdesint 52698675Sdesmm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) 52798675Sdes{ 52898675Sdes Buffer b; 52998675Sdes int len; 53098675Sdes Enc *enc; 53198675Sdes Mac *mac; 53298675Sdes Comp *comp; 533197679Sdes Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode); 53498675Sdes 53598675Sdes debug3("%s: converting %p", __func__, newkey); 53698675Sdes 53798675Sdes if (newkey == NULL) { 53898675Sdes error("%s: newkey == NULL", __func__); 53998675Sdes return 0; 54098675Sdes } 54198675Sdes enc = &newkey->enc; 54298675Sdes mac = &newkey->mac; 54398675Sdes comp = &newkey->comp; 54498675Sdes 54598675Sdes buffer_init(&b); 54698675Sdes /* Enc structure */ 54798675Sdes buffer_put_cstring(&b, enc->name); 54898675Sdes /* The cipher struct is constant and shared, you export pointer */ 54998675Sdes buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); 55098675Sdes buffer_put_int(&b, enc->enabled); 55198675Sdes buffer_put_int(&b, enc->block_size); 55298675Sdes buffer_put_string(&b, enc->key, enc->key_len); 553248619Sdes packet_get_keyiv(mode, enc->iv, enc->iv_len); 554248619Sdes buffer_put_string(&b, enc->iv, enc->iv_len); 55598675Sdes 55698675Sdes /* Mac structure */ 557248619Sdes if (cipher_authlen(enc->cipher) == 0) { 558248619Sdes buffer_put_cstring(&b, mac->name); 559248619Sdes buffer_put_int(&b, mac->enabled); 560248619Sdes buffer_put_string(&b, mac->key, mac->key_len); 561248619Sdes } 56298675Sdes 56398675Sdes /* Comp structure */ 56498675Sdes buffer_put_int(&b, comp->type); 56598675Sdes buffer_put_int(&b, comp->enabled); 56698675Sdes buffer_put_cstring(&b, comp->name); 56798675Sdes 56898675Sdes len = buffer_len(&b); 569106130Sdes if (lenp != NULL) 570106130Sdes *lenp = len; 571106130Sdes if (blobp != NULL) { 572106130Sdes *blobp = xmalloc(len); 573106130Sdes memcpy(*blobp, buffer_ptr(&b), len); 574106130Sdes } 575264377Sdes explicit_bzero(buffer_ptr(&b), len); 57698675Sdes buffer_free(&b); 57798675Sdes return len; 57898675Sdes} 57998675Sdes 58098675Sdesstatic void 58198675Sdesmm_send_kex(Buffer *m, Kex *kex) 58298675Sdes{ 58398675Sdes buffer_put_string(m, kex->session_id, kex->session_id_len); 58498675Sdes buffer_put_int(m, kex->we_need); 58598675Sdes buffer_put_int(m, kex->hostkey_type); 58698675Sdes buffer_put_int(m, kex->kex_type); 58798675Sdes buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); 58898675Sdes buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); 58998675Sdes buffer_put_int(m, kex->flags); 59098675Sdes buffer_put_cstring(m, kex->client_version_string); 59198675Sdes buffer_put_cstring(m, kex->server_version_string); 59298675Sdes} 59398675Sdes 59498675Sdesvoid 595137019Sdesmm_send_keystate(struct monitor *monitor) 59698675Sdes{ 597197679Sdes Buffer m, *input, *output; 59898675Sdes u_char *blob, *p; 59998675Sdes u_int bloblen, plen; 600124211Sdes u_int32_t seqnr, packets; 601181111Sdes u_int64_t blocks, bytes; 60298675Sdes 60398675Sdes buffer_init(&m); 60498675Sdes 60598675Sdes if (!compat20) { 60698675Sdes u_char iv[24]; 60798675Sdes u_char *key; 60898675Sdes u_int ivlen, keylen; 60998675Sdes 61098675Sdes buffer_put_int(&m, packet_get_protocol_flags()); 61198675Sdes 61298675Sdes buffer_put_int(&m, packet_get_ssh1_cipher()); 61398675Sdes 61498675Sdes debug3("%s: Sending ssh1 KEY+IV", __func__); 61598675Sdes keylen = packet_get_encryption_key(NULL); 61698675Sdes key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ 61798675Sdes keylen = packet_get_encryption_key(key); 61898675Sdes buffer_put_string(&m, key, keylen); 619264377Sdes explicit_bzero(key, keylen); 620255767Sdes free(key); 62198675Sdes 62298675Sdes ivlen = packet_get_keyiv_len(MODE_OUT); 62398675Sdes packet_get_keyiv(MODE_OUT, iv, ivlen); 62498675Sdes buffer_put_string(&m, iv, ivlen); 625248619Sdes ivlen = packet_get_keyiv_len(MODE_IN); 62698675Sdes packet_get_keyiv(MODE_IN, iv, ivlen); 62798675Sdes buffer_put_string(&m, iv, ivlen); 62898675Sdes goto skip; 62998675Sdes } else { 63098675Sdes /* Kex for rekeying */ 631137019Sdes mm_send_kex(&m, *monitor->m_pkex); 63298675Sdes } 63398675Sdes 63498675Sdes debug3("%s: Sending new keys: %p %p", 635197679Sdes __func__, packet_get_newkeys(MODE_OUT), 636197679Sdes packet_get_newkeys(MODE_IN)); 63798675Sdes 63898675Sdes /* Keys from Kex */ 63998675Sdes if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) 64098675Sdes fatal("%s: conversion of newkeys failed", __func__); 64198675Sdes 64298675Sdes buffer_put_string(&m, blob, bloblen); 643255767Sdes free(blob); 64498675Sdes 64598675Sdes if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) 64698675Sdes fatal("%s: conversion of newkeys failed", __func__); 64798675Sdes 64898675Sdes buffer_put_string(&m, blob, bloblen); 649255767Sdes free(blob); 65098675Sdes 651181111Sdes packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); 652124211Sdes buffer_put_int(&m, seqnr); 653124211Sdes buffer_put_int64(&m, blocks); 654124211Sdes buffer_put_int(&m, packets); 655181111Sdes buffer_put_int64(&m, bytes); 656181111Sdes packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes); 657124211Sdes buffer_put_int(&m, seqnr); 658124211Sdes buffer_put_int64(&m, blocks); 659124211Sdes buffer_put_int(&m, packets); 660181111Sdes buffer_put_int64(&m, bytes); 66198675Sdes 66298675Sdes debug3("%s: New keys have been sent", __func__); 66398675Sdes skip: 66498675Sdes /* More key context */ 66598675Sdes plen = packet_get_keycontext(MODE_OUT, NULL); 66698675Sdes p = xmalloc(plen+1); 66798675Sdes packet_get_keycontext(MODE_OUT, p); 66898675Sdes buffer_put_string(&m, p, plen); 669255767Sdes free(p); 67098675Sdes 67198675Sdes plen = packet_get_keycontext(MODE_IN, NULL); 67298675Sdes p = xmalloc(plen+1); 67398675Sdes packet_get_keycontext(MODE_IN, p); 67498675Sdes buffer_put_string(&m, p, plen); 675255767Sdes free(p); 67698675Sdes 67798675Sdes /* Compression state */ 67898675Sdes debug3("%s: Sending compression state", __func__); 67998675Sdes buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); 68098675Sdes buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); 68198675Sdes 68298675Sdes /* Network I/O buffers */ 683197679Sdes input = (Buffer *)packet_get_input(); 684197679Sdes output = (Buffer *)packet_get_output(); 685197679Sdes buffer_put_string(&m, buffer_ptr(input), buffer_len(input)); 686197679Sdes buffer_put_string(&m, buffer_ptr(output), buffer_len(output)); 68798675Sdes 688197679Sdes /* Roaming */ 689197679Sdes if (compat20) { 690197679Sdes buffer_put_int64(&m, get_sent_bytes()); 691197679Sdes buffer_put_int64(&m, get_recv_bytes()); 692197679Sdes } 693197679Sdes 694137019Sdes mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); 69598675Sdes debug3("%s: Finished sending state", __func__); 69698675Sdes 69798675Sdes buffer_free(&m); 69898675Sdes} 69998675Sdes 70098675Sdesint 701162856Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) 70298675Sdes{ 70398675Sdes Buffer m; 704137019Sdes char *p, *msg; 705181111Sdes int success = 0, tmp1 = -1, tmp2 = -1; 70698675Sdes 707181111Sdes /* Kludge: ensure there are fds free to receive the pty/tty */ 708181111Sdes if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || 709181111Sdes (tmp2 = dup(pmonitor->m_recvfd)) == -1) { 710181111Sdes error("%s: cannot allocate fds for pty", __func__); 711181111Sdes if (tmp1 > 0) 712181111Sdes close(tmp1); 713181111Sdes if (tmp2 > 0) 714181111Sdes close(tmp2); 715181111Sdes return 0; 716181111Sdes } 717181111Sdes close(tmp1); 718181111Sdes close(tmp2); 719181111Sdes 72098675Sdes buffer_init(&m); 72198675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); 72298675Sdes 72398675Sdes debug3("%s: waiting for MONITOR_ANS_PTY", __func__); 72498675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m); 72598675Sdes 72698675Sdes success = buffer_get_int(&m); 72798675Sdes if (success == 0) { 72898675Sdes debug3("%s: pty alloc failed", __func__); 72998675Sdes buffer_free(&m); 73098675Sdes return (0); 73198675Sdes } 73298675Sdes p = buffer_get_string(&m, NULL); 733137019Sdes msg = buffer_get_string(&m, NULL); 73498675Sdes buffer_free(&m); 73598675Sdes 73698675Sdes strlcpy(namebuf, p, namebuflen); /* Possible truncation */ 737255767Sdes free(p); 73898675Sdes 739137019Sdes buffer_append(&loginmsg, msg, strlen(msg)); 740255767Sdes free(msg); 741137019Sdes 742181111Sdes if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 || 743181111Sdes (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1) 744181111Sdes fatal("%s: receive fds failed", __func__); 74598675Sdes 74698675Sdes /* Success */ 74798675Sdes return (1); 74898675Sdes} 74998675Sdes 75098675Sdesvoid 751126277Sdesmm_session_pty_cleanup2(Session *s) 75298675Sdes{ 75398675Sdes Buffer m; 75498675Sdes 75598675Sdes if (s->ttyfd == -1) 75698675Sdes return; 75798675Sdes buffer_init(&m); 75898675Sdes buffer_put_cstring(&m, s->tty); 75998675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m); 76098675Sdes buffer_free(&m); 76198675Sdes 76298675Sdes /* closed dup'ed master */ 763181111Sdes if (s->ptymaster != -1 && close(s->ptymaster) < 0) 764181111Sdes error("close(s->ptymaster/%d): %s", 765181111Sdes s->ptymaster, strerror(errno)); 76698675Sdes 76798675Sdes /* unlink pty from session */ 76898675Sdes s->ttyfd = -1; 76998675Sdes} 77098675Sdes 77198937Sdes#ifdef USE_PAM 77298937Sdesvoid 773128460Sdesmm_start_pam(Authctxt *authctxt) 77498937Sdes{ 77598937Sdes Buffer m; 77698937Sdes 77798937Sdes debug3("%s entering", __func__); 778124211Sdes if (!options.use_pam) 779124211Sdes fatal("UsePAM=no, but ended up in %s anyway", __func__); 78098937Sdes 78198937Sdes buffer_init(&m); 78298937Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); 78398937Sdes 78498937Sdes buffer_free(&m); 78598937Sdes} 78699052Sdes 787124211Sdesu_int 788124211Sdesmm_do_pam_account(void) 789124211Sdes{ 790124211Sdes Buffer m; 791124211Sdes u_int ret; 792147005Sdes char *msg; 793124211Sdes 794124211Sdes debug3("%s entering", __func__); 795124211Sdes if (!options.use_pam) 796124211Sdes fatal("UsePAM=no, but ended up in %s anyway", __func__); 797124211Sdes 798124211Sdes buffer_init(&m); 799124211Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m); 800124211Sdes 801126277Sdes mm_request_receive_expect(pmonitor->m_recvfd, 802124211Sdes MONITOR_ANS_PAM_ACCOUNT, &m); 803124211Sdes ret = buffer_get_int(&m); 804147005Sdes msg = buffer_get_string(&m, NULL); 805147005Sdes buffer_append(&loginmsg, msg, strlen(msg)); 806255767Sdes free(msg); 807124211Sdes 808124211Sdes buffer_free(&m); 809126277Sdes 810124211Sdes debug3("%s returning %d", __func__, ret); 811124211Sdes 812124211Sdes return (ret); 813124211Sdes} 814124211Sdes 81599052Sdesvoid * 816124211Sdesmm_sshpam_init_ctx(Authctxt *authctxt) 81799052Sdes{ 81899052Sdes Buffer m; 81999052Sdes int success; 82099052Sdes 82199052Sdes debug3("%s", __func__); 82299052Sdes buffer_init(&m); 82399052Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m); 82499052Sdes debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); 82599052Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m); 82699052Sdes success = buffer_get_int(&m); 82799052Sdes if (success == 0) { 82899052Sdes debug3("%s: pam_init_ctx failed", __func__); 82999052Sdes buffer_free(&m); 83099052Sdes return (NULL); 83199052Sdes } 83299052Sdes buffer_free(&m); 83399052Sdes return (authctxt); 83499052Sdes} 83599052Sdes 83699052Sdesint 837124211Sdesmm_sshpam_query(void *ctx, char **name, char **info, 83899052Sdes u_int *num, char ***prompts, u_int **echo_on) 83999052Sdes{ 84099052Sdes Buffer m; 841149753Sdes u_int i; 842149753Sdes int ret; 84399052Sdes 84499052Sdes debug3("%s", __func__); 84599052Sdes buffer_init(&m); 84699052Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m); 84799052Sdes debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); 84899052Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m); 84999052Sdes ret = buffer_get_int(&m); 85099052Sdes debug3("%s: pam_query returned %d", __func__, ret); 85199052Sdes *name = buffer_get_string(&m, NULL); 85299052Sdes *info = buffer_get_string(&m, NULL); 85399052Sdes *num = buffer_get_int(&m); 854162856Sdes if (*num > PAM_MAX_NUM_MSG) 855162856Sdes fatal("%s: recieved %u PAM messages, expected <= %u", 856162856Sdes __func__, *num, PAM_MAX_NUM_MSG); 857162856Sdes *prompts = xcalloc((*num + 1), sizeof(char *)); 858162856Sdes *echo_on = xcalloc((*num + 1), sizeof(u_int)); 85999052Sdes for (i = 0; i < *num; ++i) { 86099052Sdes (*prompts)[i] = buffer_get_string(&m, NULL); 86199052Sdes (*echo_on)[i] = buffer_get_int(&m); 86299052Sdes } 86399052Sdes buffer_free(&m); 86499052Sdes return (ret); 86599052Sdes} 86699052Sdes 86799052Sdesint 868124211Sdesmm_sshpam_respond(void *ctx, u_int num, char **resp) 86999052Sdes{ 87099052Sdes Buffer m; 871149753Sdes u_int i; 872149753Sdes int ret; 87399052Sdes 87499052Sdes debug3("%s", __func__); 87599052Sdes buffer_init(&m); 87699052Sdes buffer_put_int(&m, num); 87799052Sdes for (i = 0; i < num; ++i) 87899052Sdes buffer_put_cstring(&m, resp[i]); 87999052Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m); 88099052Sdes debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); 88199052Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m); 88299052Sdes ret = buffer_get_int(&m); 88399052Sdes debug3("%s: pam_respond returned %d", __func__, ret); 88499052Sdes buffer_free(&m); 88599052Sdes return (ret); 88699052Sdes} 88799052Sdes 88899052Sdesvoid 889124211Sdesmm_sshpam_free_ctx(void *ctxtp) 89099052Sdes{ 89199052Sdes Buffer m; 89299052Sdes 89399052Sdes debug3("%s", __func__); 89499052Sdes buffer_init(&m); 89599052Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m); 89699052Sdes debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); 89799052Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m); 89899052Sdes buffer_free(&m); 89999052Sdes} 90098937Sdes#endif /* USE_PAM */ 90198937Sdes 90298675Sdes/* Request process termination */ 90398675Sdes 90498675Sdesvoid 90598675Sdesmm_terminate(void) 90698675Sdes{ 90798675Sdes Buffer m; 90898675Sdes 90998675Sdes buffer_init(&m); 91098675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m); 91198675Sdes buffer_free(&m); 91298675Sdes} 91398675Sdes 91498675Sdesint 91598675Sdesmm_ssh1_session_key(BIGNUM *num) 91698675Sdes{ 91798675Sdes int rsafail; 91898675Sdes Buffer m; 91998675Sdes 92098675Sdes buffer_init(&m); 92198675Sdes buffer_put_bignum2(&m, num); 92298675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); 92398675Sdes 92498675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); 92598675Sdes 92698675Sdes rsafail = buffer_get_int(&m); 92798675Sdes buffer_get_bignum2(&m, num); 92898675Sdes 92998675Sdes buffer_free(&m); 93098675Sdes 93198675Sdes return (rsafail); 93298675Sdes} 93398675Sdes 93498675Sdesstatic void 93598675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts, 93698675Sdes char ***prompts, u_int **echo_on) 93798675Sdes{ 93898675Sdes *name = xstrdup(""); 93998675Sdes *infotxt = xstrdup(""); 94098675Sdes *numprompts = 1; 941162856Sdes *prompts = xcalloc(*numprompts, sizeof(char *)); 942162856Sdes *echo_on = xcalloc(*numprompts, sizeof(u_int)); 94398675Sdes (*echo_on)[0] = 0; 94498675Sdes} 94598675Sdes 94698675Sdesint 94798675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt, 94898675Sdes u_int *numprompts, char ***prompts, u_int **echo_on) 94998675Sdes{ 95098675Sdes Buffer m; 951113911Sdes u_int success; 95298675Sdes char *challenge; 95398675Sdes 95498675Sdes debug3("%s: entering", __func__); 95598675Sdes 95698675Sdes buffer_init(&m); 95798675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m); 95898675Sdes 95998675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, 96098675Sdes &m); 961113911Sdes success = buffer_get_int(&m); 962113911Sdes if (success == 0) { 96398675Sdes debug3("%s: no challenge", __func__); 96498675Sdes buffer_free(&m); 96598675Sdes return (-1); 96698675Sdes } 96798675Sdes 96898675Sdes /* Get the challenge, and format the response */ 96998675Sdes challenge = buffer_get_string(&m, NULL); 97098675Sdes buffer_free(&m); 97198675Sdes 97298675Sdes mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); 97398675Sdes (*prompts)[0] = challenge; 97498675Sdes 97598675Sdes debug3("%s: received challenge: %s", __func__, challenge); 97698675Sdes 97798675Sdes return (0); 97898675Sdes} 97998675Sdes 98098675Sdesint 98198675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) 98298675Sdes{ 98398675Sdes Buffer m; 98498675Sdes int authok; 98598675Sdes 98698675Sdes debug3("%s: entering", __func__); 98798675Sdes if (numresponses != 1) 98898675Sdes return (-1); 98998675Sdes 99098675Sdes buffer_init(&m); 99198675Sdes buffer_put_cstring(&m, responses[0]); 99298675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); 99398675Sdes 99498675Sdes mm_request_receive_expect(pmonitor->m_recvfd, 99598675Sdes MONITOR_ANS_BSDAUTHRESPOND, &m); 99698675Sdes 99798675Sdes authok = buffer_get_int(&m); 99898675Sdes buffer_free(&m); 99998675Sdes 100098675Sdes return ((authok == 0) ? -1 : 0); 100198675Sdes} 100298675Sdes 100399046Sdes#ifdef SKEY 100498675Sdesint 100598675Sdesmm_skey_query(void *ctx, char **name, char **infotxt, 100698675Sdes u_int *numprompts, char ***prompts, u_int **echo_on) 100798675Sdes{ 100898675Sdes Buffer m; 1009113911Sdes u_int success; 1010162856Sdes char *challenge; 101198675Sdes 101298675Sdes debug3("%s: entering", __func__); 101398675Sdes 101498675Sdes buffer_init(&m); 101598675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); 101698675Sdes 101798675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, 101898675Sdes &m); 1019113911Sdes success = buffer_get_int(&m); 1020113911Sdes if (success == 0) { 102198675Sdes debug3("%s: no challenge", __func__); 102298675Sdes buffer_free(&m); 102398675Sdes return (-1); 102498675Sdes } 102598675Sdes 102698675Sdes /* Get the challenge, and format the response */ 102798675Sdes challenge = buffer_get_string(&m, NULL); 102898675Sdes buffer_free(&m); 102998675Sdes 103098675Sdes debug3("%s: received challenge: %s", __func__, challenge); 103198675Sdes 103298675Sdes mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); 103398675Sdes 1034162856Sdes xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT); 1035255767Sdes free(challenge); 103698675Sdes 103798675Sdes return (0); 103898675Sdes} 103998675Sdes 104098675Sdesint 104198675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses) 104298675Sdes{ 104398675Sdes Buffer m; 104498675Sdes int authok; 104598675Sdes 104698675Sdes debug3("%s: entering", __func__); 104798675Sdes if (numresponses != 1) 104898675Sdes return (-1); 104998675Sdes 105098675Sdes buffer_init(&m); 105198675Sdes buffer_put_cstring(&m, responses[0]); 105298675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); 105398675Sdes 105498675Sdes mm_request_receive_expect(pmonitor->m_recvfd, 105598675Sdes MONITOR_ANS_SKEYRESPOND, &m); 105698675Sdes 105798675Sdes authok = buffer_get_int(&m); 105898675Sdes buffer_free(&m); 105998675Sdes 106098675Sdes return ((authok == 0) ? -1 : 0); 106198675Sdes} 1062137019Sdes#endif /* SKEY */ 106398675Sdes 106498675Sdesvoid 106598675Sdesmm_ssh1_session_id(u_char session_id[16]) 106698675Sdes{ 106798675Sdes Buffer m; 106898675Sdes int i; 106998675Sdes 107098675Sdes debug3("%s entering", __func__); 107198675Sdes 107298675Sdes buffer_init(&m); 107398675Sdes for (i = 0; i < 16; i++) 107498675Sdes buffer_put_char(&m, session_id[i]); 107598675Sdes 107698675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); 107798675Sdes buffer_free(&m); 107898675Sdes} 107998675Sdes 108098675Sdesint 108198675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) 108298675Sdes{ 108398675Sdes Buffer m; 108498675Sdes Key *key; 108598675Sdes u_char *blob; 108698675Sdes u_int blen; 1087113911Sdes int allowed = 0, have_forced = 0; 108898675Sdes 108998675Sdes debug3("%s entering", __func__); 109098675Sdes 109198675Sdes buffer_init(&m); 109298675Sdes buffer_put_bignum2(&m, client_n); 109398675Sdes 109498675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); 109598675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); 109698675Sdes 109798675Sdes allowed = buffer_get_int(&m); 109898675Sdes 1099113911Sdes /* fake forced command */ 1100113911Sdes auth_clear_options(); 1101113911Sdes have_forced = buffer_get_int(&m); 1102113911Sdes forced_command = have_forced ? xstrdup("true") : NULL; 1103113911Sdes 110498675Sdes if (allowed && rkey != NULL) { 110598675Sdes blob = buffer_get_string(&m, &blen); 110698675Sdes if ((key = key_from_blob(blob, blen)) == NULL) 110798675Sdes fatal("%s: key_from_blob failed", __func__); 110898675Sdes *rkey = key; 1109255767Sdes free(blob); 111098675Sdes } 111198675Sdes buffer_free(&m); 111298675Sdes 111398675Sdes return (allowed); 111498675Sdes} 111598675Sdes 111698675SdesBIGNUM * 111798675Sdesmm_auth_rsa_generate_challenge(Key *key) 111898675Sdes{ 111998675Sdes Buffer m; 112098675Sdes BIGNUM *challenge; 112198675Sdes u_char *blob; 112298675Sdes u_int blen; 112398675Sdes 112498675Sdes debug3("%s entering", __func__); 112598675Sdes 112698675Sdes if ((challenge = BN_new()) == NULL) 112798675Sdes fatal("%s: BN_new failed", __func__); 112898675Sdes 112998675Sdes key->type = KEY_RSA; /* XXX cheat for key_to_blob */ 113098675Sdes if (key_to_blob(key, &blob, &blen) == 0) 113198675Sdes fatal("%s: key_to_blob failed", __func__); 113298675Sdes key->type = KEY_RSA1; 113398675Sdes 113498675Sdes buffer_init(&m); 113598675Sdes buffer_put_string(&m, blob, blen); 1136255767Sdes free(blob); 113798675Sdes 113898675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); 113998675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); 114098675Sdes 114198675Sdes buffer_get_bignum2(&m, challenge); 114298675Sdes buffer_free(&m); 114398675Sdes 114498675Sdes return (challenge); 114598675Sdes} 114698675Sdes 114798675Sdesint 114898675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) 114998675Sdes{ 115098675Sdes Buffer m; 115198675Sdes u_char *blob; 115298675Sdes u_int blen; 115398675Sdes int success = 0; 115498675Sdes 115598675Sdes debug3("%s entering", __func__); 115698675Sdes 115798675Sdes key->type = KEY_RSA; /* XXX cheat for key_to_blob */ 115898675Sdes if (key_to_blob(key, &blob, &blen) == 0) 115998675Sdes fatal("%s: key_to_blob failed", __func__); 116098675Sdes key->type = KEY_RSA1; 116198675Sdes 116298675Sdes buffer_init(&m); 116398675Sdes buffer_put_string(&m, blob, blen); 116498675Sdes buffer_put_string(&m, response, 16); 1165255767Sdes free(blob); 116698675Sdes 116798675Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); 116898675Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); 116998675Sdes 117098675Sdes success = buffer_get_int(&m); 117198675Sdes buffer_free(&m); 117298675Sdes 117398675Sdes return (success); 117498675Sdes} 1175106130Sdes 1176147005Sdes#ifdef SSH_AUDIT_EVENTS 1177147005Sdesvoid 1178147005Sdesmm_audit_event(ssh_audit_event_t event) 1179147005Sdes{ 1180147005Sdes Buffer m; 1181147005Sdes 1182147005Sdes debug3("%s entering", __func__); 1183147005Sdes 1184147005Sdes buffer_init(&m); 1185147005Sdes buffer_put_int(&m, event); 1186147005Sdes 1187147005Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m); 1188147005Sdes buffer_free(&m); 1189147005Sdes} 1190147005Sdes 1191147005Sdesvoid 1192147005Sdesmm_audit_run_command(const char *command) 1193147005Sdes{ 1194147005Sdes Buffer m; 1195147005Sdes 1196147005Sdes debug3("%s entering command %s", __func__, command); 1197147005Sdes 1198147005Sdes buffer_init(&m); 1199147005Sdes buffer_put_cstring(&m, command); 1200147005Sdes 1201147005Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m); 1202147005Sdes buffer_free(&m); 1203147005Sdes} 1204147005Sdes#endif /* SSH_AUDIT_EVENTS */ 1205147005Sdes 1206124211Sdes#ifdef GSSAPI 1207124211SdesOM_uint32 1208137019Sdesmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) 1209106130Sdes{ 1210124211Sdes Buffer m; 1211124211Sdes OM_uint32 major; 1212106130Sdes 1213124211Sdes /* Client doesn't get to see the context */ 1214124211Sdes *ctx = NULL; 1215106130Sdes 1216106130Sdes buffer_init(&m); 1217137019Sdes buffer_put_string(&m, goid->elements, goid->length); 1218106130Sdes 1219124211Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m); 1220124211Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m); 1221106130Sdes 1222124211Sdes major = buffer_get_int(&m); 1223124211Sdes 1224106130Sdes buffer_free(&m); 1225124211Sdes return (major); 1226106130Sdes} 1227106130Sdes 1228124211SdesOM_uint32 1229124211Sdesmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, 1230124211Sdes gss_buffer_desc *out, OM_uint32 *flags) 1231124211Sdes{ 1232124211Sdes Buffer m; 1233124211Sdes OM_uint32 major; 1234124211Sdes u_int len; 1235124211Sdes 1236124211Sdes buffer_init(&m); 1237124211Sdes buffer_put_string(&m, in->value, in->length); 1238124211Sdes 1239124211Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m); 1240124211Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m); 1241124211Sdes 1242124211Sdes major = buffer_get_int(&m); 1243124211Sdes out->value = buffer_get_string(&m, &len); 1244124211Sdes out->length = len; 1245124211Sdes if (flags) 1246124211Sdes *flags = buffer_get_int(&m); 1247124211Sdes 1248124211Sdes buffer_free(&m); 1249124211Sdes 1250124211Sdes return (major); 1251124211Sdes} 1252124211Sdes 1253126277SdesOM_uint32 1254126277Sdesmm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 1255126277Sdes{ 1256126277Sdes Buffer m; 1257126277Sdes OM_uint32 major; 1258126277Sdes 1259126277Sdes buffer_init(&m); 1260126277Sdes buffer_put_string(&m, gssbuf->value, gssbuf->length); 1261126277Sdes buffer_put_string(&m, gssmic->value, gssmic->length); 1262126277Sdes 1263126277Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m); 1264126277Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC, 1265126277Sdes &m); 1266126277Sdes 1267126277Sdes major = buffer_get_int(&m); 1268126277Sdes buffer_free(&m); 1269126277Sdes return(major); 1270126277Sdes} 1271126277Sdes 1272106130Sdesint 1273124211Sdesmm_ssh_gssapi_userok(char *user) 1274106130Sdes{ 1275106130Sdes Buffer m; 1276124211Sdes int authenticated = 0; 1277106130Sdes 1278106130Sdes buffer_init(&m); 1279106130Sdes 1280124211Sdes mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m); 1281124211Sdes mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, 1282124211Sdes &m); 1283106130Sdes 1284124211Sdes authenticated = buffer_get_int(&m); 1285106130Sdes 1286106130Sdes buffer_free(&m); 1287124211Sdes debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); 1288124211Sdes return (authenticated); 1289106130Sdes} 1290124211Sdes#endif /* GSSAPI */ 1291192595Sdes 1292