GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/sshd/../monitor_wrap.c Lines: 0 265 0.0 %
Date: 2017-11-13 Branches: 0 124 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: monitor_wrap.c,v 1.95 2017/10/05 15:52:03 djm Exp $ */
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * Copyright 2002 Markus Friedl <markus@openbsd.org>
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
#include <sys/types.h>
29
#include <sys/uio.h>
30
#include <sys/queue.h>
31
32
#include <errno.h>
33
#include <pwd.h>
34
#include <signal.h>
35
#include <stdio.h>
36
#include <string.h>
37
#include <unistd.h>
38
39
#ifdef WITH_OPENSSL
40
#include <openssl/bn.h>
41
#include <openssl/dh.h>
42
#endif
43
44
#include "xmalloc.h"
45
#include "ssh.h"
46
#ifdef WITH_OPENSSL
47
#include "dh.h"
48
#endif
49
#include "buffer.h"
50
#include "key.h"
51
#include "cipher.h"
52
#include "kex.h"
53
#include "hostfile.h"
54
#include "auth.h"
55
#include "auth-options.h"
56
#include "packet.h"
57
#include "mac.h"
58
#include "log.h"
59
#include <zlib.h>
60
#include "monitor.h"
61
#ifdef GSSAPI
62
#include "ssh-gss.h"
63
#endif
64
#include "monitor_wrap.h"
65
#include "atomicio.h"
66
#include "monitor_fdpass.h"
67
#include "misc.h"
68
#include "uuencode.h"
69
70
#include "channels.h"
71
#include "session.h"
72
#include "servconf.h"
73
74
#include "ssherr.h"
75
76
/* Imports */
77
extern z_stream incoming_stream;
78
extern z_stream outgoing_stream;
79
extern struct monitor *pmonitor;
80
extern Buffer loginmsg;
81
extern ServerOptions options;
82
83
void
84
mm_log_handler(LogLevel level, const char *msg, void *ctx)
85
{
86
	Buffer log_msg;
87
	struct monitor *mon = (struct monitor *)ctx;
88
89
	if (mon->m_log_sendfd == -1)
90
		fatal("%s: no log channel", __func__);
91
92
	buffer_init(&log_msg);
93
	/*
94
	 * Placeholder for packet length. Will be filled in with the actual
95
	 * packet length once the packet has been constucted. This saves
96
	 * fragile math.
97
	 */
98
	buffer_put_int(&log_msg, 0);
99
100
	buffer_put_int(&log_msg, level);
101
	buffer_put_cstring(&log_msg, msg);
102
	put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
103
	if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
104
	    buffer_len(&log_msg)) != buffer_len(&log_msg))
105
		fatal("%s: write: %s", __func__, strerror(errno));
106
	buffer_free(&log_msg);
107
}
108
109
int
110
mm_is_monitor(void)
111
{
112
	/*
113
	 * m_pid is only set in the privileged part, and
114
	 * points to the unprivileged child.
115
	 */
116
	return (pmonitor && pmonitor->m_pid > 0);
117
}
118
119
void
120
mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
121
{
122
	u_int mlen = buffer_len(m);
123
	u_char buf[5];
124
125
	debug3("%s entering: type %d", __func__, type);
126
127
	put_u32(buf, mlen + 1);
128
	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
129
	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
130
		fatal("%s: write: %s", __func__, strerror(errno));
131
	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
132
		fatal("%s: write: %s", __func__, strerror(errno));
133
}
134
135
void
136
mm_request_receive(int sock, Buffer *m)
137
{
138
	u_char buf[4];
139
	u_int msg_len;
140
141
	debug3("%s entering", __func__);
142
143
	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
144
		if (errno == EPIPE)
145
			cleanup_exit(255);
146
		fatal("%s: read: %s", __func__, strerror(errno));
147
	}
148
	msg_len = get_u32(buf);
149
	if (msg_len > 256 * 1024)
150
		fatal("%s: read: bad msg_len %d", __func__, msg_len);
151
	buffer_clear(m);
152
	buffer_append_space(m, msg_len);
153
	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
154
		fatal("%s: read: %s", __func__, strerror(errno));
