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

Collapse All | Expand All

(-)b/ChangeLog.gssapi (+113 lines)
Added Link Here
1
20110101
2
  - Finally update for OpenSSH 5.6p1
3
  - Add GSSAPIServerIdentity option from Jim Basney
4
 
5
20100308
6
  - [ Makefile.in, key.c, key.h ]
7
    Updates for OpenSSH 5.4p1
8
  - [ servconf.c ]
9
    Include GSSAPI options in the sshd -T configuration dump, and flag
10
    some older configuration options as being unsupported. Thanks to Colin 
11
    Watson.
12
  -
13
14
20100124
15
  - [ sshconnect2.c ]
16
    Adapt to deal with additional element in Authmethod structure. Thanks to
17
    Colin Watson
18
19
20090615
20
  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
21
      sshd.c ]
22
    Fix issues identified by Greg Hudson following a code review
23
	Check return value of gss_indicate_mechs
24
	Protect GSSAPI calls in monitor, so they can only be used if enabled
25
	Check return values of bignum functions in key exchange
26
	Use BN_clear_free to clear other side's DH value
27
	Make ssh_gssapi_id_kex more robust
28
	Only configure kex table pointers if GSSAPI is enabled
29
	Don't leak mechanism list, or gss mechanism list
30
	Cast data.length before printing
31
	If serverkey isn't provided, use an empty string, rather than NULL
32
33
20090201
34
  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
35
      ssh_config.5 sshconnet2.c ]
36
    Add support for the GSSAPIClientIdentity option, which allows the user
37
    to specify which GSSAPI identity to use to contact a given server
38
39
20080404
40
  - [ gss-serv.c ]
41
    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
42
    been omitted from a previous version of this patch. Reported by Borislav
43
    Stoichkov
44
45
20070317
46
  - [ gss-serv-krb5.c ]
47
    Remove C99ism, where new_ccname was being declared in the middle of a 
48
    function
49
50
20061220
51
  - [ servconf.c ]
52
    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and 
53
    documented, behaviour. Reported by Dan Watson.
54
55
20060910
56
  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
57
      ssh-gss.h ]
58
    add support for gss-group14-sha1 key exchange mechanisms
59
  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
60
    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
61
    acceptor principal checking on multi-homed machines.
62
    <Bugzilla #928>
63
  - [ sshd_config ssh_config ]
64
    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
65
    configuration files
66
  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
67
    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
68
    Limit length of error messages displayed by client
69
70
20060909
71
  - [ gss-genr.c gss-serv.c ]
72
    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
73
    only, where they belong 
74
    <Bugzilla #1225>
75
76
20060829
77
  - [ gss-serv-krb5.c ]
78
    Fix CCAPI credentials cache name when creating KRB5CCNAME environment 
79
    variable
80
81
20060828
82
  - [ gss-genr.c ]
83
    Avoid Heimdal context freeing problem
84
    <Fixed upstream 20060829>
85
86
20060818
87
  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
88
    Make sure that SPENGO is disabled 
89
    <Bugzilla #1218 - Fixed upstream 20060818>
90
91
20060421
92
  - [ gssgenr.c, sshconnect2.c ]
93
    a few type changes (signed versus unsigned, int versus size_t) to
94
    fix compiler errors/warnings 
95
    (from jbasney AT ncsa.uiuc.edu)
96
  - [ kexgssc.c, sshconnect2.c ]
97
    fix uninitialized variable warnings
98
    (from jbasney AT ncsa.uiuc.edu)
99
  - [ gssgenr.c ]
100
    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
101
    (from jbasney AT ncsa.uiuc.edu)
102
    <Bugzilla #1220 >
103
  - [ gss-serv-krb5.c ]
104
    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
105
    (from jbasney AT ncsa.uiuc.edu)
106
    <Fixed upstream 20060304>
107
  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c 
108
    add client-side GssapiKeyExchange option
109
    (from jbasney AT ncsa.uiuc.edu)
110
  - [ sshconnect2.c ]
111
    add support for GssapiTrustDns option for gssapi-with-mic
112
    (from jbasney AT ncsa.uiuc.edu)
113
    <gssapi-with-mic support is Bugzilla #1008>
(-)b/Makefile.in (-2 / +3 lines)
Lines 91-97 LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ Link Here
91
	sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
91
	sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
92
	kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
92
	kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
93
	kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
93
	kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
94
	kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o
94
	kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
95
	kexgssc.o
95
96
96
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
97
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
97
	sshconnect.o sshconnect1.o sshconnect2.o mux.o \
98
	sshconnect.o sshconnect1.o sshconnect2.o mux.o \
Lines 105-111 SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ Link Here
105
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
106
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
106
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
107
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
107
	monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \
108
	monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \
108
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
109
	auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \
109
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
110
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
110
	sftp-server.o sftp-common.o \
111
	sftp-server.o sftp-common.o \
111
	roaming_common.o roaming_serv.o \
112
	roaming_common.o roaming_serv.o \
(-)b/auth-krb5.c (-2 / +15 lines)
Lines 183-190 auth_krb5_password(Authctxt *authctxt, const char *password) Link Here
183
183
184
	len = strlen(authctxt->krb5_ticket_file) + 6;
184
	len = strlen(authctxt->krb5_ticket_file) + 6;
185
	authctxt->krb5_ccname = xmalloc(len);
185
	authctxt->krb5_ccname = xmalloc(len);
186
#ifdef USE_CCAPI
187
	snprintf(authctxt->krb5_ccname, len, "API:%s",
188
	    authctxt->krb5_ticket_file);
189
#else
186
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
190
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
187
	    authctxt->krb5_ticket_file);
191
	    authctxt->krb5_ticket_file);
192
#endif
188
193
189
#ifdef USE_PAM
194
#ifdef USE_PAM
190
	if (options.use_pam)
195
	if (options.use_pam)
Lines 241-255 krb5_cleanup_proc(Authctxt *authctxt) Link Here
241
#ifndef HEIMDAL
246
#ifndef HEIMDAL
242
krb5_error_code
247
krb5_error_code
243
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
248
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
244
	int tmpfd, ret, oerrno;
249
	int ret, oerrno;
245
	char ccname[40];
250
	char ccname[40];
246
	mode_t old_umask;
251
	mode_t old_umask;
252
#ifdef USE_CCAPI
253
	char cctemplate[] = "API:krb5cc_%d";
254
#else
255
	char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
256
	int tmpfd;
257
#endif
247
258
248
	ret = snprintf(ccname, sizeof(ccname),
259
	ret = snprintf(ccname, sizeof(ccname),
249
	    "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
260
	    cctemplate, geteuid());
250
	if (ret < 0 || (size_t)ret >= sizeof(ccname))
261
	if (ret < 0 || (size_t)ret >= sizeof(ccname))
251
		return ENOMEM;
262
		return ENOMEM;
252
263
264
#ifndef USE_CCAPI
253
	old_umask = umask(0177);
265
	old_umask = umask(0177);
254
	tmpfd = mkstemp(ccname + strlen("FILE:"));
266
	tmpfd = mkstemp(ccname + strlen("FILE:"));
255
	oerrno = errno;
267
	oerrno = errno;
Lines 266-271 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { Link Here
266
		return oerrno;
278
		return oerrno;
267
	}
279
	}
268
	close(tmpfd);
280
	close(tmpfd);
281
#endif
269
282
270
	return (krb5_cc_resolve(ctx, ccname, ccache));
283
	return (krb5_cc_resolve(ctx, ccname, ccache));
271
}
284
}
(-)b/auth.c (-1 / +2 lines)
Lines 354-360 auth_root_allowed(const char *method) Link Here
354
	case PERMIT_NO_PASSWD:
354
	case PERMIT_NO_PASSWD:
355
		if (strcmp(method, "publickey") == 0 ||
355
		if (strcmp(method, "publickey") == 0 ||
356
		    strcmp(method, "hostbased") == 0 ||
356
		    strcmp(method, "hostbased") == 0 ||
357
		    strcmp(method, "gssapi-with-mic") == 0)
357
		    strcmp(method, "gssapi-with-mic") == 0 ||
358
		    strcmp(method, "gssapi-keyex") == 0)
358
			return 1;
359
			return 1;
359
		break;
360
		break;
360
	case PERMIT_FORCED_ONLY:
361
	case PERMIT_FORCED_ONLY:
(-)b/auth2-gss.c (-3 / +45 lines)
Lines 1-7 Link Here
1
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
1
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
2
2
3
/*
3
/*
4
 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
4
 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
Lines 53-58 static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt); Link Here
53
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
53
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
54
static int input_gssapi_errtok(int, u_int32_t, void *);
54
static int input_gssapi_errtok(int, u_int32_t, void *);
55
55
56
/* 
57
 * The 'gssapi_keyex' userauth mechanism.
58
 */
59
static int
60
userauth_gsskeyex(Authctxt *authctxt)
61
{
62
	int authenticated = 0;
63
	Buffer b;
64
	gss_buffer_desc mic, gssbuf;
65
	u_int len;
66
67
	mic.value = packet_get_string(&len);
68
	mic.length = len;
69
70
	packet_check_eom();
71
72
	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
73
	    "gssapi-keyex");
74
75
	gssbuf.value = buffer_ptr(&b);
76
	gssbuf.length = buffer_len(&b);
77
78
	/* gss_kex_context is NULL with privsep, so we can't check it here */
79
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
80
	    &gssbuf, &mic))))
81
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
82
		    authctxt->pw));
83
	
84
	buffer_free(&b);
85
	free(mic.value);
86
87
	return (authenticated);
88
}
89
56
/*
90
/*
57
 * We only support those mechanisms that we know about (ie ones that we know
91
 * We only support those mechanisms that we know about (ie ones that we know
58
 * how to check local user kuserok and the like)
92
 * how to check local user kuserok and the like)
Lines 238-244 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) Link Here
238
272
239
	packet_check_eom();
273
	packet_check_eom();
240
274
241
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
275
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
276
	    authctxt->pw));
242
277
243
	authctxt->postponed = 0;
278
	authctxt->postponed = 0;
244
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
279
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
Lines 274-280 input_gssapi_mic(int type, u_int32_t plen, void *ctxt) Link Here
274
	gssbuf.length = buffer_len(&b);
309
	gssbuf.length = buffer_len(&b);
275
310
276
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
311
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
277
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
312
		authenticated = 
313
		    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
278
	else
314
	else
279
		logit("GSSAPI MIC check failed");
315
		logit("GSSAPI MIC check failed");
280
316
Lines 290-295 input_gssapi_mic(int type, u_int32_t plen, void *ctxt) Link Here
290
	return 0;
326
	return 0;
291
}
327
}
292
328
329
Authmethod method_gsskeyex = {
330
	"gssapi-keyex",
331
	userauth_gsskeyex,
332
	&options.gss_authentication
333
};
334
293
Authmethod method_gssapi = {
335
Authmethod method_gssapi = {
294
	"gssapi-with-mic",
336
	"gssapi-with-mic",
295
	userauth_gssapi,
337
	userauth_gssapi,
(-)b/auth2.c (+2 lines)
Lines 70-75 extern Authmethod method_passwd; Link Here
70
extern Authmethod method_kbdint;
70
extern Authmethod method_kbdint;
71
extern Authmethod method_hostbased;
71
extern Authmethod method_hostbased;
72
#ifdef GSSAPI
72
#ifdef GSSAPI
73
extern Authmethod method_gsskeyex;
73
extern Authmethod method_gssapi;
74
extern Authmethod method_gssapi;
74
#endif
75
#endif
75
76
Lines 77-82 Authmethod *authmethods[] = { Link Here
77
	&method_none,
78
	&method_none,
78
	&method_pubkey,
79
	&method_pubkey,
79
#ifdef GSSAPI
80
#ifdef GSSAPI
81
	&method_gsskeyex,
80
	&method_gssapi,
82
	&method_gssapi,
81
#endif
83
#endif
82
	&method_passwd,
84
	&method_passwd,
(-)b/clientloop.c (+13 lines)
Lines 115-120 Link Here
115
#include "ssherr.h"
115
#include "ssherr.h"
116
#include "hostfile.h"
116
#include "hostfile.h"
117
117
118
#ifdef GSSAPI
119
#include "ssh-gss.h"
120
#endif
121
118
/* import options */
122
/* import options */
119
extern Options options;
123
extern Options options;
120
124
Lines 1610-1615 client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) Link Here
1610
		/* Do channel operations unless rekeying in progress. */
1614
		/* Do channel operations unless rekeying in progress. */
1611
		if (!rekeying) {
1615
		if (!rekeying) {
1612
			channel_after_select(readset, writeset);
1616
			channel_after_select(readset, writeset);
1617
1618
#ifdef GSSAPI
1619
			if (options.gss_renewal_rekey &&
1620
			    ssh_gssapi_credentials_updated(NULL)) {
1621
				debug("credentials updated - forcing rekey");
1622
				need_rekeying = 1;
1623
			}
1624
#endif
1625
1613
			if (need_rekeying || packet_need_rekeying()) {
1626
			if (need_rekeying || packet_need_rekeying()) {
1614
				debug("need rekeying");
1627
				debug("need rekeying");
1615
				active_state->kex->done = 0;
1628
				active_state->kex->done = 0;
(-)b/config.h.in (+6 lines)
Lines 1623-1628 Link Here
1623
/* Use btmp to log bad logins */
1623
/* Use btmp to log bad logins */
1624
#undef USE_BTMP
1624
#undef USE_BTMP
1625
1625
1626
/* platform uses an in-memory credentials cache */
1627
#undef USE_CCAPI
1628
1626
/* Use libedit for sftp */
1629
/* Use libedit for sftp */
1627
#undef USE_LIBEDIT
1630
#undef USE_LIBEDIT
1628
1631
Lines 1638-1643 Link Here
1638
/* Use PIPES instead of a socketpair() */
1641
/* Use PIPES instead of a socketpair() */
1639
#undef USE_PIPES
1642
#undef USE_PIPES
1640
1643
1644
/* platform has the Security Authorization Session API */
1645
#undef USE_SECURITY_SESSION_API
1646
1641
/* Define if you have Solaris process contracts */
1647
/* Define if you have Solaris process contracts */
1642
#undef USE_SOLARIS_PROCESS_CONTRACTS
1648
#undef USE_SOLARIS_PROCESS_CONTRACTS
1643
1649
(-)b/configure.ac (+24 lines)
Lines 625-630 main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) Link Here
625
	    [Use tunnel device compatibility to OpenBSD])
625
	    [Use tunnel device compatibility to OpenBSD])
626
	AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
626
	AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
627
	    [Prepend the address family to IP tunnel traffic])
