summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index a762eec3b..a96153903 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -104,9 +104,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
104{ 104{
105 Kex *kex; 105 Kex *kex;
106 106
107#ifdef GSSAPI
108 char *orig = NULL, *gss = NULL;
109 char *gss_host = NULL;
110#endif
111
107 xxx_host = host; 112 xxx_host = host;
108 xxx_hostaddr = hostaddr; 113 xxx_hostaddr = hostaddr;
109 114
115#ifdef GSSAPI
116 if (options.gss_keyex) {
117 /* Add the GSSAPI mechanisms currently supported on this
118 * client to the key exchange algorithm proposal */
119 orig = myproposal[PROPOSAL_KEX_ALGS];
120
121 if (options.gss_trust_dns)
122 gss_host = (char *)get_canonical_hostname(1);
123 else
124 gss_host = host;
125
126 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
127 if (gss) {
128 debug("Offering GSSAPI proposal: %s", gss);
129 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
130 "%s,%s", gss, orig);
131 }
132 }
133#endif
134
110 if (options.ciphers == (char *)-1) { 135 if (options.ciphers == (char *)-1) {
111 logit("No valid ciphers for protocol version 2 given, using defaults."); 136 logit("No valid ciphers for protocol version 2 given, using defaults.");
112 options.ciphers = NULL; 137 options.ciphers = NULL;
@@ -134,6 +159,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
134 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 159 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
135 options.hostkeyalgorithms; 160 options.hostkeyalgorithms;
136 161
162#ifdef GSSAPI
163 /* If we've got GSSAPI algorithms, then we also support the
164 * 'null' hostkey, as a last resort */
165 if (options.gss_keyex && gss) {
166 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
167 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
168 "%s,null", orig);
169 xfree(gss);
170 }
171#endif
172
137 if (options.rekey_limit) 173 if (options.rekey_limit)
138 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 174 packet_set_rekey_limit((u_int32_t)options.rekey_limit);
139 175
@@ -143,10 +179,26 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
143 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 179 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
144 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 180 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
145 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 181 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
182#ifdef GSSAPI
183 if (options.gss_keyex) {
184 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
185 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
186 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
187 }
188#endif
146 kex->client_version_string=client_version_string; 189 kex->client_version_string=client_version_string;
147 kex->server_version_string=server_version_string; 190 kex->server_version_string=server_version_string;
148 kex->verify_host_key=&verify_host_key_callback; 191 kex->verify_host_key=&verify_host_key_callback;
149 192
193#ifdef GSSAPI
194 if (options.gss_keyex) {
195 kex->gss_deleg_creds = options.gss_deleg_creds;
196 kex->gss_trust_dns = options.gss_trust_dns;
197 kex->gss_client = options.gss_client_identity;
198 kex->gss_host = gss_host;
199 }
200#endif
201
150 xxx_kex = kex; 202 xxx_kex = kex;
151 203
152 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 204 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -235,6 +287,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
235void input_gssapi_hash(int type, u_int32_t, void *); 287void input_gssapi_hash(int type, u_int32_t, void *);
236void input_gssapi_error(int, u_int32_t, void *); 288void input_gssapi_error(int, u_int32_t, void *);
237void input_gssapi_errtok(int, u_int32_t, void *); 289void input_gssapi_errtok(int, u_int32_t, void *);
290int userauth_gsskeyex(Authctxt *authctxt);
238#endif 291#endif
239 292
240void userauth(Authctxt *, char *); 293void userauth(Authctxt *, char *);
@@ -250,6 +303,10 @@ static char *authmethods_get(void);
250 303
251Authmethod authmethods[] = { 304Authmethod authmethods[] = {
252#ifdef GSSAPI 305#ifdef GSSAPI
306 {"gssapi-keyex",
307 userauth_gsskeyex,
308 &options.gss_authentication,
309 NULL},
253 {"gssapi-with-mic", 310 {"gssapi-with-mic",
254 userauth_gssapi, 311 userauth_gssapi,
255 NULL, 312 NULL,
@@ -541,19 +598,29 @@ userauth_gssapi(Authctxt *authctxt)
541 static u_int mech = 0; 598 static u_int mech = 0;
542 OM_uint32 min; 599 OM_uint32 min;
543 int ok = 0; 600 int ok = 0;
601 const char *gss_host;
602
603 if (options.gss_trust_dns)
604 gss_host = get_canonical_hostname(1);
605 else
606 gss_host = authctxt->host;
544 607
545 /* Try one GSSAPI method at a time, rather than sending them all at 608 /* Try one GSSAPI method at a time, rather than sending them all at
546 * once. */ 609 * once. */
547 610
548 if (gss_supported == NULL) 611 if (gss_supported == NULL)
549 gss_indicate_mechs(&min, &gss_supported); 612 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
613 gss_supported = NULL;
614 return 0;
615 }
550 616
551 /* Check to see if the mechanism is usable before we offer it */ 617 /* Check to see if the mechanism is usable before we offer it */
552 while (mech < gss_supported->count && !ok) { 618 while (mech < gss_supported->count && !ok) {
553 /* My DER encoding requires length<128 */ 619 /* My DER encoding requires length<128 */
554 if (gss_supported->elements[mech].length < 128 && 620 if (gss_supported->elements[mech].length < 128 &&
555 ssh_gssapi_check_mechanism(&gssctxt, 621 ssh_gssapi_check_mechanism(&gssctxt,
556 &gss_supported->elements[mech], authctxt->host)) { 622 &gss_supported->elements[mech], gss_host,
623 options.gss_client_identity)) {
557 ok = 1; /* Mechanism works */ 624 ok = 1; /* Mechanism works */
558 } else { 625 } else {
559 mech++; 626 mech++;
@@ -650,8 +717,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
650{ 717{
651 Authctxt *authctxt = ctxt; 718 Authctxt *authctxt = ctxt;
652 Gssctxt *gssctxt; 719 Gssctxt *gssctxt;
653 int oidlen; 720 u_int oidlen;
654 char *oidv; 721 u_char *oidv;
655 722
656 if (authctxt == NULL) 723 if (authctxt == NULL)
657 fatal("input_gssapi_response: no authentication context"); 724 fatal("input_gssapi_response: no authentication context");
@@ -761,6 +828,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
761 xfree(msg); 828 xfree(msg);
762 xfree(lang); 829 xfree(lang);
763} 830}
831
832int
833userauth_gsskeyex(Authctxt *authctxt)
834{
835 Buffer b;
836 gss_buffer_desc gssbuf;
837 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
838 OM_uint32 ms;
839
840 static int attempt = 0;
841 if (attempt++ >= 1)
842 return (0);
843
844 if (gss_kex_context == NULL) {
845 debug("No valid Key exchange context");
846 return (0);
847 }
848
849 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
850 "gssapi-keyex");
851
852 gssbuf.value = buffer_ptr(&b);
853 gssbuf.length = buffer_len(&b);
854
855 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
856 buffer_free(&b);
857 return (0);
858 }
859
860 packet_start(SSH2_MSG_USERAUTH_REQUEST);
861 packet_put_cstring(authctxt->server_user);
862 packet_put_cstring(authctxt->service);
863 packet_put_cstring(authctxt->method->name);
864 packet_put_string(mic.value, mic.length);
865 packet_send();
866
867 buffer_free(&b);
868 gss_release_buffer(&ms, &mic);
869
870 return (1);
871}
872
764#endif /* GSSAPI */ 873#endif /* GSSAPI */
765 874
766int 875int