View | Details | Raw Unified | Return to bug 1242 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile.in (-2 / +2 lines)
Lines 73-79 Link Here
73
	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
73
	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
74
	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
74
	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
75
	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
75
	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
76
	entropy.o scard-opensc.o gss-genr.o
76
	entropy.o scard-opensc.o gss-genr.o kexgssc.o
77
77
78
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
78
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
79
	sshconnect.o sshconnect1.o sshconnect2.o
79
	sshconnect.o sshconnect1.o sshconnect2.o
Lines 86-92 Link Here
86
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
86
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
87
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
87
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
88
	auth-krb5.o \
88
	auth-krb5.o \
89
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
89
	auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
90
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
90
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
91
	audit.o audit-bsm.o platform.o
91
	audit.o audit-bsm.o platform.o
92
92
(-)auth2-gss.c (+39 lines)
Lines 52-57 Link Here
52
static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
52
static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
53
static void input_gssapi_errtok(int, u_int32_t, void *);
53
static void input_gssapi_errtok(int, u_int32_t, void *);
54
54
55
/* 
56
 * The 'gssapi_keyex' userauth mechanism.
57
 */
58
static int
59
userauth_gsskeyex(Authctxt *authctxt)
60
{
61
	int authenticated = 0;
62
	Buffer b;
63
	gss_buffer_desc mic, gssbuf;
64
	u_int len;
65
66
	mic.value = packet_get_string(&len);
67
	mic.length = len;
68
69
	packet_check_eom();
70
71
	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
72
	    "gssapi-keyex");
73
74
	gssbuf.value = buffer_ptr(&b);
75
	gssbuf.length = buffer_len(&b);
76
77
	/* gss_kex_context is NULL with privsep, so we can't check it here */
78
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
79
	    &gssbuf, &mic))))
80
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
81
	
82
	buffer_free(&b);
83
	xfree(mic.value);
84
85
	return (authenticated);
86
}
87
55
/*
88
/*
56
 * We only support those mechanisms that we know about (ie ones that we know
89
 * We only support those mechanisms that we know about (ie ones that we know
57
 * how to check local user kuserok and the like)
90
 * how to check local user kuserok and the like)
Lines 291-296 Link Here
291
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
324
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
292
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
325
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
293
}
326
}
327
328
Authmethod method_gsskeyex = {
329
	"gssapi-keyex",
330
	userauth_gsskeyex,
331
	&options.gss_authentication
332
};
294
333
295
Authmethod method_gssapi = {
334
Authmethod method_gssapi = {
296
	"gssapi-with-mic",
335
	"gssapi-with-mic",
(-)auth2.c (+2 lines)
Lines 64-69 Link Here
64
extern Authmethod method_kbdint;
64
extern Authmethod method_kbdint;
65
extern Authmethod method_hostbased;
65
extern Authmethod method_hostbased;
66
#ifdef GSSAPI
66
#ifdef GSSAPI
67
extern Authmethod method_gsskeyex;
67
extern Authmethod method_gssapi;
68
extern Authmethod method_gssapi;
68
#endif
69
#endif
69
70
Lines 71-76 Link Here
71
	&method_none,
72
	&method_none,
72
	&method_pubkey,
73
	&method_pubkey,
73
#ifdef GSSAPI
74
#ifdef GSSAPI
75
	&method_gsskeyex,
74
	&method_gssapi,
76
	&method_gssapi,
75
#endif
77
#endif
76
	&method_passwd,
78
	&method_passwd,
(-)gss-genr.c (-1 / +169 lines)
Lines 39-50 Link Here
39
#include "buffer.h"
39
#include "buffer.h"
40
#include "log.h"
40
#include "log.h"
41
#include "ssh2.h"
41
#include "ssh2.h"
42
#include "cipher.h"
43
#include "key.h"
44
#include "kex.h"
45
#include <openssl/evp.h>
42
46
43
#include "ssh-gss.h"
47
#include "ssh-gss.h"
44
48
45
extern u_char *session_id2;
49
extern u_char *session_id2;
46
extern u_int session_id2_len;
50
extern u_int session_id2_len;
47
51
52
typedef struct {
53
	char *encoded;
54
	gss_OID oid;
55
} ssh_gss_kex_mapping;
56
57
/*
58
 * XXX - It would be nice to find a more elegant way of handling the
59
 * XXX   passing of the key exchange context to the userauth routines
60
 */
61
62
Gssctxt *gss_kex_context = NULL;
63
64
static ssh_gss_kex_mapping *gss_enc2oid = NULL;
65
66
int 
67
ssh_gssapi_oid_table_ok() {
68
	return (gss_enc2oid != NULL);
69
}
70
71
/*
72
 * Return a list of the gss-group1-sha1 mechanisms supported by this program
73
 *
74
 * We test mechanisms to ensure that we can use them, to avoid starting
75
 * a key exchange with a bad mechanism
76
 */
77
78
char *
79
ssh_gssapi_client_mechanisms(const char *host) {
80
	gss_OID_set gss_supported;
81
	OM_uint32 min_status;
82
83
	gss_indicate_mechs(&min_status, &gss_supported);
84
85
	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
86
	    host));
87
}
88
89
char *
90
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
91
    const char *data) {
92
	Buffer buf;
93
	size_t i;
94
	int oidpos, enclen;
95
	char *mechs, *encoded;
96
	u_char digest[EVP_MAX_MD_SIZE];
97
	char deroid[2];
98
	const EVP_MD *evp_md = EVP_md5();
99
	EVP_MD_CTX md;
100
101
	if (gss_enc2oid != NULL) {
102
		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
103
			xfree(gss_enc2oid[i].encoded);
104
		xfree(gss_enc2oid);
105
	}
106
107
	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
108
	    (gss_supported->count + 1));
109
110
	buffer_init(&buf);
111
112
	oidpos = 0;
113
	for (i = 0; i < gss_supported->count; i++) {
114
		if (gss_supported->elements[i].length < 128 &&
115
		    (*check)(NULL, &(gss_supported->elements[i]), data)) {
116
117
			deroid[0] = SSH_GSS_OIDTYPE;
118
			deroid[1] = gss_supported->elements[i].length;
119
120
			EVP_DigestInit(&md, evp_md);
121
			EVP_DigestUpdate(&md, deroid, 2);
122
			EVP_DigestUpdate(&md,
123
			    gss_supported->elements[i].elements,
124
			    gss_supported->elements[i].length);
125
			EVP_DigestFinal(&md, digest, NULL);
126
127
			encoded = xmalloc(EVP_MD_size(evp_md) * 2);
128
			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
129
			    encoded, EVP_MD_size(evp_md) * 2);
130
131
			if (oidpos != 0)
132
				buffer_put_char(&buf, ',');
133
134
			buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
135
			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
136
			buffer_append(&buf, encoded, enclen);
137
			buffer_put_char(&buf, ',');
138
			buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
139
			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
140
			buffer_append(&buf, encoded, enclen);
141
			buffer_put_char(&buf, ',');
142
			buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
143
			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
144
			buffer_append(&buf, encoded, enclen);
145
146
			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
147
			gss_enc2oid[oidpos].encoded = encoded;
148
			oidpos++;
149
		}
150
	}
151
	gss_enc2oid[oidpos].oid = NULL;
152
	gss_enc2oid[oidpos].encoded = NULL;
153
154
	buffer_put_char(&buf, '\0');
155
156
	mechs = xmalloc(buffer_len(&buf));