627
	    [Prepend the address family to IP tunnel traffic])
628
	AC_MSG_CHECKING([if we have the Security Authorization Session API])
629
	AC_TRY_COMPILE([#include <Security/AuthSession.h>],
630
		[SessionCreate(0, 0);],
631
		[ac_cv_use_security_session_api="yes"
632
		 AC_DEFINE([USE_SECURITY_SESSION_API], [1], 
633
			[platform has the Security Authorization Session API])
634
		 LIBS="$LIBS -framework Security"
635
		 AC_MSG_RESULT([yes])],
636
		[ac_cv_use_security_session_api="no"
637
		 AC_MSG_RESULT([no])])
638
	AC_MSG_CHECKING([if we have an in-memory credentials cache])
639
	AC_TRY_COMPILE(
640
		[#include <Kerberos/Kerberos.h>],
641
		[cc_context_t c;
642
		 (void) cc_initialize (&c, 0, NULL, NULL);],
643
		[AC_DEFINE([USE_CCAPI], [1], 
644
			[platform uses an in-memory credentials cache])
645
		 LIBS="$LIBS -framework Security"
646
		 AC_MSG_RESULT([yes])
647
		 if test "x$ac_cv_use_security_session_api" = "xno"; then
648
			AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***])
649
		fi],
650
		[AC_MSG_RESULT([no])]
651
	)
628
	m4_pattern_allow([AU_IPv])
652
	m4_pattern_allow([AU_IPv])
629
	AC_CHECK_DECL([AU_IPv4], [], 
653
	AC_CHECK_DECL([AU_IPv4], [], 
630
	    AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
654
	    AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
(-)b/gss-genr.c (-4 / +271 lines)
Lines 1-7 Link Here
1
/* $OpenBSD: gss-genr.c,v 1.23 2015/01/20 23:14:00 deraadt Exp $ */
1
/* $OpenBSD: gss-genr.c,v 1.23 2015/01/20 23:14:00 deraadt Exp $ */
2
2
3
/*
3
/*
4
 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
4
 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
Lines 41-52 Link Here
41
#include "buffer.h"
41
#include "buffer.h"
42
#include "log.h"
42
#include "log.h"
43
#include "ssh2.h"
43
#include "ssh2.h"
44
#include "cipher.h"
45
#include "key.h"
46
#include "kex.h"
47
#include <openssl/evp.h>
44
48
45
#include "ssh-gss.h"
49
#include "ssh-gss.h"
46
50
47
extern u_char *session_id2;
51
extern u_char *session_id2;
48
extern u_int session_id2_len;
52
extern u_int session_id2_len;
49
53
54
typedef struct {
55
	char *encoded;
56
	gss_OID oid;
57
} ssh_gss_kex_mapping;
58
59
/*
60
 * XXX - It would be nice to find a more elegant way of handling the
61
 * XXX   passing of the key exchange context to the userauth routines
62
 */
63
64
Gssctxt *gss_kex_context = NULL;
65
66
static ssh_gss_kex_mapping *gss_enc2oid = NULL;
67
68
int 
69
ssh_gssapi_oid_table_ok(void) {
70
	return (gss_enc2oid != NULL);
71
}
72
73
/*
74
 * Return a list of the gss-group1-sha1 mechanisms supported by this program
75
 *
76
 * We test mechanisms to ensure that we can use them, to avoid starting
77
 * a key exchange with a bad mechanism
78
 */
79
80
char *
81
ssh_gssapi_client_mechanisms(const char *host, const char *client) {
82
	gss_OID_set gss_supported;
83
	OM_uint32 min_status;
84
85
	if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
86
		return NULL;
87
88
	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
89
	    host, client));
90
}
91
92
char *
93
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
94
    const char *host, const char *client) {
95
	Buffer buf;
96
	size_t i;
97
	int oidpos, enclen;
98
	char *mechs, *encoded;
99
	u_char digest[EVP_MAX_MD_SIZE];
100
	char deroid[2];
101
	const EVP_MD *evp_md = EVP_md5();
102
	EVP_MD_CTX md;
103
104
	if (gss_enc2oid != NULL) {
105
		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
106
			free(gss_enc2oid[i].encoded);
107
		free(gss_enc2oid);
108
	}
109
110
	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
111
	    (gss_supported->count + 1));
112
113
	buffer_init(&buf);
114
115
	oidpos = 0;
116
	for (i = 0; i < gss_supported->count; i++) {
117
		if (gss_supported->elements[i].length < 128 &&
118
		    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
119
120
			deroid[0] = SSH_GSS_OIDTYPE;
121
			deroid[1] = gss_supported->elements[i].length;
122
123
			EVP_DigestInit(&md, evp_md);
124
			EVP_DigestUpdate(&md, deroid, 2);
125
			EVP_DigestUpdate(&md,
126
			    gss_supported->elements[i].elements,
127
			    gss_supported->elements[i].length);
128
			EVP_DigestFinal(&md, digest, NULL);
129
130
			encoded = xmalloc(EVP_MD_size(evp_md) * 2);
131
			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
132
			    encoded, EVP_MD_size(evp_md) * 2);
133
134
			if (oidpos != 0)
135
				buffer_put_char(&buf, ',');
136
137
			buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
138
			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
139
			buffer_append(&buf, encoded, enclen);
140
			buffer_put_char(&buf, ',');
141
			buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
142
			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
143
			buffer_append(&buf, encoded, enclen);
144
			buffer_put_char(&buf, ',');
145
			buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
146
			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
147
			buffer_append(&buf, encoded, enclen);
148
149
			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
150
			gss_enc2oid[oidpos].encoded = encoded;
151
			oidpos++;
152
		}
153
	}
154
	gss_enc2oid[oidpos].oid = NULL;
155
	gss_enc2oid[oidpos].encoded = NULL;
156
157
	buffer_put_char(&buf, '\0');
158
159
	mechs = xmalloc(buffer_len(&buf));
160
	buffer_get(&buf, mechs, buffer_len(&buf));
161
	buffer_free(&buf);
162
163
	if (strlen(mechs) == 0) {
164
		free(mechs);
165
		mechs = NULL;
166
	}
167
	
168
	return (mechs);
169
}
170
171
gss_OID
172
ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
173
	int i = 0;
174
	
175
	switch (kex_type) {
176
	case KEX_GSS_GRP1_SHA1:
177
		if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
178
			return GSS_C_NO_OID;
179
		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
180
		break;
181
	case KEX_GSS_GRP14_SHA1:
182
		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
183
			return GSS_C_NO_OID;
184
		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
185
		break;
186
	case KEX_GSS_GEX_SHA1:
187
		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
188
			return GSS_C_NO_OID;
189
		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
190
		break;
191
	default:
192
		return GSS_C_NO_OID;
193
	}
194
195
	while (gss_enc2oid[i].encoded != NULL &&
196
	    strcmp(name, gss_enc2oid[i].encoded) != 0)
197
		i++;
198
199
	if (gss_enc2oid[i].oid != NULL && ctx != NULL)
200
		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
201
202
	return gss_enc2oid[i].oid;
203
}
204
50
/* Check that the OID in a data stream matches that in the context */
205
/* Check that the OID in a data stream matches that in the context */
51
int
206
int
52
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
207
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
Lines 199-205 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, Link Here
199
	}
354
	}
200
355
201
	ctx->major = gss_init_sec_context(&ctx->minor,
356
	ctx->major = gss_init_sec_context(&ctx->minor,
202
	    GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
357
	    ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
203
	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
358
	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
204
	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);
359
	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);
205
360
Lines 229-236 ssh_gssapi_import_name(Gssctxt *ctx, const char *host) Link Here
229
}
384
}
230
385
231
OM_uint32
386
OM_uint32
387
ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
388
{
389
	gss_buffer_desc gssbuf;
390
	gss_name_t gssname;
391
	OM_uint32 status;
392
	gss_OID_set oidset;
393
394
	gssbuf.value = (void *) name;
395
	gssbuf.length = strlen(gssbuf.value);
396
397
	gss_create_empty_oid_set(&status, &oidset);
398
	gss_add_oid_set_member(&status, ctx->oid, &oidset);
399
400
	ctx->major = gss_import_name(&ctx->minor, &gssbuf,
401
	    GSS_C_NT_USER_NAME, &gssname);
402
403
	if (!ctx->major)
404
		ctx->major = gss_acquire_cred(&ctx->minor, 
405
		    gssname, 0, oidset, GSS_C_INITIATE, 
406
		    &ctx->client_creds, NULL, NULL);
407
408
	gss_release_name(&status, &gssname);
409
	gss_release_oid_set(&status, &oidset);
410
411
	if (ctx->major)
412
		ssh_gssapi_error(ctx);
413
414
	return(ctx->major);
415
}
416
417
OM_uint32
232
ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
418
ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
233
{
419
{
420
	if (ctx == NULL) 
421
		return -1;
422
234
	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
423
	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
235
	    GSS_C_QOP_DEFAULT, buffer, hash)))
424
	    GSS_C_QOP_DEFAULT, buffer, hash)))
236
		ssh_gssapi_error(ctx);
425
		ssh_gssapi_error(ctx);
Lines 238-243 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) Link Here
238
	return (ctx->major);
427
	return (ctx->major);
239
}
428
}
240
429
430
/* Priviledged when used by server */
431
OM_uint32
432
ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
433
{
434
	if (ctx == NULL)
435
		return -1;
436
437
	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
438
	    gssbuf, gssmic, NULL);
439
440
	return (ctx->major);
441
}
442
241
void
443
void
242
ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
444
ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
243
    const char *context)
445
    const char *context)
Lines 251-261 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, Link Here
251
}
453
}
252
454
253
int
455
int
254
ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
456
ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
457
    const char *client)
255
{
458
{
256
	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
459
	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
257
	OM_uint32 major, minor;
460
	OM_uint32 major, minor;
258
	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
461
	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
462
	Gssctxt *intctx = NULL;
463
464
	if (ctx == NULL)
465
		ctx = &intctx;
259
466
260
	/* RFC 4462 says we MUST NOT do SPNEGO */
467
	/* RFC 4462 says we MUST NOT do SPNEGO */
261
	if (oid->length == spnego_oid.length && 
468
	if (oid->length == spnego_oid.length && 
Lines 265-270 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) Link Here
265
	ssh_gssapi_build_ctx(ctx);
472
	ssh_gssapi_build_ctx(ctx);
266
	ssh_gssapi_set_oid(*ctx, oid);
473
	ssh_gssapi_set_oid(*ctx, oid);
267
	major = ssh_gssapi_import_name(*ctx, host);
474
	major = ssh_gssapi_import_name(*ctx, host);
475
476
	if (!GSS_ERROR(major) && client)
477
		major = ssh_gssapi_client_identity(*ctx, client);
478
268
	if (!GSS_ERROR(major)) {
479
	if (!GSS_ERROR(major)) {
269
		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
480
		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
270
		    NULL);
481
		    NULL);
Lines 274-283 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) Link Here
274
			    GSS_C_NO_BUFFER);
485
			    GSS_C_NO_BUFFER);
275
	}
486
	}
276
487
277
	if (GSS_ERROR(major)) 
488
	if (GSS_ERROR(major) || intctx != NULL) 
278
		ssh_gssapi_delete_ctx(ctx);
489
		ssh_gssapi_delete_ctx(ctx);
279
490
280
	return (!GSS_ERROR(major));
491
	return (!GSS_ERROR(major));
281
}
492
}
282
493
494
int
495
ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
496
	static gss_name_t saved_name = GSS_C_NO_NAME;
497
	static OM_uint32 saved_lifetime = 0;
498
	static gss_OID saved_mech = GSS_C_NO_OID;
499
	static gss_name_t name;
500
	static OM_uint32 last_call = 0;
501
	OM_uint32 lifetime, now, major, minor;
502
	int equal;
503
	
504
	now = time(NULL);
505
506
	if (ctxt) {
507
		debug("Rekey has happened - updating saved versions");
508
509
		if (saved_name != GSS_C_NO_NAME)
510
			gss_release_name(&minor, &saved_name);
511
512
		major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
513
		    &saved_name, &saved_lifetime, NULL, NULL);
514
515
		if (!GSS_ERROR(major)) {
516
			saved_mech = ctxt->oid;
517
		        saved_lifetime+= now;
518
		} else {
519
			/* Handle the error */
520
		}
521
		return 0;
522
	}
523
524
	if (now - last_call < 10)
525
		return 0;
526
527
	last_call = now;
528
529
	if (saved_mech == GSS_C_NO_OID)
530
		return 0;
531
	
532
	major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
533
	    &name, &lifetime, NULL, NULL);
534
	if (major == GSS_S_CREDENTIALS_EXPIRED)
535
		return 0;
536
	else if (GSS_ERROR(major))
537
		return 0;
538
539
	major = gss_compare_name(&minor, saved_name, name, &equal);
540
	gss_release_name(&minor, &name);
541
	if (GSS_ERROR(major))
542
		return 0;
543
544
	if (equal && (saved_lifetime < lifetime + now - 10))
545
		return 1;
546
547
	return 0;
