1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without
7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions
8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met:
9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright
10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer.
11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright
12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer in the
13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    documentation and/or other materials provided with the distribution.
14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h"
28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef GSSAPI
30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h>
32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h>
34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h"
36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "key.h"
37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "hostfile.h"
38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "auth.h"
39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh2.h"
40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h"
41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "dispatch.h"
42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "buffer.h"
43d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "misc.h"
44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "servconf.h"
45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "packet.h"
46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh-gss.h"
47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "monitor_wrap.h"
48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern ServerOptions options;
50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
51d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int input_gssapi_token(int type, u_int32_t plen, void *ctxt);
52d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
53d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
54d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int input_gssapi_errtok(int, u_int32_t, void *);
55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * We only support those mechanisms that we know about (ie ones that we know
58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * how to check local user kuserok and the like)
59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int
61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanuserauth_gssapi(Authctxt *authctxt)
62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_OID_desc goid = {0, NULL};
64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Gssctxt *ctxt = NULL;
65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int mechs;
66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int present;
67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	OM_uint32 ms;
68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_int len;
69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_char *doid = NULL;
70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!authctxt->valid || authctxt->user == NULL)
72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	mechs = packet_get_int();
75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (mechs == 0) {
76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		debug("Mechanism negotiation is not supported");
77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	do {
81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		mechs--;
82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
83d059297112922cabb0c674840589be8db821fd9aAdam Langley		free(doid);
84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		present = 0;
86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		doid = packet_get_string(&len);
87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    doid[1] == len - 2) {
90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			goid.elements = doid + 2;
91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			goid.length   = len - 2;
92d059297112922cabb0c674840589be8db821fd9aAdam Langley			ssh_gssapi_test_oid_supported(&ms, &goid, &present);
93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		} else {
94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			logit("Badly formed OID received");
95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} while (mechs > 0 && !present);
97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!present) {
99d059297112922cabb0c674840589be8db821fd9aAdam Langley		free(doid);
100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		authctxt->server_caused_failure = 1;
101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (ctxt != NULL)
106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			ssh_gssapi_delete_ctx(&ctxt);
107d059297112922cabb0c674840589be8db821fd9aAdam Langley		free(doid);
108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		authctxt->server_caused_failure = 1;
109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	authctxt->methoddata = (void *)ctxt;
113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Return the OID that we received */
117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_put_string(doid, len);
118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_send();
120d059297112922cabb0c674840589be8db821fd9aAdam Langley	free(doid);
121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	authctxt->postponed = 1;
125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (0);
127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
129d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int
130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaninput_gssapi_token(int type, u_int32_t plen, void *ctxt)
131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Authctxt *authctxt = ctxt;
133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Gssctxt *gssctxt;
134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_buffer_desc recv_tok;
136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	OM_uint32 maj_status, min_status, flags;
137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_int len;
138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fatal("No authentication or GSSAPI context");
141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gssctxt = authctxt->methoddata;
143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	recv_tok.value = packet_get_string(&len);
144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	recv_tok.length = len; /* u_int vs. size_t */
145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_check_eom();
147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    &send_tok, &flags));
150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
151d059297112922cabb0c674840589be8db821fd9aAdam Langley	free(recv_tok.value);
152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (GSS_ERROR(maj_status)) {
154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (send_tok.length != 0) {
155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_put_string(send_tok.value, send_tok.length);
157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_send();
158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		authctxt->postponed = 0;
160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
161d059297112922cabb0c674840589be8db821fd9aAdam Langley		userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} else {
163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (send_tok.length != 0) {
164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_put_string(send_tok.value, send_tok.length);
166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			packet_send();
167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (maj_status == GSS_S_COMPLETE) {
169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (flags & GSS_C_INTEG_FLAG)
171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				    &input_gssapi_mic);
173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			else
174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				dispatch_set(
175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				    SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				    &input_gssapi_exchange_complete);
177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_release_buffer(&min_status, &send_tok);
181d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
184d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int
185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaninput_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Authctxt *authctxt = ctxt;
188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Gssctxt *gssctxt;
189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_buffer_desc recv_tok;
191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	OM_uint32 maj_status;
192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_int len;
193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fatal("No authentication or GSSAPI context");
196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gssctxt = authctxt->methoddata;
198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	recv_tok.value = packet_get_string(&len);
199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	recv_tok.length = len;
200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_check_eom();
202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Push the error token into GSSAPI to see what it says */
204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    &send_tok, NULL));
206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
207d059297112922cabb0c674840589be8db821fd9aAdam Langley	free(recv_tok.value);
208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* We can't return anything to the client, even if we wanted to */
210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* The client will have already moved on to the next auth */
214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_release_buffer(&maj_status, &send_tok);
216d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This is called when the client thinks we've completed authentication.
221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * It should only be enabled in the dispatch handler by the function above,
222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * which only enables it once the GSSAPI exchange is complete.
223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
225d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int
226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaninput_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Authctxt *authctxt = ctxt;
229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int authenticated;
230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fatal("No authentication or GSSAPI context");
233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/*
235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 * We don't need to check the status, because we're only enabled in
236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 * the dispatcher once the exchange is complete
237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 */
238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	packet_check_eom();
240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	authctxt->postponed = 0;
244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
248d059297112922cabb0c674840589be8db821fd9aAdam Langley	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
249d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
252d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int
253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaninput_gssapi_mic(int type, u_int32_t plen, void *ctxt)
254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Authctxt *authctxt = ctxt;
256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Gssctxt *gssctxt;
257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int authenticated = 0;
258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Buffer b;
259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gss_buffer_desc mic, gssbuf;
260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_int len;
261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fatal("No authentication or GSSAPI context");
264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gssctxt = authctxt->methoddata;
266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	mic.value = packet_get_string(&len);
268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	mic.length = len;
269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "gssapi-with-mic");
272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gssbuf.value = buffer_ptr(&b);
274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gssbuf.length = buffer_len(&b);
275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	else
279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("GSSAPI MIC check failed");
280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_free(&b);
282d059297112922cabb0c674840589be8db821fd9aAdam Langley	free(mic.value);
283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	authctxt->postponed = 0;
285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
289d059297112922cabb0c674840589be8db821fd9aAdam Langley	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
290d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanAuthmethod method_gssapi = {
294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	"gssapi-with-mic",
295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	userauth_gssapi,
296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	&options.gss_authentication
297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman};
298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* GSSAPI */
300