155
}
156
157
void
158
mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
159
{
160
	u_char rtype;
161
162
	debug3("%s entering: type %d", __func__, type);
163
164
	mm_request_receive(sock, m);
165
	rtype = buffer_get_char(m);
166
	if (rtype != type)
167
		fatal("%s: read: rtype %d != type %d", __func__,
168
		    rtype, type);
169
}
170
171
#ifdef WITH_OPENSSL
172
DH *
173
mm_choose_dh(int min, int nbits, int max)
174
{
175
	BIGNUM *p, *g;
176
	int success = 0;
177
	Buffer m;
178
179
	buffer_init(&m);
180
	buffer_put_int(&m, min);
181
	buffer_put_int(&m, nbits);
182
	buffer_put_int(&m, max);
183
184
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
185
186
	debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
187
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
188
189
	success = buffer_get_char(&m);
190
	if (success == 0)
191
		fatal("%s: MONITOR_ANS_MODULI failed", __func__);
192
193
	if ((p = BN_new()) == NULL)
194
		fatal("%s: BN_new failed", __func__);
195
	if ((g = BN_new()) == NULL)
196
		fatal("%s: BN_new failed", __func__);
197
	buffer_get_bignum2(&m, p);
198
	buffer_get_bignum2(&m, g);
199
200
	debug3("%s: remaining %d", __func__, buffer_len(&m));
201
	buffer_free(&m);
202
203
	return (dh_new_group(g, p));
204
}
205
#endif
206
207
int
208
mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
209
    const u_char *data, u_int datalen, const char *hostkey_alg)
210
{
211
	struct kex *kex = *pmonitor->m_pkex;
212
	Buffer m;
213
214
	debug3("%s entering", __func__);
215
216
	buffer_init(&m);
217
	buffer_put_int(&m, kex->host_key_index(key, 0, active_state));
218
	buffer_put_string(&m, data, datalen);
219
	buffer_put_cstring(&m, hostkey_alg);
220
221
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
222
223
	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
224
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
225
	*sigp  = buffer_get_string(&m, lenp);
226
	buffer_free(&m);
227
228
	return (0);
229
}
230
231
struct passwd *
232
mm_getpwnamallow(const char *username)
233
{
234
	struct ssh *ssh = active_state;		/* XXX */
235
	Buffer m;
236
	struct passwd *pw;
237
	u_int len, i;
238
	ServerOptions *newopts;
239
240
	debug3("%s entering", __func__);
241
242
	buffer_init(&m);
243
	buffer_put_cstring(&m, username);
244
245
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
246
247
	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
248
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
249
250
	if (buffer_get_char(&m) == 0) {
251
		pw = NULL;
252
		goto out;
253
	}
254
	pw = buffer_get_string(&m, &len);
255
	if (len != sizeof(struct passwd))
256
		fatal("%s: struct passwd size mismatch", __func__);
257
	pw->pw_name = buffer_get_string(&m, NULL);
258
	pw->pw_passwd = buffer_get_string(&m, NULL);
259
	pw->pw_gecos = buffer_get_string(&m, NULL);
260
	pw->pw_class = buffer_get_string(&m, NULL);
261
	pw->pw_dir = buffer_get_string(&m, NULL);
262
	pw->pw_shell = buffer_get_string(&m, NULL);
263
264
out:
265
	/* copy options block as a Match directive may have changed some */
266
	newopts = buffer_get_string(&m, &len);
267
	if (len != sizeof(*newopts))
268
		fatal("%s: option block size mismatch", __func__);
269
270
#define M_CP_STROPT(x) do { \
271
		if (newopts->x != NULL) \
272
			newopts->x = buffer_get_string(&m, NULL); \
273
	} while (0)
274
#define M_CP_STRARRAYOPT(x, nx) do { \
275
		newopts->x = newopts->nx == 0 ? \
276
		    NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
277
		for (i = 0; i < newopts->nx; i++) \
278
			newopts->x[i] = buffer_get_string(&m, NULL); \
279
	} while (0)
280
	/* See comment in servconf.h */
281
	COPY_MATCH_STRING_OPTS();
282
#undef M_CP_STROPT
283
#undef M_CP_STRARRAYOPT
284
285
	copy_set_server_options(&options, newopts, 1);
286
	log_change_level(options.log_level);
287
	process_permitopen(ssh, &options);
288
	free(newopts);
289
290
	buffer_free(&m);
291
292
	return (pw);
293
}
294
295
char *
296
mm_auth2_read_banner(void)
297
{
298
	Buffer m;
299
	char *banner;
300
301
	debug3("%s entering", __func__);
302
303
	buffer_init(&m);
304
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
305
	buffer_clear(&m);
306
307
	mm_request_receive_expect(pmonitor->m_recvfd,
308
	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
309
	banner = buffer_get_string(&m, NULL);
310
	buffer_free(&m);
311
312
	/* treat empty banner as missing banner */
313
	if (strlen(banner) == 0) {
314
		free(banner);
315
		banner = NULL;
316
	}
317
	return (banner);
318
}
319
320
/* Inform the privileged process about service and style */
321
322
void
323
mm_inform_authserv(char *service, char *style)
324
{
325
	Buffer m;
326
327
	debug3("%s entering", __func__);
328
329
	buffer_init(&m);
330
	buffer_put_cstring(&m, service);
331
	buffer_put_cstring(&m, style ? style : "");
332
333
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
334
335
	buffer_free(&m);
336
}
337
338
/* Do the password authentication */
339
int
340
mm_auth_password(Authctxt *authctxt, char *password)
341
{
342
	Buffer m;
343
	int authenticated = 0;
344
345
	debug3("%s entering", __func__);
346
347
	buffer_init(&m);
348
	buffer_put_cstring(&m, password);
349
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
350
351
	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
352
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
353
354
	authenticated = buffer_get_int(&m);
355
356
	buffer_free(&m);
357
358
	debug3("%s: user %sauthenticated",
359
	    __func__, authenticated ? "" : "not ");
360
	return (authenticated);
361
}
362
363
int
364
mm_user_key_allowed(struct passwd *pw, struct sshkey *key,
365
    int pubkey_auth_attempt)
366
{
367
	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
368
	    pubkey_auth_attempt));
