1190203Srpaulo/* $NetBSD: monitor_wrap.c,v 1.34 2023/12/20 17:15:20 christos Exp $ */ 2190203Srpaulo/* $OpenBSD: monitor_wrap.c,v 1.129 2023/12/18 14:45:49 djm Exp $ */ 3190203Srpaulo 4190203Srpaulo/* 5190203Srpaulo * Copyright 2002 Niels Provos <provos@citi.umich.edu> 6190203Srpaulo * Copyright 2002 Markus Friedl <markus@openbsd.org> 7190203Srpaulo * All rights reserved. 8190203Srpaulo * 9190203Srpaulo * Redistribution and use in source and binary forms, with or without 10190203Srpaulo * modification, are permitted provided that the following conditions 11190203Srpaulo * are met: 12190203Srpaulo * 1. Redistributions of source code must retain the above copyright 13190203Srpaulo * notice, this list of conditions and the following disclaimer. 14190203Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 15235530Sdelphij * notice, this list of conditions and the following disclaimer in the 16190203Srpaulo * documentation and/or other materials provided with the distribution. 17190203Srpaulo * 18190203Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19235530Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20190203Srpaulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21190203Srpaulo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22190203Srpaulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23190203Srpaulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24214478Srpaulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25190203Srpaulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26190203Srpaulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27190203Srpaulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28190203Srpaulo */ 29190203Srpaulo 30190203Srpaulo#include "includes.h" 31190203Srpaulo__RCSID("$NetBSD: monitor_wrap.c,v 1.34 2023/12/20 17:15:20 christos Exp $"); 32190203Srpaulo#include <sys/types.h> 33190203Srpaulo#include <sys/uio.h> 34190203Srpaulo#include <sys/queue.h> 35190203Srpaulo 36190203Srpaulo#include <errno.h> 37190203Srpaulo#include <pwd.h> 38190203Srpaulo#include <signal.h> 39190203Srpaulo#include <stdio.h> 40190203Srpaulo#include <string.h> 41190203Srpaulo#include <stdarg.h> 42190203Srpaulo#include <unistd.h> 43190203Srpaulo 44190203Srpaulo#ifdef WITH_OPENSSL 45190203Srpaulo#include <openssl/bn.h> 46190203Srpaulo#include <openssl/dh.h> 47190203Srpaulo#endif 48190203Srpaulo 49190203Srpaulo#include "xmalloc.h" 50190203Srpaulo#include "ssh.h" 51190203Srpaulo#ifdef WITH_OPENSSL 52190203Srpaulo#include "dh.h" 53190203Srpaulo#endif 54190203Srpaulo#include "sshbuf.h" 55190203Srpaulo#include "sshkey.h" 56190203Srpaulo#include "cipher.h" 57190203Srpaulo#include "kex.h" 58190203Srpaulo#include "hostfile.h" 59190203Srpaulo#include "auth.h" 60190203Srpaulo#include "auth-options.h" 61190203Srpaulo#include "packet.h" 62190203Srpaulo#include "mac.h" 63190203Srpaulo#include "log.h" 64190203Srpaulo#include "monitor.h" 65190203Srpaulo#ifdef GSSAPI 66190203Srpaulo#include "ssh-gss.h" 67190203Srpaulo#endif 68190203Srpaulo#include "monitor_wrap.h" 69190203Srpaulo#include "atomicio.h" 70190203Srpaulo#include "monitor_fdpass.h" 71190203Srpaulo#ifdef USE_PAM 72190203Srpaulo#include "misc.h" 73190203Srpaulo#include "servconf.h" 74190203Srpaulo#include <security/pam_appl.h> 75190203Srpaulo#endif 76190203Srpaulo#include "misc.h" 77190203Srpaulo 78190203Srpaulo#include "channels.h" 79190203Srpaulo#include "session.h" 80190203Srpaulo#include "servconf.h" 81190203Srpaulo 82190203Srpaulo#include "ssherr.h" 83190203Srpaulo 84190203Srpaulo/* Imports */ 85190203Srpauloextern struct monitor *pmonitor; 86190203Srpauloextern struct sshbuf *loginmsg; 87190203Srpauloextern ServerOptions options; 88190203Srpaulo 89190203Srpaulovoid 90190203Srpaulomm_log_handler(LogLevel level, int forced, const char *msg, void *ctx) 91190203Srpaulo{ 92190203Srpaulo struct sshbuf *log_msg; 93190203Srpaulo struct monitor *mon = (struct monitor *)ctx; 94190203Srpaulo int r; 95190203Srpaulo size_t len; 96190203Srpaulo 97190203Srpaulo if (mon->m_log_sendfd == -1) 98190203Srpaulo fatal_f("no log channel"); 99190203Srpaulo 100190203Srpaulo if ((log_msg = sshbuf_new()) == NULL) 101190203Srpaulo fatal_f("sshbuf_new failed"); 102190203Srpaulo 103190203Srpaulo if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */ 104190203Srpaulo (r = sshbuf_put_u32(log_msg, level)) != 0 || 105190203Srpaulo (r = sshbuf_put_u32(log_msg, forced)) != 0 || 106190203Srpaulo (r = sshbuf_put_cstring(log_msg, msg)) != 0) 107190203Srpaulo fatal_fr(r, "assemble"); 108190203Srpaulo if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff) 109190203Srpaulo fatal_f("bad length %zu", len); 110190203Srpaulo POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4); 111190203Srpaulo if (atomicio(vwrite, mon->m_log_sendfd, 112190203Srpaulo sshbuf_mutable_ptr(log_msg), len) != len) 113190203Srpaulo fatal_f("write: %s", strerror(errno)); 114190203Srpaulo sshbuf_free(log_msg); 115190203Srpaulo} 116190203Srpaulo 117190203Srpauloint 118190203Srpaulomm_is_monitor(void) 119190203Srpaulo{ 120190203Srpaulo /* 121190203Srpaulo * m_pid is only set in the privileged part, and 122190203Srpaulo * points to the unprivileged child. 123190203Srpaulo */ 124190203Srpaulo return (pmonitor && pmonitor->m_pid > 0); 125190203Srpaulo} 126190203Srpaulo 127190203Srpaulovoid 128190203Srpaulomm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m) 129190203Srpaulo{ 130190203Srpaulo size_t mlen = sshbuf_len(m); 131190203Srpaulo u_char buf[5]; 132190203Srpaulo 133190203Srpaulo debug3_f("entering, type %d", type); 134190203Srpaulo 135190203Srpaulo if (mlen >= 0xffffffff) 136190203Srpaulo fatal_f("bad length %zu", mlen); 137190203Srpaulo POKE_U32(buf, mlen + 1); 138190203Srpaulo buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ 139190203Srpaulo if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf)) 140190203Srpaulo fatal_f("write: %s", strerror(errno)); 141190203Srpaulo if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen) 142190203Srpaulo fatal_f("write: %s", strerror(errno)); 143190203Srpaulo} 144190203Srpaulo 145190203Srpaulovoid 146190203Srpaulomm_request_receive(int sock, struct sshbuf *m) 147190203Srpaulo{ 148190203Srpaulo u_char buf[4], *p = NULL; 149190203Srpaulo u_int msg_len; 150190203Srpaulo int r; 151190203Srpaulo 152190203Srpaulo debug3_f("entering"); 153190203Srpaulo 154190203Srpaulo if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) { 155190203Srpaulo if (errno == EPIPE) 156190203Srpaulo cleanup_exit(254); 157190203Srpaulo fatal_f("read: %s", strerror(errno)); 158190203Srpaulo } 159190203Srpaulo msg_len = PEEK_U32(buf); 160190203Srpaulo if (msg_len > 256 * 1024) 161190203Srpaulo fatal_f("read: bad msg_len %d", msg_len); 162190203Srpaulo sshbuf_reset(m); 163190203Srpaulo if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 164190203Srpaulo fatal_fr(r, "reserve"); 165190203Srpaulo if (atomicio(read, sock, p, msg_len) != msg_len) 166190203Srpaulo fatal_f("read: %s", strerror(errno)); 167190203Srpaulo} 168190203Srpaulo 169190203Srpaulovoid 170190203Srpaulomm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m) 171190203Srpaulo{ 172190203Srpaulo u_char rtype; 173190203Srpaulo int r; 174190203Srpaulo 175190203Srpaulo debug3_f("entering, type %d", type); 176190203Srpaulo 177190203Srpaulo mm_request_receive(sock, m); 178190203Srpaulo if ((r = sshbuf_get_u8(m, &rtype)) != 0) 179190203Srpaulo fatal_fr(r, "parse"); 180190203Srpaulo if (rtype != type) 181190203Srpaulo fatal_f("read: rtype %d != type %d", rtype, type); 182190203Srpaulo} 183190203Srpaulo 184190203Srpaulo#ifdef WITH_OPENSSL 185190203SrpauloDH * 186190203Srpaulomm_choose_dh(int min, int nbits, int max) 187190203Srpaulo{ 188190203Srpaulo BIGNUM *p, *g; 189190203Srpaulo int r; 190190203Srpaulo u_char success = 0; 191190203Srpaulo struct sshbuf *m; 192190203Srpaulo 193190203Srpaulo if ((m = sshbuf_new()) == NULL) 194190203Srpaulo fatal_f("sshbuf_new failed"); 195190203Srpaulo if ((r = sshbuf_put_u32(m, min)) != 0 || 196190203Srpaulo (r = sshbuf_put_u32(m, nbits)) != 0 || 197190203Srpaulo (r = sshbuf_put_u32(m, max)) != 0) 198190203Srpaulo fatal_fr(r, "assemble"); 199190203Srpaulo 200190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m); 201190203Srpaulo 202190203Srpaulo debug3_f("waiting for MONITOR_ANS_MODULI"); 203190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m); 204190203Srpaulo 205190203Srpaulo if ((r = sshbuf_get_u8(m, &success)) != 0) 206190203Srpaulo fatal_fr(r, "parse success"); 207190203Srpaulo if (success == 0) 208190203Srpaulo fatal_f("MONITOR_ANS_MODULI failed"); 209190203Srpaulo 210190203Srpaulo if ((r = sshbuf_get_bignum2(m, &p)) != 0 || 211190203Srpaulo (r = sshbuf_get_bignum2(m, &g)) != 0) 212190203Srpaulo fatal_fr(r, "parse group"); 213190203Srpaulo 214190203Srpaulo debug3_f("remaining %zu", sshbuf_len(m)); 215190203Srpaulo sshbuf_free(m); 216190203Srpaulo 217190203Srpaulo return (dh_new_group(g, p)); 218190203Srpaulo} 219190203Srpaulo#endif 220190203Srpaulo 221190203Srpauloint 222190203Srpaulomm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, 223190203Srpaulo const u_char *data, size_t datalen, const char *hostkey_alg, 224190203Srpaulo const char *sk_provider, const char *sk_pin, u_int compat) 225190203Srpaulo{ 226190203Srpaulo struct kex *kex = *pmonitor->m_pkex; 227190203Srpaulo struct sshbuf *m; 228190203Srpaulo u_int ndx = kex->host_key_index(key, 0, ssh); 229190203Srpaulo int r; 230190203Srpaulo 231190203Srpaulo debug3_f("entering"); 232190203Srpaulo if ((m = sshbuf_new()) == NULL) 233190203Srpaulo fatal_f("sshbuf_new failed"); 234190203Srpaulo if ((r = sshbuf_put_u32(m, ndx)) != 0 || 235190203Srpaulo (r = sshbuf_put_string(m, data, datalen)) != 0 || 236190203Srpaulo (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 || 237190203Srpaulo (r = sshbuf_put_u32(m, compat)) != 0) 238190203Srpaulo fatal_fr(r, "assemble"); 239190203Srpaulo 240190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m); 241190203Srpaulo 242190203Srpaulo debug3_f("waiting for MONITOR_ANS_SIGN"); 243190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m); 244190203Srpaulo if ((r = sshbuf_get_string(m, sigp, lenp)) != 0) 245190203Srpaulo fatal_fr(r, "parse"); 246190203Srpaulo sshbuf_free(m); 247190203Srpaulo 248190203Srpaulo return (0); 249190203Srpaulo} 250190203Srpaulo 251190203Srpaulo#define GETPW(b, id) \ 252190203Srpaulo do { \ 253190203Srpaulo if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \ 254190203Srpaulo fatal_fr(r, "parse pw %s", #id); \ 255190203Srpaulo if (len != sizeof(pw->id)) \ 256190203Srpaulo fatal_fr(r, "bad length for %s", #id); \ 257190203Srpaulo memcpy(&pw->id, p, len); \ 258190203Srpaulo } while (0) 259190203Srpaulo 260190203Srpaulostruct passwd * 261190203Srpaulomm_getpwnamallow(struct ssh *ssh, const char *username) 262190203Srpaulo{ 263190203Srpaulo struct sshbuf *m; 264190203Srpaulo struct passwd *pw; 265190203Srpaulo size_t len; 266190203Srpaulo u_int i; 267190203Srpaulo ServerOptions *newopts; 268190203Srpaulo int r; 269190203Srpaulo u_char ok; 270190203Srpaulo const u_char *p; 271190203Srpaulo 272190203Srpaulo debug3_f("entering"); 273190203Srpaulo 274190203Srpaulo if ((m = sshbuf_new()) == NULL) 275190203Srpaulo fatal_f("sshbuf_new failed"); 276190203Srpaulo if ((r = sshbuf_put_cstring(m, username)) != 0) 277190203Srpaulo fatal_fr(r, "assemble"); 278190203Srpaulo 279190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m); 280190203Srpaulo 281190203Srpaulo debug3_f("waiting for MONITOR_ANS_PWNAM"); 282190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m); 283190203Srpaulo 284190203Srpaulo if ((r = sshbuf_get_u8(m, &ok)) != 0) 285190203Srpaulo fatal_fr(r, "parse success"); 286190203Srpaulo if (ok == 0) { 287190203Srpaulo pw = NULL; 288190203Srpaulo goto out; 289190203Srpaulo } 290190203Srpaulo 291190203Srpaulo pw = xcalloc(sizeof(*pw), 1); 292190203Srpaulo GETPW(m, pw_uid); 293190203Srpaulo GETPW(m, pw_gid); 294190203Srpaulo GETPW(m, pw_change); 295190203Srpaulo GETPW(m, pw_expire); 296190203Srpaulo if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 || 297190203Srpaulo (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 || 298190203Srpaulo (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 || 299190203Srpaulo (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 || 300190203Srpaulo (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 || 301190203Srpaulo (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0) 302190203Srpaulo fatal_fr(r, "parse pw"); 303190203Srpaulo 304190203Srpauloout: 305190203Srpaulo /* copy options block as a Match directive may have changed some */ 306190203Srpaulo if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0) 307190203Srpaulo fatal_fr(r, "parse opts"); 308190203Srpaulo if (len != sizeof(*newopts)) 309190203Srpaulo fatal_f("option block size mismatch"); 310190203Srpaulo newopts = xcalloc(sizeof(*newopts), 1); 311190203Srpaulo memcpy(newopts, p, sizeof(*newopts)); 312190203Srpaulo 313190203Srpaulo#define M_CP_STROPT(x) do { \ 314190203Srpaulo if (newopts->x != NULL && \ 315190203Srpaulo (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \ 316190203Srpaulo fatal_fr(r, "parse %s", #x); \ 317190203Srpaulo } while (0) 318190203Srpaulo#define M_CP_STRARRAYOPT(x, nx) do { \ 319190203Srpaulo newopts->x = newopts->nx == 0 ? \ 320190203Srpaulo NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \ 321190203Srpaulo for (i = 0; i < newopts->nx; i++) { \ 322190203Srpaulo if ((r = sshbuf_get_cstring(m, \ 323190203Srpaulo &newopts->x[i], NULL)) != 0) \ 324190203Srpaulo fatal_fr(r, "parse %s", #x); \ 325190203Srpaulo } \ 326190203Srpaulo } while (0) 327190203Srpaulo /* See comment in servconf.h */ 328190203Srpaulo COPY_MATCH_STRING_OPTS(); 329190203Srpaulo#undef M_CP_STROPT 330190203Srpaulo#undef M_CP_STRARRAYOPT 331190203Srpaulo 332190203Srpaulo copy_set_server_options(&options, newopts, 1); 333190203Srpaulo log_change_level(options.log_level); 334190203Srpaulo log_verbose_reset(); 335190203Srpaulo for (i = 0; i < options.num_log_verbose; i++) 336190203Srpaulo log_verbose_add(options.log_verbose[i]); 337190203Srpaulo process_permitopen(ssh, &options); 338190203Srpaulo process_channel_timeouts(ssh, &options); 339190203Srpaulo kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); 340190203Srpaulo free(newopts); 341190203Srpaulo sshbuf_free(m); 342190203Srpaulo 343190203Srpaulo return (pw); 344190203Srpaulo} 345190203Srpaulo 346190203Srpaulochar * 347190203Srpaulomm_auth2_read_banner(void) 348190203Srpaulo{ 349190203Srpaulo struct sshbuf *m; 350190203Srpaulo char *banner; 351190203Srpaulo int r; 352190203Srpaulo 353190203Srpaulo debug3_f("entering"); 354190203Srpaulo 355190203Srpaulo if ((m = sshbuf_new()) == NULL) 356190203Srpaulo fatal_f("sshbuf_new failed"); 357190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m); 358190203Srpaulo sshbuf_reset(m); 359190203Srpaulo 360190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 361190203Srpaulo MONITOR_ANS_AUTH2_READ_BANNER, m); 362190203Srpaulo if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0) 363190203Srpaulo fatal_fr(r, "parse"); 364190203Srpaulo sshbuf_free(m); 365190203Srpaulo 366190203Srpaulo /* treat empty banner as missing banner */ 367190203Srpaulo if (strlen(banner) == 0) { 368190203Srpaulo free(banner); 369190203Srpaulo banner = NULL; 370190203Srpaulo } 371190203Srpaulo return (banner); 372190203Srpaulo} 373190203Srpaulo 374190203Srpaulo/* Inform the privileged process about service and style */ 375190203Srpaulo 376190203Srpaulovoid 377190203Srpaulomm_inform_authserv(char *service, char *style) 378190203Srpaulo{ 379190203Srpaulo struct sshbuf *m; 380190203Srpaulo int r; 381190203Srpaulo 382190203Srpaulo debug3_f("entering"); 383190203Srpaulo 384190203Srpaulo if ((m = sshbuf_new()) == NULL) 385190203Srpaulo fatal_f("sshbuf_new failed"); 386190203Srpaulo if ((r = sshbuf_put_cstring(m, service)) != 0 || 387190203Srpaulo (r = sshbuf_put_cstring(m, style ? style : "")) != 0) 388241235Sdelphij fatal_fr(r, "assemble"); 389190203Srpaulo 390241235Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); 391190203Srpaulo 392190203Srpaulo sshbuf_free(m); 393190203Srpaulo} 394190203Srpaulo 395190203Srpaulo/* Do the password authentication */ 396190203Srpauloint 397190203Srpaulomm_auth_password(struct ssh *ssh, const char *password) 398190203Srpaulo{ 399190203Srpaulo struct sshbuf *m; 400190203Srpaulo int r; 401190203Srpaulo u_int authenticated = 0; 402190203Srpaulo 403190203Srpaulo debug3_f("entering"); 404190203Srpaulo 405190203Srpaulo if ((m = sshbuf_new()) == NULL) 406190203Srpaulo fatal_f("sshbuf_new failed"); 407190203Srpaulo if ((r = sshbuf_put_cstring(m, password)) != 0) 408190203Srpaulo fatal_fr(r, "assemble"); 409190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m); 410190203Srpaulo 411190203Srpaulo debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD"); 412190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 413190203Srpaulo MONITOR_ANS_AUTHPASSWORD, m); 414190203Srpaulo 415190203Srpaulo if ((r = sshbuf_get_u32(m, &authenticated)) != 0) 416190203Srpaulo fatal_fr(r, "parse"); 417190203Srpaulo 418190203Srpaulo sshbuf_free(m); 419190203Srpaulo 420190203Srpaulo debug3_f("user %sauthenticated", authenticated ? "" : "not "); 421190203Srpaulo return (authenticated); 422190203Srpaulo} 423190203Srpaulo 424190203Srpauloint 425190203Srpaulomm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, 426190203Srpaulo int pubkey_auth_attempt, struct sshauthopt **authoptp) 427190203Srpaulo{ 428190203Srpaulo return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, 429190203Srpaulo pubkey_auth_attempt, authoptp)); 430190203Srpaulo} 431190203Srpaulo 432190203Srpauloint 433190203Srpaulomm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, 434190203Srpaulo const char *user, const char *host, struct sshkey *key) 435190203Srpaulo{ 436190203Srpaulo return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); 437190203Srpaulo} 438190203Srpaulo 439190203Srpauloint 440190203Srpaulomm_key_allowed(enum mm_keytype type, const char *user, const char *host, 441190203Srpaulo struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) 442190203Srpaulo{ 443190203Srpaulo struct sshbuf *m; 444190203Srpaulo int r; 445190203Srpaulo u_int allowed = 0; 446190203Srpaulo struct sshauthopt *opts = NULL; 447190203Srpaulo 448190203Srpaulo debug3_f("entering"); 449190203Srpaulo 450190203Srpaulo if (authoptp != NULL) 451190203Srpaulo *authoptp = NULL; 452190203Srpaulo 453190203Srpaulo if ((m = sshbuf_new()) == NULL) 454190203Srpaulo fatal_f("sshbuf_new failed"); 455190203Srpaulo if ((r = sshbuf_put_u32(m, type)) != 0 || 456190203Srpaulo (r = sshbuf_put_cstring(m, user ? user : "")) != 0 || 457190203Srpaulo (r = sshbuf_put_cstring(m, host ? host : "")) != 0 || 458190203Srpaulo (r = sshkey_puts(key, m)) != 0 || 459190203Srpaulo (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0) 460190203Srpaulo fatal_fr(r, "assemble"); 461190203Srpaulo 462190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m); 463190203Srpaulo 464190203Srpaulo debug3_f("waiting for MONITOR_ANS_KEYALLOWED"); 465190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 466190203Srpaulo MONITOR_ANS_KEYALLOWED, m); 467190203Srpaulo 468190203Srpaulo if ((r = sshbuf_get_u32(m, &allowed)) != 0) 469190203Srpaulo fatal_fr(r, "parse"); 470190203Srpaulo if (allowed && type == MM_USERKEY && 471190203Srpaulo (r = sshauthopt_deserialise(m, &opts)) != 0) 472190203Srpaulo fatal_fr(r, "sshauthopt_deserialise"); 473190203Srpaulo sshbuf_free(m); 474190203Srpaulo 475190203Srpaulo if (authoptp != NULL) { 476190203Srpaulo *authoptp = opts; 477190203Srpaulo opts = NULL; 478190203Srpaulo } 479190203Srpaulo sshauthopt_free(opts); 480190203Srpaulo 481190203Srpaulo return allowed; 482190203Srpaulo} 483190203Srpaulo 484190203Srpaulo/* 485190203Srpaulo * This key verify needs to send the key type along, because the 486190203Srpaulo * privileged parent makes the decision if the key is allowed 487190203Srpaulo * for authentication. 488190203Srpaulo */ 489190203Srpaulo 490190203Srpauloint 491190203Srpaulomm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, 492190203Srpaulo const u_char *data, size_t datalen, const char *sigalg, u_int compat, 493190203Srpaulo struct sshkey_sig_details **sig_detailsp) 494190203Srpaulo{ 495190203Srpaulo struct sshbuf *m; 496190203Srpaulo u_int encoded_ret = 0; 497190203Srpaulo int r; 498190203Srpaulo u_char sig_details_present, flags; 499190203Srpaulo u_int counter; 500190203Srpaulo 501190203Srpaulo debug3_f("entering"); 502190203Srpaulo 503190203Srpaulo if (sig_detailsp != NULL) 504190203Srpaulo *sig_detailsp = NULL; 505190203Srpaulo if ((m = sshbuf_new()) == NULL) 506190203Srpaulo fatal_f("sshbuf_new failed"); 507190203Srpaulo if ((r = sshkey_puts(key, m)) != 0 || 508190203Srpaulo (r = sshbuf_put_string(m, sig, siglen)) != 0 || 509190203Srpaulo (r = sshbuf_put_string(m, data, datalen)) != 0 || 510190203Srpaulo (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) 511190203Srpaulo fatal_fr(r, "assemble"); 512190203Srpaulo 513190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m); 514190203Srpaulo 515190203Srpaulo debug3_f("waiting for MONITOR_ANS_KEYVERIFY"); 516190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 517190203Srpaulo MONITOR_ANS_KEYVERIFY, m); 518190203Srpaulo 519190203Srpaulo if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 || 520190203Srpaulo (r = sshbuf_get_u8(m, &sig_details_present)) != 0) 521190203Srpaulo fatal_fr(r, "parse"); 522190203Srpaulo if (sig_details_present && encoded_ret == 0) { 523190203Srpaulo if ((r = sshbuf_get_u32(m, &counter)) != 0 || 524190203Srpaulo (r = sshbuf_get_u8(m, &flags)) != 0) 525190203Srpaulo fatal_fr(r, "parse sig_details"); 526190203Srpaulo if (sig_detailsp != NULL) { 527190203Srpaulo *sig_detailsp = xcalloc(1, sizeof(**sig_detailsp)); 528190203Srpaulo (*sig_detailsp)->sk_counter = counter; 529190203Srpaulo (*sig_detailsp)->sk_flags = flags; 530190203Srpaulo } 531190203Srpaulo } 532190203Srpaulo 533190203Srpaulo sshbuf_free(m); 534190203Srpaulo 535190203Srpaulo if (encoded_ret != 0) 536190203Srpaulo return SSH_ERR_SIGNATURE_INVALID; 537190203Srpaulo return 0; 538190203Srpaulo} 539190203Srpaulo 540190203Srpaulovoid 541190203Srpaulomm_send_keystate(struct ssh *ssh, struct monitor *monitor) 542190203Srpaulo{ 543190203Srpaulo struct sshbuf *m; 544190203Srpaulo int r; 545190203Srpaulo 546235530Sdelphij if ((m = sshbuf_new()) == NULL) 547235530Sdelphij fatal_f("sshbuf_new failed"); 548235530Sdelphij if ((r = ssh_packet_get_state(ssh, m)) != 0) 549235530Sdelphij fatal_fr(r, "ssh_packet_get_state"); 550235530Sdelphij mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); 551235530Sdelphij debug3_f("Finished sending state"); 552235530Sdelphij sshbuf_free(m); 553235530Sdelphij} 554235530Sdelphij 555235530Sdelphijint 556235530Sdelphijmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) 557235530Sdelphij{ 558235530Sdelphij struct sshbuf *m; 559235530Sdelphij char *p, *msg; 560235530Sdelphij u_int success = 0; 561235530Sdelphij int tmp1 = -1, tmp2 = -1, r; 562235530Sdelphij 563190203Srpaulo /* Kludge: ensure there are fds free to receive the pty/tty */ 564190203Srpaulo if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || 565190203Srpaulo (tmp2 = dup(pmonitor->m_recvfd)) == -1) { 566190203Srpaulo error_f("cannot allocate fds for pty"); 567190203Srpaulo if (tmp1 >= 0) 568190203Srpaulo close(tmp1); 569190203Srpaulo return 0; 570190203Srpaulo } 571190203Srpaulo close(tmp1); 572190203Srpaulo close(tmp2); 573190203Srpaulo 574190203Srpaulo if ((m = sshbuf_new()) == NULL) 575190203Srpaulo fatal_f("sshbuf_new failed"); 576190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m); 577235530Sdelphij 578190203Srpaulo debug3_f("waiting for MONITOR_ANS_PTY"); 579190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m); 580235530Sdelphij 581190203Srpaulo if ((r = sshbuf_get_u32(m, &success)) != 0) 582190203Srpaulo fatal_fr(r, "parse success"); 583235530Sdelphij if (success == 0) { 584190203Srpaulo debug3_f("pty alloc failed"); 585235530Sdelphij sshbuf_free(m); 586235530Sdelphij return (0); 587235530Sdelphij } 588190203Srpaulo if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 || 589190203Srpaulo (r = sshbuf_get_cstring(m, &msg, NULL)) != 0) 590190203Srpaulo fatal_fr(r, "parse"); 591190203Srpaulo sshbuf_free(m); 592190203Srpaulo 593190203Srpaulo strlcpy(namebuf, p, namebuflen); /* Possible truncation */ 594190203Srpaulo free(p); 595190203Srpaulo 596235530Sdelphij if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0) 597235530Sdelphij fatal_fr(r, "put loginmsg"); 598235530Sdelphij free(msg); 599190203Srpaulo 600190203Srpaulo if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 || 601190203Srpaulo (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1) 602190203Srpaulo fatal_f("receive fds failed"); 603235530Sdelphij 604235530Sdelphij /* Success */ 605235530Sdelphij return (1); 606190203Srpaulo} 607190203Srpaulo 608190203Srpaulovoid 609190203Srpaulomm_session_pty_cleanup2(Session *s) 610190203Srpaulo{ 611190203Srpaulo struct sshbuf *m; 612235530Sdelphij int r; 613235530Sdelphij 614235530Sdelphij if (s->ttyfd == -1) 615190203Srpaulo return; 616190203Srpaulo if ((m = sshbuf_new()) == NULL) 617235530Sdelphij fatal_f("sshbuf_new failed"); 618235530Sdelphij if ((r = sshbuf_put_cstring(m, s->tty)) != 0) 619235530Sdelphij fatal_fr(r, "assmble"); 620235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m); 621235530Sdelphij sshbuf_free(m); 622235530Sdelphij 623235530Sdelphij /* closed dup'ed master */ 624190203Srpaulo if (s->ptymaster != -1 && close(s->ptymaster) == -1) 625235530Sdelphij error("close(s->ptymaster/%d): %s", 626190203Srpaulo s->ptymaster, strerror(errno)); 627190203Srpaulo 628235530Sdelphij /* unlink pty from session */ 629235530Sdelphij s->ttyfd = -1; 630235530Sdelphij} 631235530Sdelphij 632235530Sdelphij#ifdef USE_PAM 633235530Sdelphijvoid 634235530Sdelphijmm_start_pam(struct ssh *ssh) 635190203Srpaulo{ 636235530Sdelphij struct sshbuf *m; 637190203Srpaulo 638190203Srpaulo debug3("%s entering", __func__); 639190203Srpaulo if (!options.use_pam) 640190203Srpaulo fatal("UsePAM=no, but ended up in %s anyway", __func__); 641190203Srpaulo 642190203Srpaulo if ((m = sshbuf_new()) == NULL) 643190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 644190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m); 645190203Srpaulo 646190203Srpaulo sshbuf_free(m); 647190203Srpaulo} 648235530Sdelphij 649190203Srpaulou_int 650190203Srpaulomm_do_pam_account(void) 651235530Sdelphij{ 652190203Srpaulo struct sshbuf *m; 653190203Srpaulo int r; 654190203Srpaulo u_int ret; 655235530Sdelphij size_t len; 656235530Sdelphij char *msg; 657235530Sdelphij 658190203Srpaulo debug3("%s entering", __func__); 659190203Srpaulo if (!options.use_pam) 660190203Srpaulo fatal("UsePAM=no, but ended up in %s anyway", __func__); 661190203Srpaulo 662190203Srpaulo if ((m = sshbuf_new()) == NULL) 663190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 664190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m); 665190203Srpaulo 666235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, 667235530Sdelphij MONITOR_ANS_PAM_ACCOUNT, m); 668235530Sdelphij if ((r = sshbuf_get_u32(m, &ret)) != 0 || 669190203Srpaulo (r = sshbuf_get_cstring(m, &msg, &len)) != 0) 670190203Srpaulo fatal("%s: buffer error: %s", __func__, ssh_err(r)); 671190203Srpaulo sshbuf_put_cstring(loginmsg, msg); 672190203Srpaulo free(msg); 673190203Srpaulo 674190203Srpaulo sshbuf_free(m); 675190203Srpaulo 676190203Srpaulo debug3("%s returning %d", __func__, ret); 677190203Srpaulo 678190203Srpaulo return (ret); 679190203Srpaulo} 680190203Srpaulo 681235530Sdelphijvoid * 682235530Sdelphijmm_sshpam_init_ctx(Authctxt *authctxt) 683235530Sdelphij{ 684190203Srpaulo struct sshbuf *m; 685190203Srpaulo u_int success; 686190203Srpaulo int r; 687190203Srpaulo 688190203Srpaulo debug3("%s", __func__); 689190203Srpaulo if ((m = sshbuf_new()) == NULL) 690190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 691235530Sdelphij sshbuf_put_cstring(m, authctxt->user); 692235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m); 693235530Sdelphij debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); 694190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, m); 695190203Srpaulo if ((r = sshbuf_get_u32(m, &success)) != 0) 696190203Srpaulo fatal("%s: buffer error: %s", __func__, ssh_err(r)); 697190203Srpaulo if (success == 0) { 698190203Srpaulo debug3("%s: pam_init_ctx failed", __func__); 699190203Srpaulo sshbuf_free(m); 700190203Srpaulo return (NULL); 701190203Srpaulo } 702190203Srpaulo sshbuf_free(m); 703190203Srpaulo return (authctxt); 704190203Srpaulo} 705190203Srpaulo 706190203Srpauloint 707190203Srpaulomm_sshpam_query(void *ctx, char **name, char **info, 708190203Srpaulo u_int *num, char ***prompts, u_int **echo_on) 709190203Srpaulo{ 710190203Srpaulo struct sshbuf *m; 711190203Srpaulo u_int i, ret; 712190203Srpaulo int r; 713190203Srpaulo 714190203Srpaulo debug3("%s", __func__); 715190203Srpaulo if ((m = sshbuf_new()) == NULL) 716190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 717190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m); 718190203Srpaulo debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); 719190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m); 720190203Srpaulo if ((r = sshbuf_get_u32(m, &ret)) != 0) 721190203Srpaulo fatal("%s: buffer error: %s", __func__, ssh_err(r)); 722190203Srpaulo debug3("%s: pam_query returned %d", __func__, ret); 723190203Srpaulo if ((r = sshbuf_get_cstring(m, name, NULL)) != 0 || 724190203Srpaulo (r = sshbuf_get_cstring(m, info, NULL)) != 0 || 725190203Srpaulo (r = sshbuf_get_u32(m, num)) != 0) 726190203Srpaulo fatal("%s: buffer error: %s", __func__, ssh_err(r)); 727190203Srpaulo if (*num > PAM_MAX_NUM_MSG) 728190203Srpaulo fatal("%s: received %u PAM messages, expected <= %u", 729190203Srpaulo __func__, *num, PAM_MAX_NUM_MSG); 730190203Srpaulo *prompts = xcalloc((*num + 1), sizeof(char *)); 731190203Srpaulo *echo_on = xcalloc((*num + 1), sizeof(u_int)); 732190203Srpaulo for (i = 0; i < *num; ++i) { 733190203Srpaulo if ((r = sshbuf_get_cstring(m, &(*prompts)[i], NULL)) != 0 || 734235530Sdelphij (r = sshbuf_get_u32(m, (echo_on)[i])) != 0) 735235530Sdelphij fatal("%s: buffer error: %s", __func__, ssh_err(r)); 736190203Srpaulo } 737235530Sdelphij sshbuf_free(m); 738235530Sdelphij return (ret); 739235530Sdelphij} 740190203Srpaulo 741190203Srpauloint 742190203Srpaulomm_sshpam_respond(void *ctx, u_int num, char **resp) 743190203Srpaulo{ 744190203Srpaulo struct sshbuf *m; 745190203Srpaulo int r; 746190203Srpaulo u_int i; 747190203Srpaulo u_int ret; 748235530Sdelphij 749235530Sdelphij debug3("%s", __func__); 750235530Sdelphij if ((m = sshbuf_new()) == NULL) 751190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 752190203Srpaulo sshbuf_put_u32(m, num); 753190203Srpaulo for (i = 0; i < num; ++i) 754190203Srpaulo sshbuf_put_cstring(m, resp[i]); 755190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m); 756190203Srpaulo debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); 757190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, m); 758190203Srpaulo if ((r = sshbuf_get_u32(m, &ret)) != 0) 759190203Srpaulo fatal("%s: buffer error: %s", __func__, ssh_err(r)); 760235530Sdelphij debug3("%s: pam_respond returned %d", __func__, ret); 761235530Sdelphij sshbuf_free(m); 762235530Sdelphij return (ret); 763190203Srpaulo} 764190203Srpaulo 765190203Srpaulovoid 766190203Srpaulomm_sshpam_free_ctx(void *ctxtp) 767190203Srpaulo{ 768190203Srpaulo struct sshbuf *m; 769190203Srpaulo 770190203Srpaulo debug3("%s", __func__); 771190203Srpaulo if ((m = sshbuf_new()) == NULL) 772190203Srpaulo fatal("%s: sshbuf_new failed", __func__); 773190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m); 774190203Srpaulo debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); 775190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m); 776190203Srpaulo sshbuf_free(m); 777235530Sdelphij} 778235530Sdelphij#endif /* USE_PAM */ 779235530Sdelphij 780190203Srpaulo/* Request process termination */ 781190203Srpaulo 782190203Srpaulovoid 783190203Srpaulomm_terminate(void) 784190203Srpaulo{ 785190203Srpaulo struct sshbuf *m; 786190203Srpaulo 787235530Sdelphij if ((m = sshbuf_new()) == NULL) 788235530Sdelphij fatal_f("sshbuf_new failed"); 789235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m); 790190203Srpaulo sshbuf_free(m); 791190203Srpaulo} 792190203Srpaulo 793190203Srpaulo#if defined(BSD_AUTH) || defined(SKEY) 794190203Srpaulostatic void 795190203Srpaulomm_chall_setup(char **name, char **infotxt, u_int *numprompts, 796190203Srpaulo char ***prompts, u_int **echo_on) 797190203Srpaulo{ 798190203Srpaulo *name = xstrdup(""); 799190203Srpaulo *infotxt = xstrdup(""); 800190203Srpaulo *numprompts = 1; 801190203Srpaulo *prompts = xcalloc(*numprompts, sizeof(char *)); 802190203Srpaulo *echo_on = xcalloc(*numprompts, sizeof(u_int)); 803190203Srpaulo (*echo_on)[0] = 0; 804190203Srpaulo} 805190203Srpaulo 806235530Sdelphij#ifdef BSD_AUTH 807235530Sdelphijint 808235530Sdelphijmm_bsdauth_query(void *ctx, char **name, char **infotxt, 809190203Srpaulo u_int *numprompts, char ***prompts, u_int **echo_on) 810235530Sdelphij{ 811235530Sdelphij struct sshbuf *m; 812235530Sdelphij u_int success; 813235530Sdelphij char *challenge; 814235530Sdelphij int r; 815235530Sdelphij 816190203Srpaulo debug3_f("entering"); 817190203Srpaulo 818190203Srpaulo if ((m = sshbuf_new()) == NULL) 819190203Srpaulo fatal_f("sshbuf_new failed"); 820190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m); 821190203Srpaulo 822190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 823190203Srpaulo MONITOR_ANS_BSDAUTHQUERY, m); 824190203Srpaulo if ((r = sshbuf_get_u32(m, &success)) != 0) 825190203Srpaulo fatal_fr(r, "parse success"); 826190203Srpaulo if (success == 0) { 827190203Srpaulo debug3_f("no challenge"); 828190203Srpaulo sshbuf_free(m); 829235530Sdelphij return (-1); 830235530Sdelphij } 831235530Sdelphij 832190203Srpaulo /* Get the challenge, and format the response */ 833190203Srpaulo if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0) 834190203Srpaulo fatal_fr(r, "parse challenge"); 835190203Srpaulo sshbuf_free(m); 836190203Srpaulo 837190203Srpaulo mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); 838190203Srpaulo (*prompts)[0] = challenge; 839190203Srpaulo 840190203Srpaulo debug3_f("received challenge: %s", challenge); 841190203Srpaulo 842190203Srpaulo return (0); 843190203Srpaulo} 844190203Srpaulo 845190203Srpauloint 846235530Sdelphijmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) 847235530Sdelphij{ 848235530Sdelphij struct sshbuf *m; 849190203Srpaulo int r, authok; 850190203Srpaulo 851190203Srpaulo debug3_f("entering"); 852190203Srpaulo if (numresponses != 1) 853190203Srpaulo return (-1); 854190203Srpaulo 855190203Srpaulo if ((m = sshbuf_new()) == NULL) 856190203Srpaulo fatal_f("sshbuf_new failed"); 857190203Srpaulo if ((r = sshbuf_put_cstring(m, responses[0])) != 0) 858190203Srpaulo fatal_fr(r, "assemble"); 859190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m); 860190203Srpaulo 861190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, 862190203Srpaulo MONITOR_ANS_BSDAUTHRESPOND, m); 863190203Srpaulo 864190203Srpaulo if ((r = sshbuf_get_u32(m, &authok)) != 0) 865190203Srpaulo fatal_fr(r, "parse"); 866190203Srpaulo sshbuf_free(m); 867190203Srpaulo 868235530Sdelphij return ((authok == 0) ? -1 : 0); 869235530Sdelphij} 870235530Sdelphij#endif 871190203Srpaulo 872190203Srpaulo#ifdef SKEY 873190203Srpauloint 874190203Srpaulomm_skey_query(void *ctx, char **name, char **infotxt, 875190203Srpaulo u_int *numprompts, char ***prompts, u_int **echo_on) 876190203Srpaulo{ 877190203Srpaulo struct sshbuf m; 878190203Srpaulo u_int success; 879190203Srpaulo char *challenge; 880190203Srpaulo 881190203Srpaulo debug3("%s: entering", __func__); 882190203Srpaulo 883190203Srpaulo sshbuf_new(&m); 884190203Srpaulo mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); 885190203Srpaulo 886190203Srpaulo mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, 887190203Srpaulo &m); 888190203Srpaulo success = sshbuf_get_int(&m); 889190203Srpaulo if (success == 0) { 890190203Srpaulo debug3("%s: no challenge", __func__); 891190203Srpaulo sshbuf_free(&m); 892190203Srpaulo return (-1); 893190203Srpaulo } 894190203Srpaulo 895190203Srpaulo /* Get the challenge, and format the response */ 896190203Srpaulo challenge = sshbuf_get_string(&m, NULL); 897190203Srpaulo sshbuf_free(&m); 898190203Srpaulo 899190203Srpaulo debug3("%s: received challenge: %s", __func__, challenge); 900190203Srpaulo 901190203Srpaulo mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); 902190203Srpaulo 903190203Srpaulo xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT); 904190203Srpaulo free(challenge); 905190203Srpaulo 906235530Sdelphij return (0); 907235530Sdelphij} 908235530Sdelphij 909235530Sdelphijint 910235530Sdelphijmm_skey_respond(void *ctx, u_int numresponses, char **responses) 911235530Sdelphij{ 912235530Sdelphij struct sshbuf m; 913235530Sdelphij int authok; 914235530Sdelphij 915235530Sdelphij debug3("%s: entering", __func__); 916235530Sdelphij if (numresponses != 1) 917235530Sdelphij return (-1); 918235530Sdelphij 919235530Sdelphij sshbuf_new(&m); 920235530Sdelphij sshbuf_put_cstring(&m, responses[0]); 921235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); 922235530Sdelphij 923235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, 924235530Sdelphij MONITOR_ANS_SKEYRESPOND, &m); 925235530Sdelphij 926235530Sdelphij authok = sshbuf_get_int(&m); 927235530Sdelphij sshbuf_free(&m); 928235530Sdelphij 929235530Sdelphij return ((authok == 0) ? -1 : 0); 930235530Sdelphij} 931235530Sdelphij#endif /* SKEY */ 932235530Sdelphij#endif /* BSDAUTH || SKEY */ 933235530Sdelphij 934235530Sdelphij#ifdef GSSAPI 935235530SdelphijOM_uint32 936235530Sdelphijmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) 937235530Sdelphij{ 938235530Sdelphij struct sshbuf *m; 939235530Sdelphij OM_uint32 major; 940235530Sdelphij int r; 941235530Sdelphij 942235530Sdelphij /* Client doesn't get to see the context */ 943235530Sdelphij *ctx = NULL; 944235530Sdelphij 945235530Sdelphij if ((m = sshbuf_new()) == NULL) 946235530Sdelphij fatal_f("sshbuf_new failed"); 947235530Sdelphij if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0) 948235530Sdelphij fatal_fr(r, "assemble"); 949235530Sdelphij 950235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m); 951235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m); 952235530Sdelphij 953235530Sdelphij if ((r = sshbuf_get_u32(m, &major)) != 0) 954235530Sdelphij fatal_fr(r, "parse"); 955235530Sdelphij 956235530Sdelphij sshbuf_free(m); 957235530Sdelphij return (major); 958235530Sdelphij} 959235530Sdelphij 960235530SdelphijOM_uint32 961235530Sdelphijmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, 962235530Sdelphij gss_buffer_desc *out, OM_uint32 *flagsp) 963235530Sdelphij{ 964235530Sdelphij struct sshbuf *m; 965235530Sdelphij OM_uint32 major; 966235530Sdelphij u_int flags; 967235530Sdelphij int r; 968235530Sdelphij 969235530Sdelphij if ((m = sshbuf_new()) == NULL) 970235530Sdelphij fatal_f("sshbuf_new failed"); 971235530Sdelphij if ((r = sshbuf_put_string(m, in->value, in->length)) != 0) 972235530Sdelphij fatal_fr(r, "assemble"); 973235530Sdelphij 974235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m); 975235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m); 976235530Sdelphij 977235530Sdelphij if ((r = sshbuf_get_u32(m, &major)) != 0 || 978235530Sdelphij (r = ssh_gssapi_get_buffer_desc(m, out)) != 0) 979235530Sdelphij fatal_fr(r, "parse"); 980235530Sdelphij if (flagsp != NULL) { 981235530Sdelphij if ((r = sshbuf_get_u32(m, &flags)) != 0) 982235530Sdelphij fatal_fr(r, "parse flags"); 983235530Sdelphij *flagsp = flags; 984235530Sdelphij } 985235530Sdelphij 986235530Sdelphij sshbuf_free(m); 987235530Sdelphij 988235530Sdelphij return (major); 989235530Sdelphij} 990235530Sdelphij 991235530SdelphijOM_uint32 992235530Sdelphijmm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 993235530Sdelphij{ 994235530Sdelphij struct sshbuf *m; 995235530Sdelphij OM_uint32 major; 996235530Sdelphij int r; 997235530Sdelphij 998235530Sdelphij if ((m = sshbuf_new()) == NULL) 999235530Sdelphij fatal_f("sshbuf_new failed"); 1000235530Sdelphij if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 || 1001235530Sdelphij (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0) 1002235530Sdelphij fatal_fr(r, "assemble"); 1003235530Sdelphij 1004235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m); 1005235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, 1006235530Sdelphij MONITOR_ANS_GSSCHECKMIC, m); 1007235530Sdelphij 1008235530Sdelphij if ((r = sshbuf_get_u32(m, &major)) != 0) 1009235530Sdelphij fatal_fr(r, "parse"); 1010235530Sdelphij sshbuf_free(m); 1011235530Sdelphij return(major); 1012235530Sdelphij} 1013235530Sdelphij 1014235530Sdelphijint 1015235530Sdelphijmm_ssh_gssapi_userok(char *user) 1016235530Sdelphij{ 1017235530Sdelphij struct sshbuf *m; 1018235530Sdelphij int r; 1019235530Sdelphij u_int authenticated = 0; 1020235530Sdelphij 1021235530Sdelphij if ((m = sshbuf_new()) == NULL) 1022235530Sdelphij fatal_f("sshbuf_new failed"); 1023235530Sdelphij 1024235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); 1025235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, 1026235530Sdelphij MONITOR_ANS_GSSUSEROK, m); 1027235530Sdelphij 1028235530Sdelphij if ((r = sshbuf_get_u32(m, &authenticated)) != 0) 1029235530Sdelphij fatal_fr(r, "parse"); 1030235530Sdelphij 1031235530Sdelphij sshbuf_free(m); 1032235530Sdelphij debug3_f("user %sauthenticated", authenticated ? "" : "not "); 1033235530Sdelphij return (authenticated); 1034235530Sdelphij} 1035235530Sdelphij#endif /* GSSAPI */ 1036235530Sdelphij 1037235530Sdelphij#ifdef KRB5 1038235530Sdelphijint 1039235530Sdelphijmm_auth_krb5(void *ctx, void *argp, char **userp, void *resp) 1040235530Sdelphij{ 1041235530Sdelphij krb5_data *tkt, *reply; 1042235530Sdelphij struct sshbuf *m; 1043235530Sdelphij u_int success; 1044235530Sdelphij int r; 1045235530Sdelphij 1046235530Sdelphij debug3("%s entering", __func__); 1047235530Sdelphij tkt = (krb5_data *) argp; 1048235530Sdelphij reply = (krb5_data *) resp; 1049235530Sdelphij 1050235530Sdelphij if ((m = sshbuf_new()) == NULL) 1051235530Sdelphij fatal("%s: sshbuf_new failed", __func__); 1052235530Sdelphij sshbuf_put_string(m, tkt->data, tkt->length); 1053235530Sdelphij 1054235530Sdelphij mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, m); 1055235530Sdelphij mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, m); 1056235530Sdelphij 1057235530Sdelphij if ((r = sshbuf_get_u32(m, &success)) != 0) 1058235530Sdelphij fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1059235530Sdelphij if (success) { 1060235530Sdelphij size_t len; 1061235530Sdelphij u_char *data; 1062235530Sdelphij 1063235530Sdelphij if ((r = sshbuf_get_cstring(m, userp, NULL)) != 0 || 1064235530Sdelphij (r = sshbuf_get_string(m, &data, &len)) != 0) 1065235530Sdelphij fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1066235530Sdelphij reply->data = data; 1067235530Sdelphij reply->length = len; 1068235530Sdelphij } else { 1069190203Srpaulo memset(reply, 0, sizeof(*reply)); 1070235530Sdelphij *userp = NULL; 1071190203Srpaulo } 1072190203Srpaulo 1073190203Srpaulo sshbuf_free(m); 1074190203Srpaulo return (success); 1075190203Srpaulo} 1076235530Sdelphij#endif 1077235530Sdelphij