20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 */ |
23 */ |
24 |
24 |
|
25 /* |
|
26 * May 22, 2015 |
|
27 * In version 6.8 a new packet interface has been introduced to OpenSSH, |
|
28 * while the old packet API has been provided in opacket.c. |
|
29 * At this moment we are not rewritting GSS-API key exchange code to the new |
|
30 * API, just adjusting it to still work with new struct ssh. |
|
31 * Rewritting to the new API can be considered in the future. |
|
32 */ |
|
33 |
25 #include "includes.h" |
34 #include "includes.h" |
26 |
35 |
27 #ifdef GSSAPI |
36 #ifdef GSSAPI |
28 |
37 |
|
38 #include <signal.h> /* for sig_atomic_t in kex.h */ |
29 #include <string.h> |
39 #include <string.h> |
30 |
40 |
31 #include <openssl/crypto.h> |
41 #include <openssl/crypto.h> |
32 #include <openssl/bn.h> |
42 #include <openssl/bn.h> |
33 |
43 |
34 #include "xmalloc.h" |
44 #include "xmalloc.h" |
35 #include "buffer.h" |
45 #include "buffer.h" |
36 #include "ssh2.h" |
46 #include "ssh2.h" |
37 #include "key.h" |
47 #include "key.h" |
38 #include "cipher.h" |
48 #include "cipher.h" |
|
49 #include "digest.h" |
39 #include "kex.h" |
50 #include "kex.h" |
40 #include "log.h" |
51 #include "log.h" |
41 #include "packet.h" |
52 #include "packet.h" |
42 #include "dh.h" |
53 #include "dh.h" |
43 #include "ssh-gss.h" |
54 #include "ssh-gss.h" |
44 #include "monitor_wrap.h" |
55 #include "monitor_wrap.h" |
45 |
56 |
46 void |
57 int |
47 kexgss_server(Kex *kex) |
58 kexgss_server(struct ssh *ssh) |
48 { |
59 { |
49 OM_uint32 maj_status, min_status; |
60 OM_uint32 maj_status, min_status; |
50 |
61 |
51 /* |
62 /* |
52 * Some GSSAPI implementations use the input value of ret_flags (an |
63 * Some GSSAPI implementations use the input value of ret_flags (an |
57 |
68 |
58 OM_uint32 ret_flags = 0; |
69 OM_uint32 ret_flags = 0; |
59 gss_buffer_desc gssbuf, recv_tok, msg_tok; |
70 gss_buffer_desc gssbuf, recv_tok, msg_tok; |
60 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; |
71 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; |
61 Gssctxt *ctxt = NULL; |
72 Gssctxt *ctxt = NULL; |
62 uint_t slen, klen, kout, hashlen; |
73 uint_t slen, klen, kout; |
63 uchar_t *kbuf, *hash; |
74 uchar_t *kbuf; |
64 DH *dh; |
75 DH *dh; |
65 int min = -1, max = -1, nbits = -1; |
76 int min = -1, max = -1, nbits = -1; |
66 BIGNUM *shared_secret = NULL; |
77 BIGNUM *shared_secret = NULL; |
67 BIGNUM *dh_client_pub = NULL; |
78 BIGNUM *dh_client_pub = NULL; |
68 int type = 0; |
79 int type = 0; |
69 gss_OID oid; |
80 gss_OID oid; |
70 char *mechs; |
81 char *mechs; |
|
82 struct kex *kex = ssh->kex; |
|
83 int r; |
|
84 uchar_t hash[SSH_DIGEST_MAX_LENGTH]; |
|
85 size_t hashlen; |
71 |
86 |
72 /* Initialise GSSAPI */ |
87 /* Initialise GSSAPI */ |
73 |
88 |
74 /* |
89 /* |
75 * If we're rekeying, privsep means that some of the private structures |
90 * If we're rekeying, privsep means that some of the private structures |
90 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) |
105 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) |
91 fatal("Unable to acquire credentials for the server"); |
106 fatal("Unable to acquire credentials for the server"); |
92 |
107 |
93 switch (kex->kex_type) { |
108 switch (kex->kex_type) { |
94 case KEX_GSS_GRP1_SHA1: |
109 case KEX_GSS_GRP1_SHA1: |
95 dh = dh_new_group1(); |
110 kex->dh = dh_new_group1(); |
96 break; |
111 break; |
97 case KEX_GSS_GRP14_SHA1: |
112 case KEX_GSS_GRP14_SHA1: |
98 dh = dh_new_group14(); |
113 kex->dh = dh_new_group14(); |
99 break; |
114 break; |
100 case KEX_GSS_GEX_SHA1: |
115 case KEX_GSS_GEX_SHA1: |
101 debug("Doing group exchange"); |
116 debug("Doing group exchange"); |
102 packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); |
117 packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); |
103 min = packet_get_int(); |
118 min = packet_get_int(); |
107 max = MIN(DH_GRP_MAX, max); |
122 max = MIN(DH_GRP_MAX, max); |
108 packet_check_eom(); |
123 packet_check_eom(); |
109 if (max < min || nbits < min || max < nbits) |
124 if (max < min || nbits < min || max < nbits) |
110 fatal("GSS_GEX, bad parameters: %d !< %d !< %d", |
125 fatal("GSS_GEX, bad parameters: %d !< %d !< %d", |
111 min, nbits, max); |
126 min, nbits, max); |
112 dh = PRIVSEP(choose_dh(min, nbits, max)); |
127 kex->dh = PRIVSEP(choose_dh(min, nbits, max)); |
113 if (dh == NULL) |
128 if (kex->dh == NULL) |
114 packet_disconnect("Protocol error:" |
129 packet_disconnect("Protocol error:" |
115 " no matching group found"); |
130 " no matching group found"); |
116 |
131 |
117 packet_start(SSH2_MSG_KEXGSS_GROUP); |
132 packet_start(SSH2_MSG_KEXGSS_GROUP); |
118 packet_put_bignum2(dh->p); |
133 packet_put_bignum2(kex->dh->p); |
119 packet_put_bignum2(dh->g); |
134 packet_put_bignum2(kex->dh->g); |
120 packet_send(); |
135 packet_send(); |
121 |
136 |
122 packet_write_wait(); |
137 packet_write_wait(); |
123 break; |
138 break; |
124 default: |
139 default: |
125 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); |
140 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); |
126 } |
141 } |
127 |
142 |
128 dh_gen_key(dh, kex->we_need * 8); |
143 dh_gen_key(kex->dh, kex->we_need * 8); |
129 |
144 |
130 do { |
145 do { |
131 debug("Wait SSH2_MSG_GSSAPI_INIT"); |
146 debug("Wait SSH2_MSG_GSSAPI_INIT"); |
132 type = packet_read(); |
147 type = packet_read(); |
133 switch (type) { |
148 switch (type) { |
188 fatal("Mutual Authentication flag wasn't set"); |
203 fatal("Mutual Authentication flag wasn't set"); |
189 |
204 |
190 if (!(ret_flags & GSS_C_INTEG_FLAG)) |
205 if (!(ret_flags & GSS_C_INTEG_FLAG)) |
191 fatal("Integrity flag wasn't set"); |
206 fatal("Integrity flag wasn't set"); |
192 |
207 |
193 if (!dh_pub_is_valid(dh, dh_client_pub)) |
208 if (!dh_pub_is_valid(kex->dh, dh_client_pub)) |
194 packet_disconnect("bad client public DH value"); |
209 packet_disconnect("bad client public DH value"); |
195 |
210 |
196 klen = DH_size(dh); |
211 klen = DH_size(kex->dh); |
197 kbuf = xmalloc(klen); |
212 kbuf = xmalloc(klen); |
198 kout = DH_compute_key(kbuf, dh_client_pub, dh); |
213 kout = DH_compute_key(kbuf, dh_client_pub, kex->dh); |
199 if (kout < 0) |
214 if (kout < 0) |
200 fatal("DH_compute_key: failed"); |
215 fatal("DH_compute_key: failed"); |
201 |
216 |
202 shared_secret = BN_new(); |
217 shared_secret = BN_new(); |
203 if (shared_secret == NULL) |
218 if (shared_secret == NULL) |
207 fatal("kexgss_server: BN_bin2bn failed"); |
222 fatal("kexgss_server: BN_bin2bn failed"); |
208 |
223 |
209 memset(kbuf, 0, klen); |
224 memset(kbuf, 0, klen); |
210 free(kbuf); |
225 free(kbuf); |
211 |
226 |
|
227 hashlen = sizeof (hash); |
212 switch (kex->kex_type) { |
228 switch (kex->kex_type) { |
213 case KEX_GSS_GRP1_SHA1: |
229 case KEX_GSS_GRP1_SHA1: |
214 case KEX_GSS_GRP14_SHA1: |
230 case KEX_GSS_GRP14_SHA1: |
215 kex_dh_hash( |
231 kex_dh_hash( |
216 kex->client_version_string, kex->server_version_string, |
232 kex->client_version_string, kex->server_version_string, |
217 buffer_ptr(&kex->peer), buffer_len(&kex->peer), |
233 buffer_ptr(kex->peer), buffer_len(kex->peer), |
218 buffer_ptr(&kex->my), buffer_len(&kex->my), |
234 buffer_ptr(kex->my), buffer_len(kex->my), |
219 NULL, 0, /* Change this if we start sending host keys */ |
235 NULL, 0, /* Change this if we start sending host keys */ |
220 dh_client_pub, dh->pub_key, shared_secret, |
236 dh_client_pub, kex->dh->pub_key, shared_secret, |
221 &hash, &hashlen); |
237 hash, &hashlen); |
222 break; |
238 break; |
223 case KEX_GSS_GEX_SHA1: |
239 case KEX_GSS_GEX_SHA1: |
224 kexgex_hash( |
240 kexgex_hash( |
225 kex->hash_alg, |
241 kex->hash_alg, |
226 kex->client_version_string, kex->server_version_string, |
242 kex->client_version_string, kex->server_version_string, |
227 buffer_ptr(&kex->peer), buffer_len(&kex->peer), |
243 buffer_ptr(kex->peer), buffer_len(kex->peer), |
228 buffer_ptr(&kex->my), buffer_len(&kex->my), |
244 buffer_ptr(kex->my), buffer_len(kex->my), |
229 NULL, 0, |
245 NULL, 0, |
230 min, nbits, max, |
246 min, nbits, max, |
231 dh->p, dh->g, |
247 kex->dh->p, kex->dh->g, |
232 dh_client_pub, |
248 dh_client_pub, |
233 dh->pub_key, |
249 kex->dh->pub_key, |
234 shared_secret, |
250 shared_secret, |
235 &hash, &hashlen); |
251 hash, &hashlen); |
236 break; |
252 break; |
237 default: |
253 default: |
238 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); |
254 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); |
239 } |
255 } |
240 |
256 |
251 |
267 |
252 if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) |
268 if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) |
253 fatal("Couldn't get MIC"); |
269 fatal("Couldn't get MIC"); |
254 |
270 |
255 packet_start(SSH2_MSG_KEXGSS_COMPLETE); |
271 packet_start(SSH2_MSG_KEXGSS_COMPLETE); |
256 packet_put_bignum2(dh->pub_key); |
272 packet_put_bignum2(kex->dh->pub_key); |
257 packet_put_string(msg_tok.value, msg_tok.length); |
273 packet_put_string(msg_tok.value, msg_tok.length); |
258 |
274 |
259 if (send_tok.length != 0) { |
275 if (send_tok.length != 0) { |
260 packet_put_char(1); /* true */ |
276 packet_put_char(1); /* true */ |
261 packet_put_string(send_tok.value, send_tok.length); |
277 packet_put_string(send_tok.value, send_tok.length); |
270 if (gss_kex_context == NULL) |
286 if (gss_kex_context == NULL) |
271 gss_kex_context = ctxt; |
287 gss_kex_context = ctxt; |
272 else |
288 else |
273 ssh_gssapi_delete_ctx(&ctxt); |
289 ssh_gssapi_delete_ctx(&ctxt); |
274 |
290 |
275 DH_free(dh); |
291 DH_free(kex->dh); |
276 |
292 |
277 kex_derive_keys_bn(kex, hash, hashlen, shared_secret); |
293 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) |
278 BN_clear_free(shared_secret); |
294 r = kex_send_newkeys(ssh); |
279 kex_finish(kex); |
295 return (r); |
280 } |
296 } |
281 #endif /* GSSAPI */ |
297 #endif /* GSSAPI */ |