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

Line Branch Exec Source
1
/* $OpenBSD: monitor_wrap.c,v 1.94 2017/10/02 19:33:20 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
		for (i = 0; i < newopts->nx; i++) \
276
			newopts->x[i] = buffer_get_string(&m, NULL); \
277
	} while (0)
278
#define M_CP_STRARRAYOPT_ALLOC(x, nx) do { \
279
		newopts->x = newopts->nx == 0 ? \
280
		    NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
281
		M_CP_STRARRAYOPT(x, nx); \
282
	} while (0)
283
	/* See comment in servconf.h */
284
	COPY_MATCH_STRING_OPTS();
285
#undef M_CP_STROPT
286
#undef M_CP_STRARRAYOPT
287
#undef M_CP_STRARRAYOPT_ALLOC
288
289
	copy_set_server_options(&options, newopts, 1);
290
	log_change_level(options.log_level);
291
	process_permitopen(ssh, &options);
292
	free(newopts);
293
294
	buffer_free(&m);
295
296
	return (pw);
297
}
298
299
char *
300
mm_auth2_read_banner(void)
301
{
302
	Buffer m;
303
	char *banner;
304
305
	debug3("%s entering", __func__);
306
307
	buffer_init(&m);
308
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
309
	buffer_clear(&m);
310
311
	mm_request_receive_expect(pmonitor->m_recvfd,
312
	    MONITOR_ANS_AUTH2_READ_BANNER, &m);
313
	banner = buffer_get_string(&m, NULL);
314
	buffer_free(&m);
315
316
	/* treat empty banner as missing banner */
317
	if (strlen(banner) == 0) {
318
		free(banner);
319
		banner = NULL;
320
	}
321
	return (banner);
322
}
323
324
/* Inform the privileged process about service and style */
325
326
void
327
mm_inform_authserv(char *service, char *style)
328
{
329
	Buffer m;
330
331
	debug3("%s entering", __func__);
332
333
	buffer_init(&m);
334
	buffer_put_cstring(&m, service);
335
	buffer_put_cstring(&m, style ? style : "");
336
337
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
338
339
	buffer_free(&m);
340
}
341
342
/* Do the password authentication */
343
int
344
mm_auth_password(Authctxt *authctxt, char *password)
345
{
346
	Buffer m;
347
	int authenticated = 0;
348
349
	debug3("%s entering", __func__);
350
351
	buffer_init(&m);
352
	buffer_put_cstring(&m, password);
353
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
354
355
	debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
356
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
357
358
	authenticated = buffer_get_int(&m);
359
360
	buffer_free(&m);
361
362
	debug3("%s: user %sauthenticated",
363
	    __func__, authenticated ? "" : "not ");
364
	return (authenticated);
365
}
366
367
int
368
mm_user_key_allowed(struct passwd *pw, struct sshkey *key,
369
    int pubkey_auth_attempt)
370
{
371
	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
372
	    pubkey_auth_attempt));
373
}
374
375
int
376
mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
377
    struct sshkey *key)
378
{
379
	return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
380
}
381
382
int
383
mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
384
    struct sshkey *key, int pubkey_auth_attempt)
385
{
386
	Buffer m;
387
	u_char *blob;
388
	u_int len;
389
	int allowed = 0, have_forced = 0;
390
391
	debug3("%s entering", __func__);
392
393
	/* Convert the key to a blob and the pass it over */
394
	if (!key_to_blob(key, &blob, &len))
395
		return (0);
396
397
	buffer_init(&m);
398
	buffer_put_int(&m, type);
399
	buffer_put_cstring(&m, user ? user : "");
400
	buffer_put_cstring(&m, host ? host : "");
401
	buffer_put_string(&m, blob, len);
402
	buffer_put_int(&m, pubkey_auth_attempt);
403
	free(blob);
404
405
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
406
407
	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
408
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
409
410
	allowed = buffer_get_int(&m);
411
412
	/* fake forced command */
413
	auth_clear_options();
414
	have_forced = buffer_get_int(&m);
415
	forced_command = have_forced ? xstrdup("true") : NULL;
416
417
	buffer_free(&m);
418
419
	return (allowed);
420
}
421
422
/*
423
 * This key verify needs to send the key type along, because the
424
 * privileged parent makes the decision if the key is allowed
425
 * for authentication.
426
 */
427
428
int
429
mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
430
    const u_char *data, size_t datalen, u_int compat)
431
{
432
	Buffer m;
433
	u_char *blob;
434
	u_int len;
435
	u_int encoded_ret = 0;
436
437
	debug3("%s entering", __func__);
438
439
	/* Convert the key to a blob and the pass it over */
440
	if (!key_to_blob(key, &blob, &len))
441
		return (0);
442
443
	buffer_init(&m);
444
	buffer_put_string(&m, blob, len);
445
	buffer_put_string(&m, sig, siglen);
446
	buffer_put_string(&m, data, datalen);
447
	free(blob);
448
449
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
450
451
	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
452
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
453
454
	encoded_ret = buffer_get_int(&m);
455
456
	buffer_free(&m);
457
458
	if (encoded_ret != 0)
459
		return SSH_ERR_SIGNATURE_INVALID;
460
	return 0;
461
}
462
463
void
464
mm_send_keystate(struct monitor *monitor)
465
{
466
	struct ssh *ssh = active_state;		/* XXX */
467
	struct sshbuf *m;
468
	int r;
469
470
	if ((m = sshbuf_new()) == NULL)
471
		fatal("%s: sshbuf_new failed", __func__);
472
	if ((r = ssh_packet_get_state(ssh, m)) != 0)
473
		fatal("%s: get_state failed: %s",
474
		    __func__, ssh_err(r));
475
	mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
476
	debug3("%s: Finished sending state", __func__);
477
	sshbuf_free(m);
478
}
479
480
int
481
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
482
{
483
	Buffer m;
484
	char *p, *msg;
485
	int success = 0, tmp1 = -1, tmp2 = -1;
486
487
	/* Kludge: ensure there are fds free to receive the pty/tty */
488
	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
489
	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
490
		error("%s: cannot allocate fds for pty", __func__);
491
		if (tmp1 > 0)
492
			close(tmp1);
493
		if (tmp2 > 0)
494
			close(tmp2);
495
		return 0;
496
	}
