]> andersk Git - gssapi-openssh.git/blame - openssh/gss-serv.c
bugfix: mechglue code broke krb5-only build
[gssapi-openssh.git] / openssh / gss-serv.c
CommitLineData
5598e598 1/*
23987cb8 2 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5598e598 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
29#include "ssh.h"
30#include "ssh2.h"
31#include "xmalloc.h"
32#include "buffer.h"
33#include "bufaux.h"
34#include "packet.h"
35#include "compat.h"
36#include <openssl/evp.h>
37#include "cipher.h"
38#include "kex.h"
39#include "auth.h"
40#include "log.h"
e5affddc 41#include "channels.h"
5598e598 42#include "session.h"
43#include "dispatch.h"
44#include "servconf.h"
905081a4 45#include "compat.h"
b59afbfe 46#include "monitor_wrap.h"
5598e598 47
48#include "ssh-gss.h"
49
50extern ServerOptions options;
51extern u_char *session_id2;
52extern int session_id2_len;
53
23987cb8 54static ssh_gssapi_client gssapi_client =
55 { {0,NULL}, GSS_C_NO_CREDENTIAL, NULL, {NULL,NULL,NULL}};
5598e598 56
23987cb8 57ssh_gssapi_mech gssapi_null_mech
58 = {NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
44a053a3 59
5598e598 60#ifdef KRB5
23987cb8 61extern ssh_gssapi_mech gssapi_kerberos_mech;
62extern ssh_gssapi_mech gssapi_kerberos_mech_old;
54425c7a 63#endif
5598e598 64#ifdef GSI
23987cb8 65extern ssh_gssapi_mech gssapi_gsi_mech;
66extern ssh_gssapi_mech gssapi_gsi_mech_old;
b311f64e 67#endif
68
23987cb8 69ssh_gssapi_mech* supported_mechs[]= {
5598e598 70#ifdef KRB5
23987cb8 71 &gssapi_kerberos_mech,
72 &gssapi_kerberos_mech_old, /* Support for legacy clients */
5598e598 73#endif
74#ifdef GSI
23987cb8 75 &gssapi_gsi_mech,
76 &gssapi_gsi_mech_old, /* Support for legacy clients */
7b5a625b 77#endif
23987cb8 78 &gssapi_null_mech,
79};
5598e598 80
23987cb8 81/* Return a list of the gss-group1-sha1-x mechanisms supported by this
82 * program.
5598e598 83 *
23987cb8 84 * We only support the mechanisms that we've indicated in the list above,
85 * but we check that they're supported by the GSSAPI mechanism on the
86 * machine. We also check, before including them in the list, that
87 * we have the necesary information in order to carry out the key exchange
88 * (that is, that the user has credentials, the server's creds are accessible,
89 * etc)
90 *
91 * The way that this is done is fairly nasty, as we do a lot of work that
92 * is then thrown away. This should possibly be implemented with a cache
93 * that stores the results (in an expanded Gssctxt structure), which are
94 * then used by the first calls if that key exchange mechanism is chosen.
6a8bca29 95 */
23987cb8 96
f001f132 97char *
23987cb8 98ssh_gssapi_server_mechanisms() {
f001f132 99 gss_OID_set supported;
23987cb8 100 Gssctxt *ctx = NULL;
f001f132 101 OM_uint32 maj_status, min_status;
102 Buffer buf;
103 int i = 0;
23987cb8 104 int first = 0;
f001f132 105 int present;
f001f132 106 char * mechs;
f001f132 107
108 if (datafellows & SSH_OLD_GSSAPI) return NULL;
109
23987cb8 110 ssh_gssapi_supported_oids(&supported);
f001f132 111
23987cb8 112 buffer_init(&buf);
f001f132 113
23987cb8 114 while(supported_mechs[i]->name != NULL) {
f001f132 115 if ((maj_status=gss_test_oid_set_member(&min_status,
23987cb8 116 &supported_mechs[i]->oid,
f001f132 117 supported,
118 &present))) {
119 present=0;
120 }
23987cb8 121
f001f132 122 if (present) {
23987cb8 123 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx,
124 &supported_mechs[i]->oid)))) {
125 /* Append gss_group1_sha1_x to our list */
126 if (first++!=0)
127 buffer_put_char(&buf,',');
128 buffer_append(&buf, KEX_GSS_SHA1,
129 sizeof(KEX_GSS_SHA1)-1);
130 buffer_append(&buf,
131 supported_mechs[i]->enc_name,
132 strlen(supported_mechs[i]->enc_name));
133 debug("GSSAPI mechanism %s (%s%s) supported",
134 supported_mechs[i]->name, KEX_GSS_SHA1,
135 supported_mechs[i]->enc_name);
136 } else {
137 debug("no credentials for GSSAPI mechanism %s",
138 supported_mechs[i]->name);
139 }
140 } else {
f001f132 141 debug("GSSAPI mechanism %s not supported",
23987cb8 142 supported_mechs[i]->name);
f001f132 143 }
23987cb8 144 ssh_gssapi_delete_ctx(&ctx);
145 i++;
146 }
f001f132 147
148 buffer_put_char(&buf,'\0');
149
150 mechs=xmalloc(buffer_len(&buf));
151 buffer_get(&buf,mechs,buffer_len(&buf));
152 buffer_free(&buf);
153 if (strlen(mechs)==0)
154 return(NULL);
155 else
156 return(mechs);
157}
158
f001f132 159void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
23987cb8 160 int i =0;
f001f132 161 OM_uint32 maj_status,min_status;
162 int present;
163 gss_OID_set supported;
164
165 gss_create_empty_oid_set(&min_status,oidset);
166 PRIVSEP(gss_indicate_mechs(&min_status, &supported));
167
23987cb8 168 while (supported_mechs[i]->name!=NULL) {
f001f132 169 if ((maj_status=gss_test_oid_set_member(&min_status,
23987cb8 170 &supported_mechs[i]->oid,
f001f132 171 supported,
172 &present))) {
173 present=0;
174 }
175 if (present) {
176 gss_add_oid_set_member(&min_status,
23987cb8 177 &supported_mechs[i]->oid,
f001f132 178 oidset);
179 }
180 i++;
181 }
182}
183
23987cb8 184/* Find out which GSS type (out of the list we define in ssh-gss.h) a
185 * particular connection is using
186 */
187ssh_gssapi_mech *
188ssh_gssapi_get_ctype(Gssctxt *ctxt) {
189 int i=0;
190
191 while(supported_mechs[i]->name!=NULL) {
192 if (supported_mechs[i]->oid.length == ctxt->oid->length &&
193 (memcmp(supported_mechs[i]->oid.elements,
194 ctxt->oid->elements,ctxt->oid->length)==0)) {
195 return supported_mechs[i];
196 }
197 i++;
198 }
199 return NULL;
200}
201
202/* Set the GSS context's OID to the oid indicated by the given key exchange
203 * name. */
204
205gss_OID
206ssh_gssapi_id_kex(Gssctxt *ctx, char *name) {
207 int i=0;
208
209 if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) {
210 return(NULL);
211 }
212
213 name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the MIME string */
214
215 while (supported_mechs[i]->name!=NULL &&
216 strcmp(name,supported_mechs[i]->enc_name)!=0) {
217 i++;
218 }
219
220 if (supported_mechs[i]->name==NULL)
221 return (NULL);
222
223 if (ctx) ssh_gssapi_set_oid(ctx,&supported_mechs[i]->oid);
224
225 debug("using GSSAPI mechanism %s (%s%s)", supported_mechs[i]->name,
226 KEX_GSS_SHA1, supported_mechs[i]->enc_name);
227
228 return &supported_mechs[i]->oid;
229}
230
f001f132 231/* Wrapper arround accept_sec_context
232 * Requires that the context contains:
233 * oid
234 * credentials (from ssh_gssapi_acquire_cred)
235 */
236OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
237 gss_buffer_desc *send_tok, OM_uint32 *flags)
238{
23987cb8 239 OM_uint32 status;
f001f132 240 gss_OID mech;
241
23987cb8 242 ctx->major=gss_accept_sec_context(&ctx->minor,
f001f132 243 &ctx->context,
244 ctx->creds,
245 recv_tok,
246 GSS_C_NO_CHANNEL_BINDINGS,
247 &ctx->client,
248 &mech, /* read-only pointer */
249 send_tok,
250 flags,
251 NULL,
252 &ctx->client_creds);
23987cb8 253 if (GSS_ERROR(ctx->major)) {
254 ssh_gssapi_error(ctx);
f001f132 255 }
256
257 if (ctx->client_creds) {
258 debug("Received some client credentials");
259 } else {
260 debug("Got no client credentials");
261 }
262
263 /* FIXME: We should check that the me
23987cb8 264 * the one that we asked for (in ctx->oid) */
f001f132 265
23987cb8 266 status=ctx->major;
f001f132 267
268 /* Now, if we're complete and we have the right flags, then
23987cb8 269 * we flag the user as also having been authenticated
270 */
f001f132 271
272 if (((flags==NULL) || ((*flags & GSS_C_MUTUAL_FLAG) &&
273 (*flags & GSS_C_INTEG_FLAG))) &&
23987cb8 274 (ctx->major == GSS_S_COMPLETE)) {
275 if (ssh_gssapi_getclient(ctx,&gssapi_client.mech,
276 &gssapi_client.name,
277 &gssapi_client.creds))
f001f132 278 fatal("Couldn't convert client name");
279 }
280
23987cb8 281 /* Make sure that the getclient call hasn't stamped on this */
282 return(status);
283}
284
285/* Extract the client details from a given context. This can only reliably
286 * be called once for a context */
287
288OM_uint32
289ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_mech **type,
290 gss_buffer_desc *name, gss_cred_id_t *creds) {
291
292 *type=ssh_gssapi_get_ctype(ctx);
293 if ((ctx->major=gss_display_name(&ctx->minor,ctx->client,name,NULL))) {
294 ssh_gssapi_error(ctx);
295 return(ctx->major);
296 }
297
298 /* This is icky. There appears to be no way to copy this structure,
299 * rather than the pointer to it, so we simply copy the pointer and
300 * mark the originator as empty so we don't destroy it.
301 */
302 *creds=ctx->client_creds;
303 ctx->client_creds=GSS_C_NO_CREDENTIAL;
304 return(ctx->major);
f001f132 305}
306
307void
23987cb8 308ssh_gssapi_cleanup_creds(void *ignored)
309{
310 if (gssapi_client.store.filename!=NULL) {
311 /* Unlink probably isn't sufficient */
312 debug("removing gssapi cred file\"%s\"",gssapi_client.store.filename);
313 unlink(gssapi_client.store.filename);
314 }
315}
316
317void
318ssh_gssapi_storecreds()
319{
320 if (gssapi_client.mech && gssapi_client.mech->storecreds) {
321 (*gssapi_client.mech->storecreds)(&gssapi_client);
322 if (options.gss_cleanup_creds) {
323 fatal_add_cleanup(ssh_gssapi_cleanup_creds, NULL);
324 }
325 } else {
326 debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
327 }
f001f132 328}
329
23987cb8 330/* This allows GSSAPI methods to do things to the childs environment based
331 * on the passed authentication process and credentials.
332 *
333 * Question: If we didn't use userauth_external for some reason, should we
334 * still delegate credentials?
335 */
336void
337ssh_gssapi_do_child(char ***envp, u_int *envsizep)
338{
339
340 if (gssapi_client.store.envvar!=NULL &&
341 gssapi_client.store.envval!=NULL) {
342
343 debug("Setting %s to %s", gssapi_client.store.envvar,
344 gssapi_client.store.envval);
345 child_set_env(envp, envsizep, gssapi_client.store.envvar,
346 gssapi_client.store.envval);
347 }
348}
349
350int
351ssh_gssapi_userok(char *user)
352{
353 if (gssapi_client.name.length==0 ||
354 gssapi_client.name.value==NULL) {
355 debug("No suitable client data");
356 return 0;
357 }
358 if (gssapi_client.mech && gssapi_client.mech->userok) {
359 return((*gssapi_client.mech->userok)(&gssapi_client,user));
360 } else {
361 debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
362 }
363 return(0);
364}
365
366int
367ssh_gssapi_localname(char **user)
368{
369 *user = NULL;
370 if (gssapi_client.name.length==0 ||
371 gssapi_client.name.value==NULL) {
372 debug("No suitable client data");
373 return(0);;
374 }
375 if (gssapi_client.mech && gssapi_client.mech->localname) {
376 return((*gssapi_client.mech->localname)(&gssapi_client,user));
377 } else {
378 debug("Unknown client authentication type");
379 }
380 return(0);
381}
382#endif
This page took 0.169429 seconds and 5 git commands to generate.