369
}
370
371
int
372
mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
373
    struct sshkey *key)
374
{
375
	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
376
}
377
378
int
379
mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
380
    struct sshkey *key, int pubkey_auth_attempt)
381
{
382
	Buffer m;
383
	u_char *blob;
384
	u_int len;
385
	int allowed = 0, have_forced = 0;
386
387
	debug3("%s entering", __func__);
388
389
	/* Convert the key to a blob and the pass it over */
390
	if (!key_to_blob(key, &blob, &len))
391
		return (0);
392
393
	buffer_init(&m);
394
	buffer_put_int(&m, type);
395
	buffer_put_cstring(&m, user ? user : "");
396
	buffer_put_cstring(&m, host ? host : "");
397
	buffer_put_string(&m, blob, len);
398
	buffer_put_int(&m, pubkey_auth_attempt);
399
	free(blob);
400
401
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
402
403
	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
404
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
405
406
	allowed = buffer_get_int(&m);
407
408
	/* fake forced command */
409
	auth_clear_options();
410
	have_forced = buffer_get_int(&m);
411
	forced_command = have_forced ? xstrdup("true") : NULL;
412
413
	buffer_free(&m);
414
415
	return (allowed);
416
}
417
418
/*
419
 * This key verify needs to send the key type along, because the
420
 * privileged parent makes the decision if the key is allowed
421
 * for authentication.
422
 */
423
424
int
425
mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
426
    const u_char *data, size_t datalen, u_int compat)
427
{
428
	Buffer m;
429
	u_char *blob;
430
	u_int len;
431
	u_int encoded_ret = 0;
432
433
	debug3("%s entering", __func__);
434
435
	/* Convert the key to a blob and the pass it over */
436
	if (!key_to_blob(key, &blob, &len))
437
		return (0);
438
439
	buffer_init(&m);
440
	buffer_put_string(&m, blob, len);
441
	buffer_put_string(&m, sig, siglen);
442
	buffer_put_string(&m, data, datalen);
443
	free(blob);
444
445
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
446
447
	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
448
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
449
450
	encoded_ret = buffer_get_int(&m);
451
452
	buffer_free(&m);
453
454
	if (encoded_ret != 0)
455
		return SSH_ERR_SIGNATURE_INVALID;
456
	return 0;
457
}
458
459
void
460
mm_send_keystate(struct monitor *monitor)
461
{
462
	struct ssh *ssh = active_state;		/* XXX */
463
	struct sshbuf *m;
464
	int r;
465
466
	if ((m = sshbuf_new()) == NULL)
467
		fatal("%s: sshbuf_new failed", __func__);
468
	if ((r = ssh_packet_get_state(ssh, m)) != 0)
469
		fatal("%s: get_state failed: %s",
470
		    __func__, ssh_err(r));
471
	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
472
	debug3("%s: Finished sending state", __func__);
473
	sshbuf_free(m);
474
}
475
476
int
477
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
478
{
479
	Buffer m;
480
	char *p, *msg;
481
	int success = 0, tmp1 = -1, tmp2 = -1;
482
483
	/* Kludge: ensure there are fds free to receive the pty/tty */
484
	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
485
	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
486
		error("%s: cannot allocate fds for pty", __func__);
487
		if (tmp1 > 0)
488
			close(tmp1);
489
		if (tmp2 > 0)
490
			close(tmp2);
491
		return 0;
492
	}
493
	close(tmp1);
494
	close(tmp2);
495
496
	buffer_init(&m);
497
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
498
499
	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
500
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
501
502
	success = buffer_get_int(&m);
503
	if (success == 0) {
504
		debug3("%s: pty alloc failed", __func__);
505
		buffer_free(&m);
506
		return (0);
507
	}
508
	p = buffer_get_string(&m, NULL);
509
	msg = buffer_get_string(&m, NULL);
510
	buffer_free(&m);
511
512
	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