548
}
549
283
#endif /* GSSAPI */
550
#endif /* GSSAPI */
(-)b/gss-serv-krb5.c (-7 / +78 lines)
Lines 1-7 Link Here
1
/* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */
1
/* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */
2
2
3
/*
3
/*
4
 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
4
 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
Lines 121-128 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) Link Here
121
	krb5_error_code problem;
121
	krb5_error_code problem;
122
	krb5_principal princ;
122
	krb5_principal princ;
123
	OM_uint32 maj_status, min_status;
123
	OM_uint32 maj_status, min_status;
124
	int len;
125
	const char *errmsg;
124
	const char *errmsg;
125
	const char *new_ccname;
126
126
127
	if (client->creds == NULL) {
127
	if (client->creds == NULL) {
128
		debug("No credentials stored");
128
		debug("No credentials stored");
Lines 181-191 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) Link Here
181
		return;
181
		return;
182
	}
182
	}
183
183
184
	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
184
	new_ccname = krb5_cc_get_name(krb_context, ccache);
185
185
	client->store.envvar = "KRB5CCNAME";
186
	client->store.envvar = "KRB5CCNAME";
186
	len = strlen(client->store.filename) + 6;
187
#ifdef USE_CCAPI
187
	client->store.envval = xmalloc(len);
188
	xasprintf(&client->store.envval, "API:%s", new_ccname);
188
	snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
189
	client->store.filename = NULL;
190
#else
191
	xasprintf(&client->store.envval, "FILE:%s", new_ccname);
192
	client->store.filename = xstrdup(new_ccname);
193
#endif
189
194
190
#ifdef USE_PAM
195
#ifdef USE_PAM
191
	if (options.use_pam)
196
	if (options.use_pam)
Lines 197-202 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) Link Here
197
	return;
202
	return;
198
}
203
}
199
204
205
int
206
ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
207
    ssh_gssapi_client *client)
208
{
209
	krb5_ccache ccache = NULL;
210
	krb5_principal principal = NULL;
211
	char *name = NULL;
212
	krb5_error_code problem;
213
	OM_uint32 maj_status, min_status;
214
215
   	if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
216
                logit("krb5_cc_resolve(): %.100s",
217
                    krb5_get_err_text(krb_context, problem));
218
                return 0;
219
       	}
220
	
221
	/* Find out who the principal in this cache is */
222
	if ((problem = krb5_cc_get_principal(krb_context, ccache, 
223
	    &principal))) {
224
		logit("krb5_cc_get_principal(): %.100s",
225
		    krb5_get_err_text(krb_context, problem));
226
		krb5_cc_close(krb_context, ccache);
227
		return 0;
228
	}
229
230
	if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
231
		logit("krb5_unparse_name(): %.100s",
232
		    krb5_get_err_text(krb_context, problem));
233
		krb5_free_principal(krb_context, principal);
234
		krb5_cc_close(krb_context, ccache);
235
		return 0;
236
	}
237
238
239
	if (strcmp(name,client->exportedname.value)!=0) {
240
		debug("Name in local credentials cache differs. Not storing");
241
		krb5_free_principal(krb_context, principal);
242
		krb5_cc_close(krb_context, ccache);
243
		krb5_free_unparsed_name(krb_context, name);
244
		return 0;
245
	}
246
	krb5_free_unparsed_name(krb_context, name);
247
248
	/* Name matches, so lets get on with it! */
249
250
	if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
251
		logit("krb5_cc_initialize(): %.100s",
252
		    krb5_get_err_text(krb_context, problem));
253
		krb5_free_principal(krb_context, principal);
254
		krb5_cc_close(krb_context, ccache);
255
		return 0;
256
	}
257
258
	krb5_free_principal(krb_context, principal);
259
260
	if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
261
	    ccache))) {
262
		logit("gss_krb5_copy_ccache() failed. Sorry!");
263
		krb5_cc_close(krb_context, ccache);
264
		return 0;
265
	}
266
267
	return 1;
268
}
269
200
ssh_gssapi_mech gssapi_kerberos_mech = {
270
ssh_gssapi_mech gssapi_kerberos_mech = {
201
	"toWM5Slw5Ew8Mqkay+al2g==",
271
	"toWM5Slw5Ew8Mqkay+al2g==",
202
	"Kerberos",
272
	"Kerberos",
Lines 204-210 ssh_gssapi_mech gssapi_kerberos_mech = { Link Here
204
	NULL,
274
	NULL,
205
	&ssh_gssapi_krb5_userok,
275
	&ssh_gssapi_krb5_userok,
206
	NULL,
276
	NULL,
207
	&ssh_gssapi_krb5_storecreds
277
	&ssh_gssapi_krb5_storecreds,
278
	&ssh_gssapi_krb5_updatecreds
208
};
279
};
209
280
210
#endif /* KRB5 */
281
#endif /* KRB5 */
(-)b/gss-serv.c (-14 / +171 lines)
Lines 1-7 Link Here
1
/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */
1
/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */
2
2
3
/*
3
/*
4
 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
4
 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
Lines 45-61 Link Here
45
#include "session.h"
45
#include "session.h"
46
#include "misc.h"
46
#include "misc.h"
47
#include "servconf.h"
47
#include "servconf.h"
48
#include "uidswap.h"
48
49
49
#include "ssh-gss.h"
50
#include "ssh-gss.h"
51
#include "monitor_wrap.h"
52
53
extern ServerOptions options;
50
54
51
extern ServerOptions options;
55
extern ServerOptions options;
52
56
53
static ssh_gssapi_client gssapi_client =
57
static ssh_gssapi_client gssapi_client =
54
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
58
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
55
    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
59
    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL,
60
    {NULL, NULL, NULL, NULL, NULL}, 0, 0};
56
61
57
ssh_gssapi_mech gssapi_null_mech =
62
ssh_gssapi_mech gssapi_null_mech =
58
    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
63
    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
59
64
60
#ifdef KRB5
65
#ifdef KRB5
61
extern ssh_gssapi_mech gssapi_kerberos_mech;
66
extern ssh_gssapi_mech gssapi_kerberos_mech;
Lines 142-147 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) Link Here
142
}
147
}
143
148
144
/* Unprivileged */
149
/* Unprivileged */
150
char *
151
ssh_gssapi_server_mechanisms(void) {
152
	gss_OID_set	supported;
153
154
	ssh_gssapi_supported_oids(&supported);
155
	return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
156
	    NULL, NULL));
157
}
158
159
/* Unprivileged */
160
int
161
ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
162
    const char *dummy) {
163
	Gssctxt *ctx = NULL;
164
	int res;
165
 
166
	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
167
	ssh_gssapi_delete_ctx(&ctx);
168
169
	return (res);
170
}
171
172
/* Unprivileged */
145
void
173
void
146
ssh_gssapi_supported_oids(gss_OID_set *oidset)
174
ssh_gssapi_supported_oids(gss_OID_set *oidset)
147
{
175
{
Lines 151-157 ssh_gssapi_supported_oids(gss_OID_set *oidset) Link Here
151
	gss_OID_set supported;
179
	gss_OID_set supported;
152
180
153
	gss_create_empty_oid_set(&min_status, oidset);
181
	gss_create_empty_oid_set(&min_status, oidset);
154
	gss_indicate_mechs(&min_status, &supported);
182
183
	if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
184
		return;
155
185
156
	while (supported_mechs[i]->name != NULL) {
186
	while (supported_mechs[i]->name != NULL) {
157
		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
187
		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
Lines 277-284 OM_uint32 Link Here
277
ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
307
ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
278
{
308
{
279
	int i = 0;
309
	int i = 0;
310
	int equal = 0;
311
	gss_name_t new_name = GSS_C_NO_NAME;
312
	gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
313
314
	if (options.gss_store_rekey && client->used && ctx->client_creds) {
315
		if (client->mech->oid.length != ctx->oid->length ||
316
		    (memcmp(client->mech->oid.elements,
317
		     ctx->oid->elements, ctx->oid->length) !=0)) {
318
			debug("Rekeyed credentials have different mechanism");
319
			return GSS_S_COMPLETE;
320
		}
321
322
		if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
323
		    ctx->client_creds, ctx->oid, &new_name, 
324
		    NULL, NULL, NULL))) {
325
			ssh_gssapi_error(ctx);
326
			return (ctx->major);
327
		}
328
329
		ctx->major = gss_compare_name(&ctx->minor, client->name, 
330
		    new_name, &equal);
331
332
		if (GSS_ERROR(ctx->major)) {
333
			ssh_gssapi_error(ctx);
334
			return (ctx->major);
335
		}
336
 
337
		if (!equal) {
338
			debug("Rekeyed credentials have different name");
339
			return GSS_S_COMPLETE;
340
		}
280
341
281
	gss_buffer_desc ename;
342
		debug("Marking rekeyed credentials for export");
343
344
		gss_release_name(&ctx->minor, &client->name);
345
		gss_release_cred(&ctx->minor, &client->creds);
346
		client->name = new_name;
347
		client->creds = ctx->client_creds;
348
        	ctx->client_creds = GSS_C_NO_CREDENTIAL;
349
		client->updated = 1;
350
		return GSS_S_COMPLETE;
351
	}
282
352
283
	client->mech = NULL;
353
	client->mech = NULL;
284
354
Lines 293-298 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) Link Here
293
	if (client->mech == NULL)
363
	if (client->mech == NULL)
294
		return GSS_S_FAILURE;
364
		return GSS_S_FAILURE;
295
365
366
	if (ctx->client_creds &&
367
	    (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
368
	     ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
369
		ssh_gssapi_error(ctx);
370
		return (ctx->major);
371
	}
372
296
	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
373
	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
297
	    &client->displayname, NULL))) {
374
	    &client->displayname, NULL))) {
298
		ssh_gssapi_error(ctx);
375
		ssh_gssapi_error(ctx);
Lines 310-315 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) Link Here
310
		return (ctx->major);
387
		return (ctx->major);
311
	}
388
	}
312
389
390
	gss_release_buffer(&ctx->minor, &ename);
391
313
	/* We can't copy this structure, so we just move the pointer to it */
392
	/* We can't copy this structure, so we just move the pointer to it */
314
	client->creds = ctx->client_creds;
393
	client->creds = ctx->client_creds;
315
	ctx->client_creds = GSS_C_NO_CREDENTIAL;
394
	ctx->client_creds = GSS_C_NO_CREDENTIAL;
Lines 357-363 ssh_gssapi_do_child(char ***envp, u_int *envsizep) Link Here
357
436
358
/* Privileged */
437
/* Privileged */
359
int
438
int
360
ssh_gssapi_userok(char *user)
439
ssh_gssapi_userok(char *user, struct passwd *pw)
361
{
440
{
362
	OM_uint32 lmin;
441
	OM_uint32 lmin;
363
442
Lines 367-375 ssh_gssapi_userok(char *user) Link Here
367
		return 0;
446
		return 0;
368
	}
447
	}
369
	if (gssapi_client.mech && gssapi_client.mech->userok)
448
	if (gssapi_client.mech && gssapi_client.mech->userok)
370
		if ((*gssapi_client.mech->userok)(&gssapi_client, user))
449
		if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
450
			gssapi_client.used = 1;
451
			gssapi_client.store.owner = pw;
371
			return 1;
452
			return 1;
372
		else {
453
		} else {
373
			/* Destroy delegated credentials if userok fails */
454
			/* Destroy delegated credentials if userok fails */
374
			gss_release_buffer(&lmin, &gssapi_client.displayname);
455
			gss_release_buffer(&lmin, &gssapi_client.displayname);
375
			gss_release_buffer(&lmin, &gssapi_client.exportedname);
456
			gss_release_buffer(&lmin, &gssapi_client.exportedname);
Lines 383-396 ssh_gssapi_userok(char *user) Link Here
383
	return (0);
464
	return (0);
384
}
465
}
385
466
386
/* Privileged */
467
/* These bits are only used for rekeying. The unpriviledged child is running 
387
OM_uint32
468
 * as the user, the monitor is root.
388
ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
469
 *
470
 * In the child, we want to :
471
 *    *) Ask the monitor to store our credentials into the store we specify
472
 *    *) If it succeeds, maybe do a PAM update
473
 */
474
475
/* Stuff for PAM */
476
477
#ifdef USE_PAM
478
static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
479
    struct pam_response **resp, void *data)
389
{
480
{
390
	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
481
	return (PAM_CONV_ERR);
391
	    gssbuf, gssmic, NULL);
482
}
483
#endif
392
484
393
	return (ctx->major);
485
void
486
ssh_gssapi_rekey_creds(void) {
487
	int ok;
488
	int ret;
489
#ifdef USE_PAM
490
	pam_handle_t *pamh = NULL;
491
	struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
492
	char *envstr;
493
#endif
494
495
	if (gssapi_client.store.filename == NULL && 
496
	    gssapi_client.store.envval == NULL &&
497
	    gssapi_client.store.envvar == NULL)
498
		return;
499
 
500
	ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
501
502
	if (!ok)
503
		return;
504
505
	debug("Rekeyed credentials stored successfully");
506
507
	/* Actually managing to play with the ssh pam stack from here will
508
	 * be next to impossible. In any case, we may want different options
509
	 * for rekeying. So, use our own :)
510
	 */
511
#ifdef USE_PAM	
512
	if (!use_privsep) {
513
		debug("Not even going to try and do PAM with privsep disabled");
514
		return;
515
	}
516
517
	ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
518
 	    &pamconv, &pamh);
519
	if (ret)
520
		return;
521
522
	xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
523
	    gssapi_client.store.envval);
524
525
	ret = pam_putenv(pamh, envstr);
526
	if (!ret)
527
		pam_setcred(pamh, PAM_REINITIALIZE_CRED);
528
	pam_end(pamh, PAM_SUCCESS);
529
#endif
530
}
531
532
int 
533
ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
534
	int ok = 0;
535
536
	/* Check we've got credentials to store */
537
	if (!gssapi_client.updated)
538
		return 0;
539
540
	gssapi_client.updated = 0;
541
542
	temporarily_use_uid(gssapi_client.store.owner);
543
	if (gssapi_client.mech && gssapi_client.mech->updatecreds)
544
		ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
545
	else
546
		debug("No update function for this mechanism");
547
548
	restore_uid();
549
550
	return ok;