157
	buffer_get(&buf, mechs, buffer_len(&buf));
158
	buffer_free(&buf);
159
160
	if (strlen(mechs) == 0) {
161
		xfree(mechs);
162
		mechs = NULL;
163
	}
164
	
165
	return (mechs);
166
}
167
168
gss_OID
169
ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
170
	int i = 0;
171
	
172
	switch (kex_type) {
173
	case KEX_GSS_GRP1_SHA1:
174
		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
175
		break;
176
	case KEX_GSS_GRP14_SHA1:
177
		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
178
		break;
179
	case KEX_GSS_GEX_SHA1:
180
		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
181
		break;
182
	default:
183
		return GSS_C_NO_OID;
184
	}
185
186
	while (gss_enc2oid[i].encoded != NULL &&
187
	    strcmp(name, gss_enc2oid[i].encoded) != 0)
188
		i++;
189
190
	if (gss_enc2oid[i].oid != NULL && ctx != NULL)
191
		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
192
193
	return gss_enc2oid[i].oid;
194
}
195
48
/* Check that the OID in a data stream matches that in the context */
196
/* Check that the OID in a data stream matches that in the context */
49
int
197
int
50
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
198
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
Lines 262-267 Link Here
262
OM_uint32
410
OM_uint32
263
ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
411
ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
264
{
412
{
413
	if (ctx == NULL) 
414
		return -1;
415
265
	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
416
	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
266
	    GSS_C_QOP_DEFAULT, buffer, hash)))
417
	    GSS_C_QOP_DEFAULT, buffer, hash)))
267
		ssh_gssapi_error(ctx);
418
		ssh_gssapi_error(ctx);
Lines 269-274 Link Here
269
	return (ctx->major);
420
	return (ctx->major);
270
}
421
}
271
422
423
/* Priviledged when used by server */
424
OM_uint32
425
ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
426
{
427
	if (ctx == NULL)
428
		return -1;
429
430
	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
431
	    gssbuf, gssmic, NULL);
432
433
	return (ctx->major);
434
}
435
272
void
436
void
273
ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
437
ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
274
    const char *context)
438
    const char *context)
Lines 297-302 Link Here
297
	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
461
	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
298
	OM_uint32 major, minor;
462
	OM_uint32 major, minor;
299
	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
463
	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
464
	Gssctxt *intctx = NULL;
465
466
	if (ctx == NULL)
467
		ctx = &intctx;
300
468
301
	/* RFC 4462 says we MUST NOT do SPNEGO */
469
	/* RFC 4462 says we MUST NOT do SPNEGO */
302
	if (oid->length == spnego_oid.length && 
470
	if (oid->length == spnego_oid.length && 
Lines 315-321 Link Here
315
			    GSS_C_NO_BUFFER);
483
			    GSS_C_NO_BUFFER);
316
	}
484
	}
317
485
318
	if (GSS_ERROR(major)) 
486
	if (GSS_ERROR(major) || intctx != NULL) 
319
		ssh_gssapi_delete_ctx(ctx);
487
		ssh_gssapi_delete_ctx(ctx);
320
488
321
	return (!GSS_ERROR(major));
489
	return (!GSS_ERROR(major));
(-)gss-serv.c (-10 / +23 lines)
Lines 45-50 Link Here
45
#include "misc.h"
45
#include "misc.h"
46
46
47
#include "ssh-gss.h"
47
#include "ssh-gss.h"
48
#include "monitor_wrap.h"
48
49
49
static ssh_gssapi_client gssapi_client =
50
static ssh_gssapi_client gssapi_client =
50
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
51
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
Lines 65-70 Link Here
65
};
66
};
66
67
67
/* Unprivileged */
68
/* Unprivileged */
69
char *
70
ssh_gssapi_server_mechanisms() {
71
	gss_OID_set	supported;
72
73
	ssh_gssapi_supported_oids(&supported);
74
	return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
75
	    NULL));
76
}
77
78
/* Unprivileged */
79
int
80
ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data) {
81
	Gssctxt *ctx = NULL;
82
	int res;
83
 
84
	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
85
	ssh_gssapi_delete_ctx(&ctx);
86
87
	return (res);
88
}
89
90
/* Unprivileged */
68
void
91
void
69
ssh_gssapi_supported_oids(gss_OID_set *oidset)
92
ssh_gssapi_supported_oids(gss_OID_set *oidset)
70
{
93
{
Lines 301-316 Link Here
301
	else
324
	else
302
		debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
325
		debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
303
	return (0);
326
	return (0);
304
}
305
306
/* Privileged */
307
OM_uint32
308
ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
309
{
310
	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
311
	    gssbuf, gssmic, NULL);
312
313
	return (ctx->major);
314
}
327
}
315
328
316
#endif
329
#endif
(-)kex.c (+18 lines)
Lines 49-54 Link Here
49
#include "dispatch.h"
49
#include "dispatch.h"
50
#include "monitor.h"
50
#include "monitor.h"
51
51
52
#ifdef GSSAPI
53
#include "ssh-gss.h"
54
#endif
55
52
#define KEX_COOKIE_LEN	16
56
#define KEX_COOKIE_LEN	16
53
57
54
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
58
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Lines 322-327 Link Here
322
	} else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
326
	} else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
323
		k->kex_type = KEX_DH_GEX_SHA256;
327
		k->kex_type = KEX_DH_GEX_SHA256;
324
		k->evp_md = evp_ssh_sha256();
328
		k->evp_md = evp_ssh_sha256();
329
#endif
330
#ifdef GSSAPI
331
	} else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
332
	    sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
333
		k->kex_type = KEX_GSS_GEX_SHA1;
334
		k->evp_md = EVP_sha1();
335
	} else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
336
	    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
337
		k->kex_type = KEX_GSS_GRP1_SHA1;
338
		k->evp_md = EVP_sha1();
339
	} else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
340
	    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
341
		k->kex_type = KEX_GSS_GRP14_SHA1;
342
		k->evp_md = EVP_sha1();
325
#endif
343
#endif
326
	} else
344
	} else
327
		fatal("bad kex alg %s", k->name);
345
		fatal("bad kex alg %s", k->name);
(-)kex.h (+12 lines)
Lines 63-68 Link Here
63
	KEX_DH_GRP14_SHA1,
63
	KEX_DH_GRP14_SHA1,
64
	KEX_DH_GEX_SHA1,
64
	KEX_DH_GEX_SHA1,
65
	KEX_DH_GEX_SHA256,
65
	KEX_DH_GEX_SHA256,
66
	KEX_GSS_GRP1_SHA1,
67
	KEX_GSS_GRP14_SHA1,
68
	KEX_GSS_GEX_SHA1,
66
	KEX_MAX
69
	KEX_MAX
67
};
70
};
68
71
Lines 115-120 Link Here
115
	sig_atomic_t done;
118
	sig_atomic_t done;
116
	int	flags;
119
	int	flags;
117
	const EVP_MD *evp_md;
120
	const EVP_MD *evp_md;
121
#ifdef GSSAPI
122
	int	gss_deleg_creds;
123
	char    *gss_host;
124
#endif
118
	char	*client_version_string;
125
	char	*client_version_string;
119
	char	*server_version_string;
126
	char	*server_version_string;
120
	int	(*verify_host_key)(Key *);
127
	int	(*verify_host_key)(Key *);
