diff options
Diffstat (limited to 'kexgsss.c')
-rw-r--r-- | kexgsss.c | 96 |
1 files changed, 73 insertions, 23 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2004 Simon Wilkinson. All rights reserved. | 2 | * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. |
3 | * | 3 | * |
4 | * Redistribution and use in source and binary forms, with or without | 4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions | 5 | * modification, are permitted provided that the following conditions |
@@ -53,21 +53,31 @@ kexgss_server(Kex *kex) | |||
53 | */ | 53 | */ |
54 | 54 | ||
55 | OM_uint32 ret_flags = 0; | 55 | OM_uint32 ret_flags = 0; |
56 | gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok; | 56 | gss_buffer_desc gssbuf, recv_tok, msg_tok; |
57 | gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; | ||
57 | Gssctxt *ctxt = NULL; | 58 | Gssctxt *ctxt = NULL; |
58 | unsigned int klen, kout; | 59 | unsigned int klen, kout; |
59 | unsigned char *kbuf, *hash; | 60 | unsigned char *kbuf, *hash; |
60 | DH *dh; | 61 | DH *dh; |
62 | int min = -1, max = -1, nbits = -1; | ||
61 | BIGNUM *shared_secret = NULL; | 63 | BIGNUM *shared_secret = NULL; |
62 | BIGNUM *dh_client_pub = NULL; | 64 | BIGNUM *dh_client_pub = NULL; |
63 | int type =0; | 65 | int type = 0; |
66 | int gex; | ||
64 | u_int slen; | 67 | u_int slen; |
65 | gss_OID oid; | 68 | gss_OID oid; |
66 | 69 | ||
67 | /* Initialise GSSAPI */ | 70 | /* Initialise GSSAPI */ |
68 | 71 | ||
72 | /* If we're rekeying, privsep means that some of the private structures | ||
73 | * in the GSSAPI code are no longer available. This kludges them back | ||
74 | * into life | ||
75 | */ | ||
76 | if (!ssh_gssapi_oid_table_ok()) | ||
77 | ssh_gssapi_server_mechanisms(); | ||
78 | |||
69 | debug2("%s: Identifying %s", __func__, kex->name); | 79 | debug2("%s: Identifying %s", __func__, kex->name); |
70 | oid = ssh_gssapi_id_kex(NULL, kex->name); | 80 | oid = ssh_gssapi_id_kex(NULL, kex->name, &gex); |
71 | if (oid == NULL) | 81 | if (oid == NULL) |
72 | fatal("Unknown gssapi mechanism"); | 82 | fatal("Unknown gssapi mechanism"); |
73 | 83 | ||
@@ -76,6 +86,34 @@ kexgss_server(Kex *kex) | |||
76 | if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) | 86 | if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) |
77 | fatal("Unable to acquire credentials for the server"); | 87 | fatal("Unable to acquire credentials for the server"); |
78 | 88 | ||
89 | if (gex) { | ||
90 | debug("Doing group exchange"); | ||
91 | packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); | ||
92 | min = packet_get_int(); | ||
93 | nbits = packet_get_int(); | ||
94 | max = packet_get_int(); | ||
95 | min = MAX(DH_GRP_MIN, min); | ||
96 | max = MIN(DH_GRP_MAX, max); | ||
97 | packet_check_eom(); | ||
98 | if (max < min || nbits < min || max < nbits) | ||
99 | fatal("GSS_GEX, bad parameters: %d !< %d !< %d", | ||
100 | min, nbits, max); | ||
101 | dh = PRIVSEP(choose_dh(min, nbits, max)); | ||
102 | if (dh == NULL) | ||
103 | packet_disconnect("Protocol error: no matching group found"); | ||
104 | |||
105 | packet_start(SSH2_MSG_KEXGSS_GROUP); | ||
106 | packet_put_bignum2(dh->p); | ||
107 | packet_put_bignum2(dh->g); | ||
108 | packet_send(); | ||
109 | |||
110 | packet_write_wait(); | ||
111 | |||
112 | } else { | ||
113 | dh = dh_new_group1(); | ||
114 | } | ||
115 | dh_gen_key(dh, kex->we_need * 8); | ||
116 | |||
79 | do { | 117 | do { |
80 | debug("Wait SSH2_MSG_GSSAPI_INIT"); | 118 | debug("Wait SSH2_MSG_GSSAPI_INIT"); |
81 | type = packet_read(); | 119 | type = packet_read(); |
@@ -86,10 +124,9 @@ kexgss_server(Kex *kex) | |||
86 | recv_tok.value = packet_get_string(&slen); | 124 | recv_tok.value = packet_get_string(&slen); |
87 | recv_tok.length = slen; | 125 | recv_tok.length = slen; |
88 | 126 | ||
89 | dh_client_pub = BN_new(); | 127 | if ((dh_client_pub = BN_new()) == NULL) |
90 | |||
91 | if (dh_client_pub == NULL) | ||
92 | fatal("dh_client_pub == NULL"); | 128 | fatal("dh_client_pub == NULL"); |
129 | |||
93 | packet_get_bignum2(dh_client_pub); | 130 | packet_get_bignum2(dh_client_pub); |
94 | 131 | ||
95 | /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ | 132 | /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ |
@@ -107,8 +144,8 @@ kexgss_server(Kex *kex) | |||
107 | maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, | 144 | maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, |
108 | &send_tok, &ret_flags)); | 145 | &send_tok, &ret_flags)); |
109 | 146 | ||
110 | gss_release_buffer(&min_status, &recv_tok); | 147 | xfree(recv_tok.value); |
111 | 148 | ||
112 | if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) | 149 | if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) |
113 | fatal("Zero length token output when incomplete"); | 150 | fatal("Zero length token output when incomplete"); |
114 | 151 | ||
@@ -125,7 +162,7 @@ kexgss_server(Kex *kex) | |||
125 | } while (maj_status & GSS_S_CONTINUE_NEEDED); | 162 | } while (maj_status & GSS_S_CONTINUE_NEEDED); |
126 | 163 | ||
127 | if (GSS_ERROR(maj_status)) { | 164 | if (GSS_ERROR(maj_status)) { |
128 | if (send_tok.length>0) { | 165 | if (send_tok.length > 0) { |
129 | packet_start(SSH2_MSG_KEXGSS_CONTINUE); | 166 | packet_start(SSH2_MSG_KEXGSS_CONTINUE); |
130 | packet_put_string(send_tok.value, send_tok.length); | 167 | packet_put_string(send_tok.value, send_tok.length); |
131 | packet_send(); | 168 | packet_send(); |
@@ -139,9 +176,6 @@ kexgss_server(Kex *kex) | |||
139 | if (!(ret_flags & GSS_C_INTEG_FLAG)) | 176 | if (!(ret_flags & GSS_C_INTEG_FLAG)) |
140 | fatal("Integrity flag wasn't set"); | 177 | fatal("Integrity flag wasn't set"); |
141 | 178 | ||
142 | dh = dh_new_group1(); | ||
143 | dh_gen_key(dh, kex->we_need * 8); | ||
144 | |||
145 | if (!dh_pub_is_valid(dh, dh_client_pub)) | 179 | if (!dh_pub_is_valid(dh, dh_client_pub)) |
146 | packet_disconnect("bad client public DH value"); | 180 | packet_disconnect("bad client public DH value"); |
147 | 181 | ||
@@ -154,14 +188,29 @@ kexgss_server(Kex *kex) | |||
154 | memset(kbuf, 0, klen); | 188 | memset(kbuf, 0, klen); |
155 | xfree(kbuf); | 189 | xfree(kbuf); |
156 | 190 | ||
157 | /* The GSSAPI hash is identical to the Diffie Helman one */ | 191 | if (gex) { |
158 | hash = kex_dh_hash( | 192 | hash = kexgex_hash( |
159 | kex->client_version_string, kex->server_version_string, | 193 | kex->client_version_string, kex->server_version_string, |
160 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | 194 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), |
161 | buffer_ptr(&kex->my), buffer_len(&kex->my), | 195 | buffer_ptr(&kex->my), buffer_len(&kex->my), |
162 | NULL, 0, /* Change this if we start sending host keys */ | 196 | NULL, 0, |
163 | dh_client_pub, dh->pub_key, shared_secret | 197 | min, nbits, max, |
164 | ); | 198 | dh->p, dh->g, |
199 | dh_client_pub, | ||
200 | dh->pub_key, | ||
201 | shared_secret | ||
202 | ); | ||
203 | } | ||
204 | else { | ||
205 | /* The GSSAPI hash is identical to the Diffie Helman one */ | ||
206 | hash = kex_dh_hash( | ||
207 | kex->client_version_string, kex->server_version_string, | ||
208 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | ||
209 | buffer_ptr(&kex->my), buffer_len(&kex->my), | ||
210 | NULL, 0, /* Change this if we start sending host keys */ | ||
211 | dh_client_pub, dh->pub_key, shared_secret | ||
212 | ); | ||
213 | } | ||
165 | BN_free(dh_client_pub); | 214 | BN_free(dh_client_pub); |
166 | 215 | ||
167 | if (kex->session_id == NULL) { | 216 | if (kex->session_id == NULL) { |
@@ -180,7 +229,7 @@ kexgss_server(Kex *kex) | |||
180 | packet_put_bignum2(dh->pub_key); | 229 | packet_put_bignum2(dh->pub_key); |
181 | packet_put_string((char *)msg_tok.value,msg_tok.length); | 230 | packet_put_string((char *)msg_tok.value,msg_tok.length); |
182 | 231 | ||
183 | if (send_tok.length!=0) { | 232 | if (send_tok.length != 0) { |
184 | packet_put_char(1); /* true */ | 233 | packet_put_char(1); /* true */ |
185 | packet_put_string((char *)send_tok.value, send_tok.length); | 234 | packet_put_string((char *)send_tok.value, send_tok.length); |
186 | } else { | 235 | } else { |
@@ -188,7 +237,8 @@ kexgss_server(Kex *kex) | |||
188 | } | 237 | } |
189 | packet_send(); | 238 | packet_send(); |
190 | 239 | ||
191 | gss_release_buffer(&min_status, &send_tok); | 240 | gss_release_buffer(&min_status, &send_tok); |
241 | gss_release_buffer(&min_status, &msg_tok); | ||
192 | 242 | ||
193 | if (gss_kex_context == NULL) | 243 | if (gss_kex_context == NULL) |
194 | gss_kex_context = ctxt; | 244 | gss_kex_context = ctxt; |