File: | src/sbin/isakmpd/ike_quick_mode.c |
Warning: | line 1646, column 15 Result of 'calloc' is converted to a pointer of type 'u_int8_t', which is incompatible with sizeof operand type 'char' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ike_quick_mode.c,v 1.114 2018/01/15 09:54:48 mpi Exp $ */ |
2 | /* $EOM: ike_quick_mode.c,v 1.139 2001/01/26 10:43:17 niklas Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. |
6 | * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. |
7 | * Copyright (c) 2000, 2001, 2004 Håkan Olsson. All rights reserved. |
8 | * |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions |
11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
29 | |
30 | /* |
31 | * This code was written under funding by Ericsson Radio Systems. |
32 | */ |
33 | |
34 | #include <stdlib.h> |
35 | #include <string.h> |
36 | |
37 | #include <sys/types.h> |
38 | #include <regex.h> |
39 | #include <keynote.h> |
40 | |
41 | #include "attribute.h" |
42 | #include "conf.h" |
43 | #include "connection.h" |
44 | #include "dh.h" |
45 | #include "doi.h" |
46 | #include "exchange.h" |
47 | #include "hash.h" |
48 | #include "ike_quick_mode.h" |
49 | #include "ipsec.h" |
50 | #include "log.h" |
51 | #include "message.h" |
52 | #include "policy.h" |
53 | #include "prf.h" |
54 | #include "sa.h" |
55 | #include "transport.h" |
56 | #include "util.h" |
57 | #include "key.h" |
58 | #include "x509.h" |
59 | |
60 | static void gen_g_xy(struct message *); |
61 | static int initiator_send_HASH_SA_NONCE(struct message *); |
62 | static int initiator_recv_HASH_SA_NONCE(struct message *); |
63 | static int initiator_send_HASH(struct message *); |
64 | static void post_quick_mode(struct message *); |
65 | static int responder_recv_HASH_SA_NONCE(struct message *); |
66 | static int responder_send_HASH_SA_NONCE(struct message *); |
67 | static int responder_recv_HASH(struct message *); |
68 | |
69 | static int check_policy(struct exchange *, struct sa *, struct sa *); |
70 | |
71 | int (*ike_quick_mode_initiator[])(struct message *) = { |
72 | initiator_send_HASH_SA_NONCE, |
73 | initiator_recv_HASH_SA_NONCE, |
74 | initiator_send_HASH |
75 | }; |
76 | |
77 | int (*ike_quick_mode_responder[])(struct message *) = { |
78 | responder_recv_HASH_SA_NONCE, |
79 | responder_send_HASH_SA_NONCE, |
80 | responder_recv_HASH |
81 | }; |
82 | |
83 | /* How many return values will policy handle -- true/false for now */ |
84 | #define RETVALUES_NUM2 2 |
85 | |
86 | /* |
87 | * Given an exchange and our policy, check whether the SA and IDs are |
88 | * acceptable. |
89 | */ |
90 | static int |
91 | check_policy(struct exchange *exchange, struct sa *sa, struct sa *isakmp_sa) |
92 | { |
93 | char *return_values[RETVALUES_NUM2]; |
94 | char **principal = 0; |
95 | int i, len, result = 0, nprinc = 0; |
96 | int *x509_ids = 0, *keynote_ids = 0; |
97 | unsigned char hashbuf[20]; /* Set to the largest digest result */ |
98 | struct keynote_deckey dc; |
99 | X509_NAME *subject; |
100 | |
101 | /* Do we want to use keynote policies? */ |
102 | if (ignore_policy || |
103 | strncmp("yes", conf_get_str("General", "Use-Keynote"), 3)) |
104 | return 1; |
105 | |
106 | /* Initialize if necessary -- e.g., if pre-shared key auth was used */ |
107 | if (isakmp_sa->policy_id < 0) { |
108 | if ((isakmp_sa->policy_id = kn_init()) == -1) { |
109 | log_print("check_policy: " |
110 | "failed to initialize policy session"); |
111 | return 0; |
112 | } |
113 | } |
114 | /* Add the callback that will handle attributes. */ |
115 | if (kn_add_action(isakmp_sa->policy_id, ".*", (char *)policy_callback, |
116 | ENVIRONMENT_FLAG_FUNC0x0001 | ENVIRONMENT_FLAG_REGEX0x0002) == -1) { |
117 | log_print("check_policy: " |
118 | "kn_add_action (%d, \".*\", %p, FUNC | REGEX) failed", |
119 | isakmp_sa->policy_id, policy_callback); |
120 | kn_close(isakmp_sa->policy_id); |
121 | isakmp_sa->policy_id = -1; |
122 | return 0; |
123 | } |
124 | if (policy_asserts_num) { |
125 | keynote_ids = calloc(policy_asserts_num, sizeof *keynote_ids); |
126 | if (!keynote_ids) { |
127 | log_error("check_policy: calloc (%d, %lu) failed", |
128 | policy_asserts_num, |
129 | (unsigned long)sizeof *keynote_ids); |
130 | kn_close(isakmp_sa->policy_id); |
131 | isakmp_sa->policy_id = -1; |
132 | return 0; |
133 | } |
134 | } |
135 | /* Add the policy assertions */ |
136 | for (i = 0; i < policy_asserts_num; i++) |
137 | keynote_ids[i] = kn_add_assertion(isakmp_sa->policy_id, |
138 | policy_asserts[i], |
139 | strlen(policy_asserts[i]), ASSERT_FLAG_LOCAL0x0001); |
140 | |
141 | /* Initialize -- we'll let the callback do all the work. */ |
142 | policy_exchange = exchange; |
143 | policy_sa = sa; |
144 | policy_isakmp_sa = isakmp_sa; |
145 | |
146 | /* Set the return values; true/false for now at least. */ |
147 | return_values[0] = "false"; /* Order of values in array is |
148 | * important. */ |
149 | return_values[1] = "true"; |
150 | |
151 | /* Create a principal (authorizer) for the SA/ID request. */ |
152 | switch (isakmp_sa->recv_certtype) { |
153 | case ISAKMP_CERTENC_NONE0: |
154 | /* |
155 | * For shared keys, just duplicate the passphrase with the |
156 | * appropriate prefix tag. |
157 | */ |
158 | nprinc = 3; |
159 | principal = calloc(nprinc, sizeof *principal); |
160 | if (!principal) { |
161 | log_error("check_policy: calloc (%d, %lu) failed", |
162 | nprinc, (unsigned long)sizeof *principal); |
163 | goto policydone; |
164 | } |
165 | len = strlen(isakmp_sa->recv_key) + sizeof "passphrase:"; |
166 | principal[0] = calloc(len, sizeof(char)); |
167 | if (!principal[0]) { |
168 | log_error("check_policy: calloc (%d, %lu) failed", len, |
169 | (unsigned long)sizeof(char)); |
170 | goto policydone; |
171 | } |
172 | /* |
173 | * XXX Consider changing the magic hash lengths with |
174 | * constants. |
175 | */ |
176 | strlcpy(principal[0], "passphrase:", len); |
177 | memcpy(principal[0] + sizeof "passphrase:" - 1, |
178 | isakmp_sa->recv_key, strlen(isakmp_sa->recv_key)); |
179 | |
180 | len = sizeof "passphrase-md5-hex:" + 2 * 16; |
181 | principal[1] = calloc(len, sizeof(char)); |
182 | if (!principal[1]) { |
183 | log_error("check_policy: calloc (%d, %lu) failed", len, |
184 | (unsigned long)sizeof(char)); |
185 | goto policydone; |
186 | } |
187 | strlcpy(principal[1], "passphrase-md5-hex:", len); |
188 | MD5(isakmp_sa->recv_key, strlen(isakmp_sa->recv_key), hashbuf); |
189 | for (i = 0; i < 16; i++) |
190 | snprintf(principal[1] + 2 * i + |
191 | sizeof "passphrase-md5-hex:" - 1, 3, "%02x", |
192 | hashbuf[i]); |
193 | |
194 | len = sizeof "passphrase-sha1-hex:" + 2 * 20; |
195 | principal[2] = calloc(len, sizeof(char)); |
196 | if (!principal[2]) { |
197 | log_error("check_policy: calloc (%d, %lu) failed", len, |
198 | (unsigned long)sizeof(char)); |
199 | goto policydone; |
200 | } |
201 | strlcpy(principal[2], "passphrase-sha1-hex:", len); |
202 | SHA1(isakmp_sa->recv_key, strlen(isakmp_sa->recv_key), |
203 | hashbuf); |
204 | for (i = 0; i < 20; i++) |
205 | snprintf(principal[2] + 2 * i + |
206 | sizeof "passphrase-sha1-hex:" - 1, 3, "%02x", |
207 | hashbuf[i]); |
208 | break; |
209 | |
210 | case ISAKMP_CERTENC_KEYNOTE11: |
211 | nprinc = 1; |
212 | |
213 | principal = calloc(nprinc, sizeof *principal); |
214 | if (!principal) { |
215 | log_error("check_policy: calloc (%d, %lu) failed", |
216 | nprinc, (unsigned long)sizeof *principal); |
217 | goto policydone; |
218 | } |
219 | /* Dup the keys */ |
220 | principal[0] = strdup(isakmp_sa->keynote_key); |
221 | if (!principal[0]) { |
222 | log_error("check_policy: calloc (%lu, %lu) failed", |
223 | (unsigned long)strlen(isakmp_sa->keynote_key), |
224 | (unsigned long)sizeof(char)); |
225 | goto policydone; |
226 | } |
227 | break; |
228 | |
229 | case ISAKMP_CERTENC_X509_SIG4: |
230 | principal = calloc(2, sizeof *principal); |
231 | if (!principal) { |
232 | log_error("check_policy: calloc (2, %lu) failed", |
233 | (unsigned long)sizeof *principal); |
234 | goto policydone; |
235 | } |
236 | if (isakmp_sa->recv_keytype == ISAKMP_KEY_RSA2) |
237 | dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA6; |
238 | else { |
239 | log_error("check_policy: " |
240 | "unknown/unsupported public key algorithm %d", |
241 | isakmp_sa->recv_keytype); |
242 | goto policydone; |
243 | } |
244 | |
245 | dc.dec_key = isakmp_sa->recv_key; |
246 | principal[0] = kn_encode_key(&dc, INTERNAL_ENC_PKCS11, |
247 | ENCODING_HEX1, KEYNOTE_PUBLIC_KEY0); |
248 | if (keynote_errno == ERROR_MEMORY-1) { |
249 | log_print("check_policy: " |
250 | "failed to get memory for public key"); |
251 | goto policydone; |
252 | } |
253 | if (!principal[0]) { |
254 | log_print("check_policy: " |
255 | "failed to allocate memory for principal"); |
256 | goto policydone; |
257 | } |
258 | if (asprintf(&principal[1], "rsa-hex:%s", principal[0]) == -1) { |
259 | log_error("check_policy: asprintf() failed"); |
260 | goto policydone; |
261 | } |
262 | free(principal[0]); |
263 | principal[0] = principal[1]; |
264 | principal[1] = 0; |
265 | |
266 | /* Generate a "DN:" principal. */ |
267 | subject = X509_get_subject_name(isakmp_sa->recv_cert); |
268 | if (subject) { |
269 | principal[1] = calloc(259, sizeof(char)); |
270 | if (!principal[1]) { |
271 | log_error("check_policy: " |
272 | "calloc (259, %lu) failed", |
273 | (unsigned long)sizeof(char)); |
274 | goto policydone; |
275 | } |
276 | strlcpy(principal[1], "DN:", 259); |
277 | X509_NAME_oneline(subject, principal[1] + 3, 256); |
278 | nprinc = 2; |
279 | } else { |
280 | nprinc = 1; |
281 | } |
282 | break; |
283 | |
284 | /* XXX Eventually handle these. */ |
285 | case ISAKMP_CERTENC_PKCS1: |
286 | case ISAKMP_CERTENC_PGP2: |
287 | case ISAKMP_CERTENC_DNS3: |
288 | case ISAKMP_CERTENC_X509_KE5: |
289 | case ISAKMP_CERTENC_KERBEROS6: |
290 | case ISAKMP_CERTENC_CRL7: |
291 | case ISAKMP_CERTENC_ARL8: |
292 | case ISAKMP_CERTENC_SPKI9: |
293 | case ISAKMP_CERTENC_X509_ATTR10: |
294 | default: |
295 | log_print("check_policy: " |
296 | "unknown/unsupported certificate/authentication method %d", |
297 | isakmp_sa->recv_certtype); |
298 | goto policydone; |
299 | } |
300 | |
301 | /* |
302 | * Add the authorizer (who is requesting the SA/ID); |
303 | * this may be a public or a secret key, depending on |
304 | * what mode of authentication we used in Phase 1. |
305 | */ |
306 | for (i = 0; i < nprinc; i++) { |
307 | LOG_DBG((LOG_POLICY, 40, "check_policy: "log_debug (LOG_POLICY, 40, "check_policy: " "adding authorizer [%s]" , principal[i]) |
308 | "adding authorizer [%s]", principal[i]))log_debug (LOG_POLICY, 40, "check_policy: " "adding authorizer [%s]" , principal[i]); |
309 | |
310 | if (kn_add_authorizer(isakmp_sa->policy_id, principal[i]) |
311 | == -1) { |
312 | int j; |
313 | |
314 | for (j = 0; j < i; j++) |
315 | kn_remove_authorizer(isakmp_sa->policy_id, |
316 | principal[j]); |
317 | log_print("check_policy: kn_add_authorizer failed"); |
318 | goto policydone; |
319 | } |
320 | } |
321 | |
322 | /* Ask policy */ |
323 | result = kn_do_query(isakmp_sa->policy_id, return_values, |
324 | RETVALUES_NUM2); |
325 | LOG_DBG((LOG_POLICY, 40, "check_policy: kn_do_query returned %d",log_debug (LOG_POLICY, 40, "check_policy: kn_do_query returned %d" , result) |
326 | result))log_debug (LOG_POLICY, 40, "check_policy: kn_do_query returned %d" , result); |
327 | |
328 | /* Cleanup environment */ |
329 | kn_cleanup_action_environment(isakmp_sa->policy_id); |
330 | |
331 | /* Remove authorizers from the session */ |
332 | for (i = 0; i < nprinc; i++) { |
333 | kn_remove_authorizer(isakmp_sa->policy_id, principal[i]); |
334 | free(principal[i]); |
335 | } |
336 | |
337 | free(principal); |
338 | principal = 0; |
339 | nprinc = 0; |
340 | |
341 | /* Check what policy said. */ |
342 | if (result < 0) { |
343 | LOG_DBG((LOG_POLICY, 40, "check_policy: proposal refused"))log_debug (LOG_POLICY, 40, "check_policy: proposal refused"); |
344 | result = 0; |
345 | goto policydone; |
346 | } |
347 | policydone: |
348 | for (i = 0; i < nprinc; i++) |
349 | if (principal && principal[i]) |
350 | free(principal[i]); |
351 | |
352 | free(principal); |
353 | |
354 | /* Remove the policies */ |
355 | for (i = 0; i < policy_asserts_num; i++) { |
356 | if (keynote_ids[i] != -1) |
357 | kn_remove_assertion(isakmp_sa->policy_id, |
358 | keynote_ids[i]); |
359 | } |
360 | |
361 | free(keynote_ids); |
362 | |
363 | free(x509_ids); |
364 | |
365 | /* |
366 | * XXX Currently, check_policy() is only called from |
367 | * message_negotiate_sa(), and so this log message reflects this. |
368 | * Change to something better? |
369 | */ |
370 | if (result == 0) |
371 | log_print("check_policy: negotiated SA failed policy check"); |
372 | |
373 | /* |
374 | * Given that we have only 2 return values from policy (true/false) |
375 | * we can just return the query result directly (no pre-processing |
376 | * needed). |
377 | */ |
378 | return result; |
379 | } |
380 | |
381 | /* |
382 | * Offer several sets of transforms to the responder. |
383 | * XXX Split this huge function up and look for common code with main mode. |
384 | */ |
385 | static int |
386 | initiator_send_HASH_SA_NONCE(struct message *msg) |
387 | { |
388 | struct exchange *exchange = msg->exchange; |
389 | struct doi *doi = exchange->doi; |
390 | struct ipsec_exch *ie = exchange->data; |
391 | u_int8_t ***transform = 0, ***new_transform; |
392 | u_int8_t **proposal = 0, **new_proposal; |
393 | u_int8_t *sa_buf = 0, *attr, *saved_nextp_sa, *saved_nextp_prop, |
394 | *id, *spi; |
395 | size_t spi_sz, sz; |
396 | size_t proposal_len = 0, proposals_len = 0, sa_len; |
397 | size_t **transform_len = 0, **new_transform_len; |
398 | size_t *transforms_len = 0, *new_transforms_len; |
399 | u_int32_t *transform_cnt = 0, *new_transform_cnt; |
400 | u_int32_t suite_no, prop_no, prot_no, xf_no, prop_cnt = 0; |
401 | u_int32_t i; |
402 | int value, update_nextp, protocol_num, proto_id; |
403 | struct proto *proto; |
404 | struct conf_list *suite_conf, *prot_conf = 0, *xf_conf = 0, *life_conf; |
405 | struct conf_list_node *suite, *prot, *xf, *life; |
406 | struct constant_map *id_map; |
407 | char *protocol_id, *transform_id; |
408 | char *local_id, *remote_id; |
409 | char *name; |
410 | int group_desc = -1, new_group_desc; |
411 | struct ipsec_sa *isa = msg->isakmp_sa->data; |
412 | struct hash *hash = hash_get(isa->hash); |
413 | struct sockaddr *src; |
414 | struct proto_attr *pa; |
415 | |
416 | if (!ipsec_add_hash_payload(msg, hash->hashsize)) |
417 | return -1; |
418 | |
419 | /* Get the list of protocol suites. */ |
420 | suite_conf = conf_get_list(exchange->policy, "Suites"); |
421 | if (!suite_conf) |
422 | return -1; |
423 | |
424 | for (suite = TAILQ_FIRST(&suite_conf->fields)((&suite_conf->fields)->tqh_first), suite_no = prop_no = 0; |
425 | suite_no < suite_conf->cnt; |
426 | suite_no++, suite = TAILQ_NEXT(suite, link)((suite)->link.tqe_next)) { |
427 | /* Now get each protocol in this specific protocol suite. */ |
428 | prot_conf = conf_get_list(suite->field, "Protocols"); |
429 | if (!prot_conf) |
430 | goto bail_out; |
431 | |
432 | for (prot = TAILQ_FIRST(&prot_conf->fields)((&prot_conf->fields)->tqh_first), prot_no = 0; |
433 | prot_no < prot_conf->cnt; |
434 | prot_no++, prot = TAILQ_NEXT(prot, link)((prot)->link.tqe_next)) { |
435 | /* Make sure we have a proposal/transform vectors. */ |
436 | if (prop_no >= prop_cnt) { |
437 | /* |
438 | * This resize algorithm is completely |
439 | * arbitrary. |
440 | */ |
441 | prop_cnt = 2 * prop_cnt + 10; |
442 | new_proposal = reallocarray(proposal, |
443 | prop_cnt, sizeof *proposal); |
444 | if (!new_proposal) { |
445 | log_error( |
446 | "initiator_send_HASH_SA_NONCE: " |
447 | "realloc (%p, %lu) failed", |
448 | proposal, |
449 | prop_cnt * (unsigned long)sizeof *proposal); |
450 | goto bail_out; |
451 | } |
452 | proposal = new_proposal; |
453 | |
454 | new_transforms_len = reallocarray(transforms_len, |
455 | prop_cnt, sizeof *transforms_len); |
456 | if (!new_transforms_len) { |
457 | log_error( |
458 | "initiator_send_HASH_SA_NONCE: " |
459 | "realloc (%p, %lu) failed", |
460 | transforms_len, |
461 | prop_cnt * (unsigned long)sizeof *transforms_len); |
462 | goto bail_out; |
463 | } |
464 | transforms_len = new_transforms_len; |
465 | |
466 | new_transform = reallocarray(transform, |
467 | prop_cnt, sizeof *transform); |
468 | if (!new_transform) { |
469 | log_error( |
470 | "initiator_send_HASH_SA_NONCE: " |
471 | "realloc (%p, %lu) failed", |
472 | transform, |
473 | prop_cnt * (unsigned long)sizeof *transform); |
474 | goto bail_out; |
475 | } |
476 | transform = new_transform; |
477 | |
478 | new_transform_cnt = reallocarray(transform_cnt, |
479 | prop_cnt, sizeof *transform_cnt); |
480 | if (!new_transform_cnt) { |
481 | log_error( |
482 | "initiator_send_HASH_SA_NONCE: " |
483 | "realloc (%p, %lu) failed", |
484 | transform_cnt, |
485 | prop_cnt * (unsigned long)sizeof *transform_cnt); |
486 | goto bail_out; |
487 | } |
488 | transform_cnt = new_transform_cnt; |
489 | |
490 | new_transform_len = reallocarray(transform_len, |
491 | prop_cnt, sizeof *transform_len); |
492 | if (!new_transform_len) { |
493 | log_error( |
494 | "initiator_send_HASH_SA_NONCE: " |
495 | "realloc (%p, %lu) failed", |
496 | transform_len, |
497 | prop_cnt * (unsigned long)sizeof *transform_len); |
498 | goto bail_out; |
499 | } |
500 | transform_len = new_transform_len; |
501 | } |
502 | protocol_id = conf_get_str(prot->field, "PROTOCOL_ID"); |
503 | if (!protocol_id) |
504 | goto bail_out; |
505 | |
506 | proto_id = constant_value(ipsec_proto_cst, |
507 | protocol_id); |
508 | switch (proto_id) { |
509 | case IPSEC_PROTO_IPSEC_AH2: |
510 | id_map = ipsec_ah_cst; |
511 | break; |
512 | |
513 | case IPSEC_PROTO_IPSEC_ESP3: |
514 | id_map = ipsec_esp_cst; |
515 | break; |
516 | |
517 | case IPSEC_PROTO_IPCOMP4: |
518 | id_map = ipsec_ipcomp_cst; |
519 | break; |
520 | |
521 | default: |
522 | { |
523 | log_print("initiator_send_HASH_SA_NONCE: " |
524 | "invalid PROTCOL_ID: %s", protocol_id); |
525 | goto bail_out; |
526 | } |
527 | } |
528 | |
529 | /* Now get each transform we offer for this protocol.*/ |
530 | xf_conf = conf_get_list(prot->field, "Transforms"); |
531 | if (!xf_conf) |
532 | goto bail_out; |
533 | transform_cnt[prop_no] = xf_conf->cnt; |
534 | |
535 | transform[prop_no] = calloc(transform_cnt[prop_no], |
536 | sizeof **transform); |
537 | if (!transform[prop_no]) { |
538 | log_error("initiator_send_HASH_SA_NONCE: " |
539 | "calloc (%d, %lu) failed", |
540 | transform_cnt[prop_no], |
541 | (unsigned long)sizeof **transform); |
542 | goto bail_out; |
543 | } |
544 | transform_len[prop_no] = calloc(transform_cnt[prop_no], |
545 | sizeof **transform_len); |
546 | if (!transform_len[prop_no]) { |
547 | log_error("initiator_send_HASH_SA_NONCE: " |
548 | "calloc (%d, %lu) failed", |
549 | transform_cnt[prop_no], |
550 | (unsigned long)sizeof **transform_len); |
551 | goto bail_out; |
552 | } |
553 | transforms_len[prop_no] = 0; |
554 | for (xf = TAILQ_FIRST(&xf_conf->fields)((&xf_conf->fields)->tqh_first), xf_no = 0; |
555 | xf_no < transform_cnt[prop_no]; |
556 | xf_no++, xf = TAILQ_NEXT(xf, link)((xf)->link.tqe_next)) { |
557 | |
558 | /* XXX The sizing needs to be dynamic. */ |
559 | transform[prop_no][xf_no] = |
560 | calloc(ISAKMP_TRANSFORM_SA_ATTRS_OFF8 + |
561 | 9 * ISAKMP_ATTR_VALUE_OFF4, 1); |
562 | if (!transform[prop_no][xf_no]) { |
563 | log_error( |
564 | "initiator_send_HASH_SA_NONCE: " |
565 | "calloc (%d, 1) failed", |
566 | ISAKMP_TRANSFORM_SA_ATTRS_OFF8 + |
567 | 9 * ISAKMP_ATTR_VALUE_OFF4); |
568 | goto bail_out; |
569 | } |
570 | SET_ISAKMP_TRANSFORM_NO(transform[prop_no][xf_no],field_set_num (isakmp_transform_fld + 0, transform[prop_no][xf_no ], xf_no + 1) |
571 | xf_no + 1)field_set_num (isakmp_transform_fld + 0, transform[prop_no][xf_no ], xf_no + 1); |
572 | |
573 | transform_id = conf_get_str(xf->field, |
574 | "TRANSFORM_ID"); |
575 | if (!transform_id) |
576 | goto bail_out; |
577 | SET_ISAKMP_TRANSFORM_ID(transform[prop_no][xf_no],field_set_num (isakmp_transform_fld + 1, transform[prop_no][xf_no ], constant_value(id_map, transform_id)) |
578 | constant_value(id_map, transform_id))field_set_num (isakmp_transform_fld + 1, transform[prop_no][xf_no ], constant_value(id_map, transform_id)); |
579 | SET_ISAKMP_TRANSFORM_RESERVED(transform[prop_no][xf_no], 0)field_set_num (isakmp_transform_fld + 2, transform[prop_no][xf_no ], 0); |
580 | |
581 | attr = transform[prop_no][xf_no] + |
582 | ISAKMP_TRANSFORM_SA_ATTRS_OFF8; |
583 | |
584 | /* |
585 | * Life durations are special, we should be |
586 | * able to specify several, one per type. |
587 | */ |
588 | life_conf = conf_get_list(xf->field, "Life"); |
589 | if (life_conf) { |
590 | for (life = TAILQ_FIRST(&life_conf->fields)((&life_conf->fields)->tqh_first); |
591 | life; life = TAILQ_NEXT(life, link)((life)->link.tqe_next)) { |
592 | attribute_set_constant( |
593 | life->field, "LIFE_TYPE", |
594 | ipsec_duration_cst, |
595 | IPSEC_ATTR_SA_LIFE_TYPE1, |
596 | &attr); |
597 | |
598 | /* |
599 | * XXX Deals with 16 and 32 |
600 | * bit lifetimes only |
601 | */ |
602 | value = |
603 | conf_get_num(life->field, |
604 | "LIFE_DURATION", 0); |
605 | if (value) { |
606 | if (value <= 0xffff) |
607 | attr = |
608 | attribute_set_basic( |
609 | attr, |
610 | IPSEC_ATTR_SA_LIFE_DURATION2, |
611 | value); |
612 | else { |
613 | value = htonl(value)(__uint32_t)(__builtin_constant_p(value) ? (__uint32_t)(((__uint32_t )(value) & 0xff) << 24 | ((__uint32_t)(value) & 0xff00) << 8 | ((__uint32_t)(value) & 0xff0000) >> 8 | ((__uint32_t)(value) & 0xff000000) >> 24) : __swap32md (value)); |
614 | attr = |
615 | attribute_set_var( |
616 | attr, |
617 | IPSEC_ATTR_SA_LIFE_DURATION2, |
618 | (u_int8_t *)&value, |
619 | sizeof value); |
620 | } |
621 | } |
622 | } |
623 | conf_free_list(life_conf); |
624 | } |
625 | |
626 | if (proto_id == IPSEC_PROTO_IPSEC_ESP3 && |
627 | (exchange->flags & |
628 | EXCHANGE_FLAG_NAT_T_ENABLE0x0010)) { |
629 | name = conf_get_str(xf->field, |
630 | "ENCAPSULATION_MODE"); |
631 | if (name) { |
632 | value = constant_value( |
633 | ipsec_encap_cst, |
634 | name); |
635 | switch (value) { |
636 | case IPSEC_ENCAP_TUNNEL1: |
637 | value = exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT0x0100 ? |
638 | IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT61443 : |
639 | IPSEC_ENCAP_UDP_ENCAP_TUNNEL3; |
640 | break; |
641 | case IPSEC_ENCAP_TRANSPORT2: |
642 | value = exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT0x0100 ? |
643 | IPSEC_ENCAP_UDP_ENCAP_TRANSPORT_DRAFT61444 : |
644 | IPSEC_ENCAP_UDP_ENCAP_TRANSPORT4; |
645 | break; |
646 | } |
647 | attr = attribute_set_basic( |
648 | attr, |
649 | IPSEC_ATTR_ENCAPSULATION_MODE4, |
650 | value); |
651 | } |
652 | } else { |
653 | attribute_set_constant(xf->field, |
654 | "ENCAPSULATION_MODE", |
655 | ipsec_encap_cst, |
656 | IPSEC_ATTR_ENCAPSULATION_MODE4, |
657 | &attr); |
658 | } |
659 | |
660 | if (proto_id != IPSEC_PROTO_IPCOMP4) { |
661 | attribute_set_constant(xf->field, |
662 | "AUTHENTICATION_ALGORITHM", |
663 | ipsec_auth_cst, |
664 | IPSEC_ATTR_AUTHENTICATION_ALGORITHM5, |
665 | &attr); |
666 | |
667 | attribute_set_constant(xf->field, |
668 | "GROUP_DESCRIPTION", |
669 | ike_group_desc_cst, |
670 | IPSEC_ATTR_GROUP_DESCRIPTION3, &attr); |
671 | |
672 | value = conf_get_num(xf->field, |
673 | "KEY_LENGTH", 0); |
674 | if (value) |
675 | attr = attribute_set_basic( |
676 | attr, |
677 | IPSEC_ATTR_KEY_LENGTH6, |
678 | value); |
679 | |
680 | value = conf_get_num(xf->field, |
681 | "KEY_ROUNDS", 0); |
682 | if (value) |
683 | attr = attribute_set_basic( |
684 | attr, |
685 | IPSEC_ATTR_KEY_ROUNDS7, |
686 | value); |
687 | } else { |
688 | value = conf_get_num(xf->field, |
689 | "COMPRESS_DICTIONARY_SIZE", 0); |
690 | if (value) |
691 | attr = attribute_set_basic( |
692 | attr, |
693 | IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE8, |
694 | value); |
695 | |
696 | value = conf_get_num(xf->field, |
697 | "COMPRESS_PRIVATE_ALGORITHM", 0); |
698 | if (value) |
699 | attr = attribute_set_basic( |
700 | attr, |
701 | IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM9, |
702 | value); |
703 | } |
704 | |
705 | value = conf_get_num(xf->field, "ECN_TUNNEL", |
706 | 0); |
707 | if (value) |
708 | attr = attribute_set_basic(attr, |
709 | IPSEC_ATTR_ECN_TUNNEL10, value); |
710 | |
711 | /* Record the real transform size. */ |
712 | transforms_len[prop_no] += |
713 | (transform_len[prop_no][xf_no] |
714 | = attr - transform[prop_no][xf_no]); |
715 | |
716 | if (proto_id != IPSEC_PROTO_IPCOMP4) { |
717 | /* |
718 | * Make sure that if a group |
719 | * description is specified, it is |
720 | * specified for all transforms |
721 | * equally. |
722 | */ |
723 | attr = |
724 | (u_int8_t *)conf_get_str(xf->field, |
725 | "GROUP_DESCRIPTION"); |
726 | new_group_desc |
727 | = attr ? constant_value(ike_group_desc_cst, |
728 | (char *)attr) : 0; |
729 | if (group_desc == -1) |
730 | group_desc = new_group_desc; |
731 | else if (group_desc != new_group_desc) { |
732 | log_print("initiator_send_HASH_SA_NONCE: " |
733 | "differing group descriptions in a proposal"); |
734 | goto bail_out; |
735 | } |
736 | } |
737 | } |
738 | conf_free_list(xf_conf); |
739 | xf_conf = 0; |
740 | |
741 | /* |
742 | * Get SPI from application. |
743 | * XXX Should we care about unknown constants? |
744 | */ |
745 | protocol_num = constant_value(ipsec_proto_cst, |
746 | protocol_id); |
747 | spi = doi->get_spi(&spi_sz, protocol_num, msg); |
748 | if (spi_sz && !spi) { |
749 | log_print("initiator_send_HASH_SA_NONCE: " |
750 | "doi->get_spi failed"); |
751 | goto bail_out; |
752 | } |
753 | proposal_len = ISAKMP_PROP_SPI_OFF8 + spi_sz; |
754 | proposals_len += |
755 | proposal_len + transforms_len[prop_no]; |
756 | proposal[prop_no] = malloc(proposal_len); |
757 | if (!proposal[prop_no]) { |
758 | log_error("initiator_send_HASH_SA_NONCE: " |
759 | "malloc (%lu) failed", |
760 | (unsigned long)proposal_len); |
761 | goto bail_out; |
762 | } |
763 | SET_ISAKMP_PROP_NO(proposal[prop_no], suite_no + 1)field_set_num (isakmp_prop_fld + 0, proposal[prop_no], suite_no + 1); |
764 | SET_ISAKMP_PROP_PROTO(proposal[prop_no], protocol_num)field_set_num (isakmp_prop_fld + 1, proposal[prop_no], protocol_num ); |
765 | |
766 | /* XXX I would like to see this factored out. */ |
767 | proto = calloc(1, sizeof *proto); |
768 | if (!proto) { |
769 | log_error("initiator_send_HASH_SA_NONCE: " |
770 | "calloc (1, %lu) failed", |
771 | (unsigned long)sizeof *proto); |
772 | goto bail_out; |
773 | } |
774 | if (doi->proto_size) { |
775 | proto->data = calloc(1, doi->proto_size); |
776 | if (!proto->data) { |
777 | free(proto); |
778 | log_error( |
779 | "initiator_send_HASH_SA_NONCE: " |
780 | "calloc (1, %lu) failed", |
781 | (unsigned long)doi->proto_size); |
782 | goto bail_out; |
783 | } |
784 | } |
785 | proto->no = suite_no + 1; |
786 | proto->proto = protocol_num; |
787 | proto->sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); |
788 | proto->xf_cnt = transform_cnt[prop_no]; |
789 | TAILQ_INIT(&proto->xfs)do { (&proto->xfs)->tqh_first = ((void*)0); (&proto ->xfs)->tqh_last = &(&proto->xfs)->tqh_first ; } while (0); |
790 | for (xf_no = 0; xf_no < proto->xf_cnt; xf_no++) { |
791 | pa = calloc(1, sizeof *pa); |
792 | if (!pa) { |
793 | free(proto->data); |
794 | free(proto); |
795 | goto bail_out; |
796 | } |
797 | pa->len = transform_len[prop_no][xf_no]; |
798 | pa->attrs = malloc(pa->len); |
799 | if (!pa->attrs) { |
800 | free(proto->data); |
801 | free(proto); |
802 | free(pa); |
803 | goto bail_out; |
804 | } |
805 | memcpy(pa->attrs, transform[prop_no][xf_no], |
806 | pa->len); |
807 | TAILQ_INSERT_TAIL(&proto->xfs, pa, next)do { (pa)->next.tqe_next = ((void*)0); (pa)->next.tqe_prev = (&proto->xfs)->tqh_last; *(&proto->xfs)-> tqh_last = (pa); (&proto->xfs)->tqh_last = &(pa )->next.tqe_next; } while (0); |
808 | } |
809 | TAILQ_INSERT_TAIL(&TAILQ_FIRST(&exchange->sa_list)->protos,do { (proto)->link.tqe_next = ((void*)0); (proto)->link .tqe_prev = (&((&exchange->sa_list)->tqh_first) ->protos)->tqh_last; *(&((&exchange->sa_list )->tqh_first)->protos)->tqh_last = (proto); (&(( &exchange->sa_list)->tqh_first)->protos)->tqh_last = &(proto)->link.tqe_next; } while (0) |
810 | proto, link)do { (proto)->link.tqe_next = ((void*)0); (proto)->link .tqe_prev = (&((&exchange->sa_list)->tqh_first) ->protos)->tqh_last; *(&((&exchange->sa_list )->tqh_first)->protos)->tqh_last = (proto); (&(( &exchange->sa_list)->tqh_first)->protos)->tqh_last = &(proto)->link.tqe_next; } while (0); |
811 | |
812 | /* Setup the incoming SPI. */ |
813 | SET_ISAKMP_PROP_SPI_SZ(proposal[prop_no], spi_sz)field_set_num (isakmp_prop_fld + 2, proposal[prop_no], spi_sz ); |
814 | memcpy(proposal[prop_no] + ISAKMP_PROP_SPI_OFF8, spi, |
815 | spi_sz); |
816 | proto->spi_sz[1] = spi_sz; |
817 | proto->spi[1] = spi; |
818 | |
819 | /* |
820 | * Let the DOI get at proto for initializing its own |
821 | * data. |
822 | */ |
823 | if (doi->proto_init) |
824 | doi->proto_init(proto, prot->field); |
825 | |
826 | SET_ISAKMP_PROP_NTRANSFORMS(proposal[prop_no],field_set_num (isakmp_prop_fld + 3, proposal[prop_no], transform_cnt [prop_no]) |
827 | transform_cnt[prop_no])field_set_num (isakmp_prop_fld + 3, proposal[prop_no], transform_cnt [prop_no]); |
828 | prop_no++; |
829 | } |
830 | conf_free_list(prot_conf); |
831 | prot_conf = 0; |
832 | } |
833 | |
834 | sa_len = ISAKMP_SA_SIT_OFF8 + IPSEC_SIT_SIT_LEN4; |
835 | sa_buf = malloc(sa_len); |
836 | if (!sa_buf) { |
837 | log_error("initiator_send_HASH_SA_NONCE: malloc (%lu) failed", |
838 | (unsigned long)sa_len); |
839 | goto bail_out; |
840 | } |
841 | SET_ISAKMP_SA_DOI(sa_buf, IPSEC_DOI_IPSEC)field_set_num (isakmp_sa_fld + 0, sa_buf, 1); |
842 | SET_IPSEC_SIT_SIT(sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY)field_set_num (ipsec_sit_fld + 0, sa_buf + 8, 1); |
843 | |
844 | /* |
845 | * Add the payloads. As this is a SA, we need to recompute the |
846 | * lengths of the payloads containing others. We also need to |
847 | * reset these payload's "next payload type" field. |
848 | */ |
849 | if (message_add_payload(msg, ISAKMP_PAYLOAD_SA1, sa_buf, sa_len, 1)) |
850 | goto bail_out; |
851 | SET_ISAKMP_GEN_LENGTH(sa_buf, sa_len + proposals_len)field_set_num (isakmp_gen_fld + 2, sa_buf, sa_len + proposals_len ); |
852 | sa_buf = 0; |
853 | |
854 | update_nextp = 0; |
855 | saved_nextp_sa = msg->nextp; |
856 | for (i = 0; i < prop_no; i++) { |
857 | if (message_add_payload(msg, ISAKMP_PAYLOAD_PROPOSAL2, |
858 | proposal[i], proposal_len, update_nextp)) |
859 | goto bail_out; |
860 | SET_ISAKMP_GEN_LENGTH(proposal[i],field_set_num (isakmp_gen_fld + 2, proposal[i], proposal_len + transforms_len[i]) |
861 | proposal_len + transforms_len[i])field_set_num (isakmp_gen_fld + 2, proposal[i], proposal_len + transforms_len[i]); |
862 | proposal[i] = 0; |
863 | |
864 | update_nextp = 0; |
865 | saved_nextp_prop = msg->nextp; |
866 | for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++) { |
867 | if (message_add_payload(msg, ISAKMP_PAYLOAD_TRANSFORM3, |
868 | transform[i][xf_no], |
869 | transform_len[i][xf_no], update_nextp)) |
870 | goto bail_out; |
871 | update_nextp = 1; |
872 | transform[i][xf_no] = 0; |
873 | } |
874 | msg->nextp = saved_nextp_prop; |
875 | update_nextp = 1; |
876 | } |
877 | msg->nextp = saved_nextp_sa; |
878 | |
879 | /* |
880 | * Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len. |
881 | */ |
882 | ie->sa_i_b = message_copy(msg, ISAKMP_GEN_SZ4, &ie->sa_i_b_len); |
883 | if (!ie->sa_i_b) |
884 | goto bail_out; |
885 | |
886 | /* |
887 | * Generate a nonce, and add it to the message. |
888 | * XXX I want a better way to specify the nonce's size. |
889 | */ |
890 | if (exchange_gen_nonce(msg, 16)) |
891 | return -1; |
892 | |
893 | /* Generate optional KEY_EXCH payload. */ |
894 | if (group_desc > 0) { |
895 | ie->group = group_get(group_desc); |
896 | ie->g_x_len = dh_getlen(ie->group); |
897 | |
898 | if (ipsec_gen_g_x(msg)) { |
899 | group_free(ie->group); |
900 | ie->group = 0; |
901 | return -1; |
902 | } |
903 | } |
904 | /* Generate optional client ID payloads. XXX Share with responder. */ |
905 | local_id = conf_get_str(exchange->name, "Local-ID"); |
906 | remote_id = conf_get_str(exchange->name, "Remote-ID"); |
907 | if (local_id && remote_id) { |
908 | id = ipsec_build_id(local_id, &sz); |
909 | if (!id) |
910 | return -1; |
911 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic" , id, sz) |
912 | "initiator_send_HASH_SA_NONCE: IDic", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic" , id, sz); |
913 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
914 | free(id); |
915 | return -1; |
916 | } |
917 | id = ipsec_build_id(remote_id, &sz); |
918 | if (!id) |
919 | return -1; |
920 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc" , id, sz) |
921 | "initiator_send_HASH_SA_NONCE: IDrc", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc" , id, sz); |
922 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
923 | free(id); |
924 | return -1; |
925 | } |
926 | } |
927 | /* XXX I do not judge these as errors, are they? */ |
928 | else if (local_id) |
929 | log_print("initiator_send_HASH_SA_NONCE: " |
930 | "Local-ID given without Remote-ID for \"%s\"", |
931 | exchange->name); |
932 | else if (remote_id) |
933 | /* |
934 | * This code supports the "road warrior" case, where the |
935 | * initiator doesn't have a fixed IP address, but wants to |
936 | * specify a particular remote network to talk to. -- Adrian |
937 | * Close <adrian@esec.com.au> |
938 | */ |
939 | { |
940 | log_print("initiator_send_HASH_SA_NONCE: " |
941 | "Remote-ID given without Local-ID for \"%s\"", |
942 | exchange->name); |
943 | |
944 | /* |
945 | * If we're here, then we are the initiator, so use initiator |
946 | * address for local ID |
947 | */ |
948 | msg->transport->vtbl->get_src(msg->transport, &src); |
949 | sz = ISAKMP_ID_SZ8 + sockaddr_addrlen(src); |
950 | |
951 | id = calloc(sz, sizeof(char)); |
952 | if (!id) { |
953 | log_error("initiator_send_HASH_SA_NONCE: " |
954 | "calloc (%lu, %lu) failed", (unsigned long)sz, |
955 | (unsigned long)sizeof(char)); |
956 | return -1; |
957 | } |
958 | switch (src->sa_family) { |
959 | case AF_INET624: |
960 | SET_ISAKMP_ID_TYPE(id, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, id, 5); |
961 | break; |
962 | case AF_INET2: |
963 | SET_ISAKMP_ID_TYPE(id, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, id, 1); |
964 | break; |
965 | default: |
966 | log_error("initiator_send_HASH_SA_NONCE: " |
967 | "unknown sa_family %d", src->sa_family); |
968 | free(id); |
969 | return -1; |
970 | } |
971 | memcpy(id + ISAKMP_ID_DATA_OFF8, sockaddr_addrdata(src), |
972 | sockaddr_addrlen(src)); |
973 | |
974 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic" , id, sz) |
975 | "initiator_send_HASH_SA_NONCE: IDic", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic" , id, sz); |
976 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
977 | free(id); |
978 | return -1; |
979 | } |
980 | /* Send supplied remote_id */ |
981 | id = ipsec_build_id(remote_id, &sz); |
982 | if (!id) |
983 | return -1; |
984 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc" , id, sz) |
985 | "initiator_send_HASH_SA_NONCE: IDrc", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc" , id, sz); |
986 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
987 | free(id); |
988 | return -1; |
989 | } |
990 | } |
991 | if (ipsec_fill_in_hash(msg)) |
992 | goto bail_out; |
993 | |
994 | conf_free_list(suite_conf); |
995 | for (i = 0; i < prop_no; i++) { |
996 | free(transform[i]); |
997 | free(transform_len[i]); |
998 | } |
999 | free(proposal); |
1000 | free(transform); |
1001 | free(transforms_len); |
1002 | free(transform_len); |
1003 | free(transform_cnt); |
1004 | return 0; |
1005 | |
1006 | bail_out: |
1007 | free(sa_buf); |
1008 | if (proposal) { |
1009 | for (i = 0; i < prop_no; i++) { |
1010 | free(proposal[i]); |
1011 | if (transform[i]) { |
1012 | for (xf_no = 0; xf_no < transform_cnt[i]; |
1013 | xf_no++) |
1014 | free(transform[i][xf_no]); |
1015 | free(transform[i]); |
1016 | } |
1017 | free(transform_len[i]); |
1018 | } |
1019 | free(proposal); |
1020 | free(transforms_len); |
1021 | free(transform); |
1022 | free(transform_len); |
1023 | free(transform_cnt); |
1024 | } |
1025 | if (xf_conf) |
1026 | conf_free_list(xf_conf); |
1027 | if (prot_conf) |
1028 | conf_free_list(prot_conf); |
1029 | conf_free_list(suite_conf); |
1030 | return -1; |
1031 | } |
1032 | |
1033 | /* Figure out what transform the responder chose. */ |
1034 | static int |
1035 | initiator_recv_HASH_SA_NONCE(struct message *msg) |
1036 | { |
1037 | struct exchange *exchange = msg->exchange; |
1038 | struct ipsec_exch *ie = exchange->data; |
1039 | struct sa *sa; |
1040 | struct proto *proto, *next_proto; |
1041 | struct payload *sa_p = payload_first(msg, ISAKMP_PAYLOAD_SA1); |
1042 | struct payload *xf, *idp; |
1043 | struct payload *hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH8); |
1044 | struct payload *kep = payload_first(msg, ISAKMP_PAYLOAD_KEY_EXCH4); |
1045 | struct prf *prf; |
1046 | struct sa *isakmp_sa = msg->isakmp_sa; |
1047 | struct ipsec_sa *isa = isakmp_sa->data; |
1048 | struct hash *hash = hash_get(isa->hash); |
1049 | u_int8_t *rest; |
1050 | size_t rest_len; |
1051 | struct sockaddr *src, *dst; |
1052 | |
1053 | /* Allocate the prf and start calculating our HASH(1). XXX Share? */ |
1054 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: "log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: " "SKEYID_a", (u_int8_t *)isa->skeyid_a, isa->skeyid_len ) |
1055 | "SKEYID_a", (u_int8_t *)isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: " "SKEYID_a", (u_int8_t *)isa->skeyid_a, isa->skeyid_len ); |
1056 | prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, |
1057 | isa->skeyid_len); |
1058 | if (!prf) |
1059 | return -1; |
1060 | |
1061 | prf->Init(prf->prfctx); |
1062 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1063 | "initiator_recv_HASH_SA_NONCE: message_id",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1064 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4); |
1065 | prf->Update(prf->prfctx, exchange->message_id, |
1066 | ISAKMP_HDR_MESSAGE_ID_LEN4); |
1067 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: "log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: " "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len) |
1068 | "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: " "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len); |
1069 | prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); |
1070 | rest = hashp->p + GET_ISAKMP_GEN_LENGTH(hashp->p)field_get_num (isakmp_gen_fld + 2, hashp->p); |
1071 | rest_len = (GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base)field_get_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base) |
1072 | - (rest - (u_int8_t *)msg->iov[0].iov_base)); |
1073 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)" , rest, rest_len) |
1074 | "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)", rest,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)" , rest, rest_len) |
1075 | rest_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)" , rest, rest_len); |
1076 | prf->Update(prf->prfctx, rest, rest_len); |
1077 | prf->Final(hash->digest, prf->prfctx); |
1078 | prf_free(prf); |
1079 | LOG_DBG_BUF((LOG_NEGOTIATION, 80,log_debug_buf (LOG_NEGOTIATION, 80, "initiator_recv_HASH_SA_NONCE: computed HASH(2)" , hash->digest, hash->hashsize) |
1080 | "initiator_recv_HASH_SA_NONCE: computed HASH(2)", hash->digest,log_debug_buf (LOG_NEGOTIATION, 80, "initiator_recv_HASH_SA_NONCE: computed HASH(2)" , hash->digest, hash->hashsize) |
1081 | hash->hashsize))log_debug_buf (LOG_NEGOTIATION, 80, "initiator_recv_HASH_SA_NONCE: computed HASH(2)" , hash->digest, hash->hashsize); |
1082 | if (memcmp(hashp->p + ISAKMP_HASH_DATA_OFF4, hash->digest, |
1083 | hash->hashsize) != 0) { |
1084 | message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23, 0, 1, |
1085 | 0); |
1086 | return -1; |
1087 | } |
1088 | /* Mark the HASH as handled. */ |
1089 | hashp->flags |= PL_MARK1; |
1090 | |
1091 | /* Mark message as authenticated. */ |
1092 | msg->flags |= MSG_AUTHENTICATED0x10; |
1093 | |
1094 | /* |
1095 | * As we are getting an answer on our transform offer, only one |
1096 | * transform should be given. |
1097 | * |
1098 | * XXX Currently we only support negotiating one SA per quick mode run. |
1099 | */ |
1100 | if (TAILQ_NEXT(sa_p, link)((sa_p)->link.tqe_next)) { |
1101 | log_print("initiator_recv_HASH_SA_NONCE: " |
1102 | "multiple SA payloads in quick mode not supported yet"); |
1103 | return -1; |
1104 | } |
1105 | sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); |
1106 | |
1107 | /* This is here for the policy check */ |
1108 | if (kep) |
1109 | ie->pfs = 1; |
1110 | |
1111 | /* Drop message when it contains ID types we do not implement yet. */ |
1112 | TAILQ_FOREACH(idp, &msg->payload[ISAKMP_PAYLOAD_ID], link)for((idp) = ((&msg->payload[5])->tqh_first); (idp) != ((void*)0); (idp) = ((idp)->link.tqe_next)) { |
1113 | switch (GET_ISAKMP_ID_TYPE(idp->p)field_get_num (isakmp_id_fld + 0, idp->p)) { |
1114 | case IPSEC_ID_IPV4_ADDR1: |
1115 | case IPSEC_ID_IPV4_ADDR_SUBNET4: |
1116 | case IPSEC_ID_IPV6_ADDR5: |
1117 | case IPSEC_ID_IPV6_ADDR_SUBNET6: |
1118 | break; |
1119 | |
1120 | case IPSEC_ID_FQDN2: |
1121 | /* |
1122 | * FQDN may be used for in NAT-T with transport mode. |
1123 | * We can handle the message in this case. In the |
1124 | * other cases we'll drop the message later. |
1125 | */ |
1126 | break; |
1127 | |
1128 | default: |
1129 | message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION18, |
1130 | 0, 1, 0); |
1131 | return -1; |
1132 | } |
1133 | } |
1134 | |
1135 | /* Handle optional client ID payloads. */ |
1136 | idp = payload_first(msg, ISAKMP_PAYLOAD_ID5); |
1137 | if (idp) { |
1138 | /* If IDci is there, IDcr must be too. */ |
1139 | if (!TAILQ_NEXT(idp, link)((idp)->link.tqe_next)) { |
1140 | /* XXX Is this a good notify type? */ |
1141 | message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, |
1142 | 1, 0); |
1143 | return -1; |
1144 | } |
1145 | /* XXX We should really compare, not override. */ |
1146 | ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH(idp->p)field_get_num (isakmp_gen_fld + 2, idp->p); |
1147 | ie->id_ci = malloc(ie->id_ci_sz); |
1148 | if (!ie->id_ci) { |
1149 | log_error("initiator_recv_HASH_SA_NONCE: " |
1150 | "malloc (%lu) failed", |
1151 | (unsigned long)ie->id_ci_sz); |
1152 | return -1; |
1153 | } |
1154 | memcpy(ie->id_ci, idp->p, ie->id_ci_sz); |
1155 | idp->flags |= PL_MARK1; |
1156 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4) |
1157 | "initiator_recv_HASH_SA_NONCE: IDci",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4) |
1158 | ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4); |
1159 | |
1160 | idp = TAILQ_NEXT(idp, link)((idp)->link.tqe_next); |
1161 | ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH(idp->p)field_get_num (isakmp_gen_fld + 2, idp->p); |
1162 | ie->id_cr = malloc(ie->id_cr_sz); |
1163 | if (!ie->id_cr) { |
1164 | log_error("initiator_recv_HASH_SA_NONCE: " |
1165 | "malloc (%lu) failed", |
1166 | (unsigned long)ie->id_cr_sz); |
1167 | return -1; |
1168 | } |
1169 | memcpy(ie->id_cr, idp->p, ie->id_cr_sz); |
1170 | idp->flags |= PL_MARK1; |
1171 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4) |
1172 | "initiator_recv_HASH_SA_NONCE: IDcr",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4) |
1173 | ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4); |
1174 | } else { |
1175 | /* |
1176 | * If client identifiers are not present in the exchange, |
1177 | * we fake them. RFC 2409 states: |
1178 | * The identities of the SAs negotiated in Quick Mode are |
1179 | * implicitly assumed to be the IP addresses of the ISAKMP |
1180 | * peers, without any constraints on the protocol or port |
1181 | * numbers allowed, unless client identifiers are specified |
1182 | * in Quick Mode. |
1183 | * |
1184 | * -- Michael Paddon (mwp@aba.net.au) |
1185 | */ |
1186 | |
1187 | ie->flags = IPSEC_EXCH_FLAG_NO_ID1; |
1188 | |
1189 | /* Get initiator and responder addresses. */ |
1190 | msg->transport->vtbl->get_src(msg->transport, &src); |
1191 | msg->transport->vtbl->get_dst(msg->transport, &dst); |
1192 | ie->id_ci_sz = ISAKMP_ID_DATA_OFF8 + sockaddr_addrlen(src); |
1193 | ie->id_cr_sz = ISAKMP_ID_DATA_OFF8 + sockaddr_addrlen(dst); |
1194 | ie->id_ci = calloc(ie->id_ci_sz, sizeof(char)); |
1195 | ie->id_cr = calloc(ie->id_cr_sz, sizeof(char)); |
1196 | |
1197 | if (!ie->id_ci || !ie->id_cr) { |
1198 | log_error("initiator_recv_HASH_SA_NONCE: " |
1199 | "calloc (%lu, %lu) failed", |
1200 | (unsigned long)ie->id_cr_sz, |
1201 | (unsigned long)sizeof(char)); |
1202 | free(ie->id_ci); |
1203 | ie->id_ci = 0; |
1204 | free(ie->id_cr); |
1205 | ie->id_cr = 0; |
1206 | return -1; |
1207 | } |
1208 | if (src->sa_family != dst->sa_family) { |
1209 | log_error("initiator_recv_HASH_SA_NONCE: " |
1210 | "sa_family mismatch"); |
1211 | free(ie->id_ci); |
1212 | ie->id_ci = 0; |
1213 | free(ie->id_cr); |
1214 | ie->id_cr = 0; |
1215 | return -1; |
1216 | } |
1217 | switch (src->sa_family) { |
1218 | case AF_INET2: |
1219 | SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_ci, 1); |
1220 | SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_cr, 1); |
1221 | break; |
1222 | |
1223 | case AF_INET624: |
1224 | SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_ci, 5); |
1225 | SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_cr, 5); |
1226 | break; |
1227 | |
1228 | default: |
1229 | log_error("initiator_recv_HASH_SA_NONCE: " |
1230 | "unknown sa_family %d", src->sa_family); |
1231 | free(ie->id_ci); |
1232 | ie->id_ci = 0; |
1233 | free(ie->id_cr); |
1234 | ie->id_cr = 0; |
1235 | return -1; |
1236 | } |
1237 | memcpy(ie->id_ci + ISAKMP_ID_DATA_OFF8, sockaddr_addrdata(src), |
1238 | sockaddr_addrlen(src)); |
1239 | memcpy(ie->id_cr + ISAKMP_ID_DATA_OFF8, sockaddr_addrdata(dst), |
1240 | sockaddr_addrlen(dst)); |
1241 | } |
1242 | |
1243 | /* Build the protection suite in our SA. */ |
1244 | TAILQ_FOREACH(xf, &msg->payload[ISAKMP_PAYLOAD_TRANSFORM], link)for((xf) = ((&msg->payload[3])->tqh_first); (xf) != ((void*)0); (xf) = ((xf)->link.tqe_next)) { |
1245 | /* |
1246 | * XXX We could check that the proposal each transform |
1247 | * belongs to is unique. |
1248 | */ |
1249 | |
1250 | if (sa_add_transform(sa, xf, exchange->initiator, &proto)) |
1251 | return -1; |
1252 | |
1253 | /* XXX Check that the chosen transform matches an offer. */ |
1254 | |
1255 | ipsec_decode_transform(msg, sa, proto, xf->p); |
1256 | } |
1257 | |
1258 | /* Now remove offers that we don't need anymore. */ |
1259 | for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto; proto = next_proto) { |
1260 | next_proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next); |
1261 | if (!proto->chosen) |
1262 | proto_free(proto); |
1263 | } |
1264 | |
1265 | if (!check_policy(exchange, sa, msg->isakmp_sa)) { |
1266 | message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN14, 0, 1, 0); |
1267 | log_print("initiator_recv_HASH_SA_NONCE: policy check failed"); |
1268 | return -1; |
1269 | } |
1270 | |
1271 | /* Mark the SA as handled. */ |
1272 | sa_p->flags |= PL_MARK1; |
1273 | |
1274 | isa = sa->data; |
1275 | if ((isa->group_desc && |
1276 | (!ie->group || ie->group->id != isa->group_desc)) || |
1277 | (!isa->group_desc && ie->group)) { |
1278 | log_print("initiator_recv_HASH_SA_NONCE: disagreement on PFS"); |
1279 | return -1; |
1280 | } |
1281 | /* Copy out the initiator's nonce. */ |
1282 | if (exchange_save_nonce(msg)) |
1283 | return -1; |
1284 | |
1285 | /* Handle the optional KEY_EXCH payload. */ |
1286 | if (kep && ipsec_save_g_x(msg)) |
1287 | return -1; |
1288 | |
1289 | return 0; |
1290 | } |
1291 | |
1292 | static int |
1293 | initiator_send_HASH(struct message *msg) |
1294 | { |
1295 | struct exchange *exchange = msg->exchange; |
1296 | struct ipsec_exch *ie = exchange->data; |
1297 | struct sa *isakmp_sa = msg->isakmp_sa; |
1298 | struct ipsec_sa *isa = isakmp_sa->data; |
1299 | struct prf *prf; |
1300 | u_int8_t *buf; |
1301 | struct hash *hash = hash_get(isa->hash); |
1302 | |
1303 | /* |
1304 | * We want a HASH payload to start with. XXX Share with |
1305 | * ike_main_mode.c? |
1306 | */ |
1307 | buf = malloc(ISAKMP_HASH_SZ4 + hash->hashsize); |
1308 | if (!buf) { |
1309 | log_error("initiator_send_HASH: malloc (%lu) failed", |
1310 | ISAKMP_HASH_SZ4 + (unsigned long)hash->hashsize); |
1311 | return -1; |
1312 | } |
1313 | if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH8, buf, |
1314 | ISAKMP_HASH_SZ4 + hash->hashsize, 1)) { |
1315 | free(buf); |
1316 | return -1; |
1317 | } |
1318 | /* Allocate the prf and start calculating our HASH(3). XXX Share? */ |
1319 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: SKEYID_a",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: SKEYID_a" , isa->skeyid_a, isa->skeyid_len) |
1320 | isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: SKEYID_a" , isa->skeyid_a, isa->skeyid_len); |
1321 | prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, |
1322 | isa->skeyid_len); |
1323 | if (!prf) |
1324 | return -1; |
1325 | prf->Init(prf->prfctx); |
1326 | prf->Update(prf->prfctx, (unsigned char *)"\0", 1); |
1327 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: message_id",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: message_id" , exchange->message_id, 4) |
1328 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: message_id" , exchange->message_id, 4); |
1329 | prf->Update(prf->prfctx, exchange->message_id, |
1330 | ISAKMP_HDR_MESSAGE_ID_LEN4); |
1331 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_I_b",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_I_b" , exchange->nonce_i, exchange->nonce_i_len) |
1332 | exchange->nonce_i, exchange->nonce_i_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_I_b" , exchange->nonce_i, exchange->nonce_i_len); |
1333 | prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); |
1334 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_R_b",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_R_b" , exchange->nonce_r, exchange->nonce_r_len) |
1335 | exchange->nonce_r, exchange->nonce_r_len))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_R_b" , exchange->nonce_r, exchange->nonce_r_len); |
1336 | prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); |
1337 | prf->Final(buf + ISAKMP_GEN_SZ4, prf->prfctx); |
1338 | prf_free(prf); |
1339 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: HASH(3)",log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: HASH(3)" , buf + 4, hash->hashsize) |
1340 | buf + ISAKMP_GEN_SZ, hash->hashsize))log_debug_buf (LOG_NEGOTIATION, 90, "initiator_send_HASH: HASH(3)" , buf + 4, hash->hashsize); |
1341 | |
1342 | if (ie->group) |
1343 | message_register_post_send(msg, gen_g_xy); |
1344 | |
1345 | message_register_post_send(msg, post_quick_mode); |
1346 | |
1347 | return 0; |
1348 | } |
1349 | |
1350 | static void |
1351 | post_quick_mode(struct message *msg) |
1352 | { |
1353 | struct sa *isakmp_sa = msg->isakmp_sa; |
1354 | struct ipsec_sa *isa = isakmp_sa->data; |
1355 | struct exchange *exchange = msg->exchange; |
1356 | struct ipsec_exch *ie = exchange->data; |
1357 | struct prf *prf; |
1358 | struct sa *sa; |
1359 | struct proto *proto; |
1360 | struct ipsec_proto *iproto; |
1361 | u_int8_t *keymat; |
1362 | int i; |
1363 | |
1364 | /* |
1365 | * Loop over all SA negotiations and do both an in- and an outgoing SA |
1366 | * per protocol. |
1367 | */ |
1368 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa; |
1369 | sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) { |
1370 | for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto; |
1371 | proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next)) { |
1372 | if (proto->proto == IPSEC_PROTO_IPCOMP4) |
1373 | continue; |
1374 | |
1375 | iproto = proto->data; |
1376 | |
1377 | /* |
1378 | * There are two SAs for each SA negotiation, |
1379 | * incoming and outgoing. |
1380 | */ |
1381 | for (i = 0; i < 2; i++) { |
1382 | prf = prf_alloc(isa->prf_type, isa->hash, |
1383 | isa->skeyid_d, isa->skeyid_len); |
1384 | if (!prf) { |
1385 | /* XXX What to do? */ |
1386 | continue; |
1387 | } |
1388 | ie->keymat_len = ipsec_keymat_length(proto); |
1389 | |
1390 | /* |
1391 | * We need to roundup the length of the key |
1392 | * material buffer to a multiple of the PRF's |
1393 | * blocksize as it is generated in chunks of |
1394 | * that blocksize. |
1395 | */ |
1396 | iproto->keymat[i] |
1397 | = malloc(((ie->keymat_len + prf->blocksize - 1) |
1398 | / prf->blocksize) * prf->blocksize); |
1399 | if (!iproto->keymat[i]) { |
1400 | log_error("post_quick_mode: " |
1401 | "malloc (%lu) failed", |
1402 | (((unsigned long)ie->keymat_len + |
1403 | prf->blocksize - 1) / prf->blocksize) * |
1404 | prf->blocksize); |
1405 | /* XXX What more to do? */ |
1406 | free(prf); |
1407 | continue; |
1408 | } |
1409 | for (keymat = iproto->keymat[i]; |
1410 | keymat < iproto->keymat[i] + ie->keymat_len; |
1411 | keymat += prf->blocksize) { |
1412 | prf->Init(prf->prfctx); |
1413 | |
1414 | if (keymat != iproto->keymat[i]) { |
1415 | /* |
1416 | * Hash in last round's |
1417 | * KEYMAT. |
1418 | */ |
1419 | LOG_DBG_BUF((LOG_NEGOTIATION,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "last KEYMAT" , keymat - prf->blocksize, prf->blocksize) |
1420 | 90, "post_quick_mode: "log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "last KEYMAT" , keymat - prf->blocksize, prf->blocksize) |
1421 | "last KEYMAT",log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "last KEYMAT" , keymat - prf->blocksize, prf->blocksize) |
1422 | keymat - prf->blocksize,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "last KEYMAT" , keymat - prf->blocksize, prf->blocksize) |
1423 | prf->blocksize))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "last KEYMAT" , keymat - prf->blocksize, prf->blocksize); |
1424 | prf->Update(prf->prfctx, |
1425 | keymat - prf->blocksize, |
1426 | prf->blocksize); |
1427 | } |
1428 | /* If PFS is used hash in g^xy. */ |
1429 | if (ie->g_xy) { |
1430 | LOG_DBG_BUF((LOG_NEGOTIATION,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "g^xy" , ie->g_xy, ie->g_xy_len) |
1431 | 90, "post_quick_mode: "log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "g^xy" , ie->g_xy, ie->g_xy_len) |
1432 | "g^xy", ie->g_xy,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "g^xy" , ie->g_xy, ie->g_xy_len) |
1433 | ie->g_xy_len))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: " "g^xy" , ie->g_xy, ie->g_xy_len); |
1434 | prf->Update(prf->prfctx, |
1435 | ie->g_xy, ie->g_xy_len); |
1436 | } |
1437 | LOG_DBG((LOG_NEGOTIATION, 90,log_debug (LOG_NEGOTIATION, 90, "post_quick_mode: " "suite %d proto %d" , proto->no, proto->proto) |
1438 | "post_quick_mode: "log_debug (LOG_NEGOTIATION, 90, "post_quick_mode: " "suite %d proto %d" , proto->no, proto->proto) |
1439 | "suite %d proto %d", proto->no,log_debug (LOG_NEGOTIATION, 90, "post_quick_mode: " "suite %d proto %d" , proto->no, proto->proto) |
1440 | proto->proto))log_debug (LOG_NEGOTIATION, 90, "post_quick_mode: " "suite %d proto %d" , proto->no, proto->proto); |
1441 | prf->Update(prf->prfctx, &proto->proto, |
1442 | 1); |
1443 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: SPI", proto ->spi[i], proto->spi_sz[i]) |
1444 | "post_quick_mode: SPI",log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: SPI", proto ->spi[i], proto->spi_sz[i]) |
1445 | proto->spi[i], proto->spi_sz[i]))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: SPI", proto ->spi[i], proto->spi_sz[i]); |
1446 | prf->Update(prf->prfctx, |
1447 | proto->spi[i], proto->spi_sz[i]); |
1448 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", exchange ->nonce_i, exchange->nonce_i_len) |
1449 | "post_quick_mode: Ni_b",log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", exchange ->nonce_i, exchange->nonce_i_len) |
1450 | exchange->nonce_i,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", exchange ->nonce_i, exchange->nonce_i_len) |
1451 | exchange->nonce_i_len))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", exchange ->nonce_i, exchange->nonce_i_len); |
1452 | prf->Update(prf->prfctx, |
1453 | exchange->nonce_i, |
1454 | exchange->nonce_i_len); |
1455 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", exchange ->nonce_r, exchange->nonce_r_len) |
1456 | "post_quick_mode: Nr_b",log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", exchange ->nonce_r, exchange->nonce_r_len) |
1457 | exchange->nonce_r,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", exchange ->nonce_r, exchange->nonce_r_len) |
1458 | exchange->nonce_r_len))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", exchange ->nonce_r, exchange->nonce_r_len); |
1459 | prf->Update(prf->prfctx, |
1460 | exchange->nonce_r, |
1461 | exchange->nonce_r_len); |
1462 | prf->Final(keymat, prf->prfctx); |
1463 | } |
1464 | prf_free(prf); |
1465 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: KEYMAT" , iproto->keymat[i], ie->keymat_len) |
1466 | "post_quick_mode: KEYMAT",log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: KEYMAT" , iproto->keymat[i], ie->keymat_len) |
1467 | iproto->keymat[i], ie->keymat_len))log_debug_buf (LOG_NEGOTIATION, 90, "post_quick_mode: KEYMAT" , iproto->keymat[i], ie->keymat_len); |
1468 | } |
1469 | } |
1470 | } |
1471 | |
1472 | log_verbose("isakmpd: quick mode done%s: %s", |
1473 | (exchange->initiator == 0) ? " (as responder)" : "", |
1474 | !msg->isakmp_sa || !msg->isakmp_sa->transport ? "<no transport>" |
1475 | : msg->isakmp_sa->transport->vtbl->decode_ids |
1476 | (msg->isakmp_sa->transport)); |
1477 | } |
1478 | |
1479 | /* |
1480 | * Accept a set of transforms offered by the initiator and chose one we can |
1481 | * handle. |
1482 | * XXX Describe in more detail. |
1483 | */ |
1484 | static int |
1485 | responder_recv_HASH_SA_NONCE(struct message *msg) |
1486 | { |
1487 | struct payload *hashp, *kep, *idp; |
1488 | struct sa *sa; |
1489 | struct sa *isakmp_sa = msg->isakmp_sa; |
1490 | struct ipsec_sa *isa = isakmp_sa->data; |
1491 | struct exchange *exchange = msg->exchange; |
1492 | struct ipsec_exch *ie = exchange->data; |
1493 | struct prf *prf; |
1494 | u_int8_t *hash, *my_hash = 0; |
1495 | size_t hash_len; |
1496 | u_int8_t *pkt = msg->iov[0].iov_base; |
1497 | u_int8_t group_desc = 0; |
1498 | int retval = -1; |
1499 | struct proto *proto; |
1500 | struct sockaddr *src, *dst; |
1501 | char *name; |
1502 | |
1503 | hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH8); |
1504 | hash = hashp->p; |
1505 | hashp->flags |= PL_MARK1; |
1506 | |
1507 | /* The HASH payload should be the first one. */ |
1508 | if (hash != pkt + ISAKMP_HDR_SZ28) { |
1509 | /* XXX Is there a better notification type? */ |
1510 | message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 0); |
1511 | goto cleanup; |
1512 | } |
1513 | hash_len = GET_ISAKMP_GEN_LENGTH(hash)field_get_num (isakmp_gen_fld + 2, hash); |
1514 | my_hash = malloc(hash_len - ISAKMP_GEN_SZ4); |
1515 | if (!my_hash) { |
1516 | log_error("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", |
1517 | (unsigned long)hash_len - ISAKMP_GEN_SZ4); |
1518 | goto cleanup; |
1519 | } |
1520 | /* |
1521 | * Check the payload's integrity. |
1522 | * XXX Share with ipsec_fill_in_hash? |
1523 | */ |
1524 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: "log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: " "SKEYID_a", isa->skeyid_a, isa->skeyid_len) |
1525 | "SKEYID_a", isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: " "SKEYID_a", isa->skeyid_a, isa->skeyid_len); |
1526 | prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, |
1527 | isa->skeyid_len); |
1528 | if (!prf) |
1529 | goto cleanup; |
1530 | prf->Init(prf->prfctx); |
1531 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1532 | "responder_recv_HASH_SA_NONCE: message_id",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1533 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message_id" , exchange->message_id, 4); |
1534 | prf->Update(prf->prfctx, exchange->message_id, |
1535 | ISAKMP_HDR_MESSAGE_ID_LEN4); |
1536 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message after HASH" , hash + hash_len, msg->iov[0].iov_len - 28 - hash_len) |
1537 | "responder_recv_HASH_SA_NONCE: message after HASH",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message after HASH" , hash + hash_len, msg->iov[0].iov_len - 28 - hash_len) |
1538 | hash + hash_len,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message after HASH" , hash + hash_len, msg->iov[0].iov_len - 28 - hash_len) |
1539 | msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: message after HASH" , hash + hash_len, msg->iov[0].iov_len - 28 - hash_len); |
1540 | prf->Update(prf->prfctx, hash + hash_len, |
1541 | msg->iov[0].iov_len - ISAKMP_HDR_SZ28 - hash_len); |
1542 | prf->Final(my_hash, prf->prfctx); |
1543 | prf_free(prf); |
1544 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: computed HASH(1)" , my_hash, hash_len - 4) |
1545 | "responder_recv_HASH_SA_NONCE: computed HASH(1)", my_hash,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: computed HASH(1)" , my_hash, hash_len - 4) |
1546 | hash_len - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: computed HASH(1)" , my_hash, hash_len - 4); |
1547 | if (memcmp(hash + ISAKMP_GEN_SZ4, my_hash, hash_len - ISAKMP_GEN_SZ4) |
1548 | != 0) { |
1549 | message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23, 0, |
1550 | 1, 0); |
1551 | goto cleanup; |
1552 | } |
1553 | free(my_hash); |
1554 | my_hash = 0; |
1555 | |
1556 | /* Mark message as authenticated. */ |
1557 | msg->flags |= MSG_AUTHENTICATED0x10; |
1558 | |
1559 | kep = payload_first(msg, ISAKMP_PAYLOAD_KEY_EXCH4); |
1560 | if (kep) |
1561 | ie->pfs = 1; |
1562 | |
1563 | /* Drop message when it contains ID types we do not implement yet. */ |
1564 | TAILQ_FOREACH(idp, &msg->payload[ISAKMP_PAYLOAD_ID], link)for((idp) = ((&msg->payload[5])->tqh_first); (idp) != ((void*)0); (idp) = ((idp)->link.tqe_next)) { |
1565 | switch (GET_ISAKMP_ID_TYPE(idp->p)field_get_num (isakmp_id_fld + 0, idp->p)) { |
1566 | case IPSEC_ID_IPV4_ADDR1: |
1567 | case IPSEC_ID_IPV4_ADDR_SUBNET4: |
1568 | case IPSEC_ID_IPV6_ADDR5: |
1569 | case IPSEC_ID_IPV6_ADDR_SUBNET6: |
1570 | break; |
1571 | |
1572 | case IPSEC_ID_FQDN2: |
1573 | /* |
1574 | * FQDN may be used for in NAT-T with transport mode. |
1575 | * We can handle the message in this case. In the |
1576 | * other cases we'll drop the message later. |
1577 | */ |
1578 | break; |
1579 | |
1580 | default: |
1581 | message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION18, |
1582 | 0, 1, 0); |
1583 | goto cleanup; |
1584 | } |
1585 | } |
1586 | |
1587 | /* Handle optional client ID payloads. */ |
1588 | idp = payload_first(msg, ISAKMP_PAYLOAD_ID5); |
1589 | if (idp) { |
1590 | /* If IDci is there, IDcr must be too. */ |
1591 | if (!TAILQ_NEXT(idp, link)((idp)->link.tqe_next)) { |
1592 | /* XXX Is this a good notify type? */ |
1593 | message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, |
1594 | 1, 0); |
1595 | goto cleanup; |
1596 | } |
1597 | ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH(idp->p)field_get_num (isakmp_gen_fld + 2, idp->p); |
1598 | ie->id_ci = malloc(ie->id_ci_sz); |
1599 | if (!ie->id_ci) { |
1600 | log_error("responder_recv_HASH_SA_NONCE: " |
1601 | "malloc (%lu) failed", |
1602 | (unsigned long)ie->id_ci_sz); |
1603 | goto cleanup; |
1604 | } |
1605 | memcpy(ie->id_ci, idp->p, ie->id_ci_sz); |
1606 | idp->flags |= PL_MARK1; |
1607 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4) |
1608 | "responder_recv_HASH_SA_NONCE: IDci",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4) |
1609 | ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDci" , ie->id_ci + 4, ie->id_ci_sz - 4); |
1610 | |
1611 | idp = TAILQ_NEXT(idp, link)((idp)->link.tqe_next); |
1612 | ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH(idp->p)field_get_num (isakmp_gen_fld + 2, idp->p); |
1613 | ie->id_cr = malloc(ie->id_cr_sz); |
1614 | if (!ie->id_cr) { |
1615 | log_error("responder_recv_HASH_SA_NONCE: " |
1616 | "malloc (%lu) failed", |
1617 | (unsigned long)ie->id_cr_sz); |
1618 | goto cleanup; |
1619 | } |
1620 | memcpy(ie->id_cr, idp->p, ie->id_cr_sz); |
1621 | idp->flags |= PL_MARK1; |
1622 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4) |
1623 | "responder_recv_HASH_SA_NONCE: IDcr",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4) |
1624 | ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: IDcr" , ie->id_cr + 4, ie->id_cr_sz - 4); |
1625 | } else { |
1626 | /* |
1627 | * If client identifiers are not present in the exchange, |
1628 | * we fake them. RFC 2409 states: |
1629 | * The identities of the SAs negotiated in Quick Mode are |
1630 | * implicitly assumed to be the IP addresses of the ISAKMP |
1631 | * peers, without any constraints on the protocol or port |
1632 | * numbers allowed, unless client identifiers are specified |
1633 | * in Quick Mode. |
1634 | * |
1635 | * -- Michael Paddon (mwp@aba.net.au) |
1636 | */ |
1637 | |
1638 | ie->flags = IPSEC_EXCH_FLAG_NO_ID1; |
1639 | |
1640 | /* Get initiator and responder addresses. */ |
1641 | msg->transport->vtbl->get_src(msg->transport, &src); |
1642 | msg->transport->vtbl->get_dst(msg->transport, &dst); |
1643 | ie->id_ci_sz = ISAKMP_ID_DATA_OFF8 + sockaddr_addrlen(src); |
1644 | ie->id_cr_sz = ISAKMP_ID_DATA_OFF8 + sockaddr_addrlen(dst); |
1645 | ie->id_ci = calloc(ie->id_ci_sz, sizeof(char)); |
1646 | ie->id_cr = calloc(ie->id_cr_sz, sizeof(char)); |
Result of 'calloc' is converted to a pointer of type 'u_int8_t', which is incompatible with sizeof operand type 'char' | |
1647 | |
1648 | if (!ie->id_ci || !ie->id_cr) { |
1649 | log_error("responder_recv_HASH_SA_NONCE: " |
1650 | "calloc (%lu, %lu) failed", |
1651 | (unsigned long)ie->id_ci_sz, |
1652 | (unsigned long)sizeof(char)); |
1653 | goto cleanup; |
1654 | } |
1655 | if (src->sa_family != dst->sa_family) { |
1656 | log_error("initiator_recv_HASH_SA_NONCE: " |
1657 | "sa_family mismatch"); |
1658 | goto cleanup; |
1659 | } |
1660 | switch (src->sa_family) { |
1661 | case AF_INET2: |
1662 | SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_ci, 1); |
1663 | SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_cr, 1); |
1664 | break; |
1665 | |
1666 | case AF_INET624: |
1667 | SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_ci, 5); |
1668 | SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, ie->id_cr, 5); |
1669 | break; |
1670 | |
1671 | default: |
1672 | log_error("initiator_recv_HASH_SA_NONCE: " |
1673 | "unknown sa_family %d", src->sa_family); |
1674 | goto cleanup; |
1675 | } |
1676 | |
1677 | memcpy(ie->id_cr + ISAKMP_ID_DATA_OFF8, sockaddr_addrdata(src), |
1678 | sockaddr_addrlen(src)); |
1679 | memcpy(ie->id_ci + ISAKMP_ID_DATA_OFF8, sockaddr_addrdata(dst), |
1680 | sockaddr_addrlen(dst)); |
1681 | } |
1682 | |
1683 | if (message_negotiate_sa(msg, check_policy)) |
1684 | goto cleanup; |
1685 | |
1686 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa; |
1687 | sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) { |
1688 | for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto; |
1689 | proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next)) { |
1690 | /* |
1691 | * XXX we need to have some attributes per proto, not |
1692 | * all per SA. |
1693 | */ |
1694 | ipsec_decode_transform(msg, sa, proto, |
1695 | proto->chosen->p); |
1696 | if (proto->proto == IPSEC_PROTO_IPSEC_AH2 && |
1697 | !((struct ipsec_proto *)proto->data)->auth) { |
1698 | log_print("responder_recv_HASH_SA_NONCE: " |
1699 | "AH proposed without an algorithm " |
1700 | "attribute"); |
1701 | message_drop(msg, |
1702 | ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN14, 0, 1, 0); |
1703 | goto next_sa; |
1704 | } |
1705 | } |
1706 | |
1707 | isa = sa->data; |
1708 | |
1709 | /* |
1710 | * The group description is mandatory if we got a KEY_EXCH |
1711 | * payload. |
1712 | */ |
1713 | if (kep) { |
1714 | if (!isa->group_desc) { |
1715 | log_print("responder_recv_HASH_SA_NONCE: " |
1716 | "KEY_EXCH payload without a group " |
1717 | "desc. attribute"); |
1718 | message_drop(msg, |
1719 | ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN14, 0, 1, 0); |
1720 | continue; |
1721 | } |
1722 | /* Also, all SAs must have equal groups. */ |
1723 | if (!group_desc) |
1724 | group_desc = isa->group_desc; |
1725 | else if (group_desc != isa->group_desc) { |
1726 | log_print("responder_recv_HASH_SA_NONCE: " |
1727 | "differing group descriptions in one QM"); |
1728 | message_drop(msg, |
1729 | ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN14, 0, 1, 0); |
1730 | continue; |
1731 | } |
1732 | } |
1733 | /* At least one SA was accepted. */ |
1734 | retval = 0; |
1735 | |
1736 | next_sa: |
1737 | ; /* XXX gcc3 wants this. */ |
1738 | } |
1739 | |
1740 | if (kep) { |
1741 | ie->group = group_get(group_desc); |
1742 | if (!ie->group) { |
1743 | /* |
1744 | * XXX If the error was due to an out-of-range group |
1745 | * description we should notify our peer, but this |
1746 | * should probably be done by the attribute |
1747 | * validation. Is it? |
1748 | */ |
1749 | goto cleanup; |
1750 | } |
1751 | } |
1752 | /* Copy out the initiator's nonce. */ |
1753 | if (exchange_save_nonce(msg)) |
1754 | goto cleanup; |
1755 | |
1756 | /* Handle the optional KEY_EXCH payload. */ |
1757 | if (kep && ipsec_save_g_x(msg)) |
1758 | goto cleanup; |
1759 | |
1760 | /* |
1761 | * Try to find and set the connection name on the exchange. |
1762 | */ |
1763 | |
1764 | /* |
1765 | * Check for accepted identities as well as lookup the connection |
1766 | * name and set it on the exchange. |
1767 | * |
1768 | * When not using policies make sure the peer proposes sane IDs. |
1769 | * Otherwise this is done by KeyNote. |
1770 | */ |
1771 | name = connection_passive_lookup_by_ids(ie->id_ci, ie->id_cr); |
1772 | if (name) { |
1773 | exchange->name = strdup(name); |
1774 | if (!exchange->name) { |
1775 | log_error("responder_recv_HASH_SA_NONCE: " |
1776 | "strdup (\"%s\") failed", name); |
1777 | goto cleanup; |
1778 | } |
1779 | } else if ( |
1780 | ignore_policy || |
1781 | strncmp("yes", conf_get_str("General", "Use-Keynote"), 3)) { |
1782 | log_print("responder_recv_HASH_SA_NONCE: peer proposed " |
1783 | "invalid phase 2 IDs: %s", |
1784 | (exchange->doi->decode_ids("initiator id %s, responder" |
1785 | " id %s", ie->id_ci, ie->id_ci_sz, ie->id_cr, |
1786 | ie->id_cr_sz, 1))); |
1787 | message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION18, 0, 1, |
1788 | 0); |
1789 | goto cleanup; |
1790 | } |
1791 | |
1792 | return retval; |
1793 | |
1794 | cleanup: |
1795 | /* Remove all potential protocols that have been added to the SAs. */ |
1796 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa; |
1797 | sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) |
1798 | while ((proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first)) != 0) |
1799 | proto_free(proto); |
1800 | free(my_hash); |
1801 | free(ie->id_ci); |
1802 | ie->id_ci = 0; |
1803 | free(ie->id_cr); |
1804 | ie->id_cr = 0; |
1805 | return -1; |
1806 | } |
1807 | |
1808 | /* Reply with the transform we chose. */ |
1809 | static int |
1810 | responder_send_HASH_SA_NONCE(struct message *msg) |
1811 | { |
1812 | struct exchange *exchange = msg->exchange; |
1813 | struct ipsec_exch *ie = exchange->data; |
1814 | struct sa *isakmp_sa = msg->isakmp_sa; |
1815 | struct ipsec_sa *isa = isakmp_sa->data; |
1816 | struct prf *prf; |
1817 | struct hash *hash = hash_get(isa->hash); |
1818 | size_t nonce_sz = exchange->nonce_i_len; |
1819 | u_int8_t *buf; |
1820 | int initiator = exchange->initiator; |
1821 | char header[80]; |
1822 | u_int32_t i; |
1823 | u_int8_t *id; |
1824 | size_t sz; |
1825 | |
1826 | /* |
1827 | * We want a HASH payload to start with. XXX Share with |
1828 | * ike_main_mode.c? |
1829 | */ |
1830 | buf = malloc(ISAKMP_HASH_SZ4 + hash->hashsize); |
1831 | if (!buf) { |
1832 | log_error("responder_send_HASH_SA_NONCE: malloc (%lu) failed", |
1833 | ISAKMP_HASH_SZ4 + (unsigned long)hash->hashsize); |
1834 | return -1; |
1835 | } |
1836 | if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH8, buf, |
1837 | ISAKMP_HASH_SZ4 + hash->hashsize, 1)) { |
1838 | free(buf); |
1839 | return -1; |
1840 | } |
1841 | /* Add the SA payload(s) with the transform(s) that was/were chosen. */ |
1842 | if (message_add_sa_payload(msg)) |
1843 | return -1; |
1844 | |
1845 | /* Generate a nonce, and add it to the message. */ |
1846 | if (exchange_gen_nonce(msg, nonce_sz)) |
1847 | return -1; |
1848 | |
1849 | /* Generate optional KEY_EXCH payload. This is known as PFS. */ |
1850 | if (ie->group && ipsec_gen_g_x(msg)) |
1851 | return -1; |
1852 | |
1853 | /* |
1854 | * If the initiator client ID's were acceptable, just mirror them |
1855 | * back. |
1856 | */ |
1857 | if (!(ie->flags & IPSEC_EXCH_FLAG_NO_ID1)) { |
1858 | sz = ie->id_ci_sz; |
1859 | id = malloc(sz); |
1860 | if (!id) { |
1861 | log_error("responder_send_HASH_SA_NONCE: " |
1862 | "malloc (%lu) failed", (unsigned long)sz); |
1863 | return -1; |
1864 | } |
1865 | memcpy(id, ie->id_ci, sz); |
1866 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDic" , id, sz) |
1867 | "responder_send_HASH_SA_NONCE: IDic", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDic" , id, sz); |
1868 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
1869 | free(id); |
1870 | return -1; |
1871 | } |
1872 | sz = ie->id_cr_sz; |
1873 | id = malloc(sz); |
1874 | if (!id) { |
1875 | log_error("responder_send_HASH_SA_NONCE: " |
1876 | "malloc (%lu) failed", (unsigned long)sz); |
1877 | return -1; |
1878 | } |
1879 | memcpy(id, ie->id_cr, sz); |
1880 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDrc" , id, sz) |
1881 | "responder_send_HASH_SA_NONCE: IDrc", id, sz))log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDrc" , id, sz); |
1882 | if (message_add_payload(msg, ISAKMP_PAYLOAD_ID5, id, sz, 1)) { |
1883 | free(id); |
1884 | return -1; |
1885 | } |
1886 | } |
1887 | /* Allocate the prf and start calculating our HASH(2). XXX Share? */ |
1888 | LOG_DBG((LOG_NEGOTIATION, 90, "responder_recv_HASH: "log_debug (LOG_NEGOTIATION, 90, "responder_recv_HASH: " "isakmp_sa %p isa %p" , isakmp_sa, isa) |
1889 | "isakmp_sa %p isa %p", isakmp_sa, isa))log_debug (LOG_NEGOTIATION, 90, "responder_recv_HASH: " "isakmp_sa %p isa %p" , isakmp_sa, isa); |
1890 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: "log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: " "SKEYID_a", isa->skeyid_a, isa->skeyid_len) |
1891 | "SKEYID_a", isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: " "SKEYID_a", isa->skeyid_a, isa->skeyid_len); |
1892 | prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, |
1893 | isa->skeyid_len); |
1894 | if (!prf) |
1895 | return -1; |
1896 | prf->Init(prf->prfctx); |
1897 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1898 | "responder_send_HASH_SA_NONCE: message_id",log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: message_id" , exchange->message_id, 4) |
1899 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: message_id" , exchange->message_id, 4); |
1900 | prf->Update(prf->prfctx, exchange->message_id, |
1901 | ISAKMP_HDR_MESSAGE_ID_LEN4); |
1902 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: "log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: " "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len) |
1903 | "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: " "NONCE_I_b", exchange->nonce_i, exchange->nonce_i_len); |
1904 | prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); |
1905 | |
1906 | /* Loop over all payloads after HASH(2). */ |
1907 | for (i = 2; i < msg->iovlen; i++) { |
1908 | /* XXX Misleading payload type printouts. */ |
1909 | snprintf(header, sizeof header, |
1910 | "responder_send_HASH_SA_NONCE: payload %d after HASH(2)", |
1911 | i - 1); |
1912 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, header, msg->iov[i].iov_base,log_debug_buf (LOG_NEGOTIATION, 90, header, msg->iov[i].iov_base , msg->iov[i].iov_len) |
1913 | msg->iov[i].iov_len))log_debug_buf (LOG_NEGOTIATION, 90, header, msg->iov[i].iov_base , msg->iov[i].iov_len); |
1914 | prf->Update(prf->prfctx, msg->iov[i].iov_base, |
1915 | msg->iov[i].iov_len); |
1916 | } |
1917 | prf->Final(buf + ISAKMP_HASH_DATA_OFF4, prf->prfctx); |
1918 | prf_free(prf); |
1919 | snprintf(header, sizeof header, "responder_send_HASH_SA_NONCE: " |
1920 | "HASH_%c", initiator ? 'I' : 'R'); |
1921 | LOG_DBG_BUF((LOG_NEGOTIATION, 80, header, buf + ISAKMP_HASH_DATA_OFF,log_debug_buf (LOG_NEGOTIATION, 80, header, buf + 4, hash-> hashsize) |
1922 | hash->hashsize))log_debug_buf (LOG_NEGOTIATION, 80, header, buf + 4, hash-> hashsize); |
1923 | |
1924 | if (ie->group) |
1925 | message_register_post_send(msg, gen_g_xy); |
1926 | |
1927 | return 0; |
1928 | } |
1929 | |
1930 | static void |
1931 | gen_g_xy(struct message *msg) |
1932 | { |
1933 | struct exchange *exchange = msg->exchange; |
1934 | struct ipsec_exch *ie = exchange->data; |
1935 | |
1936 | /* Compute Diffie-Hellman shared value. */ |
1937 | ie->g_xy_len = dh_secretlen(ie->group); |
1938 | ie->g_xy = malloc(ie->g_xy_len); |
1939 | if (!ie->g_xy) { |
1940 | log_error("gen_g_xy: malloc (%lu) failed", |
1941 | (unsigned long)ie->g_xy_len); |
1942 | return; |
1943 | } |
1944 | if (dh_create_shared(ie->group, ie->g_xy, |
1945 | exchange->initiator ? ie->g_xr : ie->g_xi)) { |
1946 | log_print("gen_g_xy: dh_create_shared failed"); |
1947 | return; |
1948 | } |
1949 | LOG_DBG_BUF((LOG_NEGOTIATION, 80, "gen_g_xy: g^xy", ie->g_xy,log_debug_buf (LOG_NEGOTIATION, 80, "gen_g_xy: g^xy", ie-> g_xy, ie->g_xy_len) |
1950 | ie->g_xy_len))log_debug_buf (LOG_NEGOTIATION, 80, "gen_g_xy: g^xy", ie-> g_xy, ie->g_xy_len); |
1951 | } |
1952 | |
1953 | static int |
1954 | responder_recv_HASH(struct message *msg) |
1955 | { |
1956 | struct exchange *exchange = msg->exchange; |
1957 | struct sa *isakmp_sa = msg->isakmp_sa; |
1958 | struct ipsec_sa *isa = isakmp_sa->data; |
1959 | struct prf *prf; |
1960 | u_int8_t *hash, *my_hash = 0; |
1961 | size_t hash_len; |
1962 | struct payload *hashp; |
1963 | |
1964 | /* Find HASH(3) and create our own hash, just as big. */ |
1965 | hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH8); |
1966 | hash = hashp->p; |
1967 | hashp->flags |= PL_MARK1; |
1968 | hash_len = GET_ISAKMP_GEN_LENGTH(hash)field_get_num (isakmp_gen_fld + 2, hash); |
1969 | my_hash = malloc(hash_len - ISAKMP_GEN_SZ4); |
1970 | if (!my_hash) { |
1971 | log_error("responder_recv_HASH: malloc (%lu) failed", |
1972 | (unsigned long)hash_len - ISAKMP_GEN_SZ4); |
1973 | goto cleanup; |
1974 | } |
1975 | /* Allocate the prf and start calculating our HASH(3). XXX Share? */ |
1976 | LOG_DBG((LOG_NEGOTIATION, 90, "responder_recv_HASH: "log_debug (LOG_NEGOTIATION, 90, "responder_recv_HASH: " "isakmp_sa %p isa %p" , isakmp_sa, isa) |
1977 | "isakmp_sa %p isa %p", isakmp_sa, isa))log_debug (LOG_NEGOTIATION, 90, "responder_recv_HASH: " "isakmp_sa %p isa %p" , isakmp_sa, isa); |
1978 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: SKEYID_a",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: SKEYID_a" , isa->skeyid_a, isa->skeyid_len) |
1979 | isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: SKEYID_a" , isa->skeyid_a, isa->skeyid_len); |
1980 | prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, |
1981 | isa->skeyid_len); |
1982 | if (!prf) |
1983 | goto cleanup; |
1984 | prf->Init(prf->prfctx); |
1985 | prf->Update(prf->prfctx, (unsigned char *)"\0", 1); |
1986 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: message_id",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: message_id" , exchange->message_id, 4) |
1987 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: message_id" , exchange->message_id, 4); |
1988 | prf->Update(prf->prfctx, exchange->message_id, |
1989 | ISAKMP_HDR_MESSAGE_ID_LEN4); |
1990 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_I_b",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_I_b" , exchange->nonce_i, exchange->nonce_i_len) |
1991 | exchange->nonce_i, exchange->nonce_i_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_I_b" , exchange->nonce_i, exchange->nonce_i_len); |
1992 | prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); |
1993 | LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_R_b",log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_R_b" , exchange->nonce_r, exchange->nonce_r_len) |
1994 | exchange->nonce_r, exchange->nonce_r_len))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_R_b" , exchange->nonce_r, exchange->nonce_r_len); |
1995 | prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); |
1996 | prf->Final(my_hash, prf->prfctx); |
1997 | prf_free(prf); |
1998 | LOG_DBG_BUF((LOG_NEGOTIATION, 90,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: computed HASH(3)" , my_hash, hash_len - 4) |
1999 | "responder_recv_HASH: computed HASH(3)", my_hash,log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: computed HASH(3)" , my_hash, hash_len - 4) |
2000 | hash_len - ISAKMP_GEN_SZ))log_debug_buf (LOG_NEGOTIATION, 90, "responder_recv_HASH: computed HASH(3)" , my_hash, hash_len - 4); |
2001 | if (memcmp(hash + ISAKMP_GEN_SZ4, my_hash, hash_len - ISAKMP_GEN_SZ4) |
2002 | != 0) { |
2003 | message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23, 0, |
2004 | 1, 0); |
2005 | goto cleanup; |
2006 | } |
2007 | free(my_hash); |
2008 | |
2009 | /* Mark message as authenticated. */ |
2010 | msg->flags |= MSG_AUTHENTICATED0x10; |
2011 | |
2012 | post_quick_mode(msg); |
2013 | |
2014 | return 0; |
2015 | |
2016 | cleanup: |
2017 | free(my_hash); |
2018 | return -1; |
2019 | } |