]> andersk Git - gssapi-openssh.git/blame - openssh/gss-serv.c
o Bump version to 2.7.
[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 */
e23e524c 96
97/* Unpriviledged */
f001f132 98char *
23987cb8 99ssh_gssapi_server_mechanisms() {
f001f132 100 gss_OID_set supported;
23987cb8 101 Gssctxt *ctx = NULL;
f001f132 102 OM_uint32 maj_status, min_status;
103 Buffer buf;
104 int i = 0;
23987cb8 105 int first = 0;
f001f132 106 int present;
f001f132 107 char * mechs;
f001f132 108
109 if (datafellows & SSH_OLD_GSSAPI) return NULL;
110
23987cb8 111 ssh_gssapi_supported_oids(&supported);
f001f132 112
23987cb8 113 buffer_init(&buf);
f001f132 114
23987cb8 115 while(supported_mechs[i]->name != NULL) {
f001f132 116 if ((maj_status=gss_test_oid_set_member(&min_status,
23987cb8 117 &supported_mechs[i]->oid,
f001f132 118 supported,
119 &present))) {
120 present=0;
121 }
23987cb8 122
f001f132 123 if (present) {
23987cb8 124 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx,
125 &supported_mechs[i]->oid)))) {
126 /* Append gss_group1_sha1_x to our list */
127 if (first++!=0)
128 buffer_put_char(&buf,',');
129 buffer_append(&buf, KEX_GSS_SHA1,
130 sizeof(KEX_GSS_SHA1)-1);
131 buffer_append(&buf,
132 supported_mechs[i]->enc_name,
133 strlen(supported_mechs[i]->enc_name));
134 debug("GSSAPI mechanism %s (%s%s) supported",
135 supported_mechs[i]->name, KEX_GSS_SHA1,
136 supported_mechs[i]->enc_name);
137 } else {
138 debug("no credentials for GSSAPI mechanism %s",
139 supported_mechs[i]->name);
140 }
141 } else {
f001f132 142 debug("GSSAPI mechanism %s not supported",
23987cb8 143 supported_mechs[i]->name);
f001f132 144 }
23987cb8 145 ssh_gssapi_delete_ctx(&ctx);
146 i++;
147 }
f001f132 148
149 buffer_put_char(&buf,'\0');
150
151 mechs=xmalloc(buffer_len(&buf));
152 buffer_get(&buf,mechs,buffer_len(&buf));
153 buffer_free(&buf);
154 if (strlen(mechs)==0)
155 return(NULL);
156 else
157 return(mechs);
158}
159
e23e524c 160/* Unpriviledged */
f001f132 161void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
23987cb8 162 int i =0;
f001f132 163 OM_uint32 maj_status,min_status;
164 int present;
165 gss_OID_set supported;
166
167 gss_create_empty_oid_set(&min_status,oidset);
168 PRIVSEP(gss_indicate_mechs(&min_status, &supported));
169
23987cb8 170 while (supported_mechs[i]->name!=NULL) {
f001f132 171 if ((maj_status=gss_test_oid_set_member(&min_status,
23987cb8 172 &supported_mechs[i]->oid,
f001f132 173 supported,
174 &present))) {
175 present=0;
176 }
177 if (present) {
178 gss_add_oid_set_member(&min_status,
23987cb8 179 &supported_mechs[i]->oid,
f001f132 180 oidset);
181 }
182 i++;
183 }
184}
185
23987cb8 186/* Find out which GSS type (out of the list we define in ssh-gss.h) a
187 * particular connection is using
188 */
e23e524c 189
190/* Priviledged (called ssh_gssapi_accept_ctx -> ssh_gssapi_getclient ->) */
23987cb8 191ssh_gssapi_mech *
192ssh_gssapi_get_ctype(Gssctxt *ctxt) {
193 int i=0;
194
195 while(supported_mechs[i]->name!=NULL) {
196 if (supported_mechs[i]->oid.length == ctxt->oid->length &&
197 (memcmp(supported_mechs[i]->oid.elements,
198 ctxt->oid->elements,ctxt->oid->length)==0)) {
199 return supported_mechs[i];
200 }
201 i++;
202 }
203 return NULL;
204}
205
e23e524c 206/* Return the OID that corresponds to the given context name */
23987cb8 207
e23e524c 208/* Unpriviledged */
23987cb8 209gss_OID
e23e524c 210ssh_gssapi_server_id_kex(char *name) {
23987cb8 211 int i=0;
212
213 if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) {
214 return(NULL);
215 }
216
217 name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the MIME string */
218
219 while (supported_mechs[i]->name!=NULL &&
e23e524c 220 strcmp(name,supported_mechs[i]->enc_name)!=0) {
23987cb8 221 i++;
222 }
223
224 if (supported_mechs[i]->name==NULL)
225 return (NULL);
226
23987cb8 227 debug("using GSSAPI mechanism %s (%s%s)", supported_mechs[i]->name,
228 KEX_GSS_SHA1, supported_mechs[i]->enc_name);
229
230 return &supported_mechs[i]->oid;
231}
232
e23e524c 233/* Wrapper around accept_sec_context
f001f132 234 * Requires that the context contains:
235 * oid
236 * credentials (from ssh_gssapi_acquire_cred)
237 */
e23e524c 238/* Priviledged */
f001f132 239OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
240 gss_buffer_desc *send_tok, OM_uint32 *flags)
241{
23987cb8 242 OM_uint32 status;
f001f132 243 gss_OID mech;
244
23987cb8 245 ctx->major=gss_accept_sec_context(&ctx->minor,
f001f132 246 &ctx->context,
247 ctx->creds,
248 recv_tok,
249 GSS_C_NO_CHANNEL_BINDINGS,
250 &ctx->client,
251 &mech, /* read-only pointer */
252 send_tok,
253 flags,
254 NULL,
255 &ctx->client_creds);
23987cb8 256 if (GSS_ERROR(ctx->major)) {
257 ssh_gssapi_error(ctx);
f001f132 258 }
259
260 if (ctx->client_creds) {
261 debug("Received some client credentials");
262 } else {
263 debug("Got no client credentials");
264 }
265
266 /* FIXME: We should check that the me
e23e524c 267 * the one that we asked for (in ctx->oid) */
f001f132 268
23987cb8 269 status=ctx->major;
f001f132 270
271 /* Now, if we're complete and we have the right flags, then
e23e524c 272 * we flag the user as also having been authenticated
273 */
f001f132 274
275 if (((flags==NULL) || ((*flags & GSS_C_MUTUAL_FLAG) &&
276 (*flags & GSS_C_INTEG_FLAG))) &&
23987cb8 277 (ctx->major == GSS_S_COMPLETE)) {
278 if (ssh_gssapi_getclient(ctx,&gssapi_client.mech,
279 &gssapi_client.name,
280 &gssapi_client.creds))
f001f132 281 fatal("Couldn't convert client name");
282 }
283
23987cb8 284 /* Make sure that the getclient call hasn't stamped on this */
285 return(status);
286}
287
288/* Extract the client details from a given context. This can only reliably
289 * be called once for a context */
290
e23e524c 291/* Priviledged (called from accept_secure_ctx) */
23987cb8 292OM_uint32
293ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_mech **type,
294 gss_buffer_desc *name, gss_cred_id_t *creds) {
295
296 *type=ssh_gssapi_get_ctype(ctx);
297 if ((ctx->major=gss_display_name(&ctx->minor,ctx->client,name,NULL))) {
298 ssh_gssapi_error(ctx);
299 return(ctx->major);
300 }
301
302 /* This is icky. There appears to be no way to copy this structure,
e23e524c 303 * rather than the pointer to it, so we simply copy the pointer and
304 * mark the originator as empty so we don't destroy it.
305 */
23987cb8 306 *creds=ctx->client_creds;
307 ctx->client_creds=GSS_C_NO_CREDENTIAL;
308 return(ctx->major);
f001f132 309}
310
e23e524c 311/* As user - called through fatal cleanup hook */
f001f132 312void
23987cb8 313ssh_gssapi_cleanup_creds(void *ignored)
314{
315 if (gssapi_client.store.filename!=NULL) {
316 /* Unlink probably isn't sufficient */
317 debug("removing gssapi cred file\"%s\"",gssapi_client.store.filename);
318 unlink(gssapi_client.store.filename);
319 }
320}
321
e23e524c 322/* As user */
23987cb8 323void
324ssh_gssapi_storecreds()
325{
326 if (gssapi_client.mech && gssapi_client.mech->storecreds) {
327 (*gssapi_client.mech->storecreds)(&gssapi_client);
328 if (options.gss_cleanup_creds) {
329 fatal_add_cleanup(ssh_gssapi_cleanup_creds, NULL);
330 }
331 } else {
332 debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
333 }
f001f132 334}
335
23987cb8 336/* This allows GSSAPI methods to do things to the childs environment based
337 * on the passed authentication process and credentials.
23987cb8 338 */
e23e524c 339/* As user */
23987cb8 340void
341ssh_gssapi_do_child(char ***envp, u_int *envsizep)
342{
343
344 if (gssapi_client.store.envvar!=NULL &&
345 gssapi_client.store.envval!=NULL) {
346
347 debug("Setting %s to %s", gssapi_client.store.envvar,
348 gssapi_client.store.envval);
349 child_set_env(envp, envsizep, gssapi_client.store.envvar,
350 gssapi_client.store.envval);
351 }
352}
353
e23e524c 354/* Priviledged */
23987cb8 355int
356ssh_gssapi_userok(char *user)
357{
358 if (gssapi_client.name.length==0 ||
359 gssapi_client.name.value==NULL) {
360 debug("No suitable client data");
361 return 0;
362 }
363 if (gssapi_client.mech && gssapi_client.mech->userok) {
364 return((*gssapi_client.mech->userok)(&gssapi_client,user));
365 } else {
366 debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
367 }
368 return(0);
369}
370
e23e524c 371/* Priviledged */
23987cb8 372int
373ssh_gssapi_localname(char **user)
374{
375 *user = NULL;
376 if (gssapi_client.name.length==0 ||
377 gssapi_client.name.value==NULL) {
378 debug("No suitable client data");
379 return(0);;
380 }
381 if (gssapi_client.mech && gssapi_client.mech->localname) {
382 return((*gssapi_client.mech->localname)(&gssapi_client,user));
383 } else {
384 debug("Unknown client authentication type");
385 }
386 return(0);
387}
388#endif
This page took 0.12282 seconds and 5 git commands to generate.