summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c154
1 files changed, 149 insertions, 5 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index f64aae66a..c47fc31a6 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -80,8 +80,6 @@
80#endif 80#endif
81 81
82/* import */ 82/* import */
83extern char *client_version_string;
84extern char *server_version_string;
85extern Options options; 83extern Options options;
86 84
87/* 85/*
@@ -210,6 +208,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
210 char *s, *all_key; 208 char *s, *all_key;
211 int r, use_known_hosts_order = 0; 209 int r, use_known_hosts_order = 0;
212 210
211#if defined(GSSAPI) && defined(WITH_OPENSSL)
212 char *orig = NULL, *gss = NULL;
213 char *gss_host = NULL;
214#endif
215
213 xxx_host = host; 216 xxx_host = host;
214 xxx_hostaddr = hostaddr; 217 xxx_hostaddr = hostaddr;
215 218
@@ -253,6 +256,41 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
253 compat_pkalg_proposal(options.hostkeyalgorithms); 256 compat_pkalg_proposal(options.hostkeyalgorithms);
254 } 257 }
255 258
259#if defined(GSSAPI) && defined(WITH_OPENSSL)
260 if (options.gss_keyex) {
261 /* Add the GSSAPI mechanisms currently supported on this
262 * client to the key exchange algorithm proposal */
263 orig = myproposal[PROPOSAL_KEX_ALGS];
264
265 if (options.gss_server_identity) {
266 gss_host = xstrdup(options.gss_server_identity);
267 } else if (options.gss_trust_dns) {
268 gss_host = remote_hostname(ssh);
269 /* Fall back to specified host if we are using proxy command
270 * and can not use DNS on that socket */
271 if (strcmp(gss_host, "UNKNOWN") == 0) {
272 gss_host = xstrdup(host);
273 }
274 } else {
275 gss_host = xstrdup(host);
276 }
277
278 gss = ssh_gssapi_client_mechanisms(gss_host,
279 options.gss_client_identity, options.gss_kex_algorithms);
280 if (gss) {
281 debug("Offering GSSAPI proposal: %s", gss);
282 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
283 "%s,%s", gss, orig);
284
285 /* If we've got GSSAPI algorithms, then we also support the
286 * 'null' hostkey, as a last resort */
287 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
288 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
289 "%s,null", orig);
290 }
291 }
292#endif
293
256 if (options.rekey_limit || options.rekey_interval) 294 if (options.rekey_limit || options.rekey_interval)
257 ssh_packet_set_rekey_limits(ssh, options.rekey_limit, 295 ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
258 options.rekey_interval); 296 options.rekey_interval);
@@ -271,16 +309,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
271# ifdef OPENSSL_HAS_ECC 309# ifdef OPENSSL_HAS_ECC
272 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; 310 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
273# endif 311# endif
274#endif 312# ifdef GSSAPI
313 if (options.gss_keyex) {
314 ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
315 ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
316 ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client;
317 ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client;
318 ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client;
319 ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client;
320 ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client;
321 }
322# endif
323#endif /* WITH_OPENSSL */
275 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; 324 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
276 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; 325 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
277 ssh->kex->verify_host_key=&verify_host_key_callback; 326 ssh->kex->verify_host_key=&verify_host_key_callback;
278 327
328#if defined(GSSAPI) && defined(WITH_OPENSSL)
329 if (options.gss_keyex) {
330 ssh->kex->gss_deleg_creds = options.gss_deleg_creds;
331 ssh->kex->gss_trust_dns = options.gss_trust_dns;
332 ssh->kex->gss_client = options.gss_client_identity;
333 ssh->kex->gss_host = gss_host;
334 }
335#endif
336
279 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); 337 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
280 338
281 /* remove ext-info from the KEX proposals for rekeying */ 339 /* remove ext-info from the KEX proposals for rekeying */
282 myproposal[PROPOSAL_KEX_ALGS] = 340 myproposal[PROPOSAL_KEX_ALGS] =
283 compat_kex_proposal(options.kex_algorithms); 341 compat_kex_proposal(options.kex_algorithms);
342#if defined(GSSAPI) && defined(WITH_OPENSSL)
343 /* repair myproposal after it was crumpled by the */
344 /* ext-info removal above */
345 if (gss) {
346 orig = myproposal[PROPOSAL_KEX_ALGS];
347 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
348 "%s,%s", gss, orig);
349 free(gss);
350 }
351#endif
284 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) 352 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
285 fatal("kex_prop2buf: %s", ssh_err(r)); 353 fatal("kex_prop2buf: %s", ssh_err(r));
286 354
@@ -377,6 +445,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *);
377static int input_gssapi_token(int type, u_int32_t, struct ssh *); 445static int input_gssapi_token(int type, u_int32_t, struct ssh *);
378static int input_gssapi_error(int, u_int32_t, struct ssh *); 446static int input_gssapi_error(int, u_int32_t, struct ssh *);
379static int input_gssapi_errtok(int, u_int32_t, struct ssh *); 447static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
448static int userauth_gsskeyex(struct ssh *);
380#endif 449#endif
381 450
382void userauth(struct ssh *, char *); 451void userauth(struct ssh *, char *);
@@ -393,6 +462,11 @@ static char *authmethods_get(void);
393 462
394Authmethod authmethods[] = { 463Authmethod authmethods[] = {
395#ifdef GSSAPI 464#ifdef GSSAPI
465 {"gssapi-keyex",
466 userauth_gsskeyex,
467 NULL,
468 &options.gss_keyex,
469 NULL},
396 {"gssapi-with-mic", 470 {"gssapi-with-mic",
397 userauth_gssapi, 471 userauth_gssapi,
398 userauth_gssapi_cleanup, 472 userauth_gssapi_cleanup,
@@ -763,12 +837,31 @@ userauth_gssapi(struct ssh *ssh)
763 OM_uint32 min; 837 OM_uint32 min;
764 int r, ok = 0; 838 int r, ok = 0;
765 gss_OID mech = NULL; 839 gss_OID mech = NULL;
840 char *gss_host;
841
842 if (options.gss_server_identity) {
843 gss_host = xstrdup(options.gss_server_identity);
844 } else if (options.gss_trust_dns) {
845 gss_host = remote_hostname(ssh);
846 /* Fall back to specified host if we are using proxy command
847 * and can not use DNS on that socket */
848 if (strcmp(gss_host, "UNKNOWN") == 0) {
849 gss_host = authctxt->host;
850 }
851 } else {
852 gss_host = xstrdup(authctxt->host);
853 }
766 854
767 /* Try one GSSAPI method at a time, rather than sending them all at 855 /* Try one GSSAPI method at a time, rather than sending them all at
768 * once. */ 856 * once. */
769 857
770 if (authctxt->gss_supported_mechs == NULL) 858 if (authctxt->gss_supported_mechs == NULL)
771 gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); 859 if (GSS_ERROR(gss_indicate_mechs(&min,
860 &authctxt->gss_supported_mechs))) {
861 authctxt->gss_supported_mechs = NULL;
862 free(gss_host);
863 return 0;
864 }
772 865
773 /* Check to see whether the mechanism is usable before we offer it */ 866 /* Check to see whether the mechanism is usable before we offer it */
774 while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && 867 while (authctxt->mech_tried < authctxt->gss_supported_mechs->count &&
@@ -777,13 +870,15 @@ userauth_gssapi(struct ssh *ssh)
777 elements[authctxt->mech_tried]; 870 elements[authctxt->mech_tried];
778 /* My DER encoding requires length<128 */ 871 /* My DER encoding requires length<128 */
779 if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, 872 if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt,
780 mech, authctxt->host)) { 873 mech, gss_host, options.gss_client_identity)) {
781 ok = 1; /* Mechanism works */ 874 ok = 1; /* Mechanism works */
782 } else { 875 } else {
783 authctxt->mech_tried++; 876 authctxt->mech_tried++;
784 } 877 }
785 } 878 }
786 879
880 free(gss_host);
881
787 if (!ok || mech == NULL) 882 if (!ok || mech == NULL)
788 return 0; 883 return 0;
789 884
@@ -1023,6 +1118,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
1023 free(lang); 1118 free(lang);
1024 return r; 1119 return r;
1025} 1120}
1121
1122int
1123userauth_gsskeyex(struct ssh *ssh)
1124{
1125 struct sshbuf *b = NULL;
1126 Authctxt *authctxt = ssh->authctxt;
1127 gss_buffer_desc gssbuf;
1128 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
1129 OM_uint32 ms;
1130 int r;
1131
1132 static int attempt = 0;
1133 if (attempt++ >= 1)
1134 return (0);
1135
1136 if (gss_kex_context == NULL) {
1137 debug("No valid Key exchange context");
1138 return (0);
1139 }
1140
1141 if ((b = sshbuf_new()) == NULL)
1142 fatal("%s: sshbuf_new failed", __func__);
1143
1144 ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
1145 "gssapi-keyex");
1146
1147 if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
1148 fatal("%s: sshbuf_mutable_ptr failed", __func__);
1149 gssbuf.length = sshbuf_len(b);
1150
1151 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
1152 sshbuf_free(b);
1153 return (0);
1154 }
1155
1156 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1157 (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
1158 (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
1159 (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
1160 (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 ||
1161 (r = sshpkt_send(ssh)) != 0)
1162 fatal("%s: %s", __func__, ssh_err(r));
1163
1164 sshbuf_free(b);
1165 gss_release_buffer(&ms, &mic);
1166
1167 return (1);
1168}
1169
1026#endif /* GSSAPI */ 1170#endif /* GSSAPI */
1027 1171
1028static int 1172static int