394
}
551
}
395
552
396
#endif
553
#endif
(-)b/kex.c (+16 lines)
Lines 55-60 Link Here
55
#include "sshbuf.h"
55
#include "sshbuf.h"
56
#include "digest.h"
56
#include "digest.h"
57
57
58
#ifdef GSSAPI
59
#include "ssh-gss.h"
60
#endif
61
58
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
62
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
59
# if defined(HAVE_EVP_SHA256)
63
# if defined(HAVE_EVP_SHA256)
60
# define evp_ssh_sha256 EVP_sha256
64
# define evp_ssh_sha256 EVP_sha256
Lines 97-102 static const struct kexalg kexalgs[] = { Link Here
97
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
101
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
98
	{ NULL, -1, -1, -1},
102
	{ NULL, -1, -1, -1},
99
};
103
};
104
static const struct kexalg kexalg_prefixes[] = {
105
#ifdef GSSAPI
106
	{ KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
107
	{ KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
108
	{ KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
109
#endif
110
	{ NULL, -1, -1, -1 },
111
};
100
112
101
char *
113
char *
102
kex_alg_list(char sep)
114
kex_alg_list(char sep)
Lines 129-134 kex_alg_by_name(const char *name) Link Here
129
		if (strcmp(k->name, name) == 0)
141
		if (strcmp(k->name, name) == 0)
130
			return k;
142
			return k;
131
	}
143
	}
144
	for (k = kexalg_prefixes; k->name != NULL; k++) {
145
		if (strncmp(k->name, name, strlen(k->name)) == 0)
146
			return k;
147
	}
132
	return NULL;
148
	return NULL;
133
}
149
}
134
150
(-)b/kex.h (+14 lines)
Lines 93-98 enum kex_exchange { Link Here
93
	KEX_DH_GEX_SHA256,
93
	KEX_DH_GEX_SHA256,
94
	KEX_ECDH_SHA2,
94
	KEX_ECDH_SHA2,
95
	KEX_C25519_SHA256,
95
	KEX_C25519_SHA256,
96
	KEX_GSS_GRP1_SHA1,
97
	KEX_GSS_GRP14_SHA1,
98
	KEX_GSS_GEX_SHA1,
96
	KEX_MAX
99
	KEX_MAX
97
};
100
};
98
101
Lines 139-144 struct kex { Link Here
139
	u_int	flags;
142
	u_int	flags;
140
	int	hash_alg;
143
	int	hash_alg;
141
	int	ec_nid;
144
	int	ec_nid;
145
#ifdef GSSAPI
146
	int	gss_deleg_creds;
147
	int	gss_trust_dns;
148
	char    *gss_host;
149
	char	*gss_client;
150
#endif
142
	char	*client_version_string;
151
	char	*client_version_string;
143
	char	*server_version_string;
152
	char	*server_version_string;
144
	char	*failed_choice;
153
	char	*failed_choice;
Lines 187-192 int kexecdh_server(struct ssh *); Link Here
187
int	 kexc25519_client(struct ssh *);
196
int	 kexc25519_client(struct ssh *);
188
int	 kexc25519_server(struct ssh *);
197
int	 kexc25519_server(struct ssh *);
189
198
199
#ifdef GSSAPI
200
int	 kexgss_client(struct ssh *);
201
int	 kexgss_server(struct ssh *);
202
#endif
203
190
int	 kex_dh_hash(const char *, const char *,
204
int	 kex_dh_hash(const char *, const char *,
191
    const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
205
    const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
192
    const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
206
    const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
(-)b/kexgssc.c (+336 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001-2009 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
#include "digest.h"
46
47
#include "ssh-gss.h"
48
49
int
50
kexgss_client(struct ssh *ssh) {
51
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
52
	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
53
	Gssctxt *ctxt;
54
	OM_uint32 maj_status, min_status, ret_flags;
55
	u_int klen, kout, slen = 0, strlen;
56
	DH *dh; 
57
	BIGNUM *dh_server_pub = NULL;
58
	BIGNUM *shared_secret = NULL;
59
	BIGNUM *p = NULL;
60
	BIGNUM *g = NULL;	
61
	u_char *kbuf;
62
	u_char *serverhostkey = NULL;
63
	u_char *empty = "";
64
	char *msg;
65
	int type = 0;
66
	int first = 1;
67
	int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
68
	u_char hash[SSH_DIGEST_MAX_LENGTH];
69
	size_t hashlen;
70
71
	/* Initialise our GSSAPI world */	
72
	ssh_gssapi_build_ctx(&ctxt);
73
	if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) 
74
	    == GSS_C_NO_OID)
75
		fatal("Couldn't identify host exchange");
76
77
	if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host))
78
		fatal("Couldn't import hostname");
79
80
	if (ssh->kex->gss_client && 
81
	    ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client))
82
		fatal("Couldn't acquire client credentials");
83
84
	switch (ssh->kex->kex_type) {
85
	case KEX_GSS_GRP1_SHA1:
86
		dh = dh_new_group1();
87
		break;
88
	case KEX_GSS_GRP14_SHA1:
89
		dh = dh_new_group14();
90
		break;
91
	case KEX_GSS_GEX_SHA1:
92
		debug("Doing group exchange\n");
93
		nbits = dh_estimate(ssh->kex->we_need * 8);
94
		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
95
		packet_put_int(min);
96
		packet_put_int(nbits);
97
		packet_put_int(max);
98
99
		packet_send();
100
101
		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
102
103
		if ((p = BN_new()) == NULL)
104
			fatal("BN_new() failed");
105
		packet_get_bignum2(p);
106
		if ((g = BN_new()) == NULL)
107
			fatal("BN_new() failed");
108
		packet_get_bignum2(g);
109
		packet_check_eom();
110
111
		if (BN_num_bits(p) < min || BN_num_bits(p) > max)
112
			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
113
			    min, BN_num_bits(p), max);
114
115
		dh = dh_new_group(g, p);
116
		break;
117
	default:
118
		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
119
	}
120
	
121
	/* Step 1 - e is dh->pub_key */
122
	dh_gen_key(dh, ssh->kex->we_need * 8);
123
124
	/* This is f, we initialise it now to make life easier */
125
	dh_server_pub = BN_new();
126
	if (dh_server_pub == NULL)
127
		fatal("dh_server_pub == NULL");
128
129
	token_ptr = GSS_C_NO_BUFFER;
130
			 
131
	do {
132
		debug("Calling gss_init_sec_context");
133
		
134
		maj_status = ssh_gssapi_init_ctx(ctxt,
135
		    ssh->kex->gss_deleg_creds, token_ptr, &send_tok,
136
		    &ret_flags);
137
138
		if (GSS_ERROR(maj_status)) {
139
			if (send_tok.length != 0) {
140
				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
141
				packet_put_string(send_tok.value,
142
				    send_tok.length);
143
			}
144
			fatal("gss_init_context failed");
145
		}
146
147
		/* If we've got an old receive buffer get rid of it */
148
		if (token_ptr != GSS_C_NO_BUFFER)
149
			free(recv_tok.value);
150
151
		if (maj_status == GSS_S_COMPLETE) {
152
			/* If mutual state flag is not true, kex fails */
153
			if (!(ret_flags & GSS_C_MUTUAL_FLAG))
154
				fatal("Mutual authentication failed");
155
156
			/* If integ avail flag is not true kex fails */
157
			if (!(ret_flags & GSS_C_INTEG_FLAG))
158
				fatal("Integrity check failed");
159
		}
160
161
		/* 
162
		 * If we have data to send, then the last message that we
163
		 * received cannot have been a 'complete'. 
164
		 */
165
		if (send_tok.length != 0) {
166
			if (first) {
167
				packet_start(SSH2_MSG_KEXGSS_INIT);
168
				packet_put_string(send_tok.value,
169
				    send_tok.length);
170
				packet_put_bignum2(dh->pub_key);
171
				first = 0;
172
			} else {
173
				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
174
				packet_put_string(send_tok.value,
175
				    send_tok.length);
176
			}
177
			packet_send();
178
			gss_release_buffer(&min_status, &send_tok);
179
180
			/* If we've sent them data, they should reply */
181
			do {	
182
				type = packet_read();
183
				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
184
					debug("Received KEXGSS_HOSTKEY");
185
					if (serverhostkey)
186
						fatal("Server host key received more than once");
187
					serverhostkey = 
188
					    packet_get_string(&slen);
189
				}
190
			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);
191
192
			switch (type) {
193
			case SSH2_MSG_KEXGSS_CONTINUE:
194
				debug("Received GSSAPI_CONTINUE");
195
				if (maj_status == GSS_S_COMPLETE) 
196
					fatal("GSSAPI Continue received from server when complete");
197
				recv_tok.value = packet_get_string(&strlen);
198
				recv_tok.length = strlen; 
199
				break;
200
			case SSH2_MSG_KEXGSS_COMPLETE:
201
				debug("Received GSSAPI_COMPLETE");
202
				packet_get_bignum2(dh_server_pub);
203
				msg_tok.value =  packet_get_string(&strlen);
204
				msg_tok.length = strlen; 
205
206
				/* Is there a token included? */
207
				if (packet_get_char()) {
208
					recv_tok.value=
209
					    packet_get_string(&strlen);
210
					recv_tok.length = strlen;
211
					/* If we're already complete - protocol error */
212
					if (maj_status == GSS_S_COMPLETE)
213
						packet_disconnect("Protocol error: received token when complete");
214
					} else {
215
						/* No token included */
216
						if (maj_status != GSS_S_COMPLETE)
217
							packet_disconnect("Protocol error: did not receive final token");
218
				}
219
				break;
220
			case SSH2_MSG_KEXGSS_ERROR:
221
				debug("Received Error");
222
				maj_status = packet_get_int();
223
				min_status = packet_get_int();
224
				msg = packet_get_string(NULL);
225
				(void) packet_get_string_ptr(NULL);
226
				fatal("GSSAPI Error: \n%.400s",msg);
227
			default:
228
				packet_disconnect("Protocol error: didn't expect packet type %d",
229
		    		type);
230
			}
231
			token_ptr = &recv_tok;
232
		} else {
233
			/* No data, and not complete */
234
			if (maj_status != GSS_S_COMPLETE)
235
				fatal("Not complete, and no token output");
236
		}
237
	} while (maj_status & GSS_S_CONTINUE_NEEDED);
238
239
	/* 
240
	 * We _must_ have received a COMPLETE message in reply from the 
241
	 * server, which will have set dh_server_pub and msg_tok 
242
	 */
243
244
	if (type != SSH2_MSG_KEXGSS_COMPLETE)
245
		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
246
247
	/* Check f in range [1, p-1] */
248
	if (!dh_pub_is_valid(dh, dh_server_pub))
249
		packet_disconnect("bad server public DH value");
250
251
	/* compute K=f^x mod p */
252
	klen = DH_size(dh);
253
	kbuf = xmalloc(klen);
254
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
255
	if (kout < 0)
256
		fatal("DH_compute_key: failed");
257
258
	shared_secret = BN_new();
259
	if (shared_secret == NULL)
260
		fatal("kexgss_client: BN_new failed");
261
262
	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
263
		fatal("kexdh_client: BN_bin2bn failed");
264
265
	memset(kbuf, 0, klen);
266
	free(kbuf);
267
268
	hashlen = sizeof(hash);
269
	switch (ssh->kex->kex_type) {
270
	case KEX_GSS_GRP1_SHA1:
271
	case KEX_GSS_GRP14_SHA1:
272
		kex_dh_hash( ssh->kex->client_version_string, 
273
		    ssh->kex->server_version_string,
274
		    buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
275
		    buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
276
		    (serverhostkey ? serverhostkey : empty), slen,
277
		    dh->pub_key,	/* e */
278
		    dh_server_pub,	/* f */
279
		    shared_secret,	/* K */
280
		    hash, &hashlen
281
		);
282
		break;
283
	case KEX_GSS_GEX_SHA1:
284
		kexgex_hash(
285
		    ssh->kex->hash_alg,
286
		    ssh->kex->client_version_string,
287
		    ssh->kex->server_version_string,
288
		    buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
289
		    buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
290
		    (serverhostkey ? serverhostkey : empty), slen,
291
 		    min, nbits, max,
292
		    dh->p, dh->g,
293
		    dh->pub_key,
294
		    dh_server_pub,
295
		    shared_secret,
296
		    hash, &hashlen
297
		);
298
		break;
299
	default:
300
		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
301
	}
302
303
	gssbuf.value = hash;
304
	gssbuf.length = hashlen;
305
306
	/* Verify that the hash matches the MIC we just got. */
307
	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
308
		packet_disconnect("Hash's MIC didn't verify");
309
310
	free(msg_tok.value);
311
312
	DH_free(dh);
313
	free(serverhostkey);
314
	BN_clear_free(dh_server_pub);
315
316
	/* save session id */
317
	if (ssh->kex->session_id == NULL) {
318
		ssh->kex->session_id_len = hashlen;
319
		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);
320
		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);
321
	}
322
323
	if (ssh->kex->gss_deleg_creds)
324
		ssh_gssapi_credentials_updated(ctxt);
325
326
	if (gss_kex_context == NULL)
327
		gss_kex_context = ctxt;
328
	else
329
		ssh_gssapi_delete_ctx(&ctxt);
330
331
	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);
332
	BN_clear_free(shared_secret);
333
	return kex_send_newkeys(ssh);