Lines 136-141 Link Here
136
void	 kexdh_server(Kex *);
143
void	 kexdh_server(Kex *);
137
void	 kexgex_client(Kex *);
144
void	 kexgex_client(Kex *);
138
void	 kexgex_server(Kex *);
145
void	 kexgex_server(Kex *);
146
147
#ifdef GSSAPI
148
void	kexgss_client(Kex *);
149
void	kexgss_server(Kex *);
150
#endif
139
151
140
void
152
void
141
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
153
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
(-)kexgssc.c (+319 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved.
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 "includes.h"
30
31
#include <openssl/crypto.h>
32
#include <openssl/bn.h>
33
34
#include <string.h>
35
36
#include "xmalloc.h"
37
#include "buffer.h"
38
#include "ssh2.h"
39
#include "key.h"
40
#include "cipher.h"
41
#include "kex.h"
42
#include "log.h"
43
#include "packet.h"
44
#include "dh.h"
45
46
#include "ssh-gss.h"
47
48
void
49
kexgss_client(Kex *kex) {
50
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
51
	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
52
	Gssctxt *ctxt;
53
	OM_uint32 maj_status, min_status, ret_flags;
54
	u_int klen, kout, slen = 0, hashlen, strlen;
55
	DH *dh; 
56
	BIGNUM *dh_server_pub = NULL;
57
	BIGNUM *shared_secret = NULL;
58
	BIGNUM *p = NULL;
59
	BIGNUM *g = NULL;	
60
	u_char *kbuf, *hash;
61
	u_char *serverhostkey = NULL;
62
	char *msg;
63
	char *lang;
64
	int type = 0;
65
	int first = 1;
66
	int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
67
68
	/* Initialise our GSSAPI world */	
69
	ssh_gssapi_build_ctx(&ctxt);
70
	if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) 
71
	    == GSS_C_NO_OID)
72
		fatal("Couldn't identify host exchange");
73
74
	if (ssh_gssapi_import_name(ctxt, kex->gss_host))
75
		fatal("Couldn't import hostname");
76
	
77
	switch (kex->kex_type) {
78
	case KEX_GSS_GRP1_SHA1:
79
		dh = dh_new_group1();
80
		break;
81
	case KEX_GSS_GRP14_SHA1:
82
		dh = dh_new_group14();
83
		break;
84
	case KEX_GSS_GEX_SHA1:
85
		debug("Doing group exchange\n");
86
		nbits = dh_estimate(kex->we_need * 8);
87
		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
88
		packet_put_int(min);
89
		packet_put_int(nbits);
90
		packet_put_int(max);
91
92
		packet_send();
93
94
		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
95
96
		if ((p = BN_new()) == NULL)
97
			fatal("BN_new() failed");
98
		packet_get_bignum2(p);
99
		if ((g = BN_new()) == NULL)
100
			fatal("BN_new() failed");
101
		packet_get_bignum2(g);
102
		packet_check_eom();
103
104
		if (BN_num_bits(p) < min || BN_num_bits(p) > max)
105
			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
106
			    min, BN_num_bits(p), max);
107
108
		dh = dh_new_group(g, p);
109
		break;
110
	default:
111
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
112
	}
113
	
114
	/* Step 1 - e is dh->pub_key */
115
	dh_gen_key(dh, kex->we_need * 8);
116
117
	/* This is f, we initialise it now to make life easier */
118
	dh_server_pub = BN_new();
119
	if (dh_server_pub == NULL)
120
		fatal("dh_server_pub == NULL");
121
122
	token_ptr = GSS_C_NO_BUFFER;
123
			 
124
	do {
125
		debug("Calling gss_init_sec_context");
126
		
127
		maj_status = ssh_gssapi_init_ctx(ctxt,
128
		    kex->gss_deleg_creds, token_ptr, &send_tok,
129
		    &ret_flags);
130
131
		if (GSS_ERROR(maj_status)) {
132
			if (send_tok.length != 0) {
133
				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
134
				packet_put_string(send_tok.value,
135
				    send_tok.length);
136
			}
137
			fatal("gss_init_context failed");
138
		}
139
140
		/* If we've got an old receive buffer get rid of it */
141
		if (token_ptr != GSS_C_NO_BUFFER)
142
			xfree(recv_tok.value);
143
144
		if (maj_status == GSS_S_COMPLETE) {
145
			/* If mutual state flag is not true, kex fails */
146
			if (!(ret_flags & GSS_C_MUTUAL_FLAG))
147
				fatal("Mutual authentication failed");
148
149
			/* If integ avail flag is not true kex fails */
150
			if (!(ret_flags & GSS_C_INTEG_FLAG))
151
				fatal("Integrity check failed");
152
		}
153
154
		/* 
155
		 * If we have data to send, then the last message that we
156
		 * received cannot have been a 'complete'. 
157
		 */
158
		if (send_tok.length != 0) {
159
			if (first) {
160
				packet_start(SSH2_MSG_KEXGSS_INIT);
161
				packet_put_string(send_tok.value,
162
				    send_tok.length);
163
				packet_put_bignum2(dh->pub_key);
164
				first = 0;
165
			} else {
166
				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
167
				packet_put_string(send_tok.value,
168
				    send_tok.length);
169
			}
170
			packet_send();
171
			gss_release_buffer(&min_status, &send_tok);
172
173
			/* If we've sent them data, they should reply */
174
			do {	
175
				type = packet_read();
176
				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
177
					debug("Received KEXGSS_HOSTKEY");
178
					if (serverhostkey)
179
						fatal("Server host key received more than once");
180
					serverhostkey = 
181
					    packet_get_string(&slen);
182
				}
183
			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);
184
185
			switch (type) {
186
			case SSH2_MSG_KEXGSS_CONTINUE:
187
				debug("Received GSSAPI_CONTINUE");
188
				if (maj_status == GSS_S_COMPLETE) 
189
					fatal("GSSAPI Continue received from server when complete");
190
				recv_tok.value = packet_get_string(&strlen);
191
				recv_tok.length = strlen; 
192
				break;
193
			case SSH2_MSG_KEXGSS_COMPLETE:
194
				debug("Received GSSAPI_COMPLETE");
195
				packet_get_bignum2(dh_server_pub);
196
				msg_tok.value =  packet_get_string(&strlen);
197
				msg_tok.length = strlen; 
198
199
				/* Is there a token included? */
200
				if (packet_get_char()) {
201
					recv_tok.value=
202
					    packet_get_string(&strlen);
203
					recv_tok.length = strlen;
204
					/* If we're already complete - protocol error */
205
					if (maj_status == GSS_S_COMPLETE)
206
						packet_disconnect("Protocol error: received token when complete");
207
					} else {
208
						/* No token included */
209
						if (maj_status != GSS_S_COMPLETE)
210
							packet_disconnect("Protocol error: did not receive final token");
211
				}
212
				break;
213
			case SSH2_MSG_KEXGSS_ERROR:
214
				debug("Received Error");
215
				maj_status = packet_get_int();
216
				min_status = packet_get_int();
217
				msg = packet_get_string(NULL);
218
				lang = packet_get_string(NULL);
219
				fatal("GSSAPI Error: \n%.400s",msg);
220
			default:
221
				packet_disconnect("Protocol error: didn't expect packet type %d",
222
		    		type);
223
			}
224
			token_ptr = &recv_tok;
225
		} else {
226
			/* No data, and not complete */
227
			if (maj_status != GSS_S_COMPLETE)
228
				fatal("Not complete, and no token output");
229
		}
230
	} while (maj_status & GSS_S_CONTINUE_NEEDED);
