summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c118
1 files changed, 114 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 2a5943e7e..5bf11c085 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -106,9 +106,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
106{ 106{
107 Kex *kex; 107 Kex *kex;
108 108
109#ifdef GSSAPI
110 char *orig = NULL, *gss = NULL;
111 char *gss_host = NULL;
112#endif
113
109 xxx_host = host; 114 xxx_host = host;
110 xxx_hostaddr = hostaddr; 115 xxx_hostaddr = hostaddr;
111 116
117#ifdef GSSAPI
118 if (options.gss_keyex) {
119 /* Add the GSSAPI mechanisms currently supported on this
120 * client to the key exchange algorithm proposal */
121 orig = myproposal[PROPOSAL_KEX_ALGS];
122
123 if (options.gss_trust_dns)
124 gss_host = (char *)get_canonical_hostname(1);
125 else
126 gss_host = host;
127
128 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
129 if (gss) {
130 debug("Offering GSSAPI proposal: %s", gss);
131 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
132 "%s,%s", gss, orig);
133 }
134 }
135#endif
136
112 if (options.ciphers == (char *)-1) { 137 if (options.ciphers == (char *)-1) {
113 logit("No valid ciphers for protocol version 2 given, using defaults."); 138 logit("No valid ciphers for protocol version 2 given, using defaults.");
114 options.ciphers = NULL; 139 options.ciphers = NULL;
@@ -136,6 +161,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
136 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 161 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
137 options.hostkeyalgorithms; 162 options.hostkeyalgorithms;
138 163
164#ifdef GSSAPI
165 /* If we've got GSSAPI algorithms, then we also support the
166 * 'null' hostkey, as a last resort */
167 if (options.gss_keyex && gss) {
168 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
169 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
170 "%s,null", orig);
171 xfree(gss);
172 }
173#endif
174
139 if (options.rekey_limit) 175 if (options.rekey_limit)
140 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 176 packet_set_rekey_limit((u_int32_t)options.rekey_limit);
141 177
@@ -145,10 +181,26 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
145 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 181 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
146 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 182 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
147 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 183 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
184#ifdef GSSAPI
185 if (options.gss_keyex) {
186 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
187 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
188 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
189 }
190#endif
148 kex->client_version_string=client_version_string; 191 kex->client_version_string=client_version_string;
149 kex->server_version_string=server_version_string; 192 kex->server_version_string=server_version_string;
150 kex->verify_host_key=&verify_host_key_callback; 193 kex->verify_host_key=&verify_host_key_callback;
151 194
195#ifdef GSSAPI
196 if (options.gss_keyex) {
197 kex->gss_deleg_creds = options.gss_deleg_creds;
198 kex->gss_trust_dns = options.gss_trust_dns;
199 kex->gss_client = options.gss_client_identity;
200 kex->gss_host = gss_host;
201 }
202#endif
203
152 xxx_kex = kex; 204 xxx_kex = kex;
153 205
154 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 206 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -243,6 +295,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
243void input_gssapi_hash(int type, u_int32_t, void *); 295void input_gssapi_hash(int type, u_int32_t, void *);
244void input_gssapi_error(int, u_int32_t, void *); 296void input_gssapi_error(int, u_int32_t, void *);
245void input_gssapi_errtok(int, u_int32_t, void *); 297void input_gssapi_errtok(int, u_int32_t, void *);
298int userauth_gsskeyex(Authctxt *authctxt);
246#endif 299#endif
247 300
248void userauth(Authctxt *, char *); 301void userauth(Authctxt *, char *);
@@ -258,6 +311,11 @@ static char *authmethods_get(void);
258 311
259Authmethod authmethods[] = { 312Authmethod authmethods[] = {
260#ifdef GSSAPI 313#ifdef GSSAPI
314 {"gssapi-keyex",
315 userauth_gsskeyex,
316 NULL,
317 &options.gss_authentication,
318 NULL},
261 {"gssapi-with-mic", 319 {"gssapi-with-mic",
262 userauth_gssapi, 320 userauth_gssapi,
263 NULL, 321 NULL,
@@ -564,19 +622,29 @@ userauth_gssapi(Authctxt *authctxt)
564 static u_int mech = 0; 622 static u_int mech = 0;
565 OM_uint32 min; 623 OM_uint32 min;
566 int ok = 0; 624 int ok = 0;
625 const char *gss_host;
626
627 if (options.gss_trust_dns)
628 gss_host = get_canonical_hostname(1);
629 else
630 gss_host = authctxt->host;
567 631
568 /* Try one GSSAPI method at a time, rather than sending them all at 632 /* Try one GSSAPI method at a time, rather than sending them all at
569 * once. */ 633 * once. */
570 634
571 if (gss_supported == NULL) 635 if (gss_supported == NULL)
572 gss_indicate_mechs(&min, &gss_supported); 636 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
637 gss_supported = NULL;
638 return 0;
639 }
573 640
574 /* Check to see if the mechanism is usable before we offer it */ 641 /* Check to see if the mechanism is usable before we offer it */
575 while (mech < gss_supported->count && !ok) { 642 while (mech < gss_supported->count && !ok) {
576 /* My DER encoding requires length<128 */ 643 /* My DER encoding requires length<128 */
577 if (gss_supported->elements[mech].length < 128 && 644 if (gss_supported->elements[mech].length < 128 &&
578 ssh_gssapi_check_mechanism(&gssctxt, 645 ssh_gssapi_check_mechanism(&gssctxt,
579 &gss_supported->elements[mech], authctxt->host)) { 646 &gss_supported->elements[mech], gss_host,
647 options.gss_client_identity)) {
580 ok = 1; /* Mechanism works */ 648 ok = 1; /* Mechanism works */
581 } else { 649 } else {
582 mech++; 650 mech++;
@@ -673,8 +741,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
673{ 741{
674 Authctxt *authctxt = ctxt; 742 Authctxt *authctxt = ctxt;
675 Gssctxt *gssctxt; 743 Gssctxt *gssctxt;
676 int oidlen; 744 u_int oidlen;
677 char *oidv; 745 u_char *oidv;
678 746
679 if (authctxt == NULL) 747 if (authctxt == NULL)
680 fatal("input_gssapi_response: no authentication context"); 748 fatal("input_gssapi_response: no authentication context");
@@ -784,6 +852,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
784 xfree(msg); 852 xfree(msg);
785 xfree(lang); 853 xfree(lang);
786} 854}
855
856int
857userauth_gsskeyex(Authctxt *authctxt)
858{
859 Buffer b;
860 gss_buffer_desc gssbuf;
861 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
862 OM_uint32 ms;
863
864 static int attempt = 0;
865 if (attempt++ >= 1)
866 return (0);
867
868 if (gss_kex_context == NULL) {
869 debug("No valid Key exchange context");
870 return (0);
871 }
872
873 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
874 "gssapi-keyex");
875
876 gssbuf.value = buffer_ptr(&b);
877 gssbuf.length = buffer_len(&b);
878
879 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
880 buffer_free(&b);
881 return (0);
882 }
883
884 packet_start(SSH2_MSG_USERAUTH_REQUEST);
885 packet_put_cstring(authctxt->server_user);
886 packet_put_cstring(authctxt->service);
887 packet_put_cstring(authctxt->method->name);
888 packet_put_string(mic.value, mic.length);
889 packet_send();
890
891 buffer_free(&b);
892 gss_release_buffer(&ms, &mic);
893
894 return (1);
895}
896
787#endif /* GSSAPI */ 897#endif /* GSSAPI */
788 898
789int 899int