334
}
335
336
#endif /* GSSAPI */
(-)b/kexgsss.c (+295 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001-2009 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
#include "misc.h"
46
#include "servconf.h"
47
#include "digest.h"
48
49
extern ServerOptions options;
50
51
int
52
kexgss_server(struct ssh *ssh)
53
{
54
	OM_uint32 maj_status, min_status;
55
	
56
	/* 
57
	 * Some GSSAPI implementations use the input value of ret_flags (an
58
 	 * output variable) as a means of triggering mechanism specific 
59
 	 * features. Initializing it to zero avoids inadvertently 
60
 	 * activating this non-standard behaviour.
61
	 */
62
63
	OM_uint32 ret_flags = 0;
64
	gss_buffer_desc gssbuf, recv_tok, msg_tok;
65
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
66
	Gssctxt *ctxt = NULL;
67
	u_int slen, klen, kout;
68
	u_char *kbuf;
69
	DH *dh;
70
	int min = -1, max = -1, nbits = -1;
71
	BIGNUM *shared_secret = NULL;
72
	BIGNUM *dh_client_pub = NULL;
73
	int type = 0;
74
	gss_OID oid;
75
	char *mechs;
76
	u_char hash[SSH_DIGEST_MAX_LENGTH];
77
	size_t hashlen;
78
79
	/* Initialise GSSAPI */
80
81
	/* If we're rekeying, privsep means that some of the private structures
82
	 * in the GSSAPI code are no longer available. This kludges them back
83
	 * into life
84
	 */
85
	if (!ssh_gssapi_oid_table_ok()) {
86
		mechs = ssh_gssapi_server_mechanisms();
87
		free(mechs);
88
	}
89
90
	debug2("%s: Identifying %s", __func__, ssh->kex->name);
91
	oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type);
92
	if (oid == GSS_C_NO_OID)
93
	   fatal("Unknown gssapi mechanism");
94
95
	debug2("%s: Acquiring credentials", __func__);
96
97
	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
98
		fatal("Unable to acquire credentials for the server");
99
100
	switch (ssh->kex->kex_type) {
101
	case KEX_GSS_GRP1_SHA1:
102
		dh = dh_new_group1();
103
		break;
104
	case KEX_GSS_GRP14_SHA1:
105
		dh = dh_new_group14();
106
		break;
107
	case KEX_GSS_GEX_SHA1:
108
		debug("Doing group exchange");
109
		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
110
		min = packet_get_int();
111
		nbits = packet_get_int();
112
		max = packet_get_int();
113
		min = MAX(DH_GRP_MIN, min);
114
		max = MIN(DH_GRP_MAX, max);
115
		packet_check_eom();
116
		if (max < min || nbits < min || max < nbits)
117
			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
118
			    min, nbits, max);
119
		dh = PRIVSEP(choose_dh(min, nbits, max));
120
		if (dh == NULL)
121
			packet_disconnect("Protocol error: no matching group found");
122
123
		packet_start(SSH2_MSG_KEXGSS_GROUP);
124
		packet_put_bignum2(dh->p);
125
		packet_put_bignum2(dh->g);
126
		packet_send();
127
128
		packet_write_wait();
129
		break;
130
	default:
131
		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
132
	}
133
134
	dh_gen_key(dh, ssh->kex->we_need * 8);
135
136
	do {
137
		debug("Wait SSH2_MSG_GSSAPI_INIT");
138
		type = packet_read();
139
		switch(type) {
140
		case SSH2_MSG_KEXGSS_INIT:
141
			if (dh_client_pub != NULL) 
142
				fatal("Received KEXGSS_INIT after initialising");
143
			recv_tok.value = packet_get_string(&slen);
144
			recv_tok.length = slen; 
145
146
			if ((dh_client_pub = BN_new()) == NULL)
147
				fatal("dh_client_pub == NULL");
148
149
			packet_get_bignum2(dh_client_pub);
150
151
			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
152
			break;
153
		case SSH2_MSG_KEXGSS_CONTINUE:
154
			recv_tok.value = packet_get_string(&slen);
155
			recv_tok.length = slen; 
156
			break;
157
		default:
158
			packet_disconnect(
159
			    "Protocol error: didn't expect packet type %d",
160
			    type);
161
		}
162
163
		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
164
		    &send_tok, &ret_flags));
165
166
		free(recv_tok.value);
167
168
		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
169
			fatal("Zero length token output when incomplete");
170
171
		if (dh_client_pub == NULL)
172
			fatal("No client public key");
173
		
174
		if (maj_status & GSS_S_CONTINUE_NEEDED) {
175
			debug("Sending GSSAPI_CONTINUE");
176
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
177
			packet_put_string(send_tok.value, send_tok.length);
178
			packet_send();
179
			gss_release_buffer(&min_status, &send_tok);
180
		}
181
	} while (maj_status & GSS_S_CONTINUE_NEEDED);
182
183
	if (GSS_ERROR(maj_status)) {
184
		if (send_tok.length > 0) {
185
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
186
			packet_put_string(send_tok.value, send_tok.length);
187
			packet_send();
188
		}
189
		fatal("accept_ctx died");
190
	}
191
192
	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
193
		fatal("Mutual Authentication flag wasn't set");
194
195
	if (!(ret_flags & GSS_C_INTEG_FLAG))
196
		fatal("Integrity flag wasn't set");
197
	
198
	if (!dh_pub_is_valid(dh, dh_client_pub))
199
		packet_disconnect("bad client public DH value");
200
201
	klen = DH_size(dh);
202
	kbuf = xmalloc(klen); 
203
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
204
	if (kout < 0)
205
		fatal("DH_compute_key: failed");
206
207
	shared_secret = BN_new();
208
	if (shared_secret == NULL)
209
		fatal("kexgss_server: BN_new failed");
210
211
	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
212
		fatal("kexgss_server: BN_bin2bn failed");
213
214
	memset(kbuf, 0, klen);
215
	free(kbuf);
216
217
	hashlen = sizeof(hash);
218
	switch (ssh->kex->kex_type) {
219
	case KEX_GSS_GRP1_SHA1:
220
	case KEX_GSS_GRP14_SHA1:
221
		kex_dh_hash(
222
		    ssh->kex->client_version_string, ssh->kex->server_version_string,
223
		    buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
224
		    buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
225
		    NULL, 0, /* Change this if we start sending host keys */
226
		    dh_client_pub, dh->pub_key, shared_secret,
227
		    hash, &hashlen
228
		);
229
		break;
230
	case KEX_GSS_GEX_SHA1:
231
		kexgex_hash(
232
		    ssh->kex->hash_alg,
233
		    ssh->kex->client_version_string, ssh->kex->server_version_string,
234
		    buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer),
235
		    buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my),
236
		    NULL, 0,
237
		    min, nbits, max,
238
		    dh->p, dh->g,
239
		    dh_client_pub,
240
		    dh->pub_key,
241
		    shared_secret,
242
		    hash, &hashlen
243
		);
244
		break;
245
	default:
246
		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
247
	}
248
249
	BN_clear_free(dh_client_pub);
250
251
	if (ssh->kex->session_id == NULL) {
252
		ssh->kex->session_id_len = hashlen;
253
		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);
254
		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);
255
	}
256
257
	gssbuf.value = hash;
258
	gssbuf.length = hashlen;
259
260
	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
261
		fatal("Couldn't get MIC");
262
263
	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
264
	packet_put_bignum2(dh->pub_key);
265
	packet_put_string(msg_tok.value,msg_tok.length);
266
267
	if (send_tok.length != 0) {
268
		packet_put_char(1); /* true */
269
		packet_put_string(send_tok.value, send_tok.length);
270
	} else {
271
		packet_put_char(0); /* false */
272
	}
273
	packet_send();
274
275
	gss_release_buffer(&min_status, &send_tok);
276
	gss_release_buffer(&min_status, &msg_tok);
277
278
	if (gss_kex_context == NULL)
279
		gss_kex_context = ctxt;
280
	else 
281
		ssh_gssapi_delete_ctx(&ctxt);
282
283
	DH_free(dh);
284
285
	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);
286
	BN_clear_free(shared_secret);
287
	kex_send_newkeys(ssh);
288
289
	/* If this was a rekey, then save out any delegated credentials we
290
	 * just exchanged.  */
291
	if (options.gss_store_rekey)
292
		ssh_gssapi_rekey_creds();
293
	return 0;
294
}
295
#endif /* GSSAPI */
(-)b/monitor.c (-1 / +107 lines)
Lines 157-162 int mm_answer_gss_setup_ctx(int, Buffer *); Link Here
157
int mm_answer_gss_accept_ctx(int, Buffer *);
157
int mm_answer_gss_accept_ctx(int, Buffer *);
158
int mm_answer_gss_userok(int, Buffer *);
158
int mm_answer_gss_userok(int, Buffer *);
159
int mm_answer_gss_checkmic(int, Buffer *);
159
int mm_answer_gss_checkmic(int, Buffer *);
160
int mm_answer_gss_sign(int, Buffer *);
161
int mm_answer_gss_updatecreds(int, Buffer *);
160
#endif
162
#endif
161
163
162
#ifdef SSH_AUDIT_EVENTS
164
#ifdef SSH_AUDIT_EVENTS
Lines 234-244 struct mon_table mon_dispatch_proto20[] = { Link Here
234
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
236
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
235
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
237
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
236
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
238
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
239
    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
237
#endif
240
#endif
238
    {0, 0, NULL}
241
    {0, 0, NULL}
239
};
242
};
240
243
241
struct mon_table mon_dispatch_postauth20[] = {
244
struct mon_table mon_dispatch_postauth20[] = {
245
#ifdef GSSAPI
246
    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
247
    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
248
    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
249
    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
250
#endif
242
#ifdef WITH_OPENSSL
251
#ifdef WITH_OPENSSL
243
    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
252
    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
244
#endif
253
#endif
Lines 353-358 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) Link Here
353
		/* Permit requests for moduli and signatures */
362
		/* Permit requests for moduli and signatures */
354
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
363
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
355
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
364
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
365
#ifdef GSSAPI
366
		/* and for the GSSAPI key exchange */
367
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
368
#endif
356
	} else {
369
	} else {
357
		mon_dispatch = mon_dispatch_proto15;
370
		mon_dispatch = mon_dispatch_proto15;
358
371
Lines 461-466 monitor_child_postauth(struct monitor *pmonitor) Link Here
461
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
474
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
462
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
475
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
463
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
476
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
477
#ifdef GSSAPI
478
		/* and for the GSSAPI key exchange */
479
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
480
#endif		
464
	} else {
481
	} else {
465
		mon_dispatch = mon_dispatch_postauth15;
482
		mon_dispatch = mon_dispatch_postauth15;
466
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
483
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
Lines 1864-1869 monitor_apply_keystate(struct monitor *pmonitor) Link Here
1864
# endif
1881
# endif
1865
#endif /* WITH_OPENSSL */
1882
#endif /* WITH_OPENSSL */
1866
		kex->kex[KEX_C25519_SHA256] = kexc25519_server;
1883
		kex->kex[KEX_C25519_SHA256] = kexc25519_server;
1884
#ifdef GSSAPI
1885
		if (options.gss_keyex) {
1886
			kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
1887
			kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
1888
			kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
1889
		}
1890
#endif
1867
		kex->load_host_public_key=&get_hostkey_public_by_type;
1891
		kex->load_host_public_key=&get_hostkey_public_by_type;
1868
		kex->load_host_private_key=&get_hostkey_private_by_type;
1892
		kex->load_host_private_key=&get_hostkey_private_by_type;
1869
		kex->host_key_index=&get_hostkey_index;
1893
		kex->host_key_index=&get_hostkey_index;
Lines 1963-1968 mm_answer_gss_setup_ctx(int sock, Buffer *m) Link Here
1963
	OM_uint32 major;
1987
	OM_uint32 major;
1964
	u_int len;
1988
	u_int len;
1965
1989
1990
	if (!options.gss_authentication && !options.gss_keyex)
1991
		fatal("In GSSAPI monitor when GSSAPI is disabled");
1992
1966
	goid.elements = buffer_get_string(m, &len);
1993
	goid.elements = buffer_get_string(m, &len);
1967
	goid.length = len;
1994
	goid.length = len;
1968
1995
Lines 1990-1995 mm_answer_gss_accept_ctx(int sock, Buffer *m) Link Here
1990
	OM_uint32 flags = 0; /* GSI needs this */
2017
	OM_uint32 flags = 0; /* GSI needs this */
1991
	u_int len;
2018
	u_int len;
1992
2019
2020
	if (!options.gss_authentication && !options.gss_keyex)
2021
		fatal("In GSSAPI monitor when GSSAPI is disabled");
2022
1993
	in.value = buffer_get_string(m, &len);
2023
	in.value = buffer_get_string(m, &len);
1994
	in.length = len;
2024
	in.length = len;
1995
	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
2025
	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
Lines 2007-2012 mm_answer_gss_accept_ctx(int sock, Buffer *m) Link Here
2007
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
2037
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
2008
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2038
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2009
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
2039
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
2040
		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
2010
	}
2041
	}
2011
	return (0);
2042
	return (0);
2012
}
2043
}
Lines 2018-2023 mm_answer_gss_checkmic(int sock, Buffer *m) Link Here
2018
	OM_uint32 ret;
2049
	OM_uint32 ret;
2019
	u_int len;
2050
	u_int len;
2020
2051
2052
	if (!options.gss_authentication && !options.gss_keyex)
2053
		fatal("In GSSAPI monitor when GSSAPI is disabled");
2054
2021
	gssbuf.value = buffer_get_string(m, &len);
2055
	gssbuf.value = buffer_get_string(m, &len);
2022
	gssbuf.length = len;
2056
	gssbuf.length = len;
2023
	mic.value = buffer_get_string(m, &len);
2057
	mic.value = buffer_get_string(m, &len);