231
232
	/* 
233
	 * We _must_ have received a COMPLETE message in reply from the 
234
	 * server, which will have set dh_server_pub and msg_tok 
235
	 */
236
237
	if (type != SSH2_MSG_KEXGSS_COMPLETE)
238
		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
239
240
	/* Check f in range [1, p-1] */
241
	if (!dh_pub_is_valid(dh, dh_server_pub))
242
		packet_disconnect("bad server public DH value");
243
244
	/* compute K=f^x mod p */
245
	klen = DH_size(dh);
246
	kbuf = xmalloc(klen);
247
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
248
249
	shared_secret = BN_new();
250
	BN_bin2bn(kbuf,kout, shared_secret);
251
	memset(kbuf, 0, klen);
252
	xfree(kbuf);
253
254
	switch (kex->kex_type) {
255
	case KEX_GSS_GRP1_SHA1:
256
	case KEX_GSS_GRP14_SHA1:
257
		kex_dh_hash( kex->client_version_string, 
258
		    kex->server_version_string,
259
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
260
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
261
		    serverhostkey, slen, /* server host key */
262
		    dh->pub_key,	/* e */
263
		    dh_server_pub,	/* f */
264
		    shared_secret,	/* K */
265
		    &hash, &hashlen
266
		);
267
		break;
268
	case KEX_GSS_GEX_SHA1:
269
		kexgex_hash(
270
		    kex->evp_md,
271
		    kex->client_version_string,
272
		    kex->server_version_string,
273
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
274
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
275
		    serverhostkey, slen,
276
 		    min, nbits, max,
277
		    dh->p, dh->g,
278
		    dh->pub_key,
279
		    dh_server_pub,
280
		    shared_secret,
281
		    &hash, &hashlen
282
		);
283
		break;
284
	default:
285
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
286
	}
287
288
	gssbuf.value = hash;
289
	gssbuf.length = hashlen;
290
291
	/* Verify that the hash matches the MIC we just got. */
292
	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
293
		packet_disconnect("Hash's MIC didn't verify");
294
295
	xfree(msg_tok.value);
296
297
	DH_free(dh);
298
	if (serverhostkey)
299
		xfree(serverhostkey);
300
	BN_clear_free(dh_server_pub);
301
302
	/* save session id */
303
	if (kex->session_id == NULL) {
304
		kex->session_id_len = hashlen;
305
		kex->session_id = xmalloc(kex->session_id_len);
306
		memcpy(kex->session_id, hash, kex->session_id_len);
307
	}
308
309
	if (gss_kex_context == NULL)
310
		gss_kex_context = ctxt;
311
	else
312
		ssh_gssapi_delete_ctx(&ctxt);
313
314
	kex_derive_keys(kex, hash, hashlen, shared_secret);
315
	BN_clear_free(shared_secret);
316
	kex_finish(kex);
317
}
318
319
#endif /* GSSAPI */
(-)kexgsss.c (+271 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved.
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 <string.h>
30
31
#include <openssl/crypto.h>
32
#include <openssl/bn.h>
33
34
#include "xmalloc.h"
35
#include "buffer.h"
36
#include "ssh2.h"
37
#include "key.h"
38
#include "cipher.h"
39
#include "kex.h"
40
#include "log.h"
41
#include "packet.h"
42
#include "dh.h"
43
#include "ssh-gss.h"
44
#include "monitor_wrap.h"
45
46
void
47
kexgss_server(Kex *kex)
48
{
49
	OM_uint32 maj_status, min_status;
50
	
51
	/* 
52
	 * Some GSSAPI implementations use the input value of ret_flags (an
53
 	 * output variable) as a means of triggering mechanism specific 
54
 	 * features. Initializing it to zero avoids inadvertently 
55
 	 * activating this non-standard behaviour.
56
	 */
57
58
	OM_uint32 ret_flags = 0;
59
	gss_buffer_desc gssbuf, recv_tok, msg_tok;
60
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
61
	Gssctxt *ctxt = NULL;
62
	u_int slen, klen, kout, hashlen;
63
	u_char *kbuf, *hash;
64
	DH *dh;
65
	int min = -1, max = -1, nbits = -1;
66
	BIGNUM *shared_secret = NULL;
67
	BIGNUM *dh_client_pub = NULL;
68
	int type = 0;
69
	gss_OID oid;
70
71
	/* Initialise GSSAPI */
72
73
	/* If we're rekeying, privsep means that some of the private structures
74
	 * in the GSSAPI code are no longer available. This kludges them back
75
	 * into life
76
	 */
77
	if (!ssh_gssapi_oid_table_ok()) 
78
		ssh_gssapi_server_mechanisms();
79
80
	debug2("%s: Identifying %s", __func__, kex->name);
81
	oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
82
	if (oid == GSS_C_NO_OID)
83
	   fatal("Unknown gssapi mechanism");
84
85
	debug2("%s: Acquiring credentials", __func__);
86
87
	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
88
		fatal("Unable to acquire credentials for the server");
89
90
	switch (kex->kex_type) {
91
	case KEX_GSS_GRP1_SHA1:
92
		dh = dh_new_group1();
93
		break;
94
	case KEX_GSS_GRP14_SHA1:
95
		dh = dh_new_group14();
96
		break;
97
	case KEX_GSS_GEX_SHA1:
98
		debug("Doing group exchange");
99
		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
100
		min = packet_get_int();
101
		nbits = packet_get_int();
102
		max = packet_get_int();
103
		min = MAX(DH_GRP_MIN, min);
104
		max = MIN(DH_GRP_MAX, max);
105
		packet_check_eom();
106
		if (max < min || nbits < min || max < nbits)
107
			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
108
			    min, nbits, max);
109
		dh = PRIVSEP(choose_dh(min, nbits, max));
110
		if (dh == NULL)
111
			packet_disconnect("Protocol error: no matching group found");
112
113
		packet_start(SSH2_MSG_KEXGSS_GROUP);
114
		packet_put_bignum2(dh->p);
115
		packet_put_bignum2(dh->g);
116
		packet_send();
117
118
		packet_write_wait();
119
		break;
120
	default:
121
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
122
	}
123
124
	dh_gen_key(dh, kex->we_need * 8);
125
126
	do {
127
		debug("Wait SSH2_MSG_GSSAPI_INIT");
128
		type = packet_read();
129
		switch(type) {
130
		case SSH2_MSG_KEXGSS_INIT:
131
			if (dh_client_pub != NULL) 
132
				fatal("Received KEXGSS_INIT after initialising");
133
			recv_tok.value = packet_get_string(&slen);
134
			recv_tok.length = slen; 
135
136
			if ((dh_client_pub = BN_new()) == NULL)
137
				fatal("dh_client_pub == NULL");
138
139
			packet_get_bignum2(dh_client_pub);
140
141
			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
142
			break;
143
		case SSH2_MSG_KEXGSS_CONTINUE:
144
			recv_tok.value = packet_get_string(&slen);
145
			recv_tok.length = slen; 
146
			break;
147
		default:
148
			packet_disconnect(
149
			    "Protocol error: didn't expect packet type %d",
150
			    type);
151
		}
152
153
		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
154
		    &send_tok, &ret_flags));
155
156
		xfree(recv_tok.value);
157
158
		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
159
			fatal("Zero length token output when incomplete");
160
161
		if (dh_client_pub == NULL)
162
			fatal("No client public key");
163
		
