summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c124
1 files changed, 120 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 70e3cd8c9..0b13530ce 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -160,9 +160,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
160{ 160{
161 Kex *kex; 161 Kex *kex;
162 162
163#ifdef GSSAPI
164 char *orig = NULL, *gss = NULL;
165 char *gss_host = NULL;
166#endif
167
163 xxx_host = host; 168 xxx_host = host;
164 xxx_hostaddr = hostaddr; 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 if (options.ciphers == (char *)-1) { 191 if (options.ciphers == (char *)-1) {
167 logit("No valid ciphers for protocol version 2 given, using defaults."); 192 logit("No valid ciphers for protocol version 2 given, using defaults.");
168 options.ciphers = NULL; 193 options.ciphers = NULL;
@@ -197,6 +222,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
197 if (options.kex_algorithms != NULL) 222 if (options.kex_algorithms != NULL)
198 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 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 free(gss);
233 }
234#endif
235
200 if (options.rekey_limit || options.rekey_interval) 236 if (options.rekey_limit || options.rekey_interval)
201 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 237 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
202 (time_t)options.rekey_interval); 238 (time_t)options.rekey_interval);
@@ -208,10 +244,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
208 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 244 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
209 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 245 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
210 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 246 kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
247#ifdef GSSAPI
248 if (options.gss_keyex) {
249 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
250 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
251 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
252 }
253#endif
211 kex->client_version_string=client_version_string; 254 kex->client_version_string=client_version_string;
212 kex->server_version_string=server_version_string; 255 kex->server_version_string=server_version_string;
213 kex->verify_host_key=&verify_host_key_callback; 256 kex->verify_host_key=&verify_host_key_callback;
214 257
258#ifdef GSSAPI
259 if (options.gss_keyex) {
260 kex->gss_deleg_creds = options.gss_deleg_creds;
261 kex->gss_trust_dns = options.gss_trust_dns;
262 kex->gss_client = options.gss_client_identity;
263 if (options.gss_server_identity) {
264 kex->gss_host = options.gss_server_identity;
265 } else {
266 kex->gss_host = gss_host;
267 }
268 }
269#endif
270
215 xxx_kex = kex; 271 xxx_kex = kex;
216 272
217 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 273 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -307,6 +363,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
307void input_gssapi_hash(int type, u_int32_t, void *); 363void input_gssapi_hash(int type, u_int32_t, void *);
308void input_gssapi_error(int, u_int32_t, void *); 364void input_gssapi_error(int, u_int32_t, void *);
309void input_gssapi_errtok(int, u_int32_t, void *); 365void input_gssapi_errtok(int, u_int32_t, void *);
366int userauth_gsskeyex(Authctxt *authctxt);
310#endif 367#endif
311 368
312void userauth(Authctxt *, char *); 369void userauth(Authctxt *, char *);
@@ -322,6 +379,11 @@ static char *authmethods_get(void);
322 379
323Authmethod authmethods[] = { 380Authmethod authmethods[] = {
324#ifdef GSSAPI 381#ifdef GSSAPI
382 {"gssapi-keyex",
383 userauth_gsskeyex,
384 NULL,
385 &options.gss_authentication,
386 NULL},
325 {"gssapi-with-mic", 387 {"gssapi-with-mic",
326 userauth_gssapi, 388 userauth_gssapi,
327 NULL, 389 NULL,
@@ -625,19 +687,31 @@ userauth_gssapi(Authctxt *authctxt)
625 static u_int mech = 0; 687 static u_int mech = 0;
626 OM_uint32 min; 688 OM_uint32 min;
627 int ok = 0; 689 int ok = 0;
690 const char *gss_host;
691
692 if (options.gss_server_identity)
693 gss_host = options.gss_server_identity;
694 else if (options.gss_trust_dns)
695 gss_host = get_canonical_hostname(1);
696 else
697 gss_host = authctxt->host;
628 698
629 /* Try one GSSAPI method at a time, rather than sending them all at 699 /* Try one GSSAPI method at a time, rather than sending them all at
630 * once. */ 700 * once. */
631 701
632 if (gss_supported == NULL) 702 if (gss_supported == NULL)
633 gss_indicate_mechs(&min, &gss_supported); 703 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
704 gss_supported = NULL;
705 return 0;
706 }
634 707
635 /* Check to see if the mechanism is usable before we offer it */ 708 /* Check to see if the mechanism is usable before we offer it */
636 while (mech < gss_supported->count && !ok) { 709 while (mech < gss_supported->count && !ok) {
637 /* My DER encoding requires length<128 */ 710 /* My DER encoding requires length<128 */
638 if (gss_supported->elements[mech].length < 128 && 711 if (gss_supported->elements[mech].length < 128 &&
639 ssh_gssapi_check_mechanism(&gssctxt, 712 ssh_gssapi_check_mechanism(&gssctxt,
640 &gss_supported->elements[mech], authctxt->host)) { 713 &gss_supported->elements[mech], gss_host,
714 options.gss_client_identity)) {
641 ok = 1; /* Mechanism works */ 715 ok = 1; /* Mechanism works */
642 } else { 716 } else {
643 mech++; 717 mech++;
@@ -734,8 +808,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
734{ 808{
735 Authctxt *authctxt = ctxt; 809 Authctxt *authctxt = ctxt;
736 Gssctxt *gssctxt; 810 Gssctxt *gssctxt;
737 int oidlen; 811 u_int oidlen;
738 char *oidv; 812 u_char *oidv;
739 813
740 if (authctxt == NULL) 814 if (authctxt == NULL)
741 fatal("input_gssapi_response: no authentication context"); 815 fatal("input_gssapi_response: no authentication context");
@@ -844,6 +918,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
844 free(msg); 918 free(msg);
845 free(lang); 919 free(lang);
846} 920}
921
922int
923userauth_gsskeyex(Authctxt *authctxt)
924{
925 Buffer b;
926 gss_buffer_desc gssbuf;
927 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
928 OM_uint32 ms;
929
930 static int attempt = 0;
931 if (attempt++ >= 1)
932 return (0);
933
934 if (gss_kex_context == NULL) {
935 debug("No valid Key exchange context");
936 return (0);
937 }
938
939 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
940 "gssapi-keyex");
941
942 gssbuf.value = buffer_ptr(&b);
943 gssbuf.length = buffer_len(&b);
944
945 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
946 buffer_free(&b);
947 return (0);
948 }
949
950 packet_start(SSH2_MSG_USERAUTH_REQUEST);
951 packet_put_cstring(authctxt->server_user);
952 packet_put_cstring(authctxt->service);
953 packet_put_cstring(authctxt->method->name);
954 packet_put_string(mic.value, mic.length);
955 packet_send();
956
957 buffer_free(&b);
958 gss_release_buffer(&ms, &mic);
959
960 return (1);
961}
962
847#endif /* GSSAPI */ 963#endif /* GSSAPI */
848 964
849int 965int