Lines 2044-2050 mm_answer_gss_userok(int sock, Buffer *m) Link Here
2044
{
2078
{
2045
	int authenticated;
2079
	int authenticated;
2046
2080
2047
	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
2081
	if (!options.gss_authentication && !options.gss_keyex)
2082
		fatal("In GSSAPI monitor when GSSAPI is disabled");
2083
2084
	authenticated = authctxt->valid && 
2085
	    ssh_gssapi_userok(authctxt->user, authctxt->pw);
2048
2086
2049
	buffer_clear(m);
2087
	buffer_clear(m);
2050
	buffer_put_int(m, authenticated);
2088
	buffer_put_int(m, authenticated);
Lines 2057-2061 mm_answer_gss_userok(int sock, Buffer *m) Link Here
2057
	/* Monitor loop will terminate if authenticated */
2095
	/* Monitor loop will terminate if authenticated */
2058
	return (authenticated);
2096
	return (authenticated);
2059
}
2097
}
2098
2099
int 
2100
mm_answer_gss_sign(int socket, Buffer *m)
2101
{
2102
	gss_buffer_desc data;
2103
	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
2104
	OM_uint32 major, minor;
2105
	u_int len;
2106
2107
	if (!options.gss_authentication && !options.gss_keyex)
2108
		fatal("In GSSAPI monitor when GSSAPI is disabled");
2109
2110
	data.value = buffer_get_string(m, &len);
2111
	data.length = len;
2112
	if (data.length != 20) 
2113
		fatal("%s: data length incorrect: %d", __func__, 
2114
		    (int) data.length);
2115
2116
	/* Save the session ID on the first time around */
2117
	if (session_id2_len == 0) {
2118
		session_id2_len = data.length;
2119
		session_id2 = xmalloc(session_id2_len);
2120
		memcpy(session_id2, data.value, session_id2_len);
2121
	}
2122
	major = ssh_gssapi_sign(gsscontext, &data, &hash);
2123
2124
	free(data.value);
2125
2126
	buffer_clear(m);
2127
	buffer_put_int(m, major);
2128
	buffer_put_string(m, hash.value, hash.length);
2129
2130
	mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
2131
2132
	gss_release_buffer(&minor, &hash);
2133
2134
	/* Turn on getpwnam permissions */
2135
	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
2136
	
2137
	/* And credential updating, for when rekeying */
2138
	monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
2139
2140
	return (0);
2141
}
2142
2143
int
2144
mm_answer_gss_updatecreds(int socket, Buffer *m) {
2145
	ssh_gssapi_ccache store;
2146
	int ok;
2147
2148
	store.filename = buffer_get_string(m, NULL);
2149
	store.envvar   = buffer_get_string(m, NULL);
2150
	store.envval   = buffer_get_string(m, NULL);
2151
2152
	ok = ssh_gssapi_update_creds(&store);
2153
2154
	free(store.filename);
2155
	free(store.envvar);
2156
	free(store.envval);
2157
2158
	buffer_clear(m);
2159
	buffer_put_int(m, ok);
2160
2161
	mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
2162
2163
	return(0);
2164
}
2165
2060
#endif /* GSSAPI */
2166
#endif /* GSSAPI */
2061
2167
(-)b/monitor.h (+3 lines)
Lines 65-70 enum monitor_reqtype { Link Here
65
	MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
65
	MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
66
	MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
66
	MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
67
67
68
	MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
69
	MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
70
68
};
71
};
69
72
70
struct mm_master;
73
struct mm_master;
(-)b/monitor_wrap.c (-1 / +46 lines)
Lines 1068-1074 mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) Link Here
1068
}
1068
}
1069
1069
1070
int
1070
int
1071
mm_ssh_gssapi_userok(char *user)
1071
mm_ssh_gssapi_userok(char *user, struct passwd *pw)
1072
{
1072
{
1073
	Buffer m;
1073
	Buffer m;
1074
	int authenticated = 0;
1074
	int authenticated = 0;
Lines 1085-1089 mm_ssh_gssapi_userok(char *user) Link Here
1085
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1085
	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1086
	return (authenticated);
1086
	return (authenticated);
1087
}
1087
}
1088
1089
OM_uint32
1090
mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
1091
{
1092
	Buffer m;
1093
	OM_uint32 major;
1094
	u_int len;
1095
1096
	buffer_init(&m);
1097
	buffer_put_string(&m, data->value, data->length);
1098
1099
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
1100
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
1101
1102
	major = buffer_get_int(&m);
1103
	hash->value = buffer_get_string(&m, &len);
1104
	hash->length = len;
1105
1106
	buffer_free(&m);
1107
1108
	return(major);
1109
}
1110
1111
int
1112
mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
1113
{
1114
	Buffer m;
1115
	int ok;
1116
1117
	buffer_init(&m);
1118
1119
	buffer_put_cstring(&m, store->filename ? store->filename : "");
1120
	buffer_put_cstring(&m, store->envvar ? store->envvar : "");
1121
	buffer_put_cstring(&m, store->envval ? store->envval : "");
1122
	
1123
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
1124
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
1125
1126
	ok = buffer_get_int(&m);
1127
1128
	buffer_free(&m);
1129
	
1130
	return (ok);
1131
}
1132
1088
#endif /* GSSAPI */
1133
#endif /* GSSAPI */
1089
1134
(-)b/monitor_wrap.h (-1 / +3 lines)
Lines 58-65 BIGNUM *mm_auth_rsa_generate_challenge(Key *); Link Here
58
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
58
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
59
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
59
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
60
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
60
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
61
int mm_ssh_gssapi_userok(char *user);
61
int mm_ssh_gssapi_userok(char *user, struct passwd *);
62
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
62
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
63
OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
64
int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
63
#endif
65
#endif
64
66
65
#ifdef USE_PAM
67
#ifdef USE_PAM
(-)b/readconf.c (+42 lines)
Lines 147-152 typedef enum { Link Here
147
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
147
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
148
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
148
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
149
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
149
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
150
	oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
151
	oGssServerIdentity, 
150
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
152
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
151
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
153
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
152
	oHashKnownHosts,
154
	oHashKnownHosts,
Lines 192-201 static struct { Link Here
192
	{ "afstokenpassing", oUnsupported },
194
	{ "afstokenpassing", oUnsupported },
193
#if defined(GSSAPI)
195
#if defined(GSSAPI)
194
	{ "gssapiauthentication", oGssAuthentication },
196
	{ "gssapiauthentication", oGssAuthentication },
197
	{ "gssapikeyexchange", oGssKeyEx },
195
	{ "gssapidelegatecredentials", oGssDelegateCreds },
198
	{ "gssapidelegatecredentials", oGssDelegateCreds },
199
	{ "gssapitrustdns", oGssTrustDns },
200
	{ "gssapiclientidentity", oGssClientIdentity },
201
	{ "gssapiserveridentity", oGssServerIdentity },
202
	{ "gssapirenewalforcesrekey", oGssRenewalRekey },
196
#else
203
#else
197
	{ "gssapiauthentication", oUnsupported },
204
	{ "gssapiauthentication", oUnsupported },
205
	{ "gssapikeyexchange", oUnsupported },
198
	{ "gssapidelegatecredentials", oUnsupported },
206
	{ "gssapidelegatecredentials", oUnsupported },
207
	{ "gssapitrustdns", oUnsupported },
208
	{ "gssapiclientidentity", oUnsupported },
209
	{ "gssapirenewalforcesrekey", oUnsupported },
199
#endif
210
#endif
200
	{ "fallbacktorsh", oDeprecated },
211
	{ "fallbacktorsh", oDeprecated },
201
	{ "usersh", oDeprecated },
212
	{ "usersh", oDeprecated },
Lines 894-903 parse_time: Link Here
894
		intptr = &options->gss_authentication;
905
		intptr = &options->gss_authentication;
895
		goto parse_flag;
906
		goto parse_flag;
896
907
908
	case oGssKeyEx:
909
		intptr = &options->gss_keyex;
910
		goto parse_flag;
911
897
	case oGssDelegateCreds:
912
	case oGssDelegateCreds:
898
		intptr = &options->gss_deleg_creds;
913
		intptr = &options->gss_deleg_creds;
899
		goto parse_flag;
914
		goto parse_flag;
900
915
916
	case oGssTrustDns:
917
		intptr = &options->gss_trust_dns;
918
		goto parse_flag;
919
920
	case oGssClientIdentity:
921
		charptr = &options->gss_client_identity;
922
		goto parse_string;
923
924
	case oGssServerIdentity:
925
		charptr = &options->gss_server_identity;
926
		goto parse_string;
927
928
	case oGssRenewalRekey:
929
		intptr = &options->gss_renewal_rekey;
930
		goto parse_flag;
931
901
	case oBatchMode:
932
	case oBatchMode:
902
		intptr = &options->batch_mode;
933
		intptr = &options->batch_mode;
903
		goto parse_flag;
934
		goto parse_flag;
Lines 1601-1607 initialize_options(Options * options) Link Here
1601
	options->pubkey_authentication = -1;
1632
	options->pubkey_authentication = -1;
1602
	options->challenge_response_authentication = -1;
1633
	options->challenge_response_authentication = -1;
1603
	options->gss_authentication = -1;
1634
	options->gss_authentication = -1;
1635
	options->gss_keyex = -1;
1604
	options->gss_deleg_creds = -1;
1636
	options->gss_deleg_creds = -1;
1637
	options->gss_trust_dns = -1;
1638
	options->gss_renewal_rekey = -1;
1639
	options->gss_client_identity = NULL;
1640
	options->gss_server_identity = NULL;
1605
	options->password_authentication = -1;
1641
	options->password_authentication = -1;
1606
	options->kbd_interactive_authentication = -1;
1642
	options->kbd_interactive_authentication = -1;
1607
	options->kbd_interactive_devices = NULL;
1643
	options->kbd_interactive_devices = NULL;
Lines 1729-1736 fill_default_options(Options * options) Link Here
1729
		options->challenge_response_authentication = 1;
1765
		options->challenge_response_authentication = 1;
1730
	if (options->gss_authentication == -1)
1766
	if (options->gss_authentication == -1)
1731
		options->gss_authentication = 0;
1767
		options->gss_authentication = 0;
1768
	if (options->gss_keyex == -1)
1769
		options->gss_keyex = 0;
1732
	if (options->gss_deleg_creds == -1)
1770
	if (options->gss_deleg_creds == -1)
1733
		options->gss_deleg_creds = 0;
1771
		options->gss_deleg_creds = 0;
1772
	if (options->gss_trust_dns == -1)
1773
		options->gss_trust_dns = 0;
1774
	if (options->gss_renewal_rekey == -1)
1775
		options->gss_renewal_rekey = 0;
1734
	if (options->password_authentication == -1)
1776
	if (options->password_authentication == -1)
1735
		options->password_authentication = 1;
1777
		options->password_authentication = 1;
1736
	if (options->kbd_interactive_authentication == -1)
1778
	if (options->kbd_interactive_authentication == -1)
(-)b/readconf.h (+5 lines)
Lines 45-51 typedef struct { Link Here
45
	int     challenge_response_authentication;
45
	int     challenge_response_authentication;
46
					/* Try S/Key or TIS, authentication. */
46
					/* Try S/Key or TIS, authentication. */
47
	int     gss_authentication;	/* Try GSS authentication */
47
	int     gss_authentication;	/* Try GSS authentication */
48
	int     gss_keyex;		/* Try GSS key exchange */
48
	int     gss_deleg_creds;	/* Delegate GSS credentials */
49
	int     gss_deleg_creds;	/* Delegate GSS credentials */
50
	int	gss_trust_dns;		/* Trust DNS for GSS canonicalization */
51
	int	gss_renewal_rekey;	/* Credential renewal forces rekey */
52
	char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
53
	char    *gss_server_identity;   /* GSSAPI target principal */
49
	int     password_authentication;	/* Try password
54
	int     password_authentication;	/* Try password
50
						 * authentication. */
55
						 * authentication. */
51
	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
56
	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
(-)b/servconf.c (-1 / +27 lines)
Lines 117-124 initialize_server_options(ServerOptions *options) Link Here
117
	options->kerberos_ticket_cleanup = -1;
117
	options->kerberos_ticket_cleanup = -1;
118
	options->kerberos_get_afs_token = -1;
118
	options->kerberos_get_afs_token = -1;
119
	options->gss_authentication=-1;
119
	options->gss_authentication=-1;
120
	options->gss_keyex = -1;
120
	options->gss_cleanup_creds = -1;
121
	options->gss_cleanup_creds = -1;
121
	options->gss_strict_acceptor = -1;
122
	options->gss_strict_acceptor = -1;
123
	options->gss_store_rekey = -1;
122
	options->password_authentication = -1;
124
	options->password_authentication = -1;
123
	options->kbd_interactive_authentication = -1;
125
	options->kbd_interactive_authentication = -1;
124
	options->challenge_response_authentication = -1;
126
	options->challenge_response_authentication = -1;
Lines 275-284 fill_default_server_options(ServerOptions *options) Link Here
275
		options->kerberos_get_afs_token = 0;
277
		options->kerberos_get_afs_token = 0;
276
	if (options->gss_authentication == -1)
278
	if (options->gss_authentication == -1)
277
		options->gss_authentication = 0;
279
		options->gss_authentication = 0;
280
	if (options->gss_keyex == -1)
281
		options->gss_keyex = 0;
278
	if (options->gss_cleanup_creds == -1)
282
	if (options->gss_cleanup_creds == -1)
279
		options->gss_cleanup_creds = 1;
283
		options->gss_cleanup_creds = 1;
280
	if (options->gss_strict_acceptor == -1)
284
	if (options->gss_strict_acceptor == -1)
281
		options->gss_strict_acceptor = 0;
285
		options->gss_strict_acceptor = 1;
286
	if (options->gss_store_rekey == -1)
287
		options->gss_store_rekey = 0;
282
	if (options->password_authentication == -1)
288
	if (options->password_authentication == -1)
283
		options->password_authentication = 1;
289
		options->password_authentication = 1;
284
	if (options->kbd_interactive_authentication == -1)
290
	if (options->kbd_interactive_authentication == -1)
Lines 412-417 typedef enum { Link Here
412
	sHostKeyAlgorithms,
418
	sHostKeyAlgorithms,
413
	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
419
	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
414
	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
420
	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
421
	sGssKeyEx, sGssStoreRekey,
415
	sAcceptEnv, sPermitTunnel,
422
	sAcceptEnv, sPermitTunnel,
416
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
423
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
417
	sUsePrivilegeSeparation, sAllowAgentForwarding,
424
	sUsePrivilegeSeparation, sAllowAgentForwarding,
Lines 485-496 static struct { Link Here
485
#ifdef GSSAPI
492
#ifdef GSSAPI
486
	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
493
	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
487
	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
494
	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
495
	{ "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
488
	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
496
	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
497
	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
498
	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
489
#else
499
#else
490
	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
500
	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
491
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
501
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
502
	{ "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
492
	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
503
	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
504
	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
505
	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
493
#endif
506
#endif
507
	{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
508
	{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
494
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
509
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
495
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
510
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
496
	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
511
	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
Lines 1231-1236 process_server_config_line(ServerOptions *options, char *line, Link Here
1231
		intptr = &options->gss_authentication;
1246
		intptr = &options->gss_authentication;
1232
		goto parse_flag;
1247
		goto parse_flag;
1233
1248
1249
	case sGssKeyEx:
1250
		intptr = &options->gss_keyex;
1251
		goto parse_flag;
1252
1234
	case sGssCleanupCreds:
1253
	case sGssCleanupCreds:
1235
		intptr = &options->gss_cleanup_creds;
1254
		intptr = &options->gss_cleanup_creds;
1236
		goto parse_flag;
1255
		goto parse_flag;
Lines 1239-1244 process_server_config_line(ServerOptions *options, char *line, Link Here
1239
		intptr = &options->gss_strict_acceptor;
1258
		intptr = &options->gss_strict_acceptor;
1240
		goto parse_flag;
1259
		goto parse_flag;
1241
1260
1261
	case sGssStoreRekey:
1262
		intptr = &options->gss_store_rekey;
1263
		goto parse_flag;
1264
1242
	case sPasswordAuthentication:
1265
	case sPasswordAuthentication:
1243
		intptr = &options->password_authentication;
1266
		intptr = &options->password_authentication;
1244
		goto parse_flag;
1267
		goto parse_flag;
Lines 2246-2252 dump_config(ServerOptions *o) Link Here
2246
#endif
2269
#endif
2247
#ifdef GSSAPI
2270
#ifdef GSSAPI
2248
	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2271
	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2272
	dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
2249
	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
2273
	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
2274
	dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
2275
	dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
2250
#endif
2276
#endif
2251
	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2277
	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2252
	dump_cfg_fmtint(sKbdInteractiveAuthentication,
2278
	dump_cfg_fmtint(sKbdInteractiveAuthentication,
(-)b/servconf.h (+2 lines)
Lines 118-125 typedef struct { Link Here
118
	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
118
	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
119
						 * authenticated with Kerberos. */
119
						 * authenticated with Kerberos. */
120
	int     gss_authentication;	/* If true, permit GSSAPI authentication */
120
	int     gss_authentication;	/* If true, permit GSSAPI authentication */
121
	int     gss_keyex;		/* If true, permit GSSAPI key exchange */
121
	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
122
	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
122
	int     gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */
123
	int     gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */
124
	int 	gss_store_rekey;
123
	int     password_authentication;	/* If true, permit password
125
	int     password_authentication;	/* If true, permit password
124
						 * authentication. */
126
						 * authentication. */
125
	int     kbd_interactive_authentication;	/* If true, permit */
127
	int     kbd_interactive_authentication;	/* If true, permit */
(-)b/ssh-gss.h (-4 / +37 lines)
Lines 1-6 Link Here
1
/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */
1
/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */
2
/*
2
/*
3
 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
3
 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
Lines 61-70 Link Here
61
61
62
#define SSH_GSS_OIDTYPE 0x06
62
#define SSH_GSS_OIDTYPE 0x06
63
63
64
#define SSH2_MSG_KEXGSS_INIT                            30
65
#define SSH2_MSG_KEXGSS_CONTINUE                        31
66
#define SSH2_MSG_KEXGSS_COMPLETE                        32
67
#define SSH2_MSG_KEXGSS_HOSTKEY                         33
68
#define SSH2_MSG_KEXGSS_ERROR                           34
69
#define SSH2_MSG_KEXGSS_GROUPREQ			40
70
#define SSH2_MSG_KEXGSS_GROUP				41
71
#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"
72
#define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"
73
#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"
74
64
typedef struct {
75
typedef struct {
65
	char *filename;
76
	char *filename;
66
	char *envvar;
77
	char *envvar;
67
	char *envval;
78
	char *envval;
79
	struct passwd *owner;
68
	void *data;
80
	void *data;
69
} ssh_gssapi_ccache;
81
} ssh_gssapi_ccache;
70
82
Lines 72-79 typedef struct { Link Here
72
	gss_buffer_desc displayname;
84
	gss_buffer_desc displayname;
73
	gss_buffer_desc exportedname;
85
	gss_buffer_desc exportedname;
74
	gss_cred_id_t creds;
86
	gss_cred_id_t creds;
87
	gss_name_t name;
75
	struct ssh_gssapi_mech_struct *mech;
88
	struct ssh_gssapi_mech_struct *mech;
76
	ssh_gssapi_ccache store;
89
	ssh_gssapi_ccache store;
90
	int used;
91
	int updated;
77
} ssh_gssapi_client;
92
} ssh_gssapi_client;
78
93
79
typedef struct ssh_gssapi_mech_struct {
94
typedef struct ssh_gssapi_mech_struct {
Lines 84-89 typedef struct ssh_gssapi_mech_struct { Link Here
84
	int (*userok) (ssh_gssapi_client *, char *);
99
	int (*userok) (ssh_gssapi_client *, char *);
85
	int (*localname) (ssh_gssapi_client *, char **);
100
	int (*localname) (ssh_gssapi_client *, char **);
86
	void (*storecreds) (ssh_gssapi_client *);
101
	void (*storecreds) (ssh_gssapi_client *);
102
	int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
87
} ssh_gssapi_mech;
103
} ssh_gssapi_mech;
88
104
89
typedef struct {
105
typedef struct {
Lines 94-103 typedef struct { Link Here
94
	gss_OID		oid; /* client */
110
	gss_OID		oid; /* client */
95
	gss_cred_id_t	creds; /* server */
111
	gss_cred_id_t	creds; /* server */
96
	gss_name_t	client; /* server */
112
	gss_name_t	client; /* server */
97
	gss_cred_id_t	client_creds; /* server */
113
	gss_cred_id_t	client_creds; /* both */
98
} Gssctxt;
114
} Gssctxt;
99
115
100
extern ssh_gssapi_mech *supported_mechs[];
116
extern ssh_gssapi_mech *supported_mechs[];
117
extern Gssctxt *gss_kex_context;
101
118
102
int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
119
int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
103
void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
120
void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
Lines 119-134 void ssh_gssapi_build_ctx(Gssctxt **); Link Here
119
void ssh_gssapi_delete_ctx(Gssctxt **);
136
void ssh_gssapi_delete_ctx(Gssctxt **);
120
OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
137
OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
121
void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
138
void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
122
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
139
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
140
OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
141
int ssh_gssapi_credentials_updated(Gssctxt *);
123
142
124
/* In the server */
143
/* In the server */
144
typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
145
    const char *);
146
char *ssh_gssapi_client_mechanisms(const char *, const char *);
147
char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
148
    const char *);
149
gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
150
int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
151
    const char *);
125
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
152
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
126
int ssh_gssapi_userok(char *name);
153
int ssh_gssapi_userok(char *name, struct passwd *);
127
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
154
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
128
void ssh_gssapi_do_child(char ***, u_int *);
155
void ssh_gssapi_do_child(char ***, u_int *);
129
void ssh_gssapi_cleanup_creds(void);
156
void ssh_gssapi_cleanup_creds(void);
130
void ssh_gssapi_storecreds(void);
157
void ssh_gssapi_storecreds(void);
131
158
159
char *ssh_gssapi_server_mechanisms(void);
160
int ssh_gssapi_oid_table_ok(void);
161
162
int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
163
void ssh_gssapi_rekey_creds(void);
164
132
#endif /* GSSAPI */
165
#endif /* GSSAPI */
133
166
134
#endif /* _SSH_GSS_H */
167
#endif /* _SSH_GSS_H */
(-)b/ssh_config (+2 lines)
Lines 26-31 Link Here
26
#   HostbasedAuthentication no
26
#   HostbasedAuthentication no
27
#   GSSAPIAuthentication no
27
#   GSSAPIAuthentication no
28
#   GSSAPIDelegateCredentials no
28
#   GSSAPIDelegateCredentials no
29
#   GSSAPIKeyExchange no
30
#   GSSAPITrustDNS no
29
#   BatchMode no
31
#   BatchMode no
30
#   CheckHostIP yes
32
#   CheckHostIP yes
31
#   AddressFamily any
33
#   AddressFamily any
(-)b/ssh_config.5 (-1 / +35 lines)
Lines 749-759 Specifies whether user authentication based on GSSAPI is allowed. Link Here
749
The default is
749
The default is
750
.Dq no .
750
.Dq no .
751
Note that this option applies to protocol version 2 only.
751
Note that this option applies to protocol version 2 only.
752
.It Cm GSSAPIKeyExchange
753
Specifies whether key exchange based on GSSAPI may be used. When using
754
GSSAPI key exchange the server need not have a host key.
755
The default is
756
.Dq no .
757
Note that this option applies to protocol version 2 only.
758
.It Cm GSSAPIClientIdentity
759
If set, specifies the GSSAPI client identity that ssh should use when 
760
connecting to the server. The default is unset, which means that the default 
761
identity will be used.
762
.It Cm GSSAPIServerIdentity
763
If set, specifies the GSSAPI server identity that ssh should expect when 
764
connecting to the server. The default is unset, which means that the
765
expected GSSAPI server identity will be determined from the target
766
hostname.
752
.It Cm GSSAPIDelegateCredentials
767
.It Cm GSSAPIDelegateCredentials
753
Forward (delegate) credentials to the server.
768
Forward (delegate) credentials to the server.
754
The default is
769
The default is
755
.Dq no .
770
.Dq no .
756
Note that this option applies to protocol version 2 only.
771
Note that this option applies to protocol version 2 connections using GSSAPI.
772
.It Cm GSSAPIRenewalForcesRekey
773
If set to 
774
.Dq yes
775
then renewal of the client's GSSAPI credentials will force the rekeying of the
776
ssh connection. With a compatible server, this can delegate the renewed 
777
credentials to a session on the server.
778
The default is
779
.Dq no .
780
.It Cm GSSAPITrustDns
781
Set to 
782
.Dq yes
783
to indicate that the DNS is trusted to securely canonicalize
784
the name of the host being connected to. If 
785
.Dq no ,
786
the hostname entered on the
787
command line will be passed untouched to the GSSAPI library.
788
The default is
789
.Dq no .
790
This option only applies to protocol version 2 connections using GSSAPI.
757
.It Cm HashKnownHosts
791
.It Cm HashKnownHosts
758
Indicates that
792
Indicates that
759
.Xr ssh 1
793
.Xr ssh 1
(-)b/sshconnect2.c (-4 / +116 lines)
Lines 160-165 ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) Link Here
160
	struct kex *kex;
160
	struct kex *kex;
161
	int r;
161
	int r;
162
162
163
#ifdef GSSAPI
164
	char *orig = NULL, *gss = NULL;
165
	char *gss_host = NULL;
166
#endif
167
163
	xxx_host = host;
168
	xxx_host = host;
164
	xxx_hostaddr = hostaddr;
169
	xxx_hostaddr = hostaddr;
165
170
Lines 193-198 ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) Link Here
193
		    order_hostkeyalgs(host, hostaddr, port));
198
		    order_hostkeyalgs(host, hostaddr, port));
194
	}
199
	}
195
200
201
#ifdef GSSAPI
202
	if (options.gss_keyex) {
203
		/* Add the GSSAPI mechanisms currently supported on this
204
		 * client to the key exchange algorithm proposal */
205
		orig = myproposal[PROPOSAL_KEX_ALGS];
206
207
		if (options.gss_trust_dns)
208
			gss_host = (char *)get_canonical_hostname(1);
209
		else
210
			gss_host = host;
211
212
		gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
213
		if (gss) {
214
			debug("Offering GSSAPI proposal: %s", gss);
215
			xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
216
			    "%s,%s", gss, orig);
217
218
			/* If we've got GSSAPI algorithms, then we also
219
			 * support the 'null' hostkey, as a last resort */
220
			orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
221
			xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
222
			    "%s,null", orig);
223
			free(gss);
224
		}
225
	}
226
#endif
227
196
	if (options.rekey_limit || options.rekey_interval)
228
	if (options.rekey_limit || options.rekey_interval)
197
		packet_set_rekey_limits((u_int32_t)options.rekey_limit,
229
		packet_set_rekey_limits((u_int32_t)options.rekey_limit,
198
		    (time_t)options.rekey_interval);
230
		    (time_t)options.rekey_interval);
Lines 211-220 ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) Link Here
211
# endif
243
# endif
212
#endif
244
#endif
213
	kex->kex[KEX_C25519_SHA256] = kexc25519_client;