164
		if (maj_status & GSS_S_CONTINUE_NEEDED) {
165
			debug("Sending GSSAPI_CONTINUE");
166
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
167
			packet_put_string(send_tok.value, send_tok.length);
168
			packet_send();
169
			gss_release_buffer(&min_status, &send_tok);
170
		}
171
	} while (maj_status & GSS_S_CONTINUE_NEEDED);
172
173
	if (GSS_ERROR(maj_status)) {
174
		if (send_tok.length > 0) {
175
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
176
			packet_put_string(send_tok.value, send_tok.length);
177
			packet_send();
178
		}
179
		fatal("accept_ctx died");
180
	}
181
182
	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
183
		fatal("Mutual Authentication flag wasn't set");
184
185
	if (!(ret_flags & GSS_C_INTEG_FLAG))
186
		fatal("Integrity flag wasn't set");
187
	
188
	if (!dh_pub_is_valid(dh, dh_client_pub))
189
		packet_disconnect("bad client public DH value");
190
191
	klen = DH_size(dh);
192
	kbuf = xmalloc(klen); 
193
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
194
195
	shared_secret = BN_new();
196
	BN_bin2bn(kbuf, kout, shared_secret);
197
	memset(kbuf, 0, klen);
198
	xfree(kbuf);
199
200
	switch (kex->kex_type) {
201
	case KEX_GSS_GRP1_SHA1:
202
	case KEX_GSS_GRP14_SHA1:
203
		kex_dh_hash(
204
		    kex->client_version_string, kex->server_version_string,
205
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
206
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
207
		    NULL, 0, /* Change this if we start sending host keys */
208
		    dh_client_pub, dh->pub_key, shared_secret,
209
		    &hash, &hashlen
210
		);
211
		break;
212
	case KEX_GSS_GEX_SHA1:
213
		kexgex_hash(
214
		    kex->evp_md,
215
		    kex->client_version_string, kex->server_version_string,
216
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
217
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
218
		    NULL, 0,
219
		    min, nbits, max,
220
		    dh->p, dh->g,
221
		    dh_client_pub,
222
		    dh->pub_key,
223
		    shared_secret,
224
		    &hash, &hashlen
225
		);
226
		break;
227
	default:
228
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
229
	}
230
231
	BN_free(dh_client_pub);
232
233
	if (kex->session_id == NULL) {
234
		kex->session_id_len = hashlen;
235
		kex->session_id = xmalloc(kex->session_id_len);
236
		memcpy(kex->session_id, hash, kex->session_id_len);
237
	}
238
239
	gssbuf.value = hash;
240
	gssbuf.length = hashlen;
241
242
	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
243
		fatal("Couldn't get MIC");
244
245
	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
246
	packet_put_bignum2(dh->pub_key);
247
	packet_put_string(msg_tok.value,msg_tok.length);
248
249
	if (send_tok.length != 0) {
250
		packet_put_char(1); /* true */
251
		packet_put_string(send_tok.value, send_tok.length);
252
	} else {
253
		packet_put_char(0); /* false */
254
	}
255
	packet_send();
256
257
	gss_release_buffer(&min_status, &send_tok);
258
	gss_release_buffer(&min_status, &msg_tok);
259
260
	if (gss_kex_context == NULL)
261
		gss_kex_context = ctxt;
262
	else 
263
		ssh_gssapi_delete_ctx(&ctxt);
264
265
	DH_free(dh);
266
267
	kex_derive_keys(kex, hash, hashlen, shared_secret);
268
	BN_clear_free(shared_secret);
269
	kex_finish(kex);
270
}
271
#endif /* GSSAPI */
(-)key.c (+2 lines)
Lines 648-653 Link Here
648
		return KEY_RSA;
648
		return KEY_RSA;
649
	} else if (strcmp(name, "ssh-dss") == 0) {
649
	} else if (strcmp(name, "ssh-dss") == 0) {
650
		return KEY_DSA;
650
		return KEY_DSA;
651
	} else if (strcmp(name, "null") == 0) {
652
		return KEY_NULL;
651
	}
653
	}
652
	debug2("key_type_from_name: unknown key type '%s'", name);
654
	debug2("key_type_from_name: unknown key type '%s'", name);
653
	return KEY_UNSPEC;
655
	return KEY_UNSPEC;
(-)key.h (+1 lines)
Lines 34-39 Link Here
34
	KEY_RSA1,
34
	KEY_RSA1,
35
	KEY_RSA,
35
	KEY_RSA,
36
	KEY_DSA,
36
	KEY_DSA,
37
	KEY_NULL,
37
	KEY_UNSPEC
38
	KEY_UNSPEC
38
};
39
};
39
enum fp_type {
40
enum fp_type {
(-)monitor.c (+59 lines)
Lines 163-168 Link Here
163
int mm_answer_gss_accept_ctx(int, Buffer *);
163
int mm_answer_gss_accept_ctx(int, Buffer *);
164
int mm_answer_gss_userok(int, Buffer *);
164
int mm_answer_gss_userok(int, Buffer *);
165
int mm_answer_gss_checkmic(int, Buffer *);
165
int mm_answer_gss_checkmic(int, Buffer *);
166
int mm_answer_gss_sign(int, Buffer *);
166
#endif
167
#endif
167
168
168
#ifdef SSH_AUDIT_EVENTS
169
#ifdef SSH_AUDIT_EVENTS
Lines 232-242 Link Here
232
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
233
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
233
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
234
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
234
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
235
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
236
    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
235
#endif
237
#endif
236
    {0, 0, NULL}
238
    {0, 0, NULL}
237
};
239
};
238
240
239
struct mon_table mon_dispatch_postauth20[] = {
241
struct mon_table mon_dispatch_postauth20[] = {
242
#ifdef GSSAPI
243
    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
244
    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
245
    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
246
#endif
240
    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
247
    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
241
    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
248
    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
242
    {MONITOR_REQ_PTY, 0, mm_answer_pty},
249
    {MONITOR_REQ_PTY, 0, mm_answer_pty},
Lines 341-346 Link Here
341
		/* Permit requests for moduli and signatures */
348
		/* Permit requests for moduli and signatures */
342
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
349
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
343
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
350
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
351
#ifdef GSSAPI
352
		/* and for the GSSAPI key exchange */
353
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
354
#endif
344
	} else {
355
	} else {
345
		mon_dispatch = mon_dispatch_proto15;
356
		mon_dispatch = mon_dispatch_proto15;
346
357
Lines 417-422 Link Here
417
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
428
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
418
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
429
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
419
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
430
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
431
#ifdef GSSAPI
432
		/* and for the GSSAPI key exchange */
433
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
434
#endif		
420
	} else {
435
	} else {
421
		mon_dispatch = mon_dispatch_postauth15;
436
		mon_dispatch = mon_dispatch_postauth15;
422
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
437
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
Lines 1660-1665 Link Here
1660
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
1675
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
1661
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1676
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1662
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1677
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1678
#ifdef GSSAPI
1679
	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
1680
	kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
1681
	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
1682
#endif
1663
	kex->server = 1;
1683
	kex->server = 1;
1664
	kex->hostkey_type = buffer_get_int(m);
1684
	kex->hostkey_type = buffer_get_int(m);
1665
	kex->kex_type = buffer_get_int(m);
1685
	kex->kex_type = buffer_get_int(m);
Lines 1901-1906 Link Here
1901
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
1921
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
1902
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
1922
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
1903
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
1923
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
1924
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
1904
	}
1925
	}
1905
	return (0);
1926
	return (0);
1906
}
1927
}
Lines 1951-1954 Link Here
1951
	/* Monitor loop will terminate if authenticated */
