summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c133
1 files changed, 131 insertions, 2 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 1675f3935..8c872a4fb 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -162,6 +162,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
162 struct kex *kex; 162 struct kex *kex;
163 int r; 163 int r;
164 164
165#ifdef GSSAPI
166 char *orig = NULL, *gss = NULL;
167 char *gss_host = NULL;
168#endif
169
165 xxx_host = host; 170 xxx_host = host;
166 xxx_hostaddr = hostaddr; 171 xxx_hostaddr = hostaddr;
167 172
@@ -194,6 +199,35 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
194 order_hostkeyalgs(host, hostaddr, port)); 199 order_hostkeyalgs(host, hostaddr, port));
195 } 200 }
196 201
202#ifdef GSSAPI
203 if (options.gss_keyex) {
204 /* Add the GSSAPI mechanisms currently supported on this
205 * client to the key exchange algorithm proposal */
206 orig = myproposal[PROPOSAL_KEX_ALGS];
207
208 if (options.gss_server_identity)
209 gss_host = xstrdup(options.gss_server_identity);
210 else if (options.gss_trust_dns)
211 gss_host = remote_hostname(active_state);
212 else
213 gss_host = xstrdup(host);
214
215 gss = ssh_gssapi_client_mechanisms(gss_host,
216 options.gss_client_identity);
217 if (gss) {
218 debug("Offering GSSAPI proposal: %s", gss);
219 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
220 "%s,%s", gss, orig);
221
222 /* If we've got GSSAPI algorithms, then we also
223 * support the 'null' hostkey, as a last resort */
224 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
225 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
226 "%s,null", orig);
227 }
228 }
229#endif
230
197 if (options.rekey_limit || options.rekey_interval) 231 if (options.rekey_limit || options.rekey_interval)
198 packet_set_rekey_limits(options.rekey_limit, 232 packet_set_rekey_limits(options.rekey_limit,
199 options.rekey_interval); 233 options.rekey_interval);
@@ -215,15 +249,41 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
215# endif 249# endif
216#endif 250#endif
217 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 251 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
252#ifdef GSSAPI
253 if (options.gss_keyex) {
254 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
255 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
256 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
257 }
258#endif
218 kex->client_version_string=client_version_string; 259 kex->client_version_string=client_version_string;
219 kex->server_version_string=server_version_string; 260 kex->server_version_string=server_version_string;
220 kex->verify_host_key=&verify_host_key_callback; 261 kex->verify_host_key=&verify_host_key_callback;
221 262
263#ifdef GSSAPI
264 if (options.gss_keyex) {
265 kex->gss_deleg_creds = options.gss_deleg_creds;
266 kex->gss_trust_dns = options.gss_trust_dns;
267 kex->gss_client = options.gss_client_identity;
268 kex->gss_host = gss_host;
269 }
270#endif
271
222 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); 272 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
223 273
224 /* remove ext-info from the KEX proposals for rekeying */ 274 /* remove ext-info from the KEX proposals for rekeying */
225 myproposal[PROPOSAL_KEX_ALGS] = 275 myproposal[PROPOSAL_KEX_ALGS] =
226 compat_kex_proposal(options.kex_algorithms); 276 compat_kex_proposal(options.kex_algorithms);
277#ifdef GSSAPI
278 /* repair myproposal after it was crumpled by the */
279 /* ext-info removal above */
280 if (gss) {
281 orig = myproposal[PROPOSAL_KEX_ALGS];
282 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
283 "%s,%s", gss, orig);
284 free(gss);
285 }
286#endif
227 if ((r = kex_prop2buf(kex->my, myproposal)) != 0) 287 if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
228 fatal("kex_prop2buf: %s", ssh_err(r)); 288 fatal("kex_prop2buf: %s", ssh_err(r));
229 289
@@ -314,6 +374,7 @@ int input_gssapi_token(int type, u_int32_t, struct ssh *);
314int input_gssapi_hash(int type, u_int32_t, struct ssh *); 374int input_gssapi_hash(int type, u_int32_t, struct ssh *);
315int input_gssapi_error(int, u_int32_t, struct ssh *); 375int input_gssapi_error(int, u_int32_t, struct ssh *);
316int input_gssapi_errtok(int, u_int32_t, struct ssh *); 376int input_gssapi_errtok(int, u_int32_t, struct ssh *);
377int userauth_gsskeyex(Authctxt *authctxt);
317#endif 378#endif
318 379
319void userauth(Authctxt *, char *); 380void userauth(Authctxt *, char *);
@@ -330,6 +391,11 @@ static char *authmethods_get(void);
330 391
331Authmethod authmethods[] = { 392Authmethod authmethods[] = {
332#ifdef GSSAPI 393#ifdef GSSAPI
394 {"gssapi-keyex",
395 userauth_gsskeyex,
396 NULL,
397 &options.gss_authentication,
398 NULL},
333 {"gssapi-with-mic", 399 {"gssapi-with-mic",
334 userauth_gssapi, 400 userauth_gssapi,
335 NULL, 401 NULL,
@@ -686,25 +752,40 @@ userauth_gssapi(Authctxt *authctxt)
686 static u_int mech = 0; 752 static u_int mech = 0;
687 OM_uint32 min; 753 OM_uint32 min;
688 int r, ok = 0; 754 int r, ok = 0;
755 char *gss_host;
756
757 if (options.gss_server_identity)
758 gss_host = xstrdup(options.gss_server_identity);
759 else if (options.gss_trust_dns)
760 gss_host = remote_hostname(active_state);
761 else
762 gss_host = xstrdup(authctxt->host);
689 763
690 /* Try one GSSAPI method at a time, rather than sending them all at 764 /* Try one GSSAPI method at a time, rather than sending them all at
691 * once. */ 765 * once. */
692 766
693 if (gss_supported == NULL) 767 if (gss_supported == NULL)
694 gss_indicate_mechs(&min, &gss_supported); 768 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
769 gss_supported = NULL;
770 free(gss_host);
771 return 0;
772 }
695 773
696 /* Check to see if the mechanism is usable before we offer it */ 774 /* Check to see if the mechanism is usable before we offer it */
697 while (mech < gss_supported->count && !ok) { 775 while (mech < gss_supported->count && !ok) {
698 /* My DER encoding requires length<128 */ 776 /* My DER encoding requires length<128 */
699 if (gss_supported->elements[mech].length < 128 && 777 if (gss_supported->elements[mech].length < 128 &&
700 ssh_gssapi_check_mechanism(&gssctxt, 778 ssh_gssapi_check_mechanism(&gssctxt,
701 &gss_supported->elements[mech], authctxt->host)) { 779 &gss_supported->elements[mech], gss_host,
780 options.gss_client_identity)) {
702 ok = 1; /* Mechanism works */ 781 ok = 1; /* Mechanism works */
703 } else { 782 } else {
704 mech++; 783 mech++;
705 } 784 }
706 } 785 }
707 786
787 free(gss_host);
788
708 if (!ok) 789 if (!ok)
709 return 0; 790 return 0;
710 791
@@ -935,6 +1016,54 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
935 free(lang); 1016 free(lang);
936 return r; 1017 return r;
937} 1018}
1019
1020int
1021userauth_gsskeyex(Authctxt *authctxt)
1022{
1023 struct ssh *ssh = active_state; /* XXX */
1024 struct sshbuf *b;
1025 gss_buffer_desc gssbuf;
1026 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
1027 OM_uint32 ms;
1028 int r;
1029
1030 static int attempt = 0;
1031 if (attempt++ >= 1)
1032 return (0);
1033
1034 if (gss_kex_context == NULL) {
1035 debug("No valid Key exchange context");
1036 return (0);
1037 }
1038
1039 if ((b = sshbuf_new()) == NULL)
1040 fatal("%s: sshbuf_new failed", __func__);
1041 ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
1042 "gssapi-keyex");
1043
1044 if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
1045 fatal("%s: sshbuf_mutable_ptr failed", __func__);
1046 gssbuf.length = sshbuf_len(b);
1047
1048 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
1049 sshbuf_free(b);
1050 return (0);
1051 }
1052
1053 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1054 (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
1055 (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
1056 (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
1057 (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 ||
1058 (r = sshpkt_send(ssh)) != 0)
1059 fatal("%s: %s", __func__, ssh_err(r));
1060
1061 sshbuf_free(b);
1062 gss_release_buffer(&ms, &mic);
1063
1064 return (1);
1065}
1066
938#endif /* GSSAPI */ 1067#endif /* GSSAPI */
939 1068
940int 1069int