1323124Sdes/* $OpenBSD: monitor_wrap.c,v 1.88 2016/03/07 19:02:43 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
41295367Sdes#ifdef WITH_OPENSSL
4298675Sdes#include <openssl/bn.h>
4398675Sdes#include <openssl/dh.h>
44192595Sdes#include <openssl/evp.h>
45295367Sdes#endif
4698675Sdes
47181111Sdes#include "openbsd-compat/sys-queue.h"
48162856Sdes#include "xmalloc.h"
4998675Sdes#include "ssh.h"
50295367Sdes#ifdef WITH_OPENSSL
5198675Sdes#include "dh.h"
52295367Sdes#endif
53162856Sdes#include "buffer.h"
54162856Sdes#include "key.h"
55162856Sdes#include "cipher.h"
5698675Sdes#include "kex.h"
57162856Sdes#include "hostfile.h"
5898675Sdes#include "auth.h"
59113911Sdes#include "auth-options.h"
6098675Sdes#include "packet.h"
6198675Sdes#include "mac.h"
6298675Sdes#include "log.h"
63323124Sdes#include "auth-pam.h"
64128460Sdes#ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
65128460Sdes#undef TARGET_OS_MAC
6698675Sdes#include "zlib.h"
67128460Sdes#define TARGET_OS_MAC 1
68128460Sdes#else
69128460Sdes#include "zlib.h"
70128460Sdes#endif
7198675Sdes#include "monitor.h"
72162856Sdes#ifdef GSSAPI
73162856Sdes#include "ssh-gss.h"
74162856Sdes#endif
7598675Sdes#include "monitor_wrap.h"
7698675Sdes#include "atomicio.h"
7798675Sdes#include "monitor_fdpass.h"
78162856Sdes#include "misc.h"
79221420Sdes#include "uuencode.h"
8098675Sdes
8198675Sdes#include "channels.h"
8298675Sdes#include "session.h"
83181111Sdes#include "servconf.h"
8498675Sdes
85295367Sdes#include "ssherr.h"
86295367Sdes
8798675Sdes/* Imports */
8898675Sdesextern int compat20;
8998675Sdesextern z_stream incoming_stream;
9098675Sdesextern z_stream outgoing_stream;
9198675Sdesextern struct monitor *pmonitor;
92137019Sdesextern Buffer loginmsg;
93124211Sdesextern ServerOptions options;
9498675Sdes
95226046Sdesvoid
96226046Sdesmm_log_handler(LogLevel level, const char *msg, void *ctx)
97226046Sdes{
98226046Sdes	Buffer log_msg;
99226046Sdes	struct monitor *mon = (struct monitor *)ctx;
100226046Sdes
101226046Sdes	if (mon->m_log_sendfd == -1)
102226046Sdes		fatal("%s: no log channel", __func__);
103226046Sdes
104226046Sdes	buffer_init(&log_msg);
105226046Sdes	/*
106226046Sdes	 * Placeholder for packet length. Will be filled in with the actual
107226046Sdes	 * packet length once the packet has been constucted. This saves
108226046Sdes	 * fragile math.
109226046Sdes	 */
110226046Sdes	buffer_put_int(&log_msg, 0);
111226046Sdes
112226046Sdes	buffer_put_int(&log_msg, level);
113226046Sdes	buffer_put_cstring(&log_msg, msg);
114226046Sdes	put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
115226046Sdes	if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
116226046Sdes	    buffer_len(&log_msg)) != buffer_len(&log_msg))
117226046Sdes		fatal("%s: write: %s", __func__, strerror(errno));
118226046Sdes	buffer_free(&log_msg);
119226046Sdes}
120226046Sdes
121126277Sdesint
122126277Sdesmm_is_monitor(void)
123126277Sdes{
124126277Sdes	/*
125126277Sdes	 * m_pid is only set in the privileged part, and
126126277Sdes	 * points to the unprivileged child.
127126277Sdes	 */
128126277Sdes	return (pmonitor && pmonitor->m_pid > 0);
129126277Sdes}
130126277Sdes
13198675Sdesvoid
132137019Sdesmm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
13398675Sdes{
134106130Sdes	u_int mlen = buffer_len(m);
13598675Sdes	u_char buf[5];
13698675Sdes
13798675Sdes	debug3("%s entering: type %d", __func__, type);
13898675Sdes
139162856Sdes	put_u32(buf, mlen + 1);
14098675Sdes	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
141137019Sdes	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
142149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
143137019Sdes	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
144149753Sdes		fatal("%s: write: %s", __func__, strerror(errno));
14598675Sdes}
14698675Sdes
14798675Sdesvoid
148137019Sdesmm_request_receive(int sock, Buffer *m)
14998675Sdes{
15098675Sdes	u_char buf[4];
151106130Sdes	u_int msg_len;
15298675Sdes
15398675Sdes	debug3("%s entering", __func__);
15498675Sdes
155149753Sdes	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
156149753Sdes		if (errno == EPIPE)
157126277Sdes			cleanup_exit(255);
158149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
15998675Sdes	}
160162856Sdes	msg_len = get_u32(buf);
16198675Sdes	if (msg_len > 256 * 1024)
16298675Sdes		fatal("%s: read: bad msg_len %d", __func__, msg_len);
16398675Sdes	buffer_clear(m);
16498675Sdes	buffer_append_space(m, msg_len);
165149753Sdes	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
166149753Sdes		fatal("%s: read: %s", __func__, strerror(errno));
16798675Sdes}
16898675Sdes
16998675Sdesvoid
170137019Sdesmm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
17198675Sdes{
17298675Sdes	u_char rtype;
17398675Sdes
17498675Sdes	debug3("%s entering: type %d", __func__, type);
17598675Sdes
176137019Sdes	mm_request_receive(sock, m);
17798675Sdes	rtype = buffer_get_char(m);
17898675Sdes	if (rtype != type)
17998675Sdes		fatal("%s: read: rtype %d != type %d", __func__,
18098675Sdes		    rtype, type);
18198675Sdes}
18298675Sdes
183295367Sdes#ifdef WITH_OPENSSL
18498675SdesDH *
18598675Sdesmm_choose_dh(int min, int nbits, int max)
18698675Sdes{
18798675Sdes	BIGNUM *p, *g;
18898675Sdes	int success = 0;
18998675Sdes	Buffer m;
19098675Sdes
19198675Sdes	buffer_init(&m);
19298675Sdes	buffer_put_int(&m, min);
19398675Sdes	buffer_put_int(&m, nbits);
19498675Sdes	buffer_put_int(&m, max);
19598675Sdes
19698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
19798675Sdes
19898675Sdes	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
19998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
20098675Sdes
20198675Sdes	success = buffer_get_char(&m);
20298675Sdes	if (success == 0)
20398675Sdes		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
20498675Sdes
20598675Sdes	if ((p = BN_new()) == NULL)
20698675Sdes		fatal("%s: BN_new failed", __func__);
20798675Sdes	if ((g = BN_new()) == NULL)
20898675Sdes		fatal("%s: BN_new failed", __func__);
20998675Sdes	buffer_get_bignum2(&m, p);
21098675Sdes	buffer_get_bignum2(&m, g);
21198675Sdes
21298675Sdes	debug3("%s: remaining %d", __func__, buffer_len(&m));
21398675Sdes	buffer_free(&m);
21498675Sdes
21598675Sdes	return (dh_new_group(g, p));
21698675Sdes}
217295367Sdes#endif
21898675Sdes
21998675Sdesint
220295367Sdesmm_key_sign(Key *key, u_char **sigp, u_int *lenp,
221296781Sdes    const u_char *data, u_int datalen, const char *hostkey_alg)
22298675Sdes{
223295367Sdes	struct kex *kex = *pmonitor->m_pkex;
22498675Sdes	Buffer m;
22598675Sdes
22698675Sdes	debug3("%s entering", __func__);
22798675Sdes
22898675Sdes	buffer_init(&m);
229295367Sdes	buffer_put_int(&m, kex->host_key_index(key, 0, active_state));
23098675Sdes	buffer_put_string(&m, data, datalen);
231296781Sdes	buffer_put_cstring(&m, hostkey_alg);
23298675Sdes
23398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
23498675Sdes
23598675Sdes	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
23698675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
23798675Sdes	*sigp  = buffer_get_string(&m, lenp);
23898675Sdes	buffer_free(&m);
23998675Sdes
24098675Sdes	return (0);
24198675Sdes}
24298675Sdes
24398675Sdesstruct passwd *
244137019Sdesmm_getpwnamallow(const char *username)
24598675Sdes{
24698675Sdes	Buffer m;
24798675Sdes	struct passwd *pw;
248226046Sdes	u_int len, i;
249181111Sdes	ServerOptions *newopts;
25098675Sdes
25198675Sdes	debug3("%s entering", __func__);
25298675Sdes
25398675Sdes	buffer_init(&m);
254137019Sdes	buffer_put_cstring(&m, username);
25598675Sdes
25698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
25798675Sdes
25898675Sdes	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
25998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
26098675Sdes
26198675Sdes	if (buffer_get_char(&m) == 0) {
262181111Sdes		pw = NULL;
263181111Sdes		goto out;
26498675Sdes	}
265181111Sdes	pw = buffer_get_string(&m, &len);
266181111Sdes	if (len != sizeof(struct passwd))
26798675Sdes		fatal("%s: struct passwd size mismatch", __func__);
26898675Sdes	pw->pw_name = buffer_get_string(&m, NULL);
26998675Sdes	pw->pw_passwd = buffer_get_string(&m, NULL);
270255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
27198675Sdes	pw->pw_gecos = buffer_get_string(&m, NULL);
272255767Sdes#endif
273255767Sdes#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
27498675Sdes	pw->pw_class = buffer_get_string(&m, NULL);
27598937Sdes#endif
27698675Sdes	pw->pw_dir = buffer_get_string(&m, NULL);
27798675Sdes	pw->pw_shell = buffer_get_string(&m, NULL);
278181111Sdes
279181111Sdesout:
280181111Sdes	/* copy options block as a Match directive may have changed some */
281181111Sdes	newopts = buffer_get_string(&m, &len);
282181111Sdes	if (len != sizeof(*newopts))
283181111Sdes		fatal("%s: option block size mismatch", __func__);
284226046Sdes
285226046Sdes#define M_CP_STROPT(x) do { \
286226046Sdes		if (newopts->x != NULL) \
287226046Sdes			newopts->x = buffer_get_string(&m, NULL); \
288226046Sdes	} while (0)
289226046Sdes#define M_CP_STRARRAYOPT(x, nx) do { \
290226046Sdes		for (i = 0; i < newopts->nx; i++) \
291226046Sdes			newopts->x[i] = buffer_get_string(&m, NULL); \
292226046Sdes	} while (0)
293226046Sdes	/* See comment in servconf.h */
294226046Sdes	COPY_MATCH_STRING_OPTS();
295226046Sdes#undef M_CP_STROPT
296226046Sdes#undef M_CP_STRARRAYOPT
297226046Sdes
298181111Sdes	copy_set_server_options(&options, newopts, 1);
299255767Sdes	free(newopts);
300181111Sdes
30198675Sdes	buffer_free(&m);
30298675Sdes
30398675Sdes	return (pw);
30498675Sdes}
30598675Sdes
306126277Sdeschar *
307126277Sdesmm_auth2_read_banner(void)
30898675Sdes{
30998675Sdes	Buffer m;
31098675Sdes	char *banner;
31198675Sdes
31298675Sdes	debug3("%s entering", __func__);
31398675Sdes
31498675Sdes	buffer_init(&m);
31598675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
31698675Sdes	buffer_clear(&m);
31798675Sdes
318126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
319126277Sdes	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
32098675Sdes	banner = buffer_get_string(&m, NULL);
32198675Sdes	buffer_free(&m);
32298675Sdes
323126277Sdes	/* treat empty banner as missing banner */
324126277Sdes	if (strlen(banner) == 0) {
325255767Sdes		free(banner);
326126277Sdes		banner = NULL;
327126277Sdes	}
32898675Sdes	return (banner);
32998675Sdes}
33098675Sdes
33198675Sdes/* Inform the privileged process about service and style */
33298675Sdes
33398675Sdesvoid
33498675Sdesmm_inform_authserv(char *service, char *style)
33598675Sdes{
33698675Sdes	Buffer m;
33798675Sdes
33898675Sdes	debug3("%s entering", __func__);
33998675Sdes
34098675Sdes	buffer_init(&m);
34198675Sdes	buffer_put_cstring(&m, service);
34298675Sdes	buffer_put_cstring(&m, style ? style : "");
34398675Sdes
34498675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
34598675Sdes
34698675Sdes	buffer_free(&m);
34798675Sdes}
34898675Sdes
34998675Sdes/* Do the password authentication */
35098675Sdesint
35198675Sdesmm_auth_password(Authctxt *authctxt, char *password)
35298675Sdes{
35398675Sdes	Buffer m;
35498675Sdes	int authenticated = 0;
35598675Sdes
35698675Sdes	debug3("%s entering", __func__);
35798675Sdes
35898675Sdes	buffer_init(&m);
35998675Sdes	buffer_put_cstring(&m, password);
36098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
36198675Sdes
36298675Sdes	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
36398675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
36498675Sdes
36598675Sdes	authenticated = buffer_get_int(&m);
366323124Sdes#ifdef USE_PAM
367323124Sdes	sshpam_set_maxtries_reached(buffer_get_int(&m));
368323124Sdes#endif
36998675Sdes
37098675Sdes	buffer_free(&m);
37198675Sdes
37298675Sdes	debug3("%s: user %sauthenticated",
37398675Sdes	    __func__, authenticated ? "" : "not ");
37498675Sdes	return (authenticated);
37598675Sdes}
37698675Sdes
37798675Sdesint
378295367Sdesmm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt)
37998675Sdes{
380295367Sdes	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
381295367Sdes	    pubkey_auth_attempt));
38298675Sdes}
38398675Sdes
38498675Sdesint
385323124Sdesmm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
38698675Sdes    Key *key)
38798675Sdes{
388295367Sdes	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
38998675Sdes}
39098675Sdes
39198675Sdesint
392323124Sdesmm_auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *user,
393323124Sdes    const char *host, Key *key)
39498675Sdes{
39598675Sdes	int ret;
39698675Sdes
39798675Sdes	key->type = KEY_RSA; /* XXX hack for key_to_blob */
398295367Sdes	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key, 0);
39998675Sdes	key->type = KEY_RSA1;
40098675Sdes	return (ret);
40198675Sdes}
40298675Sdes
40398675Sdesint
404323124Sdesmm_key_allowed(enum mm_keytype type, const char *user, const char *host,
405323124Sdes    Key *key, int pubkey_auth_attempt)
40698675Sdes{
40798675Sdes	Buffer m;
40898675Sdes	u_char *blob;
40998675Sdes	u_int len;
410113911Sdes	int allowed = 0, have_forced = 0;
41198675Sdes
41298675Sdes	debug3("%s entering", __func__);
41398675Sdes
41498675Sdes	/* Convert the key to a blob and the pass it over */
41598675Sdes	if (!key_to_blob(key, &blob, &len))
41698675Sdes		return (0);
41798675Sdes
41898675Sdes	buffer_init(&m);
41998675Sdes	buffer_put_int(&m, type);
42098675Sdes	buffer_put_cstring(&m, user ? user : "");
42198675Sdes	buffer_put_cstring(&m, host ? host : "");
42298675Sdes	buffer_put_string(&m, blob, len);
423295367Sdes	buffer_put_int(&m, pubkey_auth_attempt);
424255767Sdes	free(blob);
42598675Sdes
42698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
42798675Sdes
42898675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
42998675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
43098675Sdes
43198675Sdes	allowed = buffer_get_int(&m);
43298675Sdes
433113911Sdes	/* fake forced command */
434113911Sdes	auth_clear_options();
435113911Sdes	have_forced = buffer_get_int(&m);
436113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
437113911Sdes
43898675Sdes	buffer_free(&m);
43998675Sdes
44098675Sdes	return (allowed);
44198675Sdes}
44298675Sdes
44398675Sdes/*
44498675Sdes * This key verify needs to send the key type along, because the
44598675Sdes * privileged parent makes the decision if the key is allowed
44698675Sdes * for authentication.
44798675Sdes */
44898675Sdes
44998675Sdesint
45098675Sdesmm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
45198675Sdes{
45298675Sdes	Buffer m;
45398675Sdes	u_char *blob;
45498675Sdes	u_int len;
45598675Sdes	int verified = 0;
45698675Sdes
45798675Sdes	debug3("%s entering", __func__);
45898675Sdes
45998675Sdes	/* Convert the key to a blob and the pass it over */
46098675Sdes	if (!key_to_blob(key, &blob, &len))
46198675Sdes		return (0);
46298675Sdes
46398675Sdes	buffer_init(&m);
46498675Sdes	buffer_put_string(&m, blob, len);
46598675Sdes	buffer_put_string(&m, sig, siglen);
46698675Sdes	buffer_put_string(&m, data, datalen);
467255767Sdes	free(blob);
46898675Sdes
46998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
47098675Sdes
47198675Sdes	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
47298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
47398675Sdes
47498675Sdes	verified = buffer_get_int(&m);
47598675Sdes
47698675Sdes	buffer_free(&m);
47798675Sdes
47898675Sdes	return (verified);
47998675Sdes}
48098675Sdes
48198675Sdesvoid
482137019Sdesmm_send_keystate(struct monitor *monitor)
48398675Sdes{
484295367Sdes	struct ssh *ssh = active_state;		/* XXX */
485295367Sdes	struct sshbuf *m;
486295367Sdes	int r;
48798675Sdes
488295367Sdes	if ((m = sshbuf_new()) == NULL)
489295367Sdes		fatal("%s: sshbuf_new failed", __func__);
490295367Sdes	if ((r = ssh_packet_get_state(ssh, m)) != 0)
491295367Sdes		fatal("%s: get_state failed: %s",
492295367Sdes		    __func__, ssh_err(r));
493295367Sdes	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
49498675Sdes	debug3("%s: Finished sending state", __func__);
495295367Sdes	sshbuf_free(m);
49698675Sdes}
49798675Sdes
49898675Sdesint
499162856Sdesmm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
50098675Sdes{
50198675Sdes	Buffer m;
502137019Sdes	char *p, *msg;
503181111Sdes	int success = 0, tmp1 = -1, tmp2 = -1;
50498675Sdes
505181111Sdes	/* Kludge: ensure there are fds free to receive the pty/tty */
506181111Sdes	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
507181111Sdes	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
508181111Sdes		error("%s: cannot allocate fds for pty", __func__);
509181111Sdes		if (tmp1 > 0)
510181111Sdes			close(tmp1);
511181111Sdes		if (tmp2 > 0)
512181111Sdes			close(tmp2);
513181111Sdes		return 0;
514181111Sdes	}
515181111Sdes	close(tmp1);
516181111Sdes	close(tmp2);
517181111Sdes
51898675Sdes	buffer_init(&m);
51998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
52098675Sdes
52198675Sdes	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
52298675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
52398675Sdes
52498675Sdes	success = buffer_get_int(&m);
52598675Sdes	if (success == 0) {
52698675Sdes		debug3("%s: pty alloc failed", __func__);
52798675Sdes		buffer_free(&m);
52898675Sdes		return (0);
52998675Sdes	}
53098675Sdes	p = buffer_get_string(&m, NULL);
531137019Sdes	msg = buffer_get_string(&m, NULL);
53298675Sdes	buffer_free(&m);
53398675Sdes
53498675Sdes	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
535255767Sdes	free(p);
53698675Sdes
537137019Sdes	buffer_append(&loginmsg, msg, strlen(msg));
538255767Sdes	free(msg);
539137019Sdes
540181111Sdes	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
541181111Sdes	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
542181111Sdes		fatal("%s: receive fds failed", __func__);
54398675Sdes
54498675Sdes	/* Success */
54598675Sdes	return (1);
54698675Sdes}
54798675Sdes
54898675Sdesvoid
549126277Sdesmm_session_pty_cleanup2(Session *s)
55098675Sdes{
55198675Sdes	Buffer m;
55298675Sdes
55398675Sdes	if (s->ttyfd == -1)
55498675Sdes		return;
55598675Sdes	buffer_init(&m);
55698675Sdes	buffer_put_cstring(&m, s->tty);
55798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
55898675Sdes	buffer_free(&m);
55998675Sdes
56098675Sdes	/* closed dup'ed master */
561181111Sdes	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
562181111Sdes		error("close(s->ptymaster/%d): %s",
563181111Sdes		    s->ptymaster, strerror(errno));
56498675Sdes
56598675Sdes	/* unlink pty from session */
56698675Sdes	s->ttyfd = -1;
56798675Sdes}
56898675Sdes
56998937Sdes#ifdef USE_PAM
57098937Sdesvoid
571128460Sdesmm_start_pam(Authctxt *authctxt)
57298937Sdes{
57398937Sdes	Buffer m;
57498937Sdes
57598937Sdes	debug3("%s entering", __func__);
576124211Sdes	if (!options.use_pam)
577124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
57898937Sdes
57998937Sdes	buffer_init(&m);
58098937Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
58198937Sdes
58298937Sdes	buffer_free(&m);
58398937Sdes}
58499052Sdes
585124211Sdesu_int
586124211Sdesmm_do_pam_account(void)
587124211Sdes{
588124211Sdes	Buffer m;
589124211Sdes	u_int ret;
590147005Sdes	char *msg;
591124211Sdes
592124211Sdes	debug3("%s entering", __func__);
593124211Sdes	if (!options.use_pam)
594124211Sdes		fatal("UsePAM=no, but ended up in %s anyway", __func__);
595124211Sdes
596124211Sdes	buffer_init(&m);
597124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
598124211Sdes
599126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
600124211Sdes	    MONITOR_ANS_PAM_ACCOUNT, &m);
601124211Sdes	ret = buffer_get_int(&m);
602147005Sdes	msg = buffer_get_string(&m, NULL);
603147005Sdes	buffer_append(&loginmsg, msg, strlen(msg));
604255767Sdes	free(msg);
605124211Sdes
606124211Sdes	buffer_free(&m);
607126277Sdes
608124211Sdes	debug3("%s returning %d", __func__, ret);
609124211Sdes
610124211Sdes	return (ret);
611124211Sdes}
612124211Sdes
61399052Sdesvoid *
614124211Sdesmm_sshpam_init_ctx(Authctxt *authctxt)
61599052Sdes{
61699052Sdes	Buffer m;
61799052Sdes	int success;
61899052Sdes
61999052Sdes	debug3("%s", __func__);
62099052Sdes	buffer_init(&m);
62199052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
62299052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
62399052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
62499052Sdes	success = buffer_get_int(&m);
62599052Sdes	if (success == 0) {
62699052Sdes		debug3("%s: pam_init_ctx failed", __func__);
62799052Sdes		buffer_free(&m);
62899052Sdes		return (NULL);
62999052Sdes	}
63099052Sdes	buffer_free(&m);
63199052Sdes	return (authctxt);
63299052Sdes}
63399052Sdes
63499052Sdesint
635124211Sdesmm_sshpam_query(void *ctx, char **name, char **info,
63699052Sdes    u_int *num, char ***prompts, u_int **echo_on)
63799052Sdes{
63899052Sdes	Buffer m;
639149753Sdes	u_int i;
640149753Sdes	int ret;
64199052Sdes
64299052Sdes	debug3("%s", __func__);
64399052Sdes	buffer_init(&m);
64499052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
64599052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
64699052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
64799052Sdes	ret = buffer_get_int(&m);
64899052Sdes	debug3("%s: pam_query returned %d", __func__, ret);
64999052Sdes	*name = buffer_get_string(&m, NULL);
65099052Sdes	*info = buffer_get_string(&m, NULL);
651323124Sdes	sshpam_set_maxtries_reached(buffer_get_int(&m));
65299052Sdes	*num = buffer_get_int(&m);
653162856Sdes	if (*num > PAM_MAX_NUM_MSG)
654162856Sdes		fatal("%s: recieved %u PAM messages, expected <= %u",
655162856Sdes		    __func__, *num, PAM_MAX_NUM_MSG);
656162856Sdes	*prompts = xcalloc((*num + 1), sizeof(char *));
657162856Sdes	*echo_on = xcalloc((*num + 1), sizeof(u_int));
65899052Sdes	for (i = 0; i < *num; ++i) {
65999052Sdes		(*prompts)[i] = buffer_get_string(&m, NULL);
66099052Sdes		(*echo_on)[i] = buffer_get_int(&m);
66199052Sdes	}
66299052Sdes	buffer_free(&m);
66399052Sdes	return (ret);
66499052Sdes}
66599052Sdes
66699052Sdesint
667124211Sdesmm_sshpam_respond(void *ctx, u_int num, char **resp)
66899052Sdes{
66999052Sdes	Buffer m;
670149753Sdes	u_int i;
671149753Sdes	int ret;
67299052Sdes
67399052Sdes	debug3("%s", __func__);
67499052Sdes	buffer_init(&m);
67599052Sdes	buffer_put_int(&m, num);
67699052Sdes	for (i = 0; i < num; ++i)
67799052Sdes		buffer_put_cstring(&m, resp[i]);
67899052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
67999052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
68099052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
68199052Sdes	ret = buffer_get_int(&m);
68299052Sdes	debug3("%s: pam_respond returned %d", __func__, ret);
68399052Sdes	buffer_free(&m);
68499052Sdes	return (ret);
68599052Sdes}
68699052Sdes
68799052Sdesvoid
688124211Sdesmm_sshpam_free_ctx(void *ctxtp)
68999052Sdes{
69099052Sdes	Buffer m;
69199052Sdes
69299052Sdes	debug3("%s", __func__);
69399052Sdes	buffer_init(&m);
69499052Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
69599052Sdes	debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
69699052Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
69799052Sdes	buffer_free(&m);
69899052Sdes}
69998937Sdes#endif /* USE_PAM */
70098937Sdes
70198675Sdes/* Request process termination */
70298675Sdes
70398675Sdesvoid
70498675Sdesmm_terminate(void)
70598675Sdes{
70698675Sdes	Buffer m;
70798675Sdes
70898675Sdes	buffer_init(&m);
70998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
71098675Sdes	buffer_free(&m);
71198675Sdes}
71298675Sdes
713295367Sdes#ifdef WITH_SSH1
71498675Sdesint
71598675Sdesmm_ssh1_session_key(BIGNUM *num)
71698675Sdes{
71798675Sdes	int rsafail;
71898675Sdes	Buffer m;
71998675Sdes
72098675Sdes	buffer_init(&m);
72198675Sdes	buffer_put_bignum2(&m, num);
72298675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
72398675Sdes
72498675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
72598675Sdes
72698675Sdes	rsafail = buffer_get_int(&m);
72798675Sdes	buffer_get_bignum2(&m, num);
72898675Sdes
72998675Sdes	buffer_free(&m);
73098675Sdes
73198675Sdes	return (rsafail);
73298675Sdes}
733295367Sdes#endif
73498675Sdes
73598675Sdesstatic void
73698675Sdesmm_chall_setup(char **name, char **infotxt, u_int *numprompts,
73798675Sdes    char ***prompts, u_int **echo_on)
73898675Sdes{
73998675Sdes	*name = xstrdup("");
74098675Sdes	*infotxt = xstrdup("");
74198675Sdes	*numprompts = 1;
742162856Sdes	*prompts = xcalloc(*numprompts, sizeof(char *));
743162856Sdes	*echo_on = xcalloc(*numprompts, sizeof(u_int));
74498675Sdes	(*echo_on)[0] = 0;
74598675Sdes}
74698675Sdes
74798675Sdesint
74898675Sdesmm_bsdauth_query(void *ctx, char **name, char **infotxt,
74998675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
75098675Sdes{
75198675Sdes	Buffer m;
752113911Sdes	u_int success;
75398675Sdes	char *challenge;
75498675Sdes
75598675Sdes	debug3("%s: entering", __func__);
75698675Sdes
75798675Sdes	buffer_init(&m);
75898675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
75998675Sdes
76098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
76198675Sdes	    &m);
762113911Sdes	success = buffer_get_int(&m);
763113911Sdes	if (success == 0) {
76498675Sdes		debug3("%s: no challenge", __func__);
76598675Sdes		buffer_free(&m);
76698675Sdes		return (-1);
76798675Sdes	}
76898675Sdes
76998675Sdes	/* Get the challenge, and format the response */
77098675Sdes	challenge  = buffer_get_string(&m, NULL);
77198675Sdes	buffer_free(&m);
77298675Sdes
77398675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
77498675Sdes	(*prompts)[0] = challenge;
77598675Sdes
77698675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
77798675Sdes
77898675Sdes	return (0);
77998675Sdes}
78098675Sdes
78198675Sdesint
78298675Sdesmm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
78398675Sdes{
78498675Sdes	Buffer m;
78598675Sdes	int authok;
78698675Sdes
78798675Sdes	debug3("%s: entering", __func__);
78898675Sdes	if (numresponses != 1)
78998675Sdes		return (-1);
79098675Sdes
79198675Sdes	buffer_init(&m);
79298675Sdes	buffer_put_cstring(&m, responses[0]);
79398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
79498675Sdes
79598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
79698675Sdes	    MONITOR_ANS_BSDAUTHRESPOND, &m);
79798675Sdes
79898675Sdes	authok = buffer_get_int(&m);
79998675Sdes	buffer_free(&m);
80098675Sdes
80198675Sdes	return ((authok == 0) ? -1 : 0);
80298675Sdes}
80398675Sdes
80499046Sdes#ifdef SKEY
80598675Sdesint
80698675Sdesmm_skey_query(void *ctx, char **name, char **infotxt,
80798675Sdes   u_int *numprompts, char ***prompts, u_int **echo_on)
80898675Sdes{
80998675Sdes	Buffer m;
810113911Sdes	u_int success;
811162856Sdes	char *challenge;
81298675Sdes
81398675Sdes	debug3("%s: entering", __func__);
81498675Sdes
81598675Sdes	buffer_init(&m);
81698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
81798675Sdes
81898675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
81998675Sdes	    &m);
820113911Sdes	success = buffer_get_int(&m);
821113911Sdes	if (success == 0) {
82298675Sdes		debug3("%s: no challenge", __func__);
82398675Sdes		buffer_free(&m);
82498675Sdes		return (-1);
82598675Sdes	}
82698675Sdes
82798675Sdes	/* Get the challenge, and format the response */
82898675Sdes	challenge  = buffer_get_string(&m, NULL);
82998675Sdes	buffer_free(&m);
83098675Sdes
83198675Sdes	debug3("%s: received challenge: %s", __func__, challenge);
83298675Sdes
83398675Sdes	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
83498675Sdes
835162856Sdes	xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
836255767Sdes	free(challenge);
83798675Sdes
83898675Sdes	return (0);
83998675Sdes}
84098675Sdes
84198675Sdesint
84298675Sdesmm_skey_respond(void *ctx, u_int numresponses, char **responses)
84398675Sdes{
84498675Sdes	Buffer m;
84598675Sdes	int authok;
84698675Sdes
84798675Sdes	debug3("%s: entering", __func__);
84898675Sdes	if (numresponses != 1)
84998675Sdes		return (-1);
85098675Sdes
85198675Sdes	buffer_init(&m);
85298675Sdes	buffer_put_cstring(&m, responses[0]);
85398675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
85498675Sdes
85598675Sdes	mm_request_receive_expect(pmonitor->m_recvfd,
85698675Sdes	    MONITOR_ANS_SKEYRESPOND, &m);
85798675Sdes
85898675Sdes	authok = buffer_get_int(&m);
85998675Sdes	buffer_free(&m);
86098675Sdes
86198675Sdes	return ((authok == 0) ? -1 : 0);
86298675Sdes}
863137019Sdes#endif /* SKEY */
86498675Sdes
86598675Sdesvoid
86698675Sdesmm_ssh1_session_id(u_char session_id[16])
86798675Sdes{
86898675Sdes	Buffer m;
86998675Sdes	int i;
87098675Sdes
87198675Sdes	debug3("%s entering", __func__);
87298675Sdes
87398675Sdes	buffer_init(&m);
87498675Sdes	for (i = 0; i < 16; i++)
87598675Sdes		buffer_put_char(&m, session_id[i]);
87698675Sdes
87798675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
87898675Sdes	buffer_free(&m);
87998675Sdes}
88098675Sdes
881295367Sdes#ifdef WITH_SSH1
88298675Sdesint
88398675Sdesmm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
88498675Sdes{
88598675Sdes	Buffer m;
88698675Sdes	Key *key;
88798675Sdes	u_char *blob;
88898675Sdes	u_int blen;
889113911Sdes	int allowed = 0, have_forced = 0;
89098675Sdes
89198675Sdes	debug3("%s entering", __func__);
89298675Sdes
89398675Sdes	buffer_init(&m);
89498675Sdes	buffer_put_bignum2(&m, client_n);
89598675Sdes
89698675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
89798675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
89898675Sdes
89998675Sdes	allowed = buffer_get_int(&m);
90098675Sdes
901113911Sdes	/* fake forced command */
902113911Sdes	auth_clear_options();
903113911Sdes	have_forced = buffer_get_int(&m);
904113911Sdes	forced_command = have_forced ? xstrdup("true") : NULL;
905113911Sdes
90698675Sdes	if (allowed && rkey != NULL) {
90798675Sdes		blob = buffer_get_string(&m, &blen);
90898675Sdes		if ((key = key_from_blob(blob, blen)) == NULL)
90998675Sdes			fatal("%s: key_from_blob failed", __func__);
91098675Sdes		*rkey = key;
911255767Sdes		free(blob);
91298675Sdes	}
91398675Sdes	buffer_free(&m);
91498675Sdes
91598675Sdes	return (allowed);
91698675Sdes}
91798675Sdes
91898675SdesBIGNUM *
91998675Sdesmm_auth_rsa_generate_challenge(Key *key)
92098675Sdes{
92198675Sdes	Buffer m;
92298675Sdes	BIGNUM *challenge;
92398675Sdes	u_char *blob;
92498675Sdes	u_int blen;
92598675Sdes
92698675Sdes	debug3("%s entering", __func__);
92798675Sdes
92898675Sdes	if ((challenge = BN_new()) == NULL)
92998675Sdes		fatal("%s: BN_new failed", __func__);
93098675Sdes
93198675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
93298675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
93398675Sdes		fatal("%s: key_to_blob failed", __func__);
93498675Sdes	key->type = KEY_RSA1;
93598675Sdes
93698675Sdes	buffer_init(&m);
93798675Sdes	buffer_put_string(&m, blob, blen);
938255767Sdes	free(blob);
93998675Sdes
94098675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
94198675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
94298675Sdes
94398675Sdes	buffer_get_bignum2(&m, challenge);
94498675Sdes	buffer_free(&m);
94598675Sdes
94698675Sdes	return (challenge);
94798675Sdes}
94898675Sdes
94998675Sdesint
95098675Sdesmm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
95198675Sdes{
95298675Sdes	Buffer m;
95398675Sdes	u_char *blob;
95498675Sdes	u_int blen;
95598675Sdes	int success = 0;
95698675Sdes
95798675Sdes	debug3("%s entering", __func__);
95898675Sdes
95998675Sdes	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
96098675Sdes	if (key_to_blob(key, &blob, &blen) == 0)
96198675Sdes		fatal("%s: key_to_blob failed", __func__);
96298675Sdes	key->type = KEY_RSA1;
96398675Sdes
96498675Sdes	buffer_init(&m);
96598675Sdes	buffer_put_string(&m, blob, blen);
96698675Sdes	buffer_put_string(&m, response, 16);
967255767Sdes	free(blob);
96898675Sdes
96998675Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
97098675Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
97198675Sdes
97298675Sdes	success = buffer_get_int(&m);
97398675Sdes	buffer_free(&m);
97498675Sdes
97598675Sdes	return (success);
97698675Sdes}
977295367Sdes#endif
978106130Sdes
979147005Sdes#ifdef SSH_AUDIT_EVENTS
980147005Sdesvoid
981147005Sdesmm_audit_event(ssh_audit_event_t event)
982147005Sdes{
983147005Sdes	Buffer m;
984147005Sdes
985147005Sdes	debug3("%s entering", __func__);
986147005Sdes
987147005Sdes	buffer_init(&m);
988147005Sdes	buffer_put_int(&m, event);
989147005Sdes
990147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
991147005Sdes	buffer_free(&m);
992147005Sdes}
993147005Sdes
994147005Sdesvoid
995147005Sdesmm_audit_run_command(const char *command)
996147005Sdes{
997147005Sdes	Buffer m;
998147005Sdes
999147005Sdes	debug3("%s entering command %s", __func__, command);
1000147005Sdes
1001147005Sdes	buffer_init(&m);
1002147005Sdes	buffer_put_cstring(&m, command);
1003147005Sdes
1004147005Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
1005147005Sdes	buffer_free(&m);
1006147005Sdes}
1007147005Sdes#endif /* SSH_AUDIT_EVENTS */
1008147005Sdes
1009124211Sdes#ifdef GSSAPI
1010124211SdesOM_uint32
1011137019Sdesmm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
1012106130Sdes{
1013124211Sdes	Buffer m;
1014124211Sdes	OM_uint32 major;
1015106130Sdes
1016124211Sdes	/* Client doesn't get to see the context */
1017124211Sdes	*ctx = NULL;
1018106130Sdes
1019106130Sdes	buffer_init(&m);
1020137019Sdes	buffer_put_string(&m, goid->elements, goid->length);
1021106130Sdes
1022124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1023124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1024106130Sdes
1025124211Sdes	major = buffer_get_int(&m);
1026124211Sdes
1027106130Sdes	buffer_free(&m);
1028124211Sdes	return (major);
1029106130Sdes}
1030106130Sdes
1031124211SdesOM_uint32
1032124211Sdesmm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1033124211Sdes    gss_buffer_desc *out, OM_uint32 *flags)
1034124211Sdes{
1035124211Sdes	Buffer m;
1036124211Sdes	OM_uint32 major;
1037124211Sdes	u_int len;
1038124211Sdes
1039124211Sdes	buffer_init(&m);
1040124211Sdes	buffer_put_string(&m, in->value, in->length);
1041124211Sdes
1042124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1043124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1044124211Sdes
1045124211Sdes	major = buffer_get_int(&m);
1046124211Sdes	out->value = buffer_get_string(&m, &len);
1047124211Sdes	out->length = len;
1048124211Sdes	if (flags)
1049124211Sdes		*flags = buffer_get_int(&m);
1050124211Sdes
1051124211Sdes	buffer_free(&m);
1052124211Sdes
1053124211Sdes	return (major);
1054124211Sdes}
1055124211Sdes
1056126277SdesOM_uint32
1057126277Sdesmm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
1058126277Sdes{
1059126277Sdes	Buffer m;
1060126277Sdes	OM_uint32 major;
1061126277Sdes
1062126277Sdes	buffer_init(&m);
1063126277Sdes	buffer_put_string(&m, gssbuf->value, gssbuf->length);
1064126277Sdes	buffer_put_string(&m, gssmic->value, gssmic->length);
1065126277Sdes
1066126277Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
1067126277Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
1068126277Sdes	    &m);
1069126277Sdes
1070126277Sdes	major = buffer_get_int(&m);
1071126277Sdes	buffer_free(&m);
1072126277Sdes	return(major);
1073126277Sdes}
1074126277Sdes
1075106130Sdesint
1076124211Sdesmm_ssh_gssapi_userok(char *user)
1077106130Sdes{
1078106130Sdes	Buffer m;
1079124211Sdes	int authenticated = 0;
1080106130Sdes
1081106130Sdes	buffer_init(&m);
1082106130Sdes
1083124211Sdes	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1084124211Sdes	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1085124211Sdes				  &m);
1086106130Sdes
1087124211Sdes	authenticated = buffer_get_int(&m);
1088106130Sdes
1089106130Sdes	buffer_free(&m);
1090124211Sdes	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1091124211Sdes	return (authenticated);
1092106130Sdes}
1093124211Sdes#endif /* GSSAPI */
1094192595Sdes
1095