1972
	/* Monitor loop will terminate if authenticated */
1952
	return (authenticated);
1973
	return (authenticated);
1953
}
1974
}
1975
1976
int 
1977
mm_answer_gss_sign(int socket, Buffer *m)
1978
{
1979
	gss_buffer_desc data;
1980
	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
1981
	OM_uint32 major, minor;
1982
	u_int len;
1983
1984
	data.value = buffer_get_string(m, &len);
1985
	data.length = len;
1986
	if (data.length != 20) 
1987
		fatal("%s: data length incorrect: %d", __func__, data.length);
1988
1989
	/* Save the session ID on the first time around */
1990
	if (session_id2_len == 0) {
1991
		session_id2_len = data.length;
1992
		session_id2 = xmalloc(session_id2_len);
1993
		memcpy(session_id2, data.value, session_id2_len);
1994
	}
1995
	major = ssh_gssapi_sign(gsscontext, &data, &hash);
1996
1997
	xfree(data.value);
1998
1999
	buffer_clear(m);
2000
	buffer_put_int(m, major);
2001
	buffer_put_string(m, hash.value, hash.length);
2002
2003
	mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
2004
2005
	gss_release_buffer(&minor, &hash);
2006
2007
	/* Turn on getpwnam permissions */
2008
	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
2009
2010
	return (0);
2011
}
2012
1954
#endif /* GSSAPI */
2013
#endif /* GSSAPI */
(-)monitor.h (+1 lines)
Lines 53-58 Link Here
53
	MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
53
	MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
54
	MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
54
	MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
55
	MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
55
	MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
56
	MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
56
	MONITOR_REQ_PAM_START,
57
	MONITOR_REQ_PAM_START,
57
	MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
58
	MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
58
	MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
59
	MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
(-)monitor_wrap.c (+23 lines)
Lines 1224-1227 Link Here
1224
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1224
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1225
	return (authenticated);
1225
	return (authenticated);
1226
}
1226
}
1227
1228
OM_uint32
1229
mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
1230
{
1231
	Buffer m;
1232
	OM_uint32 major;
1233
	u_int len;
1234
1235
	buffer_init(&m);
1236
	buffer_put_string(&m, data->value, data->length);
1237
1238
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
1239
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
1240
1241
	major = buffer_get_int(&m);
1242
	hash->value = buffer_get_string(&m, &len);
1243
	hash->length = len;
1244
1245
	buffer_free(&m);
1246
1247
	return(major);
1248
}
1249
1227
#endif /* GSSAPI */
1250
#endif /* GSSAPI */
(-)monitor_wrap.h (+1 lines)
Lines 59-64 Link Here
59
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
59
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
60
int mm_ssh_gssapi_userok(char *user);
60
int mm_ssh_gssapi_userok(char *user);
61
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
61
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
62
OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
62
#endif
63
#endif
63
64
64
#ifdef USE_PAM
65
#ifdef USE_PAM
(-)readconf.c (+10 lines)
Lines 127-132 Link Here
127
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
127
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
128
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
129
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
130
	oGssKeyEx,
130
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
131
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
131
	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
132
	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
132
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
133
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
Lines 163-171 Link Here
163
	{ "afstokenpassing", oUnsupported },
164
	{ "afstokenpassing", oUnsupported },
164
#if defined(GSSAPI)
165
#if defined(GSSAPI)
165
	{ "gssapiauthentication", oGssAuthentication },
166
	{ "gssapiauthentication", oGssAuthentication },
167
	{ "gssapikeyexchange", oGssKeyEx },
166
	{ "gssapidelegatecredentials", oGssDelegateCreds },
168
	{ "gssapidelegatecredentials", oGssDelegateCreds },
167
#else
169
#else
168
	{ "gssapiauthentication", oUnsupported },
170
	{ "gssapiauthentication", oUnsupported },
171
	{ "gssapikeyexchange", oUnsupported },
169
	{ "gssapidelegatecredentials", oUnsupported },
172
	{ "gssapidelegatecredentials", oUnsupported },
170
#endif
173
#endif
171
	{ "fallbacktorsh", oDeprecated },
174
	{ "fallbacktorsh", oDeprecated },
Lines 441-446 Link Here
441
		intptr = &options->gss_authentication;
444
		intptr = &options->gss_authentication;
442
		goto parse_flag;
445
		goto parse_flag;
443
446
447
	case oGssKeyEx:
448
	    	intptr = &options->gss_keyex;
449
		goto parse_flag;
450
444
	case oGssDelegateCreds:
451
	case oGssDelegateCreds:
445
		intptr = &options->gss_deleg_creds;
452
		intptr = &options->gss_deleg_creds;
446
		goto parse_flag;
453
		goto parse_flag;
Lines 1010-1015 Link Here
1010
	options->pubkey_authentication = -1;
1017
	options->pubkey_authentication = -1;
1011
	options->challenge_response_authentication = -1;
1018
	options->challenge_response_authentication = -1;
1012
	options->gss_authentication = -1;
1019
	options->gss_authentication = -1;
1020
	options->gss_keyex = -1;
1013
	options->gss_deleg_creds = -1;
1021
	options->gss_deleg_creds = -1;
1014
	options->password_authentication = -1;
1022
	options->password_authentication = -1;
1015
	options->kbd_interactive_authentication = -1;
1023
	options->kbd_interactive_authentication = -1;
Lines 1099-1104 Link Here
1099
		options->challenge_response_authentication = 1;
1107
		options->challenge_response_authentication = 1;
1100
	if (options->gss_authentication == -1)
1108
	if (options->gss_authentication == -1)
1101
		options->gss_authentication = 0;
1109
		options->gss_authentication = 0;
1110
	if (options->gss_keyex == -1)
1111
		options->gss_keyex = 0;
1102
	if (options->gss_deleg_creds == -1)
1112
	if (options->gss_deleg_creds == -1)
1103
		options->gss_deleg_creds = 0;
1113
		options->gss_deleg_creds = 0;
1104
	if (options->password_authentication == -1)
1114
	if (options->password_authentication == -1)
(-)readconf.h (+1 lines)
Lines 44-49 Link Here
44
	int     challenge_response_authentication;
44
	int     challenge_response_authentication;
45
					/* Try S/Key or TIS, authentication. */
45
					/* Try S/Key or TIS, authentication. */
46
	int     gss_authentication;	/* Try GSS authentication */
46
	int     gss_authentication;	/* Try GSS authentication */
47
	int	gss_keyex;              /* Try GSS key exchange */
47
	int     gss_deleg_creds;	/* Delegate GSS credentials */
48
	int     gss_deleg_creds;	/* Delegate GSS credentials */
48
	int     password_authentication;	/* Try password
49
	int     password_authentication;	/* Try password
49
						 * authentication. */
50
						 * authentication. */
(-)servconf.c (-1 / +11 lines)
Lines 90-95 Link Here
90
	options->kerberos_ticket_cleanup = -1;
90
	options->kerberos_ticket_cleanup = -1;
91
	options->kerberos_get_afs_token = -1;
91
	options->kerberos_get_afs_token = -1;
92
	options->gss_authentication=-1;
92
	options->gss_authentication=-1;
93
	options->gss_keyex = -1;
93
	options->gss_cleanup_creds = -1;
94
	options->gss_cleanup_creds = -1;
94
	options->password_authentication = -1;
95
	options->password_authentication = -1;
95
	options->kbd_interactive_authentication = -1;