513
	free(p);
514
515
	buffer_append(&loginmsg, msg, strlen(msg));
516
	free(msg);
517
518
	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
519
	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
520
		fatal("%s: receive fds failed", __func__);
521
522
	/* Success */
523
	return (1);
524
}
525
526
void
527
mm_session_pty_cleanup2(Session *s)
528
{
529
	Buffer m;
530
531
	if (s->ttyfd == -1)
532
		return;
533
	buffer_init(&m);
534
	buffer_put_cstring(&m, s->tty);
535
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
536
	buffer_free(&m);
537
538
	/* closed dup'ed master */
539
	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
540
		error("close(s->ptymaster/%d): %s",
541
		    s->ptymaster, strerror(errno));
542
543
	/* unlink pty from session */
544
	s->ttyfd = -1;
545
}
546
547
/* Request process termination */
548
549
void
550
mm_terminate(void)
551
{
552
	Buffer m;
553
554
	buffer_init(&m);
555
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
556
	buffer_free(&m);
557
}
558
559
static void
560
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
561
    char ***prompts, u_int **echo_on)
562
{
563
	*name = xstrdup("");
564
	*infotxt = xstrdup("");
565
	*numprompts = 1;
566
	*prompts = xcalloc(*numprompts, sizeof(char *));
567
	*echo_on = xcalloc(*numprompts, sizeof(u_int));
568
	(*echo_on)[0] = 0;
569
}
570
571
int
572
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
573
   u_int *numprompts, char ***prompts, u_int **echo_on)
574
{
575
	Buffer m;
576
	u_int success;
577
	char *challenge;
578
579
	debug3("%s: entering", __func__);
580
581
	buffer_init(&m);
582
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
583
584
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
585
	    &m);
586
	success = buffer_get_int(&m);
587
	if (success == 0) {
588
		debug3("%s: no challenge", __func__);
589
		buffer_free(&m);
590
		return (-1);
591
	}
592
593
	/* Get the challenge, and format the response */
594
	challenge  = buffer_get_string(&m, NULL);
595
	buffer_free(&m);
596
597
	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
598
	(*prompts)[0] = challenge;
599
600
	debug3("%s: received challenge: %s", __func__, challenge);
601
602
	return (0);
603
}
604
605
int
606
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
607
{
608
	Buffer m;
609
	int authok;
610
611
	debug3("%s: entering", __func__);
612
	if (numresponses != 1)
613
		return (-1);
614
615
	buffer_init(&m);
616
	buffer_put_cstring(&m, responses[0]);
617
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
618
619
	mm_request_receive_expect(pmonitor->m_recvfd,
620
	    MONITOR_ANS_BSDAUTHRESPOND, &m);
621
622
	authok = buffer_get_int(&m);
623
	buffer_free(&m);
624
625
	return ((authok == 0) ? -1 : 0);
626
}
627
628
#ifdef GSSAPI
629
OM_uint32
630
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
631
{
632
	Buffer m;
633
	OM_uint32 major;
634
635
	/* Client doesn't get to see the context */
636
	*ctx = NULL;
637
638
	buffer_init(&m);
639
	buffer_put_string(&m, goid->elements, goid->length);
640
641
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
642
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
643
644
	major = buffer_get_int(&m);
645
646
	buffer_free(&m);
647
	return (major);
648
}
649
650
OM_uint32
651
mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
652
    gss_buffer_desc *out, OM_uint32 *flags)
653
{
654
	Buffer m;
655
	OM_uint32 major;
656
	u_int len;
657
658
	buffer_init(&m);
659
	buffer_put_string(&m, in->value, in->length);
660
661
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
662
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
663
664
	major = buffer_get_int(&m);
665
	out->value = buffer_get_string(&m, &len);
666
	out->length = len;
667
	if (flags)
668
		*flags = buffer_get_int(&m);
669
670
	buffer_free(&m);
671
672
	return (major);
673
}
674
675
OM_uint32
676
mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
677
{
678
	Buffer m;
679
	OM_uint32 major;
680
681
	buffer_init(&m);
682
	buffer_put_string(&m, gssbuf->value, gssbuf->length);
683
	buffer_put_string(&m, gssmic->value, gssmic->length);
684
685
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
686
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
687
	    &m);
688
689
	major = buffer_get_int(&m);
690
	buffer_free(&m);
691
	return(major);
692
}
693
694
int
695
mm_ssh_gssapi_userok(char *user)
696
{
697
	Buffer m;
698
	int authenticated = 0;
699
700
	buffer_init(&m);
701
702
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
703
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
704
				  &m);
705
706
	authenticated = buffer_get_int(&m);
707
708
	buffer_free(&m);
709
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
710
	return (authenticated);
711
}
712
#endif /* GSSAPI */
713