245
	kex->kex[KEX_C25519_SHA256] = kexc25519_client;
246
#ifdef GSSAPI
247
	if (options.gss_keyex) {
248
		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
249
		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
250
		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
251
	}
252
#endif
214
	kex->client_version_string=client_version_string;
253
	kex->client_version_string=client_version_string;
215
	kex->server_version_string=server_version_string;
254
	kex->server_version_string=server_version_string;
216
	kex->verify_host_key=&verify_host_key_callback;
255
	kex->verify_host_key=&verify_host_key_callback;
217
256
257
#ifdef GSSAPI
258
	if (options.gss_keyex) {
259
		kex->gss_deleg_creds = options.gss_deleg_creds;
260
		kex->gss_trust_dns = options.gss_trust_dns;
261
		kex->gss_client = options.gss_client_identity;
262
		if (options.gss_server_identity) {
263
			kex->gss_host = options.gss_server_identity;
264
		} else {
265
			kex->gss_host = gss_host;
266
        }
267
	}
268
#endif
269
218
	dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
270
	dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
219
271
220
	if (options.use_roaming && !kex->roaming) {
272
	if (options.use_roaming && !kex->roaming) {
Lines 306-311 int input_gssapi_token(int type, u_int32_t, void *); Link Here
306
int	input_gssapi_hash(int type, u_int32_t, void *);
358
int	input_gssapi_hash(int type, u_int32_t, void *);
307
int	input_gssapi_error(int, u_int32_t, void *);
359
int	input_gssapi_error(int, u_int32_t, void *);
308
int	input_gssapi_errtok(int, u_int32_t, void *);
360
int	input_gssapi_errtok(int, u_int32_t, void *);
361
int	userauth_gsskeyex(Authctxt *authctxt);
309
#endif
362
#endif
310
363
311
void	userauth(Authctxt *, char *);
364
void	userauth(Authctxt *, char *);
Lines 321-326 static char *authmethods_get(void); Link Here
321
374
322
Authmethod authmethods[] = {
375
Authmethod authmethods[] = {
323
#ifdef GSSAPI
376
#ifdef GSSAPI
377
	{"gssapi-keyex",
378
		userauth_gsskeyex,
379
		NULL,
380
		&options.gss_authentication,
381
		NULL},
324
	{"gssapi-with-mic",
382
	{"gssapi-with-mic",
325
		userauth_gssapi,
383
		userauth_gssapi,
326
		NULL,
384
		NULL,
Lines 627-645 userauth_gssapi(Authctxt *authctxt) Link Here
627
	static u_int mech = 0;
685
	static u_int mech = 0;
628
	OM_uint32 min;
686
	OM_uint32 min;
629
	int ok = 0;
687
	int ok = 0;
688
	const char *gss_host;
689
690
	if (options.gss_server_identity)
691
		gss_host = options.gss_server_identity;
692
	else if (options.gss_trust_dns)
693
		gss_host = get_canonical_hostname(1);
694
	else
695
		gss_host = authctxt->host;
630
696
631
	/* Try one GSSAPI method at a time, rather than sending them all at
697
	/* Try one GSSAPI method at a time, rather than sending them all at
632
	 * once. */
698
	 * once. */
633
699
634
	if (gss_supported == NULL)
700
	if (gss_supported == NULL)
635
		gss_indicate_mechs(&min, &gss_supported);
701
		if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
702
			gss_supported = NULL;
703
			return 0;
704
		}
636
705
637
	/* Check to see if the mechanism is usable before we offer it */
706
	/* Check to see if the mechanism is usable before we offer it */
638
	while (mech < gss_supported->count && !ok) {
707
	while (mech < gss_supported->count && !ok) {
639
		/* My DER encoding requires length<128 */
708
		/* My DER encoding requires length<128 */
640
		if (gss_supported->elements[mech].length < 128 &&
709
		if (gss_supported->elements[mech].length < 128 &&
641
		    ssh_gssapi_check_mechanism(&gssctxt, 
710
		    ssh_gssapi_check_mechanism(&gssctxt, 
642
		    &gss_supported->elements[mech], authctxt->host)) {
711
		    &gss_supported->elements[mech], gss_host, 
712
                    options.gss_client_identity)) {
643
			ok = 1; /* Mechanism works */
713
			ok = 1; /* Mechanism works */
644
		} else {
714
		} else {
645
			mech++;
715
			mech++;
Lines 736-743 input_gssapi_response(int type, u_int32_t plen, void *ctxt) Link Here
736
{
806
{
737
	Authctxt *authctxt = ctxt;
807
	Authctxt *authctxt = ctxt;
738
	Gssctxt *gssctxt;
808
	Gssctxt *gssctxt;
739
	int oidlen;
809
	u_int oidlen;
740
	char *oidv;
810
	u_char *oidv;
741
811
742
	if (authctxt == NULL)
812
	if (authctxt == NULL)
743
		fatal("input_gssapi_response: no authentication context");
813
		fatal("input_gssapi_response: no authentication context");
Lines 850-855 input_gssapi_error(int type, u_int32_t plen, void *ctxt) Link Here
850
	free(lang);
920
	free(lang);
851
	return 0;
921
	return 0;
852
}
922
}
923
924
int
925
userauth_gsskeyex(Authctxt *authctxt)
926
{
927
	Buffer b;
928
	gss_buffer_desc gssbuf;
929
	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
930
	OM_uint32 ms;
931
932
	static int attempt = 0;
933
	if (attempt++ >= 1)
934
		return (0);
935
936
	if (gss_kex_context == NULL) {
937
		debug("No valid Key exchange context"); 
938
		return (0);
939
	}
940
941
	ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
942
	    "gssapi-keyex");
943
944
	gssbuf.value = buffer_ptr(&b);
945
	gssbuf.length = buffer_len(&b);
946
947
	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
948
		buffer_free(&b);
949
		return (0);
950
	}
951
952
	packet_start(SSH2_MSG_USERAUTH_REQUEST);
953
	packet_put_cstring(authctxt->server_user);
954
	packet_put_cstring(authctxt->service);
955
	packet_put_cstring(authctxt->method->name);
956
	packet_put_string(mic.value, mic.length);
957
	packet_send();
958
959
	buffer_free(&b);
960
	gss_release_buffer(&ms, &mic);
961
962
	return (1);
963
}
964
853
#endif /* GSSAPI */
965
#endif /* GSSAPI */
854
966
855
int
967
int
(-)b/sshd.c (+110 lines)
Lines 126-131 Link Here
126
#include "version.h"
126
#include "version.h"
127
#include "ssherr.h"
127
#include "ssherr.h"
128
128
129
#ifdef USE_SECURITY_SESSION_API
130
#include <Security/AuthSession.h>
131
#endif
132
129
#ifndef O_NOCTTY
133
#ifndef O_NOCTTY
130
#define O_NOCTTY	0
134
#define O_NOCTTY	0
131
#endif
135
#endif
Lines 1833-1842 main(int ac, char **av) Link Here
1833
		logit("Disabling protocol version 1. Could not load host key");
1837
		logit("Disabling protocol version 1. Could not load host key");
1834
		options.protocol &= ~SSH_PROTO_1;
1838
		options.protocol &= ~SSH_PROTO_1;
1835
	}
1839
	}
1840
#ifndef GSSAPI
1841
	/* The GSSAPI key exchange can run without a host key */
1836
	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
1842
	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
1837
		logit("Disabling protocol version 2. Could not load host key");
1843
		logit("Disabling protocol version 2. Could not load host key");
1838
		options.protocol &= ~SSH_PROTO_2;
1844
		options.protocol &= ~SSH_PROTO_2;
1839
	}
1845
	}
1846
#endif
1840
	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
1847
	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
1841
		logit("sshd: no hostkeys available -- exiting.");
1848
		logit("sshd: no hostkeys available -- exiting.");
1842
		exit(1);
1849
		exit(1);
Lines 2151-2156 main(int ac, char **av) Link Here
2151
	    remote_ip, remote_port, laddr,  get_local_port());
2158
	    remote_ip, remote_port, laddr,  get_local_port());
2152
	free(laddr);
2159
	free(laddr);
2153
2160
2161
#ifdef USE_SECURITY_SESSION_API
2162
	/*
2163
	 * Create a new security session for use by the new user login if
2164
	 * the current session is the root session or we are not launched
2165
	 * by inetd (eg: debugging mode or server mode).  We do not
2166
	 * necessarily need to create a session if we are launched from
2167
	 * inetd because Panther xinetd will create a session for us.
2168
	 *
2169
	 * The only case where this logic will fail is if there is an
2170
	 * inetd running in a non-root session which is not creating
2171
	 * new sessions for us.  Then all the users will end up in the
2172
	 * same session (bad).
2173
	 *
2174
	 * When the client exits, the session will be destroyed for us
2175
	 * automatically.
2176
	 *
2177
	 * We must create the session before any credentials are stored
2178
	 * (including AFS pags, which happens a few lines below).
2179
	 */
2180
	{
2181
		OSStatus err = 0;
2182
		SecuritySessionId sid = 0;
2183
		SessionAttributeBits sattrs = 0;
2184
2185
		err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
2186
		if (err)
2187
			error("SessionGetInfo() failed with error %.8X",
2188
			    (unsigned) err);
2189
		else
2190
			debug("Current Session ID is %.8X / Session Attributes are %.8X",
2191
			    (unsigned) sid, (unsigned) sattrs);
2192
2193
		if (inetd_flag && !(sattrs & sessionIsRoot))
2194
			debug("Running in inetd mode in a non-root session... "
2195
			    "assuming inetd created the session for us.");
2196
		else {
2197
			debug("Creating new security session...");
2198
			err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
2199
			if (err)
2200
				error("SessionCreate() failed with error %.8X",
2201
				    (unsigned) err);
2202
2203
			err = SessionGetInfo(callerSecuritySession, &sid, 
2204
			    &sattrs);
2205
			if (err)
2206
				error("SessionGetInfo() failed with error %.8X",
2207
				    (unsigned) err);
2208
			else
2209
				debug("New Session ID is %.8X / Session Attributes are %.8X",
2210
				    (unsigned) sid, (unsigned) sattrs);
2211
		}
2212
	}
2213
#endif
2214
2154
	/*
2215
	/*
2155
	 * We don't want to listen forever unless the other side
2216
	 * We don't want to listen forever unless the other side
2156
	 * successfully authenticates itself.  So we set up an alarm which is
2217
	 * successfully authenticates itself.  So we set up an alarm which is
Lines 2569-2574 do_ssh2_kex(void) Link Here
2569
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
2630
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
2570
	    list_hostkey_types());
2631
	    list_hostkey_types());
2571
2632
2633
#ifdef GSSAPI
2634
	{
2635
	char *orig;
2636
	char *gss = NULL;
2637
	char *newstr = NULL;
2638
	orig = myproposal[PROPOSAL_KEX_ALGS];
2639
2640
	/* 
2641
	 * If we don't have a host key, then there's no point advertising
2642
	 * the other key exchange algorithms
2643
	 */
2644
2645
	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
2646
		orig = NULL;
2647
2648
	if (options.gss_keyex)
2649
		gss = ssh_gssapi_server_mechanisms();
2650
	else
2651
		gss = NULL;
2652
2653
	if (gss && orig)
2654
		xasprintf(&newstr, "%s,%s", gss, orig);
2655
	else if (gss)
2656
		newstr = gss;
2657
	else if (orig)
2658
		newstr = orig;
2659
2660
	/* 
2661
	 * If we've got GSSAPI mechanisms, then we've got the 'null' host
2662
	 * key alg, but we can't tell people about it unless its the only
2663
  	 * host key algorithm we support
2664
	 */
2665
	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
2666
		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
2667
2668
	if (newstr)
2669
		myproposal[PROPOSAL_KEX_ALGS] = newstr;
2670
	else
2671
		fatal("No supported key exchange algorithms");
2672
	}