96
	options->kbd_interactive_authentication = -1;
Lines 204-209 Link Here
204
		options->kerberos_get_afs_token = 0;
205
		options->kerberos_get_afs_token = 0;
205
	if (options->gss_authentication == -1)
206
	if (options->gss_authentication == -1)
206
		options->gss_authentication = 0;
207
		options->gss_authentication = 0;
208
	if (options->gss_keyex == -1)
209
		options->gss_keyex = 0;
207
	if (options->gss_cleanup_creds == -1)
210
	if (options->gss_cleanup_creds == -1)
208
		options->gss_cleanup_creds = 1;
211
		options->gss_cleanup_creds = 1;
209
	if (options->password_authentication == -1)
212
	if (options->password_authentication == -1)
Lines 290-296 Link Here
290
	sBanner, sUseDNS, sHostbasedAuthentication,
293
	sBanner, sUseDNS, sHostbasedAuthentication,
291
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
294
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
292
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
295
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
293
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
296
	sGssAuthentication, sGssKeyEx, sGssCleanupCreds, 
297
	sAcceptEnv, sPermitTunnel,
294
	sMatch, sPermitOpen, sForceCommand,
298
	sMatch, sPermitOpen, sForceCommand,
295
	sUsePrivilegeSeparation,
299
	sUsePrivilegeSeparation,
296
	sDeprecated, sUnsupported
300
	sDeprecated, sUnsupported
Lines 350-358 Link Here
350
	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
354
	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
351
#ifdef GSSAPI
355
#ifdef GSSAPI
352
	{ "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
356
	{ "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
357
	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
353
	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
358
	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
354
#else
359
#else
355
	{ "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
360
	{ "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
361
	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
356
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
362
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
357
#endif
363
#endif
358
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
364
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
Lines 870-875 Link Here
870
876
871
	case sGssAuthentication:
877
	case sGssAuthentication:
872
		intptr = &options->gss_authentication;
878
		intptr = &options->gss_authentication;
879
		goto parse_flag;
880
881
	case sGssKeyEx:
882
		intptr = &options->gss_keyex;
873
		goto parse_flag;
883
		goto parse_flag;
874
884
875
	case sGssCleanupCreds:
885
	case sGssCleanupCreds:
(-)servconf.h (+1 lines)
Lines 87-92 Link Here
87
	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
87
	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
88
						 * authenticated with Kerberos. */
88
						 * authenticated with Kerberos. */
89
	int     gss_authentication;	/* If true, permit GSSAPI authentication */
89
	int     gss_authentication;	/* If true, permit GSSAPI authentication */
90
	int 	gss_keyex;		/* If true, permit GSSAPI key exchange */
90
	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
91
	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
91
	int     password_authentication;	/* If true, permit password
92
	int     password_authentication;	/* If true, permit password
92
						 * authentication. */
93
						 * authentication. */
(-)ssh-gss.h (+19 lines)
Lines 60-65 Link Here
60
60
61
#define SSH_GSS_OIDTYPE 0x06
61
#define SSH_GSS_OIDTYPE 0x06
62
62
63
#define SSH2_MSG_KEXGSS_INIT                            30
64
#define SSH2_MSG_KEXGSS_CONTINUE                        31
65
#define SSH2_MSG_KEXGSS_COMPLETE                        32
66
#define SSH2_MSG_KEXGSS_HOSTKEY                         33
67
#define SSH2_MSG_KEXGSS_ERROR                           34
68
#define SSH2_MSG_KEXGSS_GROUPREQ			40
69
#define SSH2_MSG_KEXGSS_GROUP				41
70
#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"
71
#define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"
72
#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"
73
63
typedef struct {
74
typedef struct {
64
	char *filename;
75
	char *filename;
65
	char *envvar;
76
	char *envvar;
Lines 97-102 Link Here
97
} Gssctxt;
108
} Gssctxt;
98
109
99
extern ssh_gssapi_mech *supported_mechs[];
110
extern ssh_gssapi_mech *supported_mechs[];
111
extern Gssctxt *gss_kex_context;
100
112
101
int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
113
int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
102
void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
114
void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
Lines 121-132 Link Here
121
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
133
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
122
134
123
/* In the server */
135
/* In the server */
136
typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *);
137
char *ssh_gssapi_client_mechanisms(const char *host);
138
char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *);
139
gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
140
int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *);
124
int ssh_gssapi_userok(char *name);
141
int ssh_gssapi_userok(char *name);
125
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
142
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
126
void ssh_gssapi_do_child(char ***, u_int *);
143
void ssh_gssapi_do_child(char ***, u_int *);
127
void ssh_gssapi_cleanup_creds(void);
144
void ssh_gssapi_cleanup_creds(void);
128
void ssh_gssapi_storecreds(void);
145
void ssh_gssapi_storecreds(void);
129
146
147
char *ssh_gssapi_server_mechanisms(void);
148
int ssh_gssapi_oid_table_ok();
130
#endif /* GSSAPI */
149
#endif /* GSSAPI */
131
150
132
#endif /* _SSH_GSS_H */
151
#endif /* _SSH_GSS_H */
(-)ssh_config.5 (+6 lines)
Lines 479-484 Link Here
479
The default is
479
The default is
480
.Dq no .
480
.Dq no .
481
Note that this option applies to protocol version 2 only.
481
Note that this option applies to protocol version 2 only.
482
.It Cm GSSAPIKeyExchange
483
Specifies whether key exchange based on GSSAPI may be used. When using
484
GSSAPI key exchange the server need not have a host key.
485
The default is
486
.Dq no .
487
Note that this option applies to protocol version 2 only.
482
.It Cm GSSAPIDelegateCredentials
488
.It Cm GSSAPIDelegateCredentials
483
Forward (delegate) credentials to the server.
489
Forward (delegate) credentials to the server.
484
The default is
490
The default is
(-)sshconnect2.c (+86 lines)
Lines 98-106 Link Here
98
{
98
{
99
	Kex *kex;
99
	Kex *kex;
100
100
101
#ifdef GSSAPI
102
	char *orig = NULL, *gss = NULL;
103
#endif
104
101
	xxx_host = host;
105
	xxx_host = host;
102
	xxx_hostaddr = hostaddr;
106
	xxx_hostaddr = hostaddr;
103
107
108
#ifdef GSSAPI
109
	if (options.gss_keyex) {
110
		/* Add the GSSAPI mechanisms currently supported on this 
111
		 * client to the key exchange algorithm proposal */
112
		orig = myproposal[PROPOSAL_KEX_ALGS];
113
114
		gss = ssh_gssapi_client_mechanisms(host);
115
		if (gss) {
116
			debug("Offering GSSAPI proposal: %s", gss);
117
			xasprintf(&myproposal[PROPOSAL_KEX_ALGS], 
118
			    "%s,%s", gss, orig);
119
		}
120
	}
121
#endif
122
104
	if (options.ciphers == (char *)-1) {
123
	if (options.ciphers == (char *)-1) {
105
		logit("No valid ciphers for protocol version 2 given, using defaults.");
124
		logit("No valid ciphers for protocol version 2 given, using defaults.");
106
		options.ciphers = NULL;
125
		options.ciphers = NULL;
Lines 128-133 Link Here
128
		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
147
		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
129
		    options.hostkeyalgorithms;
148
		    options.hostkeyalgorithms;
130
149
150
#ifdef GSSAPI
151
	/* If we've got GSSAPI algorithms, then we also support the
152
	 * 'null' hostkey, as a last resort */
153
	if (options.gss_keyex && gss) {
154
		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
155
		xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
156
		    "%s,null", orig);
157
	}
158
#endif
159
131
	if (options.rekey_limit)
160
	if (options.rekey_limit)
132
		packet_set_rekey_limit(options.rekey_limit);
161
		packet_set_rekey_limit(options.rekey_limit);
133
162
Lines 137-146 Link Here
137
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
166
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
138
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
167
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
139
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
168
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
169
#ifdef GSSAPI
170
	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
171
	kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
172
	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
173
#endif
140
	kex->client_version_string=client_version_string;
174
	kex->client_version_string=client_version_string;
141
	kex->server_version_string=server_version_string;
175
	kex->server_version_string=server_version_string;
142
	kex->verify_host_key=&verify_host_key_callback;
176
	kex->verify_host_key=&verify_host_key_callback;
143
177
178
#ifdef GSSAPI
179
	kex->gss_deleg_creds = options.gss_deleg_creds;
180
	kex->gss_host = host;
181
#endif
182
144
	xxx_kex = kex;
183
	xxx_kex = kex;
145
184
146
	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
185
	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
Lines 223-228 Link Here
223
void	input_gssapi_hash(int type, u_int32_t, void *);
262
void	input_gssapi_hash(int type, u_int32_t, void *);
224
void	input_gssapi_error(int, u_int32_t, void *);
263
void	input_gssapi_error(int, u_int32_t, void *);
225
void	input_gssapi_errtok(int, u_int32_t, void *);
264
void	input_gssapi_errtok(int, u_int32_t, void *);
265
int	userauth_gsskeyex(Authctxt *authctxt);
226
#endif
266
#endif
227
267
228
void	userauth(Authctxt *, char *);
268
void	userauth(Authctxt *, char *);
Lines 238-243 Link Here
238
278
239
Authmethod authmethods[] = {
279
Authmethod authmethods[] = {
240
#ifdef GSSAPI
280
#ifdef GSSAPI
281
	{"gssapi-keyex",
282
		userauth_gsskeyex,
283
		&options.gss_authentication,
284
		NULL},
241
	{"gssapi-with-mic",
285
	{"gssapi-with-mic",
242
		userauth_gssapi,
286
		userauth_gssapi,
243
		&options.gss_authentication,
287
		&options.gss_authentication,
Lines 716-721 Link Here
716
	xfree(msg);
760
	xfree(msg);
717
	xfree(lang);
761
	xfree(lang);
718
}
762
}
763
764
int
765
userauth_gsskeyex(Authctxt *authctxt)
766
{
767
	Buffer b;
768
	gss_buffer_desc gssbuf;
769
	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
770
	OM_uint32 ms;
771
772
	static int attempt = 0;
773
	if (attempt++ >= 1)
774
		return (0);
775
776
	if (gss_kex_context == NULL) {
777
		debug("No valid Key exchange context"); 
778
		return (0);
779
	}
780
781
	ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
782
	    "gssapi-keyex");
783
784
	gssbuf.value = buffer_ptr(&b);
785
	gssbuf.length = buffer_len(&b);
786
787
	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
788
		buffer_free(&b);
789
		return (0);
790
	}
791
792
	packet_start(SSH2_MSG_USERAUTH_REQUEST);
793
	packet_put_cstring(authctxt->server_user);
794
	packet_put_cstring(authctxt->service);
795
	packet_put_cstring(authctxt->method->name);
796
	packet_put_string(mic.value, mic.length);
797
	packet_send();
798
799
	buffer_free(&b);
800
	gss_release_buffer(&ms, &mic);
801
802
	return (1);
803
}
804
719
#endif /* GSSAPI */
805
#endif /* GSSAPI */
720
806
721
int
807
int
(-)sshd.c (+50 lines)
Lines 1472-1481 Link Here
1472
		logit("Disabling protocol version 1. Could not load host key");
1472
		logit("Disabling protocol version 1. Could not load host key");
1473
		options.protocol &= ~SSH_PROTO_1;
1473
		options.protocol &= ~SSH_PROTO_1;
1474
	}
1474
	}
1475
#ifndef GSSAPI
1476
	/* The GSSAPI key exchange can run without a host key */
1475
	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
1477
	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
1476
		logit("Disabling protocol version 2. Could not load host key");
1478
		logit("Disabling protocol version 2. Could not load host key");
1477
		options.protocol &= ~SSH_PROTO_2;
1479
		options.protocol &= ~SSH_PROTO_2;
1478
	}
1480
	}
