]> andersk Git - gssapi-openssh.git/blame - openssh/auth2-gss.c
o Bump version to 2.7.
[gssapi-openssh.git] / openssh / auth2-gss.c
CommitLineData
b59afbfe 1/*
23987cb8 2 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
b59afbfe 3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
27#ifdef GSSAPI
28#include "auth.h"
29#include "ssh2.h"
30#include "ssh1.h"
31#include "xmalloc.h"
32#include "log.h"
33#include "dispatch.h"
34#include "servconf.h"
35#include "compat.h"
36#include "packet.h"
37#include "monitor_wrap.h"
38
39#include "ssh-gss.h"
40
41extern ServerOptions options;
23987cb8 42unsigned char ssh1_key_digest[16];
b59afbfe 43
44static int
45userauth_external(Authctxt *authctxt)
46{
47 packet_check_eom();
48
49 return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
50}
51
23987cb8 52static void ssh_gssapi_userauth_error(Gssctxt *ctxt);
b59afbfe 53static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
54static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
e23e524c 55static void input_gssapi_errtok(int, u_int32_t, void *);
b59afbfe 56
57/* We only support those mechanisms that we know about (ie ones that we know
58 * how to check local user kuserok and the like
59 */
60static int
61userauth_gssapi(Authctxt *authctxt)
62{
63 gss_OID_desc oid= {0,NULL};
64 Gssctxt *ctxt = NULL;
65 int mechs;
66 gss_OID_set supported;
67 int present;
68 OM_uint32 ms;
69 u_int len;
23987cb8 70 char * doid = NULL;
b59afbfe 71
72 if (!authctxt->valid || authctxt->user == NULL)
73 return 0;
74
75 if (datafellows & SSH_OLD_GSSAPI) {
76 debug("Early drafts of GSSAPI userauth not supported");
77 return 0;
78 }
79
80 mechs=packet_get_int();
81 if (mechs==0) {
82 debug("Mechanism negotiation is not supported");
83 return 0;
84 }
85
86 ssh_gssapi_supported_oids(&supported);
87 do {
b59afbfe 88 mechs--;
23987cb8 89
90 if (doid)
91 xfree(doid);
92
93 debug("Trying to get OID string");
94 doid = packet_get_string(&len);
95 debug("Got string");
96
e23e524c 97 if (doid[0]!=0x06 || doid[1]!=len-2) {
98 log("Mechanism OID received using the old encoding form");
99 oid.elements = doid;
100 oid.length = len;
101 } else {
102 oid.elements = doid + 2;
103 oid.length = len - 2;
104 }
105 gss_test_oid_set_member(&ms, &oid, supported, &present);
b59afbfe 106 } while (mechs>0 && !present);
107
108 if (!present) {
23987cb8 109 xfree(doid);
b59afbfe 110 return(0);
111 }
112
23987cb8 113 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt,&oid)))) {
114 ssh_gssapi_userauth_error(ctxt);
b59afbfe 115 return(0);
23987cb8 116 }
b59afbfe 117
118 authctxt->methoddata=(void *)ctxt;
119
120 /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */
121
23987cb8 122 if (!compat20) {
123
124 packet_start(SSH_SMSG_AUTH_GSSAPI_RESPONSE);
125 packet_put_string(oid.elements,oid.length);
126
127 } else {
128
129 packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
130
e23e524c 131 /* Just return whatever they sent */
132 packet_put_string(doid,len);
23987cb8 133
134 } /* !compat20 */
135
b59afbfe 136 packet_send();
137 packet_write_wait();
23987cb8 138 xfree(doid);
b59afbfe 139
140 if (!compat20)
141 dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN,
142 &input_gssapi_token);
143 else
23987cb8 144 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,
145 &input_gssapi_token);
e23e524c 146 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,
147 &input_gssapi_errtok);
b59afbfe 148 authctxt->postponed = 1;
149
150 return 0;
151}
152
153static void
154input_gssapi_token(int type, u_int32_t plen, void *ctxt)
155{
156 Authctxt *authctxt = ctxt;
157 Gssctxt *gssctxt;
158 gss_buffer_desc send_tok,recv_tok;
159 OM_uint32 maj_status, min_status;
d7590ddf 160 u_int len;
b59afbfe 161
162 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
163 fatal("No authentication or GSSAPI context");
164
165 gssctxt=authctxt->methoddata;
007914b3 166 recv_tok.value=packet_get_string(&len);
d7590ddf 167 recv_tok.length=len; /* u_int vs. size_t */
b59afbfe 168
169 maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
e23e524c 170 &send_tok, NULL));
b59afbfe 171 packet_check_eom();
23987cb8 172
705f2ba4 173 if (GSS_ERROR(maj_status)) {
e23e524c 174 ssh_gssapi_userauth_error(gssctxt);
175 if (send_tok.length != 0) {
176 if (!compat20)
177 packet_start(SSH_MSG_AUTH_GSSAPI_TOKEN);
178 else
179 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
180 packet_put_string(send_tok.value,send_tok.length);
181 packet_send();
182 packet_write_wait();
183 }
705f2ba4 184 authctxt->postponed = 0;
185 dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
186 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
187 userauth_finish(authctxt, 0, "gssapi");
e23e524c 188 } else {
189 if (send_tok.length != 0) {
190 if (!compat20)
191 packet_start(SSH_MSG_AUTH_GSSAPI_TOKEN);
192 else
193 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
194 packet_put_string(send_tok.value,send_tok.length);
195 packet_send();
196 packet_write_wait();
197 }
198 if (maj_status == GSS_S_COMPLETE) {
199 dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
200 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
201 if (!compat20)
202 input_gssapi_exchange_complete(0, 0, ctxt);
203 else
204 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
205 &input_gssapi_exchange_complete);
206 }
705f2ba4 207 }
e23e524c 208
209 gss_release_buffer(&min_status, &send_tok);
210}
23987cb8 211
e23e524c 212static void
213input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
214{
215 Authctxt *authctxt = ctxt;
216 Gssctxt *gssctxt;
217 gss_buffer_desc send_tok,recv_tok;
218 OM_uint32 maj_status;
219
220 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
221 fatal("No authentication or GSSAPI context");
222
223 gssctxt=authctxt->methoddata;
224 recv_tok.value=packet_get_string(&recv_tok.length);
225
226 /* Push the error token into GSSAPI to see what it says */
227 maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
228 &send_tok, NULL));
229 packet_check_eom();
230
231 /* We can't return anything to the client, even if we wanted to */
232 dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
233 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
234 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,NULL);
235
236 /* The client will have already moved on to the next auth */
237
b59afbfe 238}
239
240/* This is called when the client thinks we've completed authentication.
241 * It should only be enabled in the dispatch handler by the function above,
242 * which only enables it once the GSSAPI exchange is complete.
243 */
244
245static void
246input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
247{
248 Authctxt *authctxt = ctxt;
249 Gssctxt *gssctxt;
250 int authenticated;
251
252 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
253 fatal("No authentication or GSSAPI context");
254
d13dfff4 255 if ((strcmp(authctxt->user, "") == 0) && (authctxt->pw == NULL)) {
256 char *lname = NULL;
257 PRIVSEP(ssh_gssapi_localname(&lname));
258 if (lname && lname[0] != '\0') {
259 xfree(authctxt->user);
260 authctxt->user = lname;
261 debug("set username to %s from gssapi context", lname);
262 authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
263 } else {
264 debug("failed to set username from gssapi context");
265 }
266 }
267 if (authctxt->pw) {
268#ifdef USE_PAM
269 PRIVSEP(start_pam(authctxt->pw->pw_name));
270#endif
271 } else {
272 authctxt->valid = 0;
273 authenticated = 0;
274 goto finish;
275 }
276
b59afbfe 277 gssctxt=authctxt->methoddata;
23987cb8 278
b59afbfe 279 /* ssh1 needs to exchange the hash of the keys */
280 if (!compat20) {
281
282 OM_uint32 min_status;
283 gss_buffer_desc dummy, msg_tok;
284
285 /* ssh1 wraps the keys, in the monitor */
286
287 dummy.value=malloc(sizeof(ssh1_key_digest));
288 memcpy(dummy.value,ssh1_key_digest,sizeof(ssh1_key_digest));
289 dummy.length=sizeof(ssh1_key_digest);
290 if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(gssctxt,&dummy,&msg_tok))))
291 fatal("Couldn't wrap keys");
292
293 packet_start(SSH_SMSG_AUTH_GSSAPI_HASH);
294 packet_put_string((char *)msg_tok.value,msg_tok.length);
295 packet_send();
296 packet_write_wait();
297 gss_release_buffer(&min_status,&msg_tok);
298 }
299
300
301 /* We don't need to check the status, because the stored credentials
302 * which userok uses are only populated once the context init step
303 * has returned complete.
304 */
305
306 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
307
d13dfff4 308finish:
b59afbfe 309 authctxt->postponed = 0;
310 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
e23e524c 311 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
b59afbfe 312 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
313 userauth_finish(authctxt, authenticated, "gssapi");
314}
315
23987cb8 316static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
317 char *errstr;
318 OM_uint32 maj,min;
319
320 errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
321 if (errstr) {
e23e524c 322 if (!compat20) {
323 packet_send_debug(errstr);
324 } else {
23987cb8 325 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR);
326 packet_put_int(maj);
327 packet_put_int(min);
328 packet_put_cstring(errstr);
329 packet_put_cstring("");
330 packet_send();
331 packet_write_wait();
332 xfree(errstr);
e23e524c 333 }
23987cb8 334 }
335}
336
b59afbfe 337Authmethod method_external = {
338 "external-keyx",
339 userauth_external,
340 &options.gss_authentication
341};
342
343Authmethod method_gssapi = {
344 "gssapi",
345 userauth_gssapi,
346 &options.gss_authentication
347};
348
349#endif /* GSSAPI */
This page took 0.1083 seconds and 5 git commands to generate.