Ticket #27250: 0001-GSS-key-exchange-patch.patch
File 0001-GSS-key-exchange-patch.patch, 90.0 KB (added by lassi.tuura@…, 13 years ago) |
---|
-
new file ChangeLog.gssapi
From 29169b27afb10a3743bfd272c990503f6559637b Mon Sep 17 00:00:00 2001 From: Lassi Tuura <lat@cern.ch> Date: Wed, 21 Sep 2011 19:35:20 +0200 Subject: [PATCH 1/2] GSS key exchange patch. --- ChangeLog.gssapi | 113 ++++++++++++++++++ Makefile.in | 3 +- auth-krb5.c | 17 +++- auth2-gss.c | 48 ++++++++- auth2.c | 2 + clientloop.c | 13 ++ configure.ac | 24 ++++ gss-genr.c | 276 ++++++++++++++++++++++++++++++++++++++++++++- gss-serv-krb5.c | 84 +++++++++++++- gss-serv.c | 220 +++++++++++++++++++++++++++++++----- kex.c | 18 +++ kex.h | 14 +++ kexgssc.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ kexgsss.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++ key.c | 4 + key.h | 1 + monitor.c | 108 +++++++++++++++++- monitor.h | 2 + monitor_wrap.c | 47 ++++++++- monitor_wrap.h | 4 +- readconf.c | 42 +++++++ readconf.h | 5 + servconf.c | 38 ++++++- servconf.h | 3 + ssh-gss.h | 39 ++++++- ssh_config | 2 + ssh_config.5 | 34 ++++++- sshconnect2.c | 124 +++++++++++++++++++- sshd.c | 110 ++++++++++++++++++ sshd_config | 2 + sshd_config.5 | 28 +++++ 31 files changed, 1990 insertions(+), 57 deletions(-) create mode 100644 ChangeLog.gssapi create mode 100644 kexgssc.c create mode 100644 kexgsss.c diff --git a/ChangeLog.gssapi b/ChangeLog.gssapi new file mode 100644 index 0000000..f117a33
- + 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> -
Makefile.in
diff --git a/Makefile.in b/Makefile.in index 3be3aa6..e479a44 100644
a b LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 70 70 atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ 71 71 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ 72 72 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ 73 kexgssc.o \ 73 74 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \ 74 75 schnorr.o ssh-pkcs11.o 75 76 … … SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ 86 87 auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ 87 88 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ 88 89 auth-krb5.o \ 89 auth2-gss.o gss-serv.o gss-serv-krb5.o \90 auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ 90 91 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ 91 92 sftp-server.o sftp-common.o \ 92 93 roaming_common.o roaming_serv.o \ -
auth-krb5.c
diff --git a/auth-krb5.c b/auth-krb5.c index d019fe2..8219133 100644
a b auth_krb5_password(Authctxt *authctxt, const char *password) 170 170 171 171 len = strlen(authctxt->krb5_ticket_file) + 6; 172 172 authctxt->krb5_ccname = xmalloc(len); 173 #ifdef USE_CCAPI 174 snprintf(authctxt->krb5_ccname, len, "API:%s", 175 authctxt->krb5_ticket_file); 176 #else 173 177 snprintf(authctxt->krb5_ccname, len, "FILE:%s", 174 178 authctxt->krb5_ticket_file); 179 #endif 175 180 176 181 #ifdef USE_PAM 177 182 if (options.use_pam) … … krb5_cleanup_proc(Authctxt *authctxt) 226 231 #ifndef HEIMDAL 227 232 krb5_error_code 228 233 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { 229 int tmpfd,ret;234 int ret; 230 235 char ccname[40]; 231 236 mode_t old_umask; 237 #ifdef USE_CCAPI 238 char cctemplate[] = "API:krb5cc_%d"; 239 #else 240 char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; 241 int tmpfd; 242 #endif 232 243 233 244 ret = snprintf(ccname, sizeof(ccname), 234 "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());245 cctemplate, geteuid()); 235 246 if (ret < 0 || (size_t)ret >= sizeof(ccname)) 236 247 return ENOMEM; 237 248 249 #ifndef USE_CCAPI 238 250 old_umask = umask(0177); 239 251 tmpfd = mkstemp(ccname + strlen("FILE:")); 240 252 umask(old_umask); … … ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { 249 261 return errno; 250 262 } 251 263 close(tmpfd); 264 #endif 252 265 253 266 return (krb5_cc_resolve(ctx, ccname, ccache)); 254 267 } -
auth2-gss.c
diff --git a/auth2-gss.c b/auth2-gss.c index 0d59b21..7dc87db 100644
a b 1 1 /* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */ 2 2 3 3 /* 4 * Copyright (c) 2001-200 3Simon Wilkinson. All rights reserved.4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. 5 5 * 6 6 * Redistribution and use in source and binary forms, with or without 7 7 * modification, are permitted provided that the following conditions … … static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); 52 52 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); 53 53 static void input_gssapi_errtok(int, u_int32_t, void *); 54 54 55 /* 56 * The 'gssapi_keyex' userauth mechanism. 57 */ 58 static int 59 userauth_gsskeyex(Authctxt *authctxt) 60 { 61 int authenticated = 0; 62 Buffer b; 63 gss_buffer_desc mic, gssbuf; 64 u_int len; 65 66 mic.value = packet_get_string(&len); 67 mic.length = len; 68 69 packet_check_eom(); 70 71 ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, 72 "gssapi-keyex"); 73 74 gssbuf.value = buffer_ptr(&b); 75 gssbuf.length = buffer_len(&b); 76 77 /* gss_kex_context is NULL with privsep, so we can't check it here */ 78 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 79 &gssbuf, &mic)))) 80 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, 81 authctxt->pw)); 82 83 buffer_free(&b); 84 xfree(mic.value); 85 86 return (authenticated); 87 } 88 55 89 /* 56 90 * We only support those mechanisms that we know about (ie ones that we know 57 91 * how to check local user kuserok and the like) … … input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) 244 278 245 279 packet_check_eom(); 246 280 247 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 281 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, 282 authctxt->pw)); 248 283 249 284 authctxt->postponed = 0; 250 285 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); … … input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 279 314 gssbuf.length = buffer_len(&b); 280 315 281 316 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) 282 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 317 authenticated = 318 PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); 283 319 else 284 320 logit("GSSAPI MIC check failed"); 285 321 … … input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 294 330 userauth_finish(authctxt, authenticated, "gssapi-with-mic"); 295 331 } 296 332 333 Authmethod method_gsskeyex = { 334 "gssapi-keyex", 335 userauth_gsskeyex, 336 &options.gss_authentication 337 }; 338 297 339 Authmethod method_gssapi = { 298 340 "gssapi-with-mic", 299 341 userauth_gssapi, -
auth2.c
diff --git a/auth2.c b/auth2.c index c06c95f..f73ac18 100644
a b extern Authmethod method_passwd; 69 69 extern Authmethod method_kbdint; 70 70 extern Authmethod method_hostbased; 71 71 #ifdef GSSAPI 72 extern Authmethod method_gsskeyex; 72 73 extern Authmethod method_gssapi; 73 74 #endif 74 75 #ifdef JPAKE … … Authmethod *authmethods[] = { 79 80 &method_none, 80 81 &method_pubkey, 81 82 #ifdef GSSAPI 83 &method_gsskeyex, 82 84 &method_gssapi, 83 85 #endif 84 86 #ifdef JPAKE -
clientloop.c
diff --git a/clientloop.c b/clientloop.c index c19b01f..17628ef 100644
a b 111 111 #include "msg.h" 112 112 #include "roaming.h" 113 113 114 #ifdef GSSAPI 115 #include "ssh-gss.h" 116 #endif 117 114 118 /* import options */ 115 119 extern Options options; 116 120 … … client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 1508 1512 /* Do channel operations unless rekeying in progress. */ 1509 1513 if (!rekeying) { 1510 1514 channel_after_select(readset, writeset); 1515 1516 #ifdef GSSAPI 1517 if (options.gss_renewal_rekey && 1518 ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { 1519 debug("credentials updated - forcing rekey"); 1520 need_rekeying = 1; 1521 } 1522 #endif 1523 1511 1524 if (need_rekeying || packet_need_rekeying()) { 1512 1525 debug("need rekeying"); 1513 1526 xxx_kex->done = 0; -
configure.ac
diff --git a/configure.ac b/configure.ac index 7a91527..8cc7ce9 100644
a b main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) 515 515 [Use tunnel device compatibility to OpenBSD]) 516 516 AC_DEFINE([SSH_TUN_PREPEND_AF], [1], 517 517 [Prepend the address family to IP tunnel traffic]) 518 AC_MSG_CHECKING(if we have the Security Authorization Session API) 519 AC_TRY_COMPILE([#include <Security/AuthSession.h>], 520 [SessionCreate(0, 0);], 521 [ac_cv_use_security_session_api="yes" 522 AC_DEFINE(USE_SECURITY_SESSION_API, 1, 523 [platform has the Security Authorization Session API]) 524 LIBS="$LIBS -framework Security" 525 AC_MSG_RESULT(yes)], 526 [ac_cv_use_security_session_api="no" 527 AC_MSG_RESULT(no)]) 528 AC_MSG_CHECKING(if we have an in-memory credentials cache) 529 AC_TRY_COMPILE( 530 [#include <Kerberos/Kerberos.h>], 531 [cc_context_t c; 532 (void) cc_initialize (&c, 0, NULL, NULL);], 533 [AC_DEFINE(USE_CCAPI, 1, 534 [platform uses an in-memory credentials cache]) 535 LIBS="$LIBS -framework Security" 536 AC_MSG_RESULT(yes) 537 if test "x$ac_cv_use_security_session_api" = "xno"; then 538 AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) 539 fi], 540 [AC_MSG_RESULT(no)] 541 ) 518 542 m4_pattern_allow([AU_IPv]) 519 543 AC_CHECK_DECL([AU_IPv4], [], 520 544 AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -
gss-genr.c
diff --git a/gss-genr.c b/gss-genr.c index 842f385..f9b39cf 100644
a b 1 1 /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */ 2 2 3 3 /* 4 * Copyright (c) 2001-200 7Simon Wilkinson. All rights reserved.4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 5 5 * 6 6 * Redistribution and use in source and binary forms, with or without 7 7 * modification, are permitted provided that the following conditions … … 39 39 #include "buffer.h" 40 40 #include "log.h" 41 41 #include "ssh2.h" 42 #include "cipher.h" 43 #include "key.h" 44 #include "kex.h" 45 #include <openssl/evp.h> 42 46 43 47 #include "ssh-gss.h" 44 48 45 49 extern u_char *session_id2; 46 50 extern u_int session_id2_len; 47 51 52 typedef struct { 53 char *encoded; 54 gss_OID oid; 55 } ssh_gss_kex_mapping; 56 57 /* 58 * XXX - It would be nice to find a more elegant way of handling the 59 * XXX passing of the key exchange context to the userauth routines 60 */ 61 62 Gssctxt *gss_kex_context = NULL; 63 64 static ssh_gss_kex_mapping *gss_enc2oid = NULL; 65 66 int 67 ssh_gssapi_oid_table_ok() { 68 return (gss_enc2oid != NULL); 69 } 70 71 /* 72 * Return a list of the gss-group1-sha1 mechanisms supported by this program 73 * 74 * We test mechanisms to ensure that we can use them, to avoid starting 75 * a key exchange with a bad mechanism 76 */ 77 78 char * 79 ssh_gssapi_client_mechanisms(const char *host, const char *client) { 80 gss_OID_set gss_supported; 81 OM_uint32 min_status; 82 83 if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) 84 return NULL; 85 86 return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, 87 host, client)); 88 } 89 90 char * 91 ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, 92 const char *host, const char *client) { 93 Buffer buf; 94 size_t i; 95 int oidpos, enclen; 96 char *mechs, *encoded; 97 u_char digest[EVP_MAX_MD_SIZE]; 98 char deroid[2]; 99 const EVP_MD *evp_md = EVP_md5(); 100 EVP_MD_CTX md; 101 102 if (gss_enc2oid != NULL) { 103 for (i = 0; gss_enc2oid[i].encoded != NULL; i++) 104 xfree(gss_enc2oid[i].encoded); 105 xfree(gss_enc2oid); 106 } 107 108 gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * 109 (gss_supported->count + 1)); 110 111 buffer_init(&buf); 112 113 oidpos = 0; 114 for (i = 0; i < gss_supported->count; i++) { 115 if (gss_supported->elements[i].length < 128 && 116 (*check)(NULL, &(gss_supported->elements[i]), host, client)) { 117 118 deroid[0] = SSH_GSS_OIDTYPE; 119 deroid[1] = gss_supported->elements[i].length; 120 121 EVP_DigestInit(&md, evp_md); 122 EVP_DigestUpdate(&md, deroid, 2); 123 EVP_DigestUpdate(&md, 124 gss_supported->elements[i].elements, 125 gss_supported->elements[i].length); 126 EVP_DigestFinal(&md, digest, NULL); 127 128 encoded = xmalloc(EVP_MD_size(evp_md) * 2); 129 enclen = __b64_ntop(digest, EVP_MD_size(evp_md), 130 encoded, EVP_MD_size(evp_md) * 2); 131 132 if (oidpos != 0) 133 buffer_put_char(&buf, ','); 134 135 buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, 136 sizeof(KEX_GSS_GEX_SHA1_ID) - 1); 137 buffer_append(&buf, encoded, enclen); 138 buffer_put_char(&buf, ','); 139 buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 140 sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); 141 buffer_append(&buf, encoded, enclen); 142 buffer_put_char(&buf, ','); 143 buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, 144 sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); 145 buffer_append(&buf, encoded, enclen); 146 147 gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); 148 gss_enc2oid[oidpos].encoded = encoded; 149 oidpos++; 150 } 151 } 152 gss_enc2oid[oidpos].oid = NULL; 153 gss_enc2oid[oidpos].encoded = NULL; 154 155 buffer_put_char(&buf, '\0'); 156 157 mechs = xmalloc(buffer_len(&buf)); 158 buffer_get(&buf, mechs, buffer_len(&buf)); 159 buffer_free(&buf); 160 161 if (strlen(mechs) == 0) { 162 xfree(mechs); 163 mechs = NULL; 164 } 165 166 return (mechs); 167 } 168 169 gss_OID 170 ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { 171 int i = 0; 172 173 switch (kex_type) { 174 case KEX_GSS_GRP1_SHA1: 175 if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) 176 return GSS_C_NO_OID; 177 name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; 178 break; 179 case KEX_GSS_GRP14_SHA1: 180 if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) 181 return GSS_C_NO_OID; 182 name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; 183 break; 184 case KEX_GSS_GEX_SHA1: 185 if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) 186 return GSS_C_NO_OID; 187 name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; 188 break; 189 default: 190 return GSS_C_NO_OID; 191 } 192 193 while (gss_enc2oid[i].encoded != NULL && 194 strcmp(name, gss_enc2oid[i].encoded) != 0) 195 i++; 196 197 if (gss_enc2oid[i].oid != NULL && ctx != NULL) 198 ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); 199 200 return gss_enc2oid[i].oid; 201 } 202 48 203 /* Check that the OID in a data stream matches that in the context */ 49 204 int 50 205 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) … … ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, 197 352 } 198 353 199 354 ctx->major = gss_init_sec_context(&ctx->minor, 200 GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,355 ctx->client_creds, &ctx->context, ctx->name, ctx->oid, 201 356 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 202 357 0, NULL, recv_tok, NULL, send_tok, flags, NULL); 203 358 … … ssh_gssapi_import_name(Gssctxt *ctx, const char *host) 227 382 } 228 383 229 384 OM_uint32 385 ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) 386 { 387 gss_buffer_desc gssbuf; 388 gss_name_t gssname; 389 OM_uint32 status; 390 gss_OID_set oidset; 391 392 gssbuf.value = (void *) name; 393 gssbuf.length = strlen(gssbuf.value); 394 395 gss_create_empty_oid_set(&status, &oidset); 396 gss_add_oid_set_member(&status, ctx->oid, &oidset); 397 398 ctx->major = gss_import_name(&ctx->minor, &gssbuf, 399 GSS_C_NT_USER_NAME, &gssname); 400 401 if (!ctx->major) 402 ctx->major = gss_acquire_cred(&ctx->minor, 403 gssname, 0, oidset, GSS_C_INITIATE, 404 &ctx->client_creds, NULL, NULL); 405 406 gss_release_name(&status, &gssname); 407 gss_release_oid_set(&status, &oidset); 408 409 if (ctx->major) 410 ssh_gssapi_error(ctx); 411 412 return(ctx->major); 413 } 414 415 OM_uint32 230 416 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 231 417 { 418 if (ctx == NULL) 419 return -1; 420 232 421 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, 233 422 GSS_C_QOP_DEFAULT, buffer, hash))) 234 423 ssh_gssapi_error(ctx); … … ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 236 425 return (ctx->major); 237 426 } 238 427 428 /* Priviledged when used by server */ 429 OM_uint32 430 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 431 { 432 if (ctx == NULL) 433 return -1; 434 435 ctx->major = gss_verify_mic(&ctx->minor, ctx->context, 436 gssbuf, gssmic, NULL); 437 438 return (ctx->major); 439 } 440 239 441 void 240 442 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, 241 443 const char *context) … … ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, 249 451 } 250 452 251 453 int 252 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 454 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 455 const char *client) 253 456 { 254 457 gss_buffer_desc token = GSS_C_EMPTY_BUFFER; 255 458 OM_uint32 major, minor; 256 459 gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; 460 Gssctxt *intctx = NULL; 461 462 if (ctx == NULL) 463 ctx = &intctx; 257 464 258 465 /* RFC 4462 says we MUST NOT do SPNEGO */ 259 466 if (oid->length == spnego_oid.length && … … ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 263 470 ssh_gssapi_build_ctx(ctx); 264 471 ssh_gssapi_set_oid(*ctx, oid); 265 472 major = ssh_gssapi_import_name(*ctx, host); 473 474 if (!GSS_ERROR(major) && client) 475 major = ssh_gssapi_client_identity(*ctx, client); 476 266 477 if (!GSS_ERROR(major)) { 267 478 major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 268 479 NULL); … … ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 272 483 GSS_C_NO_BUFFER); 273 484 } 274 485 275 if (GSS_ERROR(major) )486 if (GSS_ERROR(major) || intctx != NULL) 276 487 ssh_gssapi_delete_ctx(ctx); 277 488 278 489 return (!GSS_ERROR(major)); 279 490 } 280 491 492 int 493 ssh_gssapi_credentials_updated(Gssctxt *ctxt) { 494 static gss_name_t saved_name = GSS_C_NO_NAME; 495 static OM_uint32 saved_lifetime = 0; 496 static gss_OID saved_mech = GSS_C_NO_OID; 497 static gss_name_t name; 498 static OM_uint32 last_call = 0; 499 OM_uint32 lifetime, now, major, minor; 500 int equal; 501 gss_cred_usage_t usage = GSS_C_INITIATE; 502 503 now = time(NULL); 504 505 if (ctxt) { 506 debug("Rekey has happened - updating saved versions"); 507 508 if (saved_name != GSS_C_NO_NAME) 509 gss_release_name(&minor, &saved_name); 510 511 major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 512 &saved_name, &saved_lifetime, NULL, NULL); 513 514 if (!GSS_ERROR(major)) { 515 saved_mech = ctxt->oid; 516 saved_lifetime+= now; 517 } else { 518 /* Handle the error */ 519 } 520 return 0; 521 } 522 523 if (now - last_call < 10) 524 return 0; 525 526 last_call = now; 527 528 if (saved_mech == GSS_C_NO_OID) 529 return 0; 530 531 major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 532 &name, &lifetime, NULL, NULL); 533 if (major == GSS_S_CREDENTIALS_EXPIRED) 534 return 0; 535 else if (GSS_ERROR(major)) 536 return 0; 537 538 major = gss_compare_name(&minor, saved_name, name, &equal); 539 gss_release_name(&minor, &name); 540 if (GSS_ERROR(major)) 541 return 0; 542 543 if (equal && (saved_lifetime < lifetime + now - 10)) 544 return 1; 545 546 return 0; 547 } 548 281 549 #endif /* GSSAPI */ -
gss-serv-krb5.c
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c index 5a625ac..e7170ee 100644
a b 1 1 /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ 2 2 3 3 /* 4 * Copyright (c) 2001-200 3Simon Wilkinson. All rights reserved.4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. 5 5 * 6 6 * Redistribution and use in source and binary forms, with or without 7 7 * modification, are permitted provided that the following conditions … … ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 120 120 krb5_principal princ; 121 121 OM_uint32 maj_status, min_status; 122 122 int len; 123 const char *new_ccname; 123 124 124 125 if (client->creds == NULL) { 125 126 debug("No credentials stored"); … … ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 168 169 return; 169 170 } 170 171 171 client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); 172 new_ccname = krb5_cc_get_name(krb_context, ccache); 173 172 174 client->store.envvar = "KRB5CCNAME"; 173 len = strlen(client->store.filename) + 6; 174 client->store.envval = xmalloc(len); 175 snprintf(client->store.envval, len, "FILE:%s", client->store.filename); 175 #ifdef USE_CCAPI 176 xasprintf(&client->store.envval, "API:%s", new_ccname); 177 client->store.filename = NULL; 178 #else 179 xasprintf(&client->store.envval, "FILE:%s", new_ccname); 180 client->store.filename = xstrdup(new_ccname); 181 #endif 176 182 177 183 #ifdef USE_PAM 178 184 if (options.use_pam) … … ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 184 190 return; 185 191 } 186 192 193 int 194 ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 195 ssh_gssapi_client *client) 196 { 197 krb5_ccache ccache = NULL; 198 krb5_principal principal = NULL; 199 char *name = NULL; 200 krb5_error_code problem; 201 OM_uint32 maj_status, min_status; 202 203 if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { 204 logit("krb5_cc_resolve(): %.100s", 205 krb5_get_err_text(krb_context, problem)); 206 return 0; 207 } 208 209 /* Find out who the principal in this cache is */ 210 if ((problem = krb5_cc_get_principal(krb_context, ccache, 211 &principal))) { 212 logit("krb5_cc_get_principal(): %.100s", 213 krb5_get_err_text(krb_context, problem)); 214 krb5_cc_close(krb_context, ccache); 215 return 0; 216 } 217 218 if ((problem = krb5_unparse_name(krb_context, principal, &name))) { 219 logit("krb5_unparse_name(): %.100s", 220 krb5_get_err_text(krb_context, problem)); 221 krb5_free_principal(krb_context, principal); 222 krb5_cc_close(krb_context, ccache); 223 return 0; 224 } 225 226 227 if (strcmp(name,client->exportedname.value)!=0) { 228 debug("Name in local credentials cache differs. Not storing"); 229 krb5_free_principal(krb_context, principal); 230 krb5_cc_close(krb_context, ccache); 231 krb5_free_unparsed_name(krb_context, name); 232 return 0; 233 } 234 krb5_free_unparsed_name(krb_context, name); 235 236 /* Name matches, so lets get on with it! */ 237 238 if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { 239 logit("krb5_cc_initialize(): %.100s", 240 krb5_get_err_text(krb_context, problem)); 241 krb5_free_principal(krb_context, principal); 242 krb5_cc_close(krb_context, ccache); 243 return 0; 244 } 245 246 krb5_free_principal(krb_context, principal); 247 248 if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, 249 ccache))) { 250 logit("gss_krb5_copy_ccache() failed. Sorry!"); 251 krb5_cc_close(krb_context, ccache); 252 return 0; 253 } 254 255 return 1; 256 } 257 187 258 ssh_gssapi_mech gssapi_kerberos_mech = { 188 259 "toWM5Slw5Ew8Mqkay+al2g==", 189 260 "Kerberos", … … ssh_gssapi_mech gssapi_kerberos_mech = { 191 262 NULL, 192 263 &ssh_gssapi_krb5_userok, 193 264 NULL, 194 &ssh_gssapi_krb5_storecreds 265 &ssh_gssapi_krb5_storecreds, 266 &ssh_gssapi_krb5_updatecreds 195 267 }; 196 268 197 269 #endif /* KRB5 */ -
gss-serv.c
diff --git a/gss-serv.c b/gss-serv.c index c719c13..380895e 100644
a b 1 1 /* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */ 2 2 3 3 /* 4 * Copyright (c) 2001-200 3Simon Wilkinson. All rights reserved.4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 5 5 * 6 6 * Redistribution and use in source and binary forms, with or without 7 7 * modification, are permitted provided that the following conditions … … 45 45 #include "channels.h" 46 46 #include "session.h" 47 47 #include "misc.h" 48 #include "servconf.h" 49 #include "uidswap.h" 48 50 49 51 #include "ssh-gss.h" 52 #include "monitor_wrap.h" 53 54 extern ServerOptions options; 50 55 51 56 static ssh_gssapi_client gssapi_client = 52 57 { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, 53 GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};58 GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; 54 59 55 60 ssh_gssapi_mech gssapi_null_mech = 56 { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL };61 { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; 57 62 58 63 #ifdef KRB5 59 64 extern ssh_gssapi_mech gssapi_kerberos_mech; … … ssh_gssapi_acquire_cred(Gssctxt *ctx) 81 86 char lname[MAXHOSTNAMELEN]; 82 87 gss_OID_set oidset; 83 88 84 gss_create_empty_oid_set(&status, &oidset); 85 gss_add_oid_set_member(&status, ctx->oid, &oidset); 89 if (options.gss_strict_acceptor) { 90 gss_create_empty_oid_set(&status, &oidset); 91 gss_add_oid_set_member(&status, ctx->oid, &oidset); 86 92 87 if (gethostname(lname, MAXHOSTNAMELEN)) { 88 gss_release_oid_set(&status, &oidset); 89 return (-1); 90 } 93 if (gethostname(lname, MAXHOSTNAMELEN)) { 94 gss_release_oid_set(&status, &oidset); 95 return (-1); 96 } 97 98 if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { 99 gss_release_oid_set(&status, &oidset); 100 return (ctx->major); 101 } 102 103 if ((ctx->major = gss_acquire_cred(&ctx->minor, 104 ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, 105 NULL, NULL))) 106 ssh_gssapi_error(ctx); 91 107 92 if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {93 108 gss_release_oid_set(&status, &oidset); 94 109 return (ctx->major); 110 } else { 111 ctx->name = GSS_C_NO_NAME; 112 ctx->creds = GSS_C_NO_CREDENTIAL; 95 113 } 96 97 if ((ctx->major = gss_acquire_cred(&ctx->minor, 98 ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) 99 ssh_gssapi_error(ctx); 100 101 gss_release_oid_set(&status, &oidset); 102 return (ctx->major); 114 return GSS_S_COMPLETE; 103 115 } 104 116 105 117 /* Privileged */ … … ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) 114 126 } 115 127 116 128 /* Unprivileged */ 129 char * 130 ssh_gssapi_server_mechanisms() { 131 gss_OID_set supported; 132 133 ssh_gssapi_supported_oids(&supported); 134 return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, 135 NULL, NULL)); 136 } 137 138 /* Unprivileged */ 139 int 140 ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, 141 const char *dummy) { 142 Gssctxt *ctx = NULL; 143 int res; 144 145 res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); 146 ssh_gssapi_delete_ctx(&ctx); 147 148 return (res); 149 } 150 151 /* Unprivileged */ 117 152 void 118 153 ssh_gssapi_supported_oids(gss_OID_set *oidset) 119 154 { … … ssh_gssapi_supported_oids(gss_OID_set *oidset) 123 158 gss_OID_set supported; 124 159 125 160 gss_create_empty_oid_set(&min_status, oidset); 126 gss_indicate_mechs(&min_status, &supported); 161 162 if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) 163 return; 127 164 128 165 while (supported_mechs[i]->name != NULL) { 129 166 if (GSS_ERROR(gss_test_oid_set_member(&min_status, … … OM_uint32 249 286 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 250 287 { 251 288 int i = 0; 289 int equal = 0; 290 gss_name_t new_name = GSS_C_NO_NAME; 291 gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; 292 293 if (options.gss_store_rekey && client->used && ctx->client_creds) { 294 if (client->mech->oid.length != ctx->oid->length || 295 (memcmp(client->mech->oid.elements, 296 ctx->oid->elements, ctx->oid->length) !=0)) { 297 debug("Rekeyed credentials have different mechanism"); 298 return GSS_S_COMPLETE; 299 } 300 301 if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 302 ctx->client_creds, ctx->oid, &new_name, 303 NULL, NULL, NULL))) { 304 ssh_gssapi_error(ctx); 305 return (ctx->major); 306 } 307 308 ctx->major = gss_compare_name(&ctx->minor, client->name, 309 new_name, &equal); 252 310 253 gss_buffer_desc ename; 311 if (GSS_ERROR(ctx->major)) { 312 ssh_gssapi_error(ctx); 313 return (ctx->major); 314 } 315 316 if (!equal) { 317 debug("Rekeyed credentials have different name"); 318 return GSS_S_COMPLETE; 319 } 320 321 debug("Marking rekeyed credentials for export"); 322 323 gss_release_name(&ctx->minor, &client->name); 324 gss_release_cred(&ctx->minor, &client->creds); 325 client->name = new_name; 326 client->creds = ctx->client_creds; 327 ctx->client_creds = GSS_C_NO_CREDENTIAL; 328 client->updated = 1; 329 return GSS_S_COMPLETE; 330 } 254 331 255 332 client->mech = NULL; 256 333 … … ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 265 342 if (client->mech == NULL) 266 343 return GSS_S_FAILURE; 267 344 345 if (ctx->client_creds && 346 (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 347 ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { 348 ssh_gssapi_error(ctx); 349 return (ctx->major); 350 } 351 268 352 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, 269 353 &client->displayname, NULL))) { 270 354 ssh_gssapi_error(ctx); … … ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 282 366 return (ctx->major); 283 367 } 284 368 369 gss_release_buffer(&ctx->minor, &ename); 370 285 371 /* We can't copy this structure, so we just move the pointer to it */ 286 372 client->creds = ctx->client_creds; 287 373 ctx->client_creds = GSS_C_NO_CREDENTIAL; … … ssh_gssapi_do_child(char ***envp, u_int *envsizep) 329 415 330 416 /* Privileged */ 331 417 int 332 ssh_gssapi_userok(char *user )418 ssh_gssapi_userok(char *user, struct passwd *pw) 333 419 { 334 420 OM_uint32 lmin; 335 421 … … ssh_gssapi_userok(char *user) 339 425 return 0; 340 426 } 341 427 if (gssapi_client.mech && gssapi_client.mech->userok) 342 if ((*gssapi_client.mech->userok)(&gssapi_client, user)) 428 if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { 429 gssapi_client.used = 1; 430 gssapi_client.store.owner = pw; 343 431 return 1; 344 else {432 } else { 345 433 /* Destroy delegated credentials if userok fails */ 346 434 gss_release_buffer(&lmin, &gssapi_client.displayname); 347 435 gss_release_buffer(&lmin, &gssapi_client.exportedname); … … ssh_gssapi_userok(char *user) 354 442 return (0); 355 443 } 356 444 357 /* Privileged */ 358 OM_uint32 359 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 445 /* These bits are only used for rekeying. The unpriviledged child is running 446 * as the user, the monitor is root. 447 * 448 * In the child, we want to : 449 * *) Ask the monitor to store our credentials into the store we specify 450 * *) If it succeeds, maybe do a PAM update 451 */ 452 453 /* Stuff for PAM */ 454 455 #ifdef USE_PAM 456 static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 457 struct pam_response **resp, void *data) 360 458 { 361 ctx->major = gss_verify_mic(&ctx->minor, ctx->context, 362 gssbuf, gssmic, NULL); 459 return (PAM_CONV_ERR); 460 } 461 #endif 363 462 364 return (ctx->major); 463 void 464 ssh_gssapi_rekey_creds() { 465 int ok; 466 int ret; 467 #ifdef USE_PAM 468 pam_handle_t *pamh = NULL; 469 struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; 470 char *envstr; 471 #endif 472 473 if (gssapi_client.store.filename == NULL && 474 gssapi_client.store.envval == NULL && 475 gssapi_client.store.envvar == NULL) 476 return; 477 478 ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); 479 480 if (!ok) 481 return; 482 483 debug("Rekeyed credentials stored successfully"); 484 485 /* Actually managing to play with the ssh pam stack from here will 486 * be next to impossible. In any case, we may want different options 487 * for rekeying. So, use our own :) 488 */ 489 #ifdef USE_PAM 490 if (!use_privsep) { 491 debug("Not even going to try and do PAM with privsep disabled"); 492 return; 493 } 494 495 ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, 496 &pamconv, &pamh); 497 if (ret) 498 return; 499 500 xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 501 gssapi_client.store.envval); 502 503 ret = pam_putenv(pamh, envstr); 504 if (!ret) 505 pam_setcred(pamh, PAM_REINITIALIZE_CRED); 506 pam_end(pamh, PAM_SUCCESS); 507 #endif 508 } 509 510 int 511 ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { 512 int ok = 0; 513 514 /* Check we've got credentials to store */ 515 if (!gssapi_client.updated) 516 return 0; 517 518 gssapi_client.updated = 0; 519 520 temporarily_use_uid(gssapi_client.store.owner); 521 if (gssapi_client.mech && gssapi_client.mech->updatecreds) 522 ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); 523 else 524 debug("No update function for this mechanism"); 525 526 restore_uid(); 527 528 return ok; 365 529 } 366 530 367 531 #endif -
kex.c
diff --git a/kex.c b/kex.c index c65e28f..58349fc 100644
a b 50 50 #include "monitor.h" 51 51 #include "roaming.h" 52 52 53 #ifdef GSSAPI 54 #include "ssh-gss.h" 55 #endif 56 53 57 #if OPENSSL_VERSION_NUMBER >= 0x00907000L 54 58 # if defined(HAVE_EVP_SHA256) 55 59 # define evp_ssh_sha256 EVP_sha256 … … choose_kex(Kex *k, char *client, char *server) 358 362 k->kex_type = KEX_ECDH_SHA2; 359 363 k->evp_md = kex_ecdh_name_to_evpmd(k->name); 360 364 #endif 365 #ifdef GSSAPI 366 } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, 367 sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) { 368 k->kex_type = KEX_GSS_GEX_SHA1; 369 k->evp_md = EVP_sha1(); 370 } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, 371 sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) { 372 k->kex_type = KEX_GSS_GRP1_SHA1; 373 k->evp_md = EVP_sha1(); 374 } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID, 375 sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) { 376 k->kex_type = KEX_GSS_GRP14_SHA1; 377 k->evp_md = EVP_sha1(); 378 #endif 361 379 } else 362 380 fatal("bad kex alg %s", k->name); 363 381 } -
kex.h
diff --git a/kex.h b/kex.h index 7373d3c..fa50b2c 100644
a b enum kex_exchange { 73 73 KEX_DH_GEX_SHA1, 74 74 KEX_DH_GEX_SHA256, 75 75 KEX_ECDH_SHA2, 76 KEX_GSS_GRP1_SHA1, 77 KEX_GSS_GRP14_SHA1, 78 KEX_GSS_GEX_SHA1, 76 79 KEX_MAX 77 80 }; 78 81 … … struct Kex { 129 132 sig_atomic_t done; 130 133 int flags; 131 134 const EVP_MD *evp_md; 135 #ifdef GSSAPI 136 int gss_deleg_creds; 137 int gss_trust_dns; 138 char *gss_host; 139 char *gss_client; 140 #endif 132 141 char *client_version_string; 133 142 char *server_version_string; 134 143 int (*verify_host_key)(Key *); … … void kexgex_server(Kex *); 156 165 void kexecdh_client(Kex *); 157 166 void kexecdh_server(Kex *); 158 167 168 #ifdef GSSAPI 169 void kexgss_client(Kex *); 170 void kexgss_server(Kex *); 171 #endif 172 159 173 void 160 174 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, 161 175 BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); -
new file kexgssc.c
diff --git a/kexgssc.c b/kexgssc.c new file mode 100644 index 0000000..39be405
- + 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 46 #include "ssh-gss.h" 47 48 void 49 kexgss_client(Kex *kex) { 50 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 51 gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; 52 Gssctxt *ctxt; 53 OM_uint32 maj_status, min_status, ret_flags; 54 u_int klen, kout, slen = 0, hashlen, strlen; 55 DH *dh; 56 BIGNUM *dh_server_pub = NULL; 57 BIGNUM *shared_secret = NULL; 58 BIGNUM *p = NULL; 59 BIGNUM *g = NULL; 60 u_char *kbuf, *hash; 61 u_char *serverhostkey = NULL; 62 u_char *empty = ""; 63 char *msg; 64 char *lang; 65 int type = 0; 66 int first = 1; 67 int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; 68 69 /* Initialise our GSSAPI world */ 70 ssh_gssapi_build_ctx(&ctxt); 71 if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) 72 == GSS_C_NO_OID) 73 fatal("Couldn't identify host exchange"); 74 75 if (ssh_gssapi_import_name(ctxt, kex->gss_host)) 76 fatal("Couldn't import hostname"); 77 78 if (kex->gss_client && 79 ssh_gssapi_client_identity(ctxt, kex->gss_client)) 80 fatal("Couldn't acquire client credentials"); 81 82 switch (kex->kex_type) { 83 case KEX_GSS_GRP1_SHA1: 84 dh = dh_new_group1(); 85 break; 86 case KEX_GSS_GRP14_SHA1: 87 dh = dh_new_group14(); 88 break; 89 case KEX_GSS_GEX_SHA1: 90 debug("Doing group exchange\n"); 91 nbits = dh_estimate(kex->we_need * 8); 92 packet_start(SSH2_MSG_KEXGSS_GROUPREQ); 93 packet_put_int(min); 94 packet_put_int(nbits); 95 packet_put_int(max); 96 97 packet_send(); 98 99 packet_read_expect(SSH2_MSG_KEXGSS_GROUP); 100 101 if ((p = BN_new()) == NULL) 102 fatal("BN_new() failed"); 103 packet_get_bignum2(p); 104 if ((g = BN_new()) == NULL) 105 fatal("BN_new() failed"); 106 packet_get_bignum2(g); 107 packet_check_eom(); 108 109 if (BN_num_bits(p) < min || BN_num_bits(p) > max) 110 fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", 111 min, BN_num_bits(p), max); 112 113 dh = dh_new_group(g, p); 114 break; 115 default: 116 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 117 } 118 119 /* Step 1 - e is dh->pub_key */ 120 dh_gen_key(dh, kex->we_need * 8); 121 122 /* This is f, we initialise it now to make life easier */ 123 dh_server_pub = BN_new(); 124 if (dh_server_pub == NULL) 125 fatal("dh_server_pub == NULL"); 126 127 token_ptr = GSS_C_NO_BUFFER; 128 129 do { 130 debug("Calling gss_init_sec_context"); 131 132 maj_status = ssh_gssapi_init_ctx(ctxt, 133 kex->gss_deleg_creds, token_ptr, &send_tok, 134 &ret_flags); 135 136 if (GSS_ERROR(maj_status)) { 137 if (send_tok.length != 0) { 138 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 139 packet_put_string(send_tok.value, 140 send_tok.length); 141 } 142 fatal("gss_init_context failed"); 143 } 144 145 /* If we've got an old receive buffer get rid of it */ 146 if (token_ptr != GSS_C_NO_BUFFER) 147 xfree(recv_tok.value); 148 149 if (maj_status == GSS_S_COMPLETE) { 150 /* If mutual state flag is not true, kex fails */ 151 if (!(ret_flags & GSS_C_MUTUAL_FLAG)) 152 fatal("Mutual authentication failed"); 153 154 /* If integ avail flag is not true kex fails */ 155 if (!(ret_flags & GSS_C_INTEG_FLAG)) 156 fatal("Integrity check failed"); 157 } 158 159 /* 160 * If we have data to send, then the last message that we 161 * received cannot have been a 'complete'. 162 */ 163 if (send_tok.length != 0) { 164 if (first) { 165 packet_start(SSH2_MSG_KEXGSS_INIT); 166 packet_put_string(send_tok.value, 167 send_tok.length); 168 packet_put_bignum2(dh->pub_key); 169 first = 0; 170 } else { 171 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 172 packet_put_string(send_tok.value, 173 send_tok.length); 174 } 175 packet_send(); 176 gss_release_buffer(&min_status, &send_tok); 177 178 /* If we've sent them data, they should reply */ 179 do { 180 type = packet_read(); 181 if (type == SSH2_MSG_KEXGSS_HOSTKEY) { 182 debug("Received KEXGSS_HOSTKEY"); 183 if (serverhostkey) 184 fatal("Server host key received more than once"); 185 serverhostkey = 186 packet_get_string(&slen); 187 } 188 } while (type == SSH2_MSG_KEXGSS_HOSTKEY); 189 190 switch (type) { 191 case SSH2_MSG_KEXGSS_CONTINUE: 192 debug("Received GSSAPI_CONTINUE"); 193 if (maj_status == GSS_S_COMPLETE) 194 fatal("GSSAPI Continue received from server when complete"); 195 recv_tok.value = packet_get_string(&strlen); 196 recv_tok.length = strlen; 197 break; 198 case SSH2_MSG_KEXGSS_COMPLETE: 199 debug("Received GSSAPI_COMPLETE"); 200 packet_get_bignum2(dh_server_pub); 201 msg_tok.value = packet_get_string(&strlen); 202 msg_tok.length = strlen; 203 204 /* Is there a token included? */ 205 if (packet_get_char()) { 206 recv_tok.value= 207 packet_get_string(&strlen); 208 recv_tok.length = strlen; 209 /* If we're already complete - protocol error */ 210 if (maj_status == GSS_S_COMPLETE) 211 packet_disconnect("Protocol error: received token when complete"); 212 } else { 213 /* No token included */ 214 if (maj_status != GSS_S_COMPLETE) 215 packet_disconnect("Protocol error: did not receive final token"); 216 } 217 break; 218 case SSH2_MSG_KEXGSS_ERROR: 219 debug("Received Error"); 220 maj_status = packet_get_int(); 221 min_status = packet_get_int(); 222 msg = packet_get_string(NULL); 223 lang = packet_get_string(NULL); 224 fatal("GSSAPI Error: \n%.400s",msg); 225 default: 226 packet_disconnect("Protocol error: didn't expect packet type %d", 227 type); 228 } 229 token_ptr = &recv_tok; 230 } else { 231 /* No data, and not complete */ 232 if (maj_status != GSS_S_COMPLETE) 233 fatal("Not complete, and no token output"); 234 } 235 } while (maj_status & GSS_S_CONTINUE_NEEDED); 236 237 /* 238 * We _must_ have received a COMPLETE message in reply from the 239 * server, which will have set dh_server_pub and msg_tok 240 */ 241 242 if (type != SSH2_MSG_KEXGSS_COMPLETE) 243 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); 244 245 /* Check f in range [1, p-1] */ 246 if (!dh_pub_is_valid(dh, dh_server_pub)) 247 packet_disconnect("bad server public DH value"); 248 249 /* compute K=f^x mod p */ 250 klen = DH_size(dh); 251 kbuf = xmalloc(klen); 252 kout = DH_compute_key(kbuf, dh_server_pub, dh); 253 if (kout < 0) 254 fatal("DH_compute_key: failed"); 255 256 shared_secret = BN_new(); 257 if (shared_secret == NULL) 258 fatal("kexgss_client: BN_new failed"); 259 260 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) 261 fatal("kexdh_client: BN_bin2bn failed"); 262 263 memset(kbuf, 0, klen); 264 xfree(kbuf); 265 266 switch (kex->kex_type) { 267 case KEX_GSS_GRP1_SHA1: 268 case KEX_GSS_GRP14_SHA1: 269 kex_dh_hash( kex->client_version_string, 270 kex->server_version_string, 271 buffer_ptr(&kex->my), buffer_len(&kex->my), 272 buffer_ptr(&kex->peer), buffer_len(&kex->peer), 273 (serverhostkey ? serverhostkey : empty), slen, 274 dh->pub_key, /* e */ 275 dh_server_pub, /* f */ 276 shared_secret, /* K */ 277 &hash, &hashlen 278 ); 279 break; 280 case KEX_GSS_GEX_SHA1: 281 kexgex_hash( 282 kex->evp_md, 283 kex->client_version_string, 284 kex->server_version_string, 285 buffer_ptr(&kex->my), buffer_len(&kex->my), 286 buffer_ptr(&kex->peer), buffer_len(&kex->peer), 287 (serverhostkey ? serverhostkey : empty), slen, 288 min, nbits, max, 289 dh->p, dh->g, 290 dh->pub_key, 291 dh_server_pub, 292 shared_secret, 293 &hash, &hashlen 294 ); 295 break; 296 default: 297 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 298 } 299 300 gssbuf.value = hash; 301 gssbuf.length = hashlen; 302 303 /* Verify that the hash matches the MIC we just got. */ 304 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) 305 packet_disconnect("Hash's MIC didn't verify"); 306 307 xfree(msg_tok.value); 308 309 DH_free(dh); 310 if (serverhostkey) 311 xfree(serverhostkey); 312 BN_clear_free(dh_server_pub); 313 314 /* save session id */ 315 if (kex->session_id == NULL) { 316 kex->session_id_len = hashlen; 317 kex->session_id = xmalloc(kex->session_id_len); 318 memcpy(kex->session_id, hash, kex->session_id_len); 319 } 320 321 if (kex->gss_deleg_creds) 322 ssh_gssapi_credentials_updated(ctxt); 323 324 if (gss_kex_context == NULL) 325 gss_kex_context = ctxt; 326 else 327 ssh_gssapi_delete_ctx(&ctxt); 328 329 kex_derive_keys(kex, hash, hashlen, shared_secret); 330 BN_clear_free(shared_secret); 331 kex_finish(kex); 332 } 333 334 #endif /* GSSAPI */ -
new file kexgsss.c
diff --git a/kexgsss.c b/kexgsss.c new file mode 100644 index 0000000..0c3eeaa
- + 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 "servconf.h" 46 47 extern ServerOptions options; 48 49 void 50 kexgss_server(Kex *kex) 51 { 52 OM_uint32 maj_status, min_status; 53 54 /* 55 * Some GSSAPI implementations use the input value of ret_flags (an 56 * output variable) as a means of triggering mechanism specific 57 * features. Initializing it to zero avoids inadvertently 58 * activating this non-standard behaviour. 59 */ 60 61 OM_uint32 ret_flags = 0; 62 gss_buffer_desc gssbuf, recv_tok, msg_tok; 63 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 64 Gssctxt *ctxt = NULL; 65 u_int slen, klen, kout, hashlen; 66 u_char *kbuf, *hash; 67 DH *dh; 68 int min = -1, max = -1, nbits = -1; 69 BIGNUM *shared_secret = NULL; 70 BIGNUM *dh_client_pub = NULL; 71 int type = 0; 72 gss_OID oid; 73 char *mechs; 74 75 /* Initialise GSSAPI */ 76 77 /* If we're rekeying, privsep means that some of the private structures 78 * in the GSSAPI code are no longer available. This kludges them back 79 * into life 80 */ 81 if (!ssh_gssapi_oid_table_ok()) 82 if ((mechs = ssh_gssapi_server_mechanisms())) 83 xfree(mechs); 84 85 debug2("%s: Identifying %s", __func__, kex->name); 86 oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); 87 if (oid == GSS_C_NO_OID) 88 fatal("Unknown gssapi mechanism"); 89 90 debug2("%s: Acquiring credentials", __func__); 91 92 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) 93 fatal("Unable to acquire credentials for the server"); 94 95 switch (kex->kex_type) { 96 case KEX_GSS_GRP1_SHA1: 97 dh = dh_new_group1(); 98 break; 99 case KEX_GSS_GRP14_SHA1: 100 dh = dh_new_group14(); 101 break; 102 case KEX_GSS_GEX_SHA1: 103 debug("Doing group exchange"); 104 packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); 105 min = packet_get_int(); 106 nbits = packet_get_int(); 107 max = packet_get_int(); 108 min = MAX(DH_GRP_MIN, min); 109 max = MIN(DH_GRP_MAX, max); 110 packet_check_eom(); 111 if (max < min || nbits < min || max < nbits) 112 fatal("GSS_GEX, bad parameters: %d !< %d !< %d", 113 min, nbits, max); 114 dh = PRIVSEP(choose_dh(min, nbits, max)); 115 if (dh == NULL) 116 packet_disconnect("Protocol error: no matching group found"); 117 118 packet_start(SSH2_MSG_KEXGSS_GROUP); 119 packet_put_bignum2(dh->p); 120 packet_put_bignum2(dh->g); 121 packet_send(); 122 123 packet_write_wait(); 124 break; 125 default: 126 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 127 } 128 129 dh_gen_key(dh, kex->we_need * 8); 130 131 do { 132 debug("Wait SSH2_MSG_GSSAPI_INIT"); 133 type = packet_read(); 134 switch(type) { 135 case SSH2_MSG_KEXGSS_INIT: 136 if (dh_client_pub != NULL) 137 fatal("Received KEXGSS_INIT after initialising"); 138 recv_tok.value = packet_get_string(&slen); 139 recv_tok.length = slen; 140 141 if ((dh_client_pub = BN_new()) == NULL) 142 fatal("dh_client_pub == NULL"); 143 144 packet_get_bignum2(dh_client_pub); 145 146 /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ 147 break; 148 case SSH2_MSG_KEXGSS_CONTINUE: 149 recv_tok.value = packet_get_string(&slen); 150 recv_tok.length = slen; 151 break; 152 default: 153 packet_disconnect( 154 "Protocol error: didn't expect packet type %d", 155 type); 156 } 157 158 maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 159 &send_tok, &ret_flags)); 160 161 xfree(recv_tok.value); 162 163 if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) 164 fatal("Zero length token output when incomplete"); 165 166 if (dh_client_pub == NULL) 167 fatal("No client public key"); 168 169 if (maj_status & GSS_S_CONTINUE_NEEDED) { 170 debug("Sending GSSAPI_CONTINUE"); 171 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 172 packet_put_string(send_tok.value, send_tok.length); 173 packet_send(); 174 gss_release_buffer(&min_status, &send_tok); 175 } 176 } while (maj_status & GSS_S_CONTINUE_NEEDED); 177 178 if (GSS_ERROR(maj_status)) { 179 if (send_tok.length > 0) { 180 packet_start(SSH2_MSG_KEXGSS_CONTINUE); 181 packet_put_string(send_tok.value, send_tok.length); 182 packet_send(); 183 } 184 fatal("accept_ctx died"); 185 } 186 187 if (!(ret_flags & GSS_C_MUTUAL_FLAG)) 188 fatal("Mutual Authentication flag wasn't set"); 189 190 if (!(ret_flags & GSS_C_INTEG_FLAG)) 191 fatal("Integrity flag wasn't set"); 192 193 if (!dh_pub_is_valid(dh, dh_client_pub)) 194 packet_disconnect("bad client public DH value"); 195 196 klen = DH_size(dh); 197 kbuf = xmalloc(klen); 198 kout = DH_compute_key(kbuf, dh_client_pub, dh); 199 if (kout < 0) 200 fatal("DH_compute_key: failed"); 201 202 shared_secret = BN_new(); 203 if (shared_secret == NULL) 204 fatal("kexgss_server: BN_new failed"); 205 206 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) 207 fatal("kexgss_server: BN_bin2bn failed"); 208 209 memset(kbuf, 0, klen); 210 xfree(kbuf); 211 212 switch (kex->kex_type) { 213 case KEX_GSS_GRP1_SHA1: 214 case KEX_GSS_GRP14_SHA1: 215 kex_dh_hash( 216 kex->client_version_string, kex->server_version_string, 217 buffer_ptr(&kex->peer), buffer_len(&kex->peer), 218 buffer_ptr(&kex->my), buffer_len(&kex->my), 219 NULL, 0, /* Change this if we start sending host keys */ 220 dh_client_pub, dh->pub_key, shared_secret, 221 &hash, &hashlen 222 ); 223 break; 224 case KEX_GSS_GEX_SHA1: 225 kexgex_hash( 226 kex->evp_md, 227 kex->client_version_string, kex->server_version_string, 228 buffer_ptr(&kex->peer), buffer_len(&kex->peer), 229 buffer_ptr(&kex->my), buffer_len(&kex->my), 230 NULL, 0, 231 min, nbits, max, 232 dh->p, dh->g, 233 dh_client_pub, 234 dh->pub_key, 235 shared_secret, 236 &hash, &hashlen 237 ); 238 break; 239 default: 240 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 241 } 242 243 BN_clear_free(dh_client_pub); 244 245 if (kex->session_id == NULL) { 246 kex->session_id_len = hashlen; 247 kex->session_id = xmalloc(kex->session_id_len); 248 memcpy(kex->session_id, hash, kex->session_id_len); 249 } 250 251 gssbuf.value = hash; 252 gssbuf.length = hashlen; 253 254 if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) 255 fatal("Couldn't get MIC"); 256 257 packet_start(SSH2_MSG_KEXGSS_COMPLETE); 258 packet_put_bignum2(dh->pub_key); 259 packet_put_string(msg_tok.value,msg_tok.length); 260 261 if (send_tok.length != 0) { 262 packet_put_char(1); /* true */ 263 packet_put_string(send_tok.value, send_tok.length); 264 } else { 265 packet_put_char(0); /* false */ 266 } 267 packet_send(); 268 269 gss_release_buffer(&min_status, &send_tok); 270 gss_release_buffer(&min_status, &msg_tok); 271 272 if (gss_kex_context == NULL) 273 gss_kex_context = ctxt; 274 else 275 ssh_gssapi_delete_ctx(&ctxt); 276 277 DH_free(dh); 278 279 kex_derive_keys(kex, hash, hashlen, shared_secret); 280 BN_clear_free(shared_secret); 281 kex_finish(kex); 282 283 /* If this was a rekey, then save out any delegated credentials we 284 * just exchanged. */ 285 if (options.gss_store_rekey) 286 ssh_gssapi_rekey_creds(); 287 } 288 #endif /* GSSAPI */ -
key.c
diff --git a/key.c b/key.c index 498cf5a..fc65c29 100644
a b key_ssh_name_from_type_nid(int type, int nid) 971 971 } 972 972 break; 973 973 #endif /* OPENSSL_HAS_ECC */ 974 case KEY_NULL: 975 return "null"; 974 976 } 975 977 return "ssh-unknown"; 976 978 } … … key_type_from_name(char *name) 1276 1278 strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { 1277 1279 return KEY_ECDSA_CERT; 1278 1280 #endif 1281 } else if (strcmp(name, "null") == 0) { 1282 return KEY_NULL; 1279 1283 } 1280 1284 1281 1285 debug2("key_type_from_name: unknown key type '%s'", name); -
key.h
diff --git a/key.h b/key.h index ec5ac5e..8b5c565 100644
a b enum types { 44 44 KEY_ECDSA_CERT, 45 45 KEY_RSA_CERT_V00, 46 46 KEY_DSA_CERT_V00, 47 KEY_NULL, 47 48 KEY_UNSPEC 48 49 }; 49 50 enum fp_type { -
monitor.c
diff --git a/monitor.c b/monitor.c index a166fed..2d46b7b 100644
a b int mm_answer_gss_setup_ctx(int, Buffer *); 180 180 int mm_answer_gss_accept_ctx(int, Buffer *); 181 181 int mm_answer_gss_userok(int, Buffer *); 182 182 int mm_answer_gss_checkmic(int, Buffer *); 183 int mm_answer_gss_sign(int, Buffer *); 184 int mm_answer_gss_updatecreds(int, Buffer *); 183 185 #endif 184 186 185 187 #ifdef SSH_AUDIT_EVENTS … … struct mon_table mon_dispatch_proto20[] = { 251 253 {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, 252 254 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 253 255 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 256 {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, 254 257 #endif 255 258 #ifdef JPAKE 256 259 {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, … … struct mon_table mon_dispatch_proto20[] = { 263 266 }; 264 267 265 268 struct mon_table mon_dispatch_postauth20[] = { 269 #ifdef GSSAPI 270 {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, 271 {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, 272 {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, 273 {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, 274 #endif 266 275 {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 267 276 {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 268 277 {MONITOR_REQ_PTY, 0, mm_answer_pty}, … … monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 371 380 /* Permit requests for moduli and signatures */ 372 381 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 373 382 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 383 #ifdef GSSAPI 384 /* and for the GSSAPI key exchange */ 385 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); 386 #endif 374 387 } else { 375 388 mon_dispatch = mon_dispatch_proto15; 376 389 … … monitor_child_postauth(struct monitor *pmonitor) 468 481 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 469 482 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 470 483 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 484 #ifdef GSSAPI 485 /* and for the GSSAPI key exchange */ 486 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); 487 #endif 471 488 } else { 472 489 mon_dispatch = mon_dispatch_postauth15; 473 490 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); … … mm_get_kex(Buffer *m) 1802 1819 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1803 1820 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1804 1821 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1822 #ifdef GSSAPI 1823 if (options.gss_keyex) { 1824 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; 1825 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; 1826 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; 1827 } 1828 #endif 1805 1829 kex->server = 1; 1806 1830 kex->hostkey_type = buffer_get_int(m); 1807 1831 kex->kex_type = buffer_get_int(m); … … mm_answer_gss_setup_ctx(int sock, Buffer *m) 2008 2032 OM_uint32 major; 2009 2033 u_int len; 2010 2034 2035 if (!options.gss_authentication && !options.gss_keyex) 2036 fatal("In GSSAPI monitor when GSSAPI is disabled"); 2037 2011 2038 goid.elements = buffer_get_string(m, &len); 2012 2039 goid.length = len; 2013 2040 … … mm_answer_gss_accept_ctx(int sock, Buffer *m) 2035 2062 OM_uint32 flags = 0; /* GSI needs this */ 2036 2063 u_int len; 2037 2064 2065 if (!options.gss_authentication && !options.gss_keyex) 2066 fatal("In GSSAPI monitor when GSSAPI is disabled"); 2067 2038 2068 in.value = buffer_get_string(m, &len); 2039 2069 in.length = len; 2040 2070 major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); … … mm_answer_gss_accept_ctx(int sock, Buffer *m) 2052 2082 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 2053 2083 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 2054 2084 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 2085 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); 2055 2086 } 2056 2087 return (0); 2057 2088 } … … mm_answer_gss_checkmic(int sock, Buffer *m) 2063 2094 OM_uint32 ret; 2064 2095 u_int len; 2065 2096 2097 if (!options.gss_authentication && !options.gss_keyex) 2098 fatal("In GSSAPI monitor when GSSAPI is disabled"); 2099 2066 2100 gssbuf.value = buffer_get_string(m, &len); 2067 2101 gssbuf.length = len; 2068 2102 mic.value = buffer_get_string(m, &len); … … mm_answer_gss_userok(int sock, Buffer *m) 2089 2123 { 2090 2124 int authenticated; 2091 2125 2092 authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 2126 if (!options.gss_authentication && !options.gss_keyex) 2127 fatal("In GSSAPI monitor when GSSAPI is disabled"); 2128 2129 authenticated = authctxt->valid && 2130 ssh_gssapi_userok(authctxt->user, authctxt->pw); 2093 2131 2094 2132 buffer_clear(m); 2095 2133 buffer_put_int(m, authenticated); … … mm_answer_gss_userok(int sock, Buffer *m) 2102 2140 /* Monitor loop will terminate if authenticated */ 2103 2141 return (authenticated); 2104 2142 } 2143 2144 int 2145 mm_answer_gss_sign(int socket, Buffer *m) 2146 { 2147 gss_buffer_desc data; 2148 gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; 2149 OM_uint32 major, minor; 2150 u_int len; 2151 2152 if (!options.gss_authentication && !options.gss_keyex) 2153 fatal("In GSSAPI monitor when GSSAPI is disabled"); 2154 2155 data.value = buffer_get_string(m, &len); 2156 data.length = len; 2157 if (data.length != 20) 2158 fatal("%s: data length incorrect: %d", __func__, 2159 (int) data.length); 2160 2161 /* Save the session ID on the first time around */ 2162 if (session_id2_len == 0) { 2163 session_id2_len = data.length; 2164 session_id2 = xmalloc(session_id2_len); 2165 memcpy(session_id2, data.value, session_id2_len); 2166 } 2167 major = ssh_gssapi_sign(gsscontext, &data, &hash); 2168 2169 xfree(data.value); 2170 2171 buffer_clear(m); 2172 buffer_put_int(m, major); 2173 buffer_put_string(m, hash.value, hash.length); 2174 2175 mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); 2176 2177 gss_release_buffer(&minor, &hash); 2178 2179 /* Turn on getpwnam permissions */ 2180 monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 2181 2182 /* And credential updating, for when rekeying */ 2183 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); 2184 2185 return (0); 2186 } 2187 2188 int 2189 mm_answer_gss_updatecreds(int socket, Buffer *m) { 2190 ssh_gssapi_ccache store; 2191 int ok; 2192 2193 store.filename = buffer_get_string(m, NULL); 2194 store.envvar = buffer_get_string(m, NULL); 2195 store.envval = buffer_get_string(m, NULL); 2196 2197 ok = ssh_gssapi_update_creds(&store); 2198 2199 xfree(store.filename); 2200 xfree(store.envvar); 2201 xfree(store.envval); 2202 2203 buffer_clear(m); 2204 buffer_put_int(m, ok); 2205 2206 mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); 2207 2208 return(0); 2209 } 2210 2105 2211 #endif /* GSSAPI */ 2106 2212 2107 2213 #ifdef JPAKE -
monitor.h
diff --git a/monitor.h b/monitor.h index 5e7d552..db0443f 100644
a b enum monitor_reqtype { 53 53 MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, 54 54 MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, 55 55 MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, 56 MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, 57 MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS, 56 58 MONITOR_REQ_PAM_START, 57 59 MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, 58 60 MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, -
monitor_wrap.c
diff --git a/monitor_wrap.c b/monitor_wrap.c index 1f60658..fc6bbcd 100644
a b mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 1270 1270 } 1271 1271 1272 1272 int 1273 mm_ssh_gssapi_userok(char *user )1273 mm_ssh_gssapi_userok(char *user, struct passwd *pw) 1274 1274 { 1275 1275 Buffer m; 1276 1276 int authenticated = 0; … … mm_ssh_gssapi_userok(char *user) 1287 1287 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); 1288 1288 return (authenticated); 1289 1289 } 1290 1291 OM_uint32 1292 mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) 1293 { 1294 Buffer m; 1295 OM_uint32 major; 1296 u_int len; 1297 1298 buffer_init(&m); 1299 buffer_put_string(&m, data->value, data->length); 1300 1301 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); 1302 mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); 1303 1304 major = buffer_get_int(&m); 1305 hash->value = buffer_get_string(&m, &len); 1306 hash->length = len; 1307 1308 buffer_free(&m); 1309 1310 return(major); 1311 } 1312 1313 int 1314 mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) 1315 { 1316 Buffer m; 1317 int ok; 1318 1319 buffer_init(&m); 1320 1321 buffer_put_cstring(&m, store->filename ? store->filename : ""); 1322 buffer_put_cstring(&m, store->envvar ? store->envvar : ""); 1323 buffer_put_cstring(&m, store->envval ? store->envval : ""); 1324 1325 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); 1326 mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); 1327 1328 ok = buffer_get_int(&m); 1329 1330 buffer_free(&m); 1331 1332 return (ok); 1333 } 1334 1290 1335 #endif /* GSSAPI */ 1291 1336 1292 1337 #ifdef JPAKE -
monitor_wrap.h
diff --git a/monitor_wrap.h b/monitor_wrap.h index 0c7f2e3..ec9b9b1 100644
a b BIGNUM *mm_auth_rsa_generate_challenge(Key *); 58 58 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); 59 59 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, 60 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 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 65 #endif 64 66 65 67 #ifdef USE_PAM -
readconf.c
diff --git a/readconf.c b/readconf.c index 91dfa56..60befde 100644
a b typedef enum { 129 129 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 130 130 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 131 131 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 132 oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, 133 oGssServerIdentity, 132 134 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 133 135 oSendEnv, oControlPath, oControlMaster, oControlPersist, 134 136 oHashKnownHosts, … … static struct { 169 171 { "afstokenpassing", oUnsupported }, 170 172 #if defined(GSSAPI) 171 173 { "gssapiauthentication", oGssAuthentication }, 174 { "gssapikeyexchange", oGssKeyEx }, 172 175 { "gssapidelegatecredentials", oGssDelegateCreds }, 176 { "gssapitrustdns", oGssTrustDns }, 177 { "gssapiclientidentity", oGssClientIdentity }, 178 { "gssapiserveridentity", oGssServerIdentity }, 179 { "gssapirenewalforcesrekey", oGssRenewalRekey }, 173 180 #else 174 181 { "gssapiauthentication", oUnsupported }, 182 { "gssapikeyexchange", oUnsupported }, 175 183 { "gssapidelegatecredentials", oUnsupported }, 184 { "gssapitrustdns", oUnsupported }, 185 { "gssapiclientidentity", oUnsupported }, 186 { "gssapirenewalforcesrekey", oUnsupported }, 176 187 #endif 177 188 { "fallbacktorsh", oDeprecated }, 178 189 { "usersh", oDeprecated }, … … parse_flag: 482 493 intptr = &options->gss_authentication; 483 494 goto parse_flag; 484 495 496 case oGssKeyEx: 497 intptr = &options->gss_keyex; 498 goto parse_flag; 499 485 500 case oGssDelegateCreds: 486 501 intptr = &options->gss_deleg_creds; 487 502 goto parse_flag; 488 503 504 case oGssTrustDns: 505 intptr = &options->gss_trust_dns; 506 goto parse_flag; 507 508 case oGssClientIdentity: 509 charptr = &options->gss_client_identity; 510 goto parse_string; 511 512 case oGssServerIdentity: 513 charptr = &options->gss_server_identity; 514 goto parse_string; 515 516 case oGssRenewalRekey: 517 intptr = &options->gss_renewal_rekey; 518 goto parse_flag; 519 489 520 case oBatchMode: 490 521 intptr = &options->batch_mode; 491 522 goto parse_flag; … … initialize_options(Options * options) 1138 1169 options->pubkey_authentication = -1; 1139 1170 options->challenge_response_authentication = -1; 1140 1171 options->gss_authentication = -1; 1172 options->gss_keyex = -1; 1141 1173 options->gss_deleg_creds = -1; 1174 options->gss_trust_dns = -1; 1175 options->gss_renewal_rekey = -1; 1176 options->gss_client_identity = NULL; 1177 options->gss_server_identity = NULL; 1142 1178 options->password_authentication = -1; 1143 1179 options->kbd_interactive_authentication = -1; 1144 1180 options->kbd_interactive_devices = NULL; … … fill_default_options(Options * options) 1238 1274 options->challenge_response_authentication = 1; 1239 1275 if (options->gss_authentication == -1) 1240 1276 options->gss_authentication = 0; 1277 if (options->gss_keyex == -1) 1278 options->gss_keyex = 0; 1241 1279 if (options->gss_deleg_creds == -1) 1242 1280 options->gss_deleg_creds = 0; 1281 if (options->gss_trust_dns == -1) 1282 options->gss_trust_dns = 0; 1283 if (options->gss_renewal_rekey == -1) 1284 options->gss_renewal_rekey = 0; 1243 1285 if (options->password_authentication == -1) 1244 1286 options->password_authentication = 1; 1245 1287 if (options->kbd_interactive_authentication == -1) -
readconf.h
diff --git a/readconf.h b/readconf.h index 5944cff..617686f 100644
a b typedef struct { 47 47 int challenge_response_authentication; 48 48 /* Try S/Key or TIS, authentication. */ 49 49 int gss_authentication; /* Try GSS authentication */ 50 int gss_keyex; /* Try GSS key exchange */ 50 51 int gss_deleg_creds; /* Delegate GSS credentials */ 52 int gss_trust_dns; /* Trust DNS for GSS canonicalization */ 53 int gss_renewal_rekey; /* Credential renewal forces rekey */ 54 char *gss_client_identity; /* Principal to initiate GSSAPI with */ 55 char *gss_server_identity; /* GSSAPI target principal */ 51 56 int password_authentication; /* Try password 52 57 * authentication. */ 53 58 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -
servconf.c
diff --git a/servconf.c b/servconf.c index 91986e5..756a3a2 100644
a b initialize_server_options(ServerOptions *options) 97 97 options->kerberos_ticket_cleanup = -1; 98 98 options->kerberos_get_afs_token = -1; 99 99 options->gss_authentication=-1; 100 options->gss_keyex = -1; 100 101 options->gss_cleanup_creds = -1; 102 options->gss_strict_acceptor = -1; 103 options->gss_store_rekey = -1; 101 104 options->password_authentication = -1; 102 105 options->kbd_interactive_authentication = -1; 103 106 options->challenge_response_authentication = -1; … … fill_default_server_options(ServerOptions *options) 225 228 options->kerberos_get_afs_token = 0; 226 229 if (options->gss_authentication == -1) 227 230 options->gss_authentication = 0; 231 if (options->gss_keyex == -1) 232 options->gss_keyex = 0; 228 233 if (options->gss_cleanup_creds == -1) 229 234 options->gss_cleanup_creds = 1; 235 if (options->gss_strict_acceptor == -1) 236 options->gss_strict_acceptor = 1; 237 if (options->gss_store_rekey == -1) 238 options->gss_store_rekey = 0; 230 239 if (options->password_authentication == -1) 231 240 options->password_authentication = 1; 232 241 if (options->kbd_interactive_authentication == -1) … … typedef enum { 318 327 sBanner, sUseDNS, sHostbasedAuthentication, 319 328 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 320 329 sClientAliveCountMax, sAuthorizedKeysFile, 321 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, 330 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 331 sGssKeyEx, sGssStoreRekey, 332 sAcceptEnv, sPermitTunnel, 322 333 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 323 334 sUsePrivilegeSeparation, sAllowAgentForwarding, 324 335 sZeroKnowledgePasswordAuthentication, sHostCertificate, … … static struct { 382 393 #ifdef GSSAPI 383 394 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 384 395 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 396 { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, 397 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, 398 { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, 399 { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, 385 400 #else 386 401 { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 387 402 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 403 { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, 404 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, 405 { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, 406 { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, 388 407 #endif 408 { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, 409 { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, 389 410 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 390 411 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 391 412 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, … … process_server_config_line(ServerOptions *options, char *line, 962 983 intptr = &options->gss_authentication; 963 984 goto parse_flag; 964 985 986 case sGssKeyEx: 987 intptr = &options->gss_keyex; 988 goto parse_flag; 989 965 990 case sGssCleanupCreds: 966 991 intptr = &options->gss_cleanup_creds; 967 992 goto parse_flag; 968 993 994 case sGssStrictAcceptor: 995 intptr = &options->gss_strict_acceptor; 996 goto parse_flag; 997 998 case sGssStoreRekey: 999 intptr = &options->gss_store_rekey; 1000 goto parse_flag; 1001 969 1002 case sPasswordAuthentication: 970 1003 intptr = &options->password_authentication; 971 1004 goto parse_flag; … … dump_config(ServerOptions *o) 1720 1753 #endif 1721 1754 #ifdef GSSAPI 1722 1755 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 1756 dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); 1723 1757 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 1758 dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); 1759 dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); 1724 1760 #endif 1725 1761 #ifdef JPAKE 1726 1762 dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, -
servconf.h
diff --git a/servconf.h b/servconf.h index 89f38e2..a434c6f 100644
a b typedef struct { 103 103 int kerberos_get_afs_token; /* If true, try to get AFS token if 104 104 * authenticated with Kerberos. */ 105 105 int gss_authentication; /* If true, permit GSSAPI authentication */ 106 int gss_keyex; /* If true, permit GSSAPI key exchange */ 106 107 int gss_cleanup_creds; /* If true, destroy cred cache on logout */ 108 int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ 109 int gss_store_rekey; 107 110 int password_authentication; /* If true, permit password 108 111 * authentication. */ 109 112 int kbd_interactive_authentication; /* If true, permit */ -
ssh-gss.h
diff --git a/ssh-gss.h b/ssh-gss.h index c29a1b7..31d5a08 100644
a b 1 1 /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ 2 2 /* 3 * Copyright (c) 2001-200 3Simon Wilkinson. All rights reserved.3 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without 6 6 * modification, are permitted provided that the following conditions … … 60 60 61 61 #define SSH_GSS_OIDTYPE 0x06 62 62 63 #define SSH2_MSG_KEXGSS_INIT 30 64 #define SSH2_MSG_KEXGSS_CONTINUE 31 65 #define SSH2_MSG_KEXGSS_COMPLETE 32 66 #define SSH2_MSG_KEXGSS_HOSTKEY 33 67 #define SSH2_MSG_KEXGSS_ERROR 34 68 #define SSH2_MSG_KEXGSS_GROUPREQ 40 69 #define SSH2_MSG_KEXGSS_GROUP 41 70 #define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" 71 #define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" 72 #define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" 73 63 74 typedef struct { 64 75 char *filename; 65 76 char *envvar; 66 77 char *envval; 78 struct passwd *owner; 67 79 void *data; 68 80 } ssh_gssapi_ccache; 69 81 … … typedef struct { 71 83 gss_buffer_desc displayname; 72 84 gss_buffer_desc exportedname; 73 85 gss_cred_id_t creds; 86 gss_name_t name; 74 87 struct ssh_gssapi_mech_struct *mech; 75 88 ssh_gssapi_ccache store; 89 int used; 90 int updated; 76 91 } ssh_gssapi_client; 77 92 78 93 typedef struct ssh_gssapi_mech_struct { … … typedef struct ssh_gssapi_mech_struct { 83 98 int (*userok) (ssh_gssapi_client *, char *); 84 99 int (*localname) (ssh_gssapi_client *, char **); 85 100 void (*storecreds) (ssh_gssapi_client *); 101 int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); 86 102 } ssh_gssapi_mech; 87 103 88 104 typedef struct { … … typedef struct { 93 109 gss_OID oid; /* client */ 94 110 gss_cred_id_t creds; /* server */ 95 111 gss_name_t client; /* server */ 96 gss_cred_id_t client_creds; /* server*/112 gss_cred_id_t client_creds; /* both */ 97 113 } Gssctxt; 98 114 99 115 extern ssh_gssapi_mech *supported_mechs[]; 116 extern Gssctxt *gss_kex_context; 100 117 101 118 int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); 102 119 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); … … void ssh_gssapi_build_ctx(Gssctxt **); 116 133 void ssh_gssapi_delete_ctx(Gssctxt **); 117 134 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); 118 135 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); 119 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); 136 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); 137 OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); 138 int ssh_gssapi_credentials_updated(Gssctxt *); 120 139 121 140 /* In the server */ 141 typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 142 const char *); 143 char *ssh_gssapi_client_mechanisms(const char *, const char *); 144 char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, 145 const char *); 146 gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); 147 int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 148 const char *); 122 149 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); 123 int ssh_gssapi_userok(char *name );150 int ssh_gssapi_userok(char *name, struct passwd *); 124 151 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); 125 152 void ssh_gssapi_do_child(char ***, u_int *); 126 153 void ssh_gssapi_cleanup_creds(void); 127 154 void ssh_gssapi_storecreds(void); 128 155 156 char *ssh_gssapi_server_mechanisms(void); 157 int ssh_gssapi_oid_table_ok(); 158 159 int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); 129 160 #endif /* GSSAPI */ 130 161 131 162 #endif /* _SSH_GSS_H */ -
ssh_config
diff --git a/ssh_config b/ssh_config index 1893674..2c06ba7 100644
a b 26 26 # HostbasedAuthentication no 27 27 # GSSAPIAuthentication no 28 28 # GSSAPIDelegateCredentials no 29 # GSSAPIKeyExchange no 30 # GSSAPITrustDNS no 29 31 # BatchMode no 30 32 # CheckHostIP yes 31 33 # AddressFamily any -
ssh_config.5
diff --git a/ssh_config.5 b/ssh_config.5 index a782d6f..9e1e9a6 100644
a b Specifies whether user authentication based on GSSAPI is allowed. 527 527 The default is 528 528 .Dq no . 529 529 Note that this option applies to protocol version 2 only. 530 .It Cm GSSAPIKeyExchange 531 Specifies whether key exchange based on GSSAPI may be used. When using 532 GSSAPI key exchange the server need not have a host key. 533 The default is 534 .Dq no . 535 Note that this option applies to protocol version 2 only. 536 .It Cm GSSAPIClientIdentity 537 If set, specifies the GSSAPI client identity that ssh should use when 538 connecting to the server. The default is unset, which means that the default 539 identity will be used. 540 .It Cm GSSAPIServerIdentity 541 If set, specifies the GSSAPI server identity that ssh should expect when 542 connecting to the server. The default is unset, which means that the 543 expected GSSAPI server identity will be determined from the target 544 hostname. 530 545 .It Cm GSSAPIDelegateCredentials 531 546 Forward (delegate) credentials to the server. 532 547 The default is 533 548 .Dq no . 534 Note that this option applies to protocol version 2 only. 549 Note that this option applies to protocol version 2 connections using GSSAPI. 550 .It Cm GSSAPIRenewalForcesRekey 551 If set to 552 .Dq yes 553 then renewal of the client's GSSAPI credentials will force the rekeying of the 554 ssh connection. With a compatible server, this can delegate the renewed 555 credentials to a session on the server. 556 The default is 557 .Dq no . 558 .It Cm GSSAPITrustDns 559 Set to 560 .Dq yes to indicate that the DNS is trusted to securely canonicalize 561 the name of the host being connected to. If 562 .Dq no, the hostname entered on the 563 command line will be passed untouched to the GSSAPI library. 564 The default is 565 .Dq no . 566 This option only applies to protocol version 2 connections using GSSAPI. 535 567 .It Cm HashKnownHosts 536 568 Indicates that 537 569 .Xr ssh 1 -
sshconnect2.c
diff --git a/sshconnect2.c b/sshconnect2.c index c24b202..3ddef32 100644
a b ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 160 160 { 161 161 Kex *kex; 162 162 163 #ifdef GSSAPI 164 char *orig = NULL, *gss = NULL; 165 char *gss_host = NULL; 166 #endif 167 163 168 xxx_host = host; 164 169 xxx_hostaddr = hostaddr; 165 170 171 #ifdef GSSAPI 172 if (options.gss_keyex) { 173 /* Add the GSSAPI mechanisms currently supported on this 174 * client to the key exchange algorithm proposal */ 175 orig = myproposal[PROPOSAL_KEX_ALGS]; 176 177 if (options.gss_trust_dns) 178 gss_host = (char *)get_canonical_hostname(1); 179 else 180 gss_host = host; 181 182 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); 183 if (gss) { 184 debug("Offering GSSAPI proposal: %s", gss); 185 xasprintf(&myproposal[PROPOSAL_KEX_ALGS], 186 "%s,%s", gss, orig); 187 } 188 } 189 #endif 190 166 191 if (options.ciphers == (char *)-1) { 167 192 logit("No valid ciphers for protocol version 2 given, using defaults."); 168 193 options.ciphers = NULL; … … ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 197 222 if (options.kex_algorithms != NULL) 198 223 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 199 224 225 #ifdef GSSAPI 226 /* If we've got GSSAPI algorithms, then we also support the 227 * 'null' hostkey, as a last resort */ 228 if (options.gss_keyex && gss) { 229 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; 230 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 231 "%s,null", orig); 232 xfree(gss); 233 } 234 #endif 235 200 236 if (options.rekey_limit) 201 237 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 202 238 … … ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 207 243 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 208 244 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 209 245 kex->kex[KEX_ECDH_SHA2] = kexecdh_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 210 253 kex->client_version_string=client_version_string; 211 254 kex->server_version_string=server_version_string; 212 255 kex->verify_host_key=&verify_host_key_callback; 213 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 214 270 xxx_kex = kex; 215 271 216 272 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); … … void input_gssapi_token(int type, u_int32_t, void *); 305 361 void input_gssapi_hash(int type, u_int32_t, void *); 306 362 void input_gssapi_error(int, u_int32_t, void *); 307 363 void input_gssapi_errtok(int, u_int32_t, void *); 364 int userauth_gsskeyex(Authctxt *authctxt); 308 365 #endif 309 366 310 367 void userauth(Authctxt *, char *); … … static char *authmethods_get(void); 320 377 321 378 Authmethod authmethods[] = { 322 379 #ifdef GSSAPI 380 {"gssapi-keyex", 381 userauth_gsskeyex, 382 NULL, 383 &options.gss_authentication, 384 NULL}, 323 385 {"gssapi-with-mic", 324 386 userauth_gssapi, 325 387 NULL, … … userauth_gssapi(Authctxt *authctxt) 626 688 static u_int mech = 0; 627 689 OM_uint32 min; 628 690 int ok = 0; 691 const char *gss_host; 692 693 if (options.gss_server_identity) 694 gss_host = options.gss_server_identity; 695 else if (options.gss_trust_dns) 696 gss_host = get_canonical_hostname(1); 697 else 698 gss_host = authctxt->host; 629 699 630 700 /* Try one GSSAPI method at a time, rather than sending them all at 631 701 * once. */ 632 702 633 703 if (gss_supported == NULL) 634 gss_indicate_mechs(&min, &gss_supported); 704 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { 705 gss_supported = NULL; 706 return 0; 707 } 635 708 636 709 /* Check to see if the mechanism is usable before we offer it */ 637 710 while (mech < gss_supported->count && !ok) { 638 711 /* My DER encoding requires length<128 */ 639 712 if (gss_supported->elements[mech].length < 128 && 640 713 ssh_gssapi_check_mechanism(&gssctxt, 641 &gss_supported->elements[mech], authctxt->host)) { 714 &gss_supported->elements[mech], gss_host, 715 options.gss_client_identity)) { 642 716 ok = 1; /* Mechanism works */ 643 717 } else { 644 718 mech++; … … input_gssapi_response(int type, u_int32_t plen, void *ctxt) 735 809 { 736 810 Authctxt *authctxt = ctxt; 737 811 Gssctxt *gssctxt; 738 int oidlen;739 char *oidv;812 u_int oidlen; 813 u_char *oidv; 740 814 741 815 if (authctxt == NULL) 742 816 fatal("input_gssapi_response: no authentication context"); … … input_gssapi_error(int type, u_int32_t plen, void *ctxt) 846 920 xfree(msg); 847 921 xfree(lang); 848 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 849 965 #endif /* GSSAPI */ 850 966 851 967 int -
sshd.c
diff --git a/sshd.c b/sshd.c index cc10395..112a5f9 100644
a b 121 121 #include "ssh-sandbox.h" 122 122 #include "version.h" 123 123 124 #ifdef USE_SECURITY_SESSION_API 125 #include <Security/AuthSession.h> 126 #endif 127 124 128 #ifdef LIBWRAP 125 129 #include <tcpd.h> 126 130 #include <syslog.h> … … main(int ac, char **av) 1612 1616 logit("Disabling protocol version 1. Could not load host key"); 1613 1617 options.protocol &= ~SSH_PROTO_1; 1614 1618 } 1619 #ifndef GSSAPI 1620 /* The GSSAPI key exchange can run without a host key */ 1615 1621 if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { 1616 1622 logit("Disabling protocol version 2. Could not load host key"); 1617 1623 options.protocol &= ~SSH_PROTO_2; 1618 1624 } 1625 #endif 1619 1626 if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { 1620 1627 logit("sshd: no hostkeys available -- exiting."); 1621 1628 exit(1); … … main(int ac, char **av) 1944 1951 /* Log the connection. */ 1945 1952 verbose("Connection from %.500s port %d", remote_ip, remote_port); 1946 1953 1954 #ifdef USE_SECURITY_SESSION_API 1955 /* 1956 * Create a new security session for use by the new user login if 1957 * the current session is the root session or we are not launched 1958 * by inetd (eg: debugging mode or server mode). We do not 1959 * necessarily need to create a session if we are launched from 1960 * inetd because Panther xinetd will create a session for us. 1961 * 1962 * The only case where this logic will fail is if there is an 1963 * inetd running in a non-root session which is not creating 1964 * new sessions for us. Then all the users will end up in the 1965 * same session (bad). 1966 * 1967 * When the client exits, the session will be destroyed for us 1968 * automatically. 1969 * 1970 * We must create the session before any credentials are stored 1971 * (including AFS pags, which happens a few lines below). 1972 */ 1973 { 1974 OSStatus err = 0; 1975 SecuritySessionId sid = 0; 1976 SessionAttributeBits sattrs = 0; 1977 1978 err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); 1979 if (err) 1980 error("SessionGetInfo() failed with error %.8X", 1981 (unsigned) err); 1982 else 1983 debug("Current Session ID is %.8X / Session Attributes are %.8X", 1984 (unsigned) sid, (unsigned) sattrs); 1985 1986 if (inetd_flag && !(sattrs & sessionIsRoot)) 1987 debug("Running in inetd mode in a non-root session... " 1988 "assuming inetd created the session for us."); 1989 else { 1990 debug("Creating new security session..."); 1991 err = SessionCreate(0, sessionHasTTY | sessionIsRemote); 1992 if (err) 1993 error("SessionCreate() failed with error %.8X", 1994 (unsigned) err); 1995 1996 err = SessionGetInfo(callerSecuritySession, &sid, 1997 &sattrs); 1998 if (err) 1999 error("SessionGetInfo() failed with error %.8X", 2000 (unsigned) err); 2001 else 2002 debug("New Session ID is %.8X / Session Attributes are %.8X", 2003 (unsigned) sid, (unsigned) sattrs); 2004 } 2005 } 2006 #endif 2007 1947 2008 /* 1948 2009 * We don't want to listen forever unless the other side 1949 2010 * successfully authenticates itself. So we set up an alarm which is … … do_ssh2_kex(void) 2325 2386 2326 2387 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); 2327 2388 2389 #ifdef GSSAPI 2390 { 2391 char *orig; 2392 char *gss = NULL; 2393 char *newstr = NULL; 2394 orig = myproposal[PROPOSAL_KEX_ALGS]; 2395 2396 /* 2397 * If we don't have a host key, then there's no point advertising 2398 * the other key exchange algorithms 2399 */ 2400 2401 if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) 2402 orig = NULL; 2403 2404 if (options.gss_keyex) 2405 gss = ssh_gssapi_server_mechanisms(); 2406 else 2407 gss = NULL; 2408 2409 if (gss && orig) 2410 xasprintf(&newstr, "%s,%s", gss, orig); 2411 else if (gss) 2412 newstr = gss; 2413 else if (orig) 2414 newstr = orig; 2415 2416 /* 2417 * If we've got GSSAPI mechanisms, then we've got the 'null' host 2418 * key alg, but we can't tell people about it unless its the only 2419 * host key algorithm we support 2420 */ 2421 if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) 2422 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; 2423 2424 if (newstr) 2425 myproposal[PROPOSAL_KEX_ALGS] = newstr; 2426 else 2427 fatal("No supported key exchange algorithms"); 2428 } 2429 #endif 2430 2328 2431 /* start key exchange */ 2329 2432 kex = kex_setup(myproposal); 2330 2433 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; … … do_ssh2_kex(void) 2332 2435 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 2333 2436 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 2334 2437 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 2438 #ifdef GSSAPI 2439 if (options.gss_keyex) { 2440 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; 2441 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; 2442 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; 2443 } 2444 #endif 2335 2445 kex->server = 1; 2336 2446 kex->client_version_string=client_version_string; 2337 2447 kex->server_version_string=server_version_string; -
sshd_config
diff --git a/sshd_config b/sshd_config index 473e866..d02d7a7 100644
a b AuthorizedKeysFile .ssh/authorized_keys 75 75 # GSSAPI options 76 76 #GSSAPIAuthentication no 77 77 #GSSAPICleanupCredentials yes 78 #GSSAPIStrictAcceptorCheck yes 79 #GSSAPIKeyExchange no 78 80 79 81 # Set this to 'yes' to enable PAM authentication, account processing, 80 82 # and session processing. If this is enabled, PAM authentication will -
sshd_config.5
diff --git a/sshd_config.5 b/sshd_config.5 index a6c3787..76c95aa 100644
a b Specifies whether user authentication based on GSSAPI is allowed. 424 424 The default is 425 425 .Dq no . 426 426 Note that this option applies to protocol version 2 only. 427 .It Cm GSSAPIKeyExchange 428 Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 429 doesn't rely on ssh keys to verify host identity. 430 The default is 431 .Dq no . 432 Note that this option applies to protocol version 2 only. 427 433 .It Cm GSSAPICleanupCredentials 428 434 Specifies whether to automatically destroy the user's credentials cache 429 435 on logout. 430 436 The default is 431 437 .Dq yes . 432 438 Note that this option applies to protocol version 2 only. 439 .It Cm GSSAPIStrictAcceptorCheck 440 Determines whether to be strict about the identity of the GSSAPI acceptor 441 a client authenticates against. If 442 .Dq yes 443 then the client must authenticate against the 444 .Pa host 445 service on the current hostname. If 446 .Dq no 447 then the client may authenticate against any service key stored in the 448 machine's default store. This facility is provided to assist with operation 449 on multi homed machines. 450 The default is 451 .Dq yes . 452 Note that this option applies only to protocol version 2 GSSAPI connections, 453 and setting it to 454 .Dq no 455 may only work with recent Kerberos GSSAPI libraries. 456 .It Cm GSSAPIStoreCredentialsOnRekey 457 Controls whether the user's GSSAPI credentials should be updated following a 458 successful connection rekeying. This option can be used to accepted renewed 459 or updated credentials from a compatible client. The default is 460 .Dq no . 433 461 .It Cm HostbasedAuthentication 434 462 Specifies whether rhosts or /etc/hosts.equiv authentication together 435 463 with successful public key client host authentication is allowed