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