1481
#endif
1479
	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
1482
	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
1480
		logit("sshd: no hostkeys available -- exiting.");
1483
		logit("sshd: no hostkeys available -- exiting.");
1481
		exit(1);
1484
		exit(1);
Lines 2108-2119 Link Here
2108
2111
2109
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
2112
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
2110
2113
2114
#ifdef GSSAPI
2115
	{
2116
	char *orig;
2117
	char *gss = NULL;
2118
	char *newstr = NULL;
2119
	orig = myproposal[PROPOSAL_KEX_ALGS];
2120
2121
	/* 
2122
	 * If we don't have a host key, then there's no point advertising
2123
	 * the other key exchange algorithms
2124
	 */
2125
2126
	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
2127
		orig = NULL;
2128
2129
	if (options.gss_keyex)
2130
		gss = ssh_gssapi_server_mechanisms();
2131
	else
2132
		gss = NULL;
2133
2134
	if (gss && orig)
2135
		xasprintf(&newstr, "%s,%s", gss, orig);
2136
	else if (gss)
2137
		newstr = gss;
2138
	else if (orig)
2139
		newstr = orig;
2140
2141
	/* 
2142
	 * If we've got GSSAPI mechanisms, then we've got the 'null' host
2143
	 * key alg, but we can't tell people about it unless its the only
2144
  	 * host key algorithm we support
2145
	 */
2146
	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
2147
		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
2148
2149
	if (newstr)
2150
		myproposal[PROPOSAL_KEX_ALGS] = newstr;
2151
	else
2152
		fatal("No supported key exchange algorithms");
2153
	}
2154
#endif
2155
2111
	/* start key exchange */
2156
	/* start key exchange */
2112
	kex = kex_setup(myproposal);
2157
	kex = kex_setup(myproposal);
2113
	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
2158
	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
2114
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
2159
	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
2115
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
2160
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
2116
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
2161
	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
2162
#ifdef GSSAPI
2163
	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
2164
	kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
2165
	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
2166
#endif
2117
	kex->server = 1;
2167
	kex->server = 1;
2118
	kex->client_version_string=client_version_string;
2168
	kex->client_version_string=client_version_string;
2119
	kex->server_version_string=server_version_string;
2169
	kex->server_version_string=server_version_string;
(-)sshd_config.5 (+6 lines)
Lines 320-325 Link Here
320
The default is
320
The default is
321
.Dq no .
321
.Dq no .
322
Note that this option applies to protocol version 2 only.
322
Note that this option applies to protocol version 2 only.
323
.It Cm GSSAPIKeyExchange
324
Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 
325
doesn't rely on ssh keys to verify host identity.
326
The default is
327
.Dq no .
328
Note that this option applies to protocol version 2 only.
323
.It Cm GSSAPICleanupCredentials
329
.It Cm GSSAPICleanupCredentials
324
Specifies whether to automatically destroy the user's credentials cache
330
Specifies whether to automatically destroy the user's credentials cache
325
on logout.
331
on logout.

Return to bug 1242