summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c140
1 files changed, 136 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 87fa70a40..a4ec75ca1 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -78,8 +78,6 @@
78#endif 78#endif
79 79
80/* import */ 80/* import */
81extern char *client_version_string;
82extern char *server_version_string;
83extern Options options; 81extern Options options;
84 82
85/* 83/*
@@ -161,6 +159,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
161 char *s, *all_key; 159 char *s, *all_key;
162 int r; 160 int r;
163 161
162#if defined(GSSAPI) && defined(WITH_OPENSSL)
163 char *orig = NULL, *gss = NULL;
164 char *gss_host = NULL;
165#endif
166
164 xxx_host = host; 167 xxx_host = host;
165 xxx_hostaddr = hostaddr; 168 xxx_hostaddr = hostaddr;
166 169
@@ -193,6 +196,35 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
193 order_hostkeyalgs(host, hostaddr, port)); 196 order_hostkeyalgs(host, hostaddr, port));
194 } 197 }
195 198
199#if defined(GSSAPI) && defined(WITH_OPENSSL)
200 if (options.gss_keyex) {
201 /* Add the GSSAPI mechanisms currently supported on this
202 * client to the key exchange algorithm proposal */
203 orig = myproposal[PROPOSAL_KEX_ALGS];
204
205 if (options.gss_server_identity)
206 gss_host = xstrdup(options.gss_server_identity);
207 else if (options.gss_trust_dns)
208 gss_host = remote_hostname(ssh);
209 else
210 gss_host = xstrdup(host);
211
212 gss = ssh_gssapi_client_mechanisms(gss_host,
213 options.gss_client_identity, options.gss_kex_algorithms);
214 if (gss) {
215 debug("Offering GSSAPI proposal: %s", gss);
216 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
217 "%s,%s", gss, orig);
218
219 /* If we've got GSSAPI algorithms, then we also support the
220 * 'null' hostkey, as a last resort */
221 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
222 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
223 "%s,null", orig);
224 }
225 }
226#endif
227
196 if (options.rekey_limit || options.rekey_interval) 228 if (options.rekey_limit || options.rekey_interval)
197 ssh_packet_set_rekey_limits(ssh, options.rekey_limit, 229 ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
198 options.rekey_interval); 230 options.rekey_interval);
@@ -211,16 +243,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
211# ifdef OPENSSL_HAS_ECC 243# ifdef OPENSSL_HAS_ECC
212 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; 244 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
213# endif 245# endif
246# ifdef GSSAPI
247 if (options.gss_keyex) {
248 ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
249 ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
250 ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client;
251 ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client;
252 ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client;
253 ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client;
254 ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client;
255 }
256# endif
214#endif 257#endif
215 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; 258 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
216 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; 259 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
217 ssh->kex->verify_host_key=&verify_host_key_callback; 260 ssh->kex->verify_host_key=&verify_host_key_callback;
218 261
262#if defined(GSSAPI) && defined(WITH_OPENSSL)
263 if (options.gss_keyex) {
264 ssh->kex->gss_deleg_creds = options.gss_deleg_creds;
265 ssh->kex->gss_trust_dns = options.gss_trust_dns;
266 ssh->kex->gss_client = options.gss_client_identity;
267 ssh->kex->gss_host = gss_host;
268 }
269#endif
270
219 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); 271 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
220 272
221 /* remove ext-info from the KEX proposals for rekeying */ 273 /* remove ext-info from the KEX proposals for rekeying */
222 myproposal[PROPOSAL_KEX_ALGS] = 274 myproposal[PROPOSAL_KEX_ALGS] =
223 compat_kex_proposal(options.kex_algorithms); 275 compat_kex_proposal(options.kex_algorithms);
276#if defined(GSSAPI) && defined(WITH_OPENSSL)
277 /* repair myproposal after it was crumpled by the */
278 /* ext-info removal above */
279 if (gss) {
280 orig = myproposal[PROPOSAL_KEX_ALGS];
281 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
282 "%s,%s", gss, orig);
283 free(gss);
284 }
285#endif
224 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) 286 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
225 fatal("kex_prop2buf: %s", ssh_err(r)); 287 fatal("kex_prop2buf: %s", ssh_err(r));
226 288
@@ -317,6 +379,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *);
317static int input_gssapi_token(int type, u_int32_t, struct ssh *); 379static int input_gssapi_token(int type, u_int32_t, struct ssh *);
318static int input_gssapi_error(int, u_int32_t, struct ssh *); 380static int input_gssapi_error(int, u_int32_t, struct ssh *);
319static int input_gssapi_errtok(int, u_int32_t, struct ssh *); 381static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
382static int userauth_gsskeyex(struct ssh *);
320#endif 383#endif
321 384
322void userauth(struct ssh *, char *); 385void userauth(struct ssh *, char *);
@@ -333,6 +396,11 @@ static char *authmethods_get(void);
333 396
334Authmethod authmethods[] = { 397Authmethod authmethods[] = {
335#ifdef GSSAPI 398#ifdef GSSAPI
399 {"gssapi-keyex",
400 userauth_gsskeyex,
401 NULL,
402 &options.gss_keyex,
403 NULL},
336 {"gssapi-with-mic", 404 {"gssapi-with-mic",
337 userauth_gssapi, 405 userauth_gssapi,
338 userauth_gssapi_cleanup, 406 userauth_gssapi_cleanup,
@@ -697,12 +765,25 @@ userauth_gssapi(struct ssh *ssh)
697 OM_uint32 min; 765 OM_uint32 min;
698 int r, ok = 0; 766 int r, ok = 0;
699 gss_OID mech = NULL; 767 gss_OID mech = NULL;
768 char *gss_host;
769
770 if (options.gss_server_identity)
771 gss_host = xstrdup(options.gss_server_identity);
772 else if (options.gss_trust_dns)
773 gss_host = remote_hostname(ssh);
774 else
775 gss_host = xstrdup(authctxt->host);
700 776
701 /* Try one GSSAPI method at a time, rather than sending them all at 777 /* Try one GSSAPI method at a time, rather than sending them all at
702 * once. */ 778 * once. */
703 779
704 if (authctxt->gss_supported_mechs == NULL) 780 if (authctxt->gss_supported_mechs == NULL)
705 gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); 781 if (GSS_ERROR(gss_indicate_mechs(&min,
782 &authctxt->gss_supported_mechs))) {
783 authctxt->gss_supported_mechs = NULL;
784 free(gss_host);
785 return 0;
786 }
706 787
707 /* Check to see whether the mechanism is usable before we offer it */ 788 /* Check to see whether the mechanism is usable before we offer it */
708 while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && 789 while (authctxt->mech_tried < authctxt->gss_supported_mechs->count &&
@@ -711,13 +792,15 @@ userauth_gssapi(struct ssh *ssh)
711 elements[authctxt->mech_tried]; 792 elements[authctxt->mech_tried];
712 /* My DER encoding requires length<128 */ 793 /* My DER encoding requires length<128 */
713 if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, 794 if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt,
714 mech, authctxt->host)) { 795 mech, gss_host, options.gss_client_identity)) {
715 ok = 1; /* Mechanism works */ 796 ok = 1; /* Mechanism works */
716 } else { 797 } else {
717 authctxt->mech_tried++; 798 authctxt->mech_tried++;
718 } 799 }
719 } 800 }
720 801
802 free(gss_host);
803
721 if (!ok || mech == NULL) 804 if (!ok || mech == NULL)
722 return 0; 805 return 0;
723 806
@@ -957,6 +1040,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
957 free(lang); 1040 free(lang);
958 return r; 1041 return r;
959} 1042}
1043
1044int
1045userauth_gsskeyex(struct ssh *ssh)
1046{
1047 struct sshbuf *b = NULL;
1048 Authctxt *authctxt = ssh->authctxt;
1049 gss_buffer_desc gssbuf;
1050 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
1051 OM_uint32 ms;
1052 int r;
1053
1054 static int attempt = 0;
1055 if (attempt++ >= 1)
1056 return (0);
1057
1058 if (gss_kex_context == NULL) {
1059 debug("No valid Key exchange context");
1060 return (0);
1061 }
1062
1063 if ((b = sshbuf_new()) == NULL)
1064 fatal("%s: sshbuf_new failed", __func__);
1065
1066 ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
1067 "gssapi-keyex");
1068
1069 if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
1070 fatal("%s: sshbuf_mutable_ptr failed", __func__);
1071 gssbuf.length = sshbuf_len(b);
1072
1073 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
1074 sshbuf_free(b);
1075 return (0);
1076 }
1077
1078 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1079 (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
1080 (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
1081 (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
1082 (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 ||
1083 (r = sshpkt_send(ssh)) != 0)
1084 fatal("%s: %s", __func__, ssh_err(r));
1085
1086 sshbuf_free(b);
1087 gss_release_buffer(&ms, &mic);
1088
1089 return (1);
1090}
1091
960#endif /* GSSAPI */ 1092#endif /* GSSAPI */
961 1093
962static int 1094static int