2673
#endif
2674
2572
	/* start key exchange */
2675
	/* start key exchange */
2573
	if ((r = kex_setup(active_state, myproposal)) != 0)
2676
	if ((r = kex_setup(active_state, myproposal)) != 0)
2574
		fatal("kex_setup: %s", ssh_err(r));
2677
		fatal("kex_setup: %s", ssh_err(r));
Lines 2583-2588 do_ssh2_kex(void) Link Here
2583
# endif
2686
# endif
2584
#endif
2687
#endif
2585
	kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2688
	kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2689
#ifdef GSSAPI
2690
	if (options.gss_keyex) {
2691
		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
2692
		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
2693
		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
2694
	}
2695
#endif
2586
	kex->server = 1;
2696
	kex->server = 1;
2587
	kex->client_version_string=client_version_string;
2697
	kex->client_version_string=client_version_string;
2588
	kex->server_version_string=server_version_string;
2698
	kex->server_version_string=server_version_string;
(-)b/sshd_config (+2 lines)
Lines 84-89 AuthorizedKeysFile .ssh/authorized_keys Link Here
84
# GSSAPI options
84
# GSSAPI options
85
#GSSAPIAuthentication no
85
#GSSAPIAuthentication no
86
#GSSAPICleanupCredentials yes
86
#GSSAPICleanupCredentials yes
87
#GSSAPIStrictAcceptorCheck yes
88
#GSSAPIKeyExchange no
87
89
88
# Set this to 'yes' to enable PAM authentication, account processing,
90
# Set this to 'yes' to enable PAM authentication, account processing,
89
# and session processing. If this is enabled, PAM authentication will
91
# and session processing. If this is enabled, PAM authentication will
(-)b/sshd_config.5 (+11 lines)
Lines 621-626 Specifies whether user authentication based on GSSAPI is allowed. Link Here
621
The default is
621
The default is
622
.Dq no .
622
.Dq no .
623
Note that this option applies to protocol version 2 only.
623
Note that this option applies to protocol version 2 only.
624
.It Cm GSSAPIKeyExchange
625
Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
626
doesn't rely on ssh keys to verify host identity.
627
The default is
628
.Dq no .
629
Note that this option applies to protocol version 2 only.
624
.It Cm GSSAPICleanupCredentials
630
.It Cm GSSAPICleanupCredentials
625
Specifies whether to automatically destroy the user's credentials cache
631
Specifies whether to automatically destroy the user's credentials cache
626
on logout.
632
on logout.
Lines 642-647 machine's default store. Link Here
642
This facility is provided to assist with operation on multi homed machines.
648
This facility is provided to assist with operation on multi homed machines.
643
The default is
649
The default is
644
.Dq yes .
650
.Dq yes .
651
.It Cm GSSAPIStoreCredentialsOnRekey
652
Controls whether the user's GSSAPI credentials should be updated following a 
653
successful connection rekeying. This option can be used to accepted renewed 
654
or updated credentials from a compatible client. The default is
655
.Dq no .
645
.It Cm HostbasedAcceptedKeyTypes
656
.It Cm HostbasedAcceptedKeyTypes
646
Specifies the key types that will be accepted for hostbased authentication
657
Specifies the key types that will be accepted for hostbased authentication
647
as a comma-separated pattern list.
658
as a comma-separated pattern list.
(-)b/sshkey.c (-1 / +2 lines)
Lines 112-117 static const struct keytype keytypes[] = { Link Here
112
#  endif /* OPENSSL_HAS_NISTP521 */
112
#  endif /* OPENSSL_HAS_NISTP521 */
113
# endif /* OPENSSL_HAS_ECC */
113
# endif /* OPENSSL_HAS_ECC */
114
#endif /* WITH_OPENSSL */
114
#endif /* WITH_OPENSSL */
115
	{ "null", "null", KEY_NULL, 0, 0 },
115
	{ NULL, NULL, -1, -1, 0 }
116
	{ NULL, NULL, -1, -1, 0 }
116
};
117
};
117
118
Lines 200-206 key_alg_list(int certs_only, int plain_only) Link Here
200
	const struct keytype *kt;
201
	const struct keytype *kt;
201
202
202
	for (kt = keytypes; kt->type != -1; kt++) {
203
	for (kt = keytypes; kt->type != -1; kt++) {
203
		if (kt->name == NULL)
204
		if (kt->name == NULL || kt->type == KEY_NULL)
204
			continue;
205
			continue;
205
		if ((certs_only && !kt->cert) || (plain_only && kt->cert))
206
		if ((certs_only && !kt->cert) || (plain_only && kt->cert))
206
			continue;
207
			continue;
(-)b/sshkey.h (+1 lines)
Lines 62-67 enum sshkey_types { Link Here
62
	KEY_DSA_CERT,
62
	KEY_DSA_CERT,
63
	KEY_ECDSA_CERT,
63
	KEY_ECDSA_CERT,
64
	KEY_ED25519_CERT,
64
	KEY_ED25519_CERT,
65
	KEY_NULL,
65
	KEY_UNSPEC
66
	KEY_UNSPEC
66
};
67
};
67
68

Return to bug 206346