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 3cb9b101c..aaf02ece4 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -159,9 +159,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
159{ 159{
160 Kex *kex; 160 Kex *kex;
161 161
162#ifdef GSSAPI
163 char *orig = NULL, *gss = NULL;
164 char *gss_host = NULL;
165#endif
166
162 xxx_host = host; 167 xxx_host = host;
163 xxx_hostaddr = hostaddr; 168 xxx_hostaddr = hostaddr;
164 169
170#ifdef GSSAPI
171 if (options.gss_keyex) {
172 /* Add the GSSAPI mechanisms currently supported on this
173 * client to the key exchange algorithm proposal */
174 orig = myproposal[PROPOSAL_KEX_ALGS];
175
176 if (options.gss_trust_dns)
177 gss_host = (char *)get_canonical_hostname(1);
178 else
179 gss_host = host;
180
181 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
182 if (gss) {
183 debug("Offering GSSAPI proposal: %s", gss);
184 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
185 "%s,%s", gss, orig);
186 }
187 }
188#endif
189
165 if (options.ciphers == (char *)-1) { 190 if (options.ciphers == (char *)-1) {
166 logit("No valid ciphers for protocol version 2 given, using defaults."); 191 logit("No valid ciphers for protocol version 2 given, using defaults.");
167 options.ciphers = NULL; 192 options.ciphers = NULL;
@@ -196,6 +221,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
196 if (options.kex_algorithms != NULL) 221 if (options.kex_algorithms != NULL)
197 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 222 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
198 223
224#ifdef GSSAPI
225 /* If we've got GSSAPI algorithms, then we also support the
226 * 'null' hostkey, as a last resort */
227 if (options.gss_keyex && gss) {
228 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
229 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
230 "%s,null", orig);
231 xfree(gss);
232 }
233#endif
234
199 if (options.rekey_limit) 235 if (options.rekey_limit)
200 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 236 packet_set_rekey_limit((u_int32_t)options.rekey_limit);
201 237
@@ -206,10 +242,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
206 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 242 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
207 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 243 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
208 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 244 kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
245#ifdef GSSAPI
246 if (options.gss_keyex) {
247 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
248 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
249 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
250 }
251#endif
209 kex->client_version_string=client_version_string; 252 kex->client_version_string=client_version_string;
210 kex->server_version_string=server_version_string; 253 kex->server_version_string=server_version_string;
211 kex->verify_host_key=&verify_host_key_callback; 254 kex->verify_host_key=&verify_host_key_callback;
212 255
256#ifdef GSSAPI
257 if (options.gss_keyex) {
258 kex->gss_deleg_creds = options.gss_deleg_creds;
259 kex->gss_trust_dns = options.gss_trust_dns;
260 kex->gss_client = options.gss_client_identity;
261 if (options.gss_server_identity) {
262 kex->gss_host = options.gss_server_identity;
263 } else {
264 kex->gss_host = gss_host;
265 }
266 }
267#endif
268
213 xxx_kex = kex; 269 xxx_kex = kex;
214 270
215 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 271 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -304,6 +360,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
304void input_gssapi_hash(int type, u_int32_t, void *); 360void input_gssapi_hash(int type, u_int32_t, void *);
305void input_gssapi_error(int, u_int32_t, void *); 361void input_gssapi_error(int, u_int32_t, void *);
306void input_gssapi_errtok(int, u_int32_t, void *); 362void input_gssapi_errtok(int, u_int32_t, void *);
363int userauth_gsskeyex(Authctxt *authctxt);
307#endif 364#endif
308 365
309void userauth(Authctxt *, char *); 366void userauth(Authctxt *, char *);
@@ -319,6 +376,11 @@ static char *authmethods_get(void);
319 376
320Authmethod authmethods[] = { 377Authmethod authmethods[] = {
321#ifdef GSSAPI 378#ifdef GSSAPI
379 {"gssapi-keyex",
380 userauth_gsskeyex,
381 NULL,
382 &options.gss_authentication,
383 NULL},
322 {"gssapi-with-mic", 384 {"gssapi-with-mic",
323 userauth_gssapi, 385 userauth_gssapi,
324 NULL, 386 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");
@@ -845,6 +919,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
845 xfree(msg); 919 xfree(msg);
846 xfree(lang); 920 xfree(lang);
847} 921}
922
923int
924userauth_gsskeyex(Authctxt *authctxt)
925{
926 Buffer b;
927 gss_buffer_desc gssbuf;
928 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
929 OM_uint32 ms;
930
931 static int attempt = 0;
932 if (attempt++ >= 1)
933 return (0);
934
935 if (gss_kex_context == NULL) {
936 debug("No valid Key exchange context");
937 return (0);
938 }
939
940 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
941 "gssapi-keyex");
942
943 gssbuf.value = buffer_ptr(&b);
944 gssbuf.length = buffer_len(&b);
945
946 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
947 buffer_free(&b);
948 return (0);
949 }
950
951 packet_start(SSH2_MSG_USERAUTH_REQUEST);
952 packet_put_cstring(authctxt->server_user);
953 packet_put_cstring(authctxt->service);
954 packet_put_cstring(authctxt->method->name);
955 packet_put_string(mic.value, mic.length);
956 packet_send();
957
958 buffer_free(&b);
959 gss_release_buffer(&ms, &mic);
960
961 return (1);
962}
963
848#endif /* GSSAPI */ 964#endif /* GSSAPI */
849 965
850int 966int