497
	close(tmp1);
498
	close(tmp2);
499
500
	buffer_init(&m);
501
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
502
503
	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
504
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
505
506
	success = buffer_get_int(&m);
507
	if (success == 0) {
508
		debug3("%s: pty alloc failed", __func__);
509
		buffer_free(&m);
510
		return (0);
511
	}
512
	p = buffer_get_string(&m, NULL);
513
	msg = buffer_get_string(&m, NULL);
514
	buffer_free(&m);
515
516
	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
517
	free(p);
518
519
	buffer_append(&loginmsg, msg, strlen(msg));
520
	free(msg);
521
522
	if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
523
	    (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
524
		fatal("%s: receive fds failed", __func__);
525
526
	/* Success */
527
	return (1);
528
}
529
530
void
531
mm_session_pty_cleanup2(Session *s)
532
{
533
	Buffer m;
534
535
	if (s->ttyfd == -1)
536
		return;
537
	buffer_init(&m);
538
	buffer_put_cstring(&m, s->tty);
539
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
540
	buffer_free(&m);
541
542
	/* closed dup'ed master */
543
	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
544
		error("close(s->ptymaster/%d): %s",
545
		    s->ptymaster, strerror(errno));
546
547
	/* unlink pty from session */
548
	s->ttyfd = -1;
549
}
550
551
/* Request process termination */
552
553
void
554
mm_terminate(void)
555
{
556
	Buffer m;
557
558
	buffer_init(&m);
559
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
560
	buffer_free(&m);
561
}
562
563
static void
564
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
565
    char ***prompts, u_int **echo_on)
566
{
567
	*name = xstrdup("");
568
	*infotxt = xstrdup("");
569
	*numprompts = 1;
570
	*prompts = xcalloc(*numprompts, sizeof(char *));
571
	*echo_on = xcalloc(*numprompts, sizeof(u_int));
572
	(*echo_on)[0] = 0;
573
}
574
575
int
576
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
577
   u_int *numprompts, char ***prompts, u_int **echo_on)
578
{
579
	Buffer m;
580
	u_int success;
581
	char *challenge;
582
583
	debug3("%s: entering", __func__);
584
585
	buffer_init(&m);
586
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
587
588
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
589
	    &m);
590
	success = buffer_get_int(&m);
591
	if (success == 0) {
592
		debug3("%s: no challenge", __func__);
593
		buffer_free(&m);
594
		return (-1);
595
	}
596
597
	/* Get the challenge, and format the response */
598
	challenge  = buffer_get_string(&m, NULL);
599
	buffer_free(&m);
600
601
	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
602
	(*prompts)[0] = challenge;
603
604
	debug3("%s: received challenge: %s", __func__, challenge);
605
606
	return (0);
607
}
608
609
int
610
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
611
{
612
	Buffer m;
613
	int authok;
614
615
	debug3("%s: entering", __func__);
616
	if (numresponses != 1)
617
		return (-1);
618
619
	buffer_init(&m);
620
	buffer_put_cstring(&m, responses[0]);
621
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
622
623
	mm_request_receive_expect(pmonitor->m_recvfd,
624
	    MONITOR_ANS_BSDAUTHRESPOND, &m);
625
626
	authok = buffer_get_int(&m);
627
	buffer_free(&m);
628
629
	return ((authok == 0) ? -1 : 0);
630
}
631
632
#ifdef GSSAPI
633
OM_uint32
634
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
635
{
636
	Buffer m;
637
	OM_uint32 major;
638
639
	/* Client doesn't get to see the context */
640
	*ctx = NULL;
641
642
	buffer_init(&m);
643
	buffer_put_string(&m, goid->elements, goid->length);
644
645
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
646
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
647
648
	major = buffer_get_int(&m);
649
650
	buffer_free(&m);
651
	return (major);
652
}
653
654
OM_uint32
655
mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
656
    gss_buffer_desc *out, OM_uint32 *flags)
657
{
658
	Buffer m;
659
	OM_uint32 major;
660
	u_int len;
661
662
	buffer_init(&m);
663
	buffer_put_string(&m, in->value, in->length);
664
665
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
666
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
667
668
	major = buffer_get_int(&m);
669
	out->value = buffer_get_string(&m, &len);
670
	out->length = len;
671
	if (flags)
672
		*flags = buffer_get_int(&m);
673
674
	buffer_free(&m);
675
676
	return (major);
677
}
678
679
OM_uint32
680
mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
681
{
682
	Buffer m;
683
	OM_uint32 major;
684
685
	buffer_init(&m);
686
	buffer_put_string(&m, gssbuf->value, gssbuf->length);
687
	buffer_put_string(&m, gssmic->value, gssmic->length);
688
689
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
690
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
691
	    &m);
692
693
	major = buffer_get_int(&m);
694
	buffer_free(&m);
695
	return(major);
696
}
697
698
int
699
mm_ssh_gssapi_userok(char *user)
700
{
701
	Buffer m;
702
	int authenticated = 0;
703
704
	buffer_init(&m);
705
706
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
707
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
708
				  &m);
709
710
	authenticated = buffer_get_int(&m);
711
712
	buffer_free(&m);
713
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
714
	return (authenticated);
715
}
716
#endif /* GSSAPI */
717