]>
Commit | Line | Data |
---|---|---|
c7dd2a7b MW |
1 | /** |
2 | * @file ike_sa_init_responded.c | |
3 | * | |
4 | * @brief State of a IKE_SA after responding to an IKE_SA_INIT request | |
5 | * | |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
5113680f MW |
22 | |
23 | #include <string.h> | |
24 | ||
c7dd2a7b MW |
25 | #include "ike_sa_init_responded.h" |
26 | ||
d45ec1de | 27 | #include <daemon.h> |
0fdc3c7f | 28 | #include <sa/authenticator.h> |
aeda79ff | 29 | #include <sa/child_sa.h> |
d45ec1de MW |
30 | #include <encoding/payloads/ts_payload.h> |
31 | #include <encoding/payloads/sa_payload.h> | |
32 | #include <encoding/payloads/id_payload.h> | |
33 | #include <encoding/payloads/auth_payload.h> | |
f6ba78c3 | 34 | #include <encoding/payloads/notify_payload.h> |
68621281 MW |
35 | #include <crypto/signers/signer.h> |
36 | #include <crypto/crypters/crypter.h> | |
ccf783d2 | 37 | #include <sa/states/ike_sa_established.h> |
c7dd2a7b | 38 | |
5796aa16 MW |
39 | |
40 | typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t; | |
41 | ||
c7dd2a7b MW |
42 | /** |
43 | * Private data of a ike_sa_init_responded_t object. | |
44 | * | |
45 | */ | |
5796aa16 | 46 | struct private_ike_sa_init_responded_t { |
c7dd2a7b | 47 | /** |
6d0310e8 | 48 | * Public interface of ike_sa_init_responded_t. |
c7dd2a7b MW |
49 | */ |
50 | ike_sa_init_responded_t public; | |
51 | ||
52 | /** | |
6d0310e8 | 53 | * Assigned IKE_SA. |
c7dd2a7b | 54 | */ |
ccf783d2 | 55 | protected_ike_sa_t *ike_sa; |
c7dd2a7b | 56 | |
0fdc3c7f JH |
57 | /** |
58 | * Received nonce. | |
59 | */ | |
60 | chunk_t received_nonce; | |
61 | ||
8d68033e JH |
62 | /** |
63 | * Sent nonce. | |
64 | */ | |
65 | chunk_t sent_nonce; | |
66 | ||
67 | /** | |
6d0310e8 | 68 | * Binary representation of the IKE_SA_INIT response. |
8d68033e JH |
69 | */ |
70 | chunk_t ike_sa_init_response_data; | |
71 | ||
72 | /** | |
6d0310e8 | 73 | * Binary representation of the IKE_SA_INIT request. |
8d68033e JH |
74 | */ |
75 | chunk_t ike_sa_init_request_data; | |
76 | ||
c7dd2a7b | 77 | /** |
6d0310e8 | 78 | * SA config to use. |
c7dd2a7b | 79 | */ |
16b9a73c | 80 | policy_t *policy; |
c7dd2a7b | 81 | |
a527a426 | 82 | /** |
fb8aa445 | 83 | * CHILD_SA, if set up |
a527a426 | 84 | */ |
fb8aa445 | 85 | child_sa_t *child_sa; |
a527a426 MW |
86 | |
87 | /** | |
88 | * Traffic selectors applicable at our site | |
89 | */ | |
90 | linked_list_t *my_ts; | |
91 | ||
92 | /** | |
93 | * Traffic selectors applicable at remote site | |
94 | */ | |
95 | linked_list_t *other_ts; | |
96 | ||
c7dd2a7b | 97 | /** |
6d0310e8 | 98 | * Assigned logger. |
c7dd2a7b MW |
99 | * |
100 | * Is logger of ike_sa! | |
101 | */ | |
102 | logger_t *logger; | |
ccf783d2 | 103 | |
6d0310e8 JH |
104 | /** |
105 | * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response. | |
106 | * | |
107 | * @param this calling object | |
108 | * @param request_idi ID payload representing initiator | |
109 | * @param request_idr ID payload representing responder (May be zero) | |
110 | * @param response The created IDr payload is added to this message_t object | |
111 | * @param response_idr The created IDr payload is also written to this location | |
112 | */ | |
113 | status_t (*build_idr_payload) (private_ike_sa_init_responded_t *this, | |
114 | id_payload_t *request_idi, | |
115 | id_payload_t *request_idr, | |
116 | message_t *response, | |
117 | id_payload_t **response_idr); | |
118 | ||
119 | /** | |
120 | * Process received SA payload and build SA payload for IKE_AUTH response. | |
121 | * | |
122 | * @param this calling object | |
123 | * @param request SA payload received in IKE_AUTH request | |
124 | * @param response The created SA payload is added to this message_t object | |
125 | */ | |
ccf783d2 | 126 | status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response); |
6d0310e8 JH |
127 | |
128 | /** | |
129 | * Process received AUTH payload and build AUTH payload for IKE_AUTH response. | |
130 | * | |
131 | * @param this calling object | |
132 | * @param request AUTH payload received in IKE_AUTH request | |
133 | * @param other_id_payload other ID payload needed to verify AUTH data | |
134 | * @param my_id_payload my ID payload needed to compute AUTH data | |
135 | * @param response The created AUTH payload is added to this message_t object | |
136 | */ | |
8d68033e | 137 | status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response); |
6d0310e8 JH |
138 | |
139 | /** | |
140 | * Process received TS payload and build TS payload for IKE_AUTH response. | |
141 | * | |
142 | * @param this calling object | |
143 | * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr | |
144 | * @param request TS payload received in IKE_AUTH request | |
145 | * @param response the created TS payload is added to this message_t object | |
146 | */ | |
ccf783d2 | 147 | status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *response); |
f6ba78c3 JH |
148 | |
149 | /** | |
6d0310e8 | 150 | * Sends a IKE_AUTH reply containing a notify payload. |
f6ba78c3 JH |
151 | * |
152 | * @param this calling object | |
283dbcc5 MW |
153 | * @param notify_payload payload to process |
154 | * @return | |
155 | * - DELETE_ME if IKE_SA should be deleted | |
156 | * - SUCCSS if processed successfull | |
f6ba78c3 | 157 | */ |
283dbcc5 | 158 | status_t (*process_notify_payload) (private_ike_sa_init_responded_t *this, notify_payload_t* notify_payload); |
fb8aa445 MW |
159 | |
160 | /** | |
161 | * Destroy function called internally of this class after state change to | |
162 | * state IKE_SA_ESTABLISHED succeeded. | |
163 | * | |
164 | * This destroy function does not destroy objects which were passed to the new state. | |
165 | * | |
166 | * @param this calling object | |
167 | */ | |
168 | void (*destroy_after_state_change) (private_ike_sa_init_responded_t *this); | |
c7dd2a7b MW |
169 | }; |
170 | ||
171 | /** | |
172 | * Implements state_t.get_state | |
173 | */ | |
ccf783d2 | 174 | static status_t process_message(private_ike_sa_init_responded_t *this, message_t *request) |
c7dd2a7b | 175 | { |
283dbcc5 MW |
176 | id_payload_t *idi_request = NULL, *idr_request = NULL,*idr_response; |
177 | ts_payload_t *tsi_request = NULL, *tsr_request = NULL; | |
178 | auth_payload_t *auth_request = NULL; | |
179 | sa_payload_t *sa_request = NULL; | |
6d0310e8 | 180 | iterator_t *payloads; |
ccf783d2 | 181 | message_t *response; |
6d0310e8 JH |
182 | crypter_t *crypter; |
183 | signer_t *signer; | |
184 | status_t status; | |
283dbcc5 | 185 | host_t *my_host, *other_host; |
16b9a73c | 186 | connection_t *connection; |
a527a426 | 187 | |
6d0310e8 | 188 | if (request->get_exchange_type(request) != IKE_AUTH) |
9b8f174d | 189 | { |
aee3eb52 | 190 | this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_responded", |
6d0310e8 | 191 | mapping_find(exchange_type_m,request->get_exchange_type(request))); |
9b8f174d MW |
192 | return FAILED; |
193 | } | |
194 | ||
ccf783d2 | 195 | if (!request->get_request(request)) |
9b8f174d | 196 | { |
283dbcc5 | 197 | this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH responses not allowed state ike_sa_init_responded"); |
9b8f174d MW |
198 | return FAILED; |
199 | } | |
200 | ||
9b8f174d MW |
201 | /* get signer for verification and crypter for decryption */ |
202 | signer = this->ike_sa->get_signer_initiator(this->ike_sa); | |
203 | crypter = this->ike_sa->get_crypter_initiator(this->ike_sa); | |
204 | ||
ccf783d2 | 205 | status = request->parse_body(request, crypter, signer); |
9b8f174d MW |
206 | if (status != SUCCESS) |
207 | { | |
6d0310e8 JH |
208 | if (status == NOT_SUPPORTED) |
209 | { | |
283dbcc5 MW |
210 | this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH request contains unsupported payload with critical flag set." |
211 | "Deleting IKE_SA"); | |
212 | this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER); | |
6d0310e8 JH |
213 | return DELETE_ME; |
214 | } | |
215 | else | |
216 | { | |
283dbcc5 | 217 | this->logger->log(this->logger, AUDIT, "IKE_AUTH request decryption faild. Ignoring message"); |
6d0310e8 | 218 | } |
9b8f174d MW |
219 | return status; |
220 | } | |
221 | ||
d45ec1de | 222 | /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */ |
ccf783d2 | 223 | payloads = request->get_payload_iterator(request); |
9b8f174d MW |
224 | while (payloads->has_next(payloads)) |
225 | { | |
226 | payload_t *payload; | |
9b8f174d MW |
227 | payloads->current(payloads, (void**)&payload); |
228 | ||
9b8f174d MW |
229 | switch (payload->get_type(payload)) |
230 | { | |
d45ec1de MW |
231 | case ID_INITIATOR: |
232 | { | |
ccf783d2 | 233 | idi_request = (id_payload_t*)payload; |
d45ec1de MW |
234 | break; |
235 | } | |
236 | case AUTHENTICATION: | |
237 | { | |
ccf783d2 | 238 | auth_request = (auth_payload_t*)payload; |
d45ec1de MW |
239 | break; |
240 | } | |
241 | case ID_RESPONDER: | |
242 | { | |
ccf783d2 | 243 | idr_request = (id_payload_t*)payload; |
d45ec1de MW |
244 | break; |
245 | } | |
246 | case SECURITY_ASSOCIATION: | |
247 | { | |
ccf783d2 | 248 | sa_request = (sa_payload_t*)payload; |
d45ec1de MW |
249 | break; |
250 | } | |
d45ec1de MW |
251 | case TRAFFIC_SELECTOR_INITIATOR: |
252 | { | |
87a217f9 | 253 | tsi_request = (ts_payload_t*)payload; |
d45ec1de MW |
254 | break; |
255 | } | |
256 | case TRAFFIC_SELECTOR_RESPONDER: | |
257 | { | |
ccf783d2 | 258 | tsr_request = (ts_payload_t*)payload; |
d45ec1de MW |
259 | break; |
260 | } | |
f6ba78c3 JH |
261 | case NOTIFY: |
262 | { | |
6d0310e8 | 263 | notify_payload_t *notify_payload = (notify_payload_t *) payload; |
283dbcc5 MW |
264 | status = this->process_notify_payload(this, notify_payload); |
265 | if (status != SUCCESS) | |
6d0310e8 | 266 | { |
6d0310e8 | 267 | payloads->destroy(payloads); |
283dbcc5 | 268 | return status; |
6d0310e8 | 269 | } |
283dbcc5 MW |
270 | } |
271 | case CERTIFICATE: | |
272 | { | |
273 | /* TODO handle cert payloads */ | |
274 | } | |
275 | case CERTIFICATE_REQUEST: | |
276 | { | |
277 | /* TODO handle certrequest payloads */ | |
f6ba78c3 | 278 | } |
9b8f174d MW |
279 | default: |
280 | { | |
5346c894 | 281 | this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", |
283dbcc5 | 282 | mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); |
6d0310e8 | 283 | break; |
9b8f174d MW |
284 | } |
285 | } | |
286 | } | |
287 | /* iterator can be destroyed */ | |
288 | payloads->destroy(payloads); | |
283dbcc5 MW |
289 | |
290 | /* check if we have all payloads */ | |
291 | if (!(idi_request && sa_request && auth_request && tsi_request && tsr_request)) | |
292 | { | |
293 | this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA"); | |
294 | return DELETE_ME; | |
295 | } | |
6d0310e8 | 296 | |
ccf783d2 MW |
297 | /* build response */ |
298 | this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response); | |
9b8f174d | 299 | |
ccf783d2 | 300 | /* add payloads to it */ |
8d68033e | 301 | status = this->build_idr_payload(this, idi_request, idr_request, response,&idr_response); |
ccf783d2 MW |
302 | if (status != SUCCESS) |
303 | { | |
ccf783d2 MW |
304 | response->destroy(response); |
305 | return status; | |
306 | } | |
fb8aa445 | 307 | status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); |
ccf783d2 MW |
308 | if (status != SUCCESS) |
309 | { | |
ccf783d2 MW |
310 | response->destroy(response); |
311 | return status; | |
312 | } | |
fb8aa445 | 313 | status = this->build_sa_payload(this, sa_request, response); |
ccf783d2 MW |
314 | if (status != SUCCESS) |
315 | { | |
ccf783d2 MW |
316 | response->destroy(response); |
317 | return status; | |
318 | } | |
319 | status = this->build_ts_payload(this, TRUE, tsi_request, response); | |
320 | if (status != SUCCESS) | |
321 | { | |
ccf783d2 MW |
322 | response->destroy(response); |
323 | return status; | |
324 | } | |
325 | status = this->build_ts_payload(this, FALSE, tsr_request, response); | |
326 | if (status != SUCCESS) | |
327 | { | |
ccf783d2 MW |
328 | response->destroy(response); |
329 | return status; | |
5534ee84 JH |
330 | } |
331 | ||
5534ee84 | 332 | status = this->ike_sa->send_response(this->ike_sa, response); |
5534ee84 | 333 | /* message can now be sent (must not be destroyed) */ |
ccf783d2 MW |
334 | if (status != SUCCESS) |
335 | { | |
283dbcc5 | 336 | this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH reply. Deleting IKE_SA"); |
ccf783d2 | 337 | response->destroy(response); |
5534ee84 | 338 | return DELETE_ME; |
ccf783d2 | 339 | } |
ccf783d2 | 340 | |
fb8aa445 MW |
341 | /* install child SA policies */ |
342 | if (!this->child_sa) | |
a527a426 MW |
343 | { |
344 | this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); | |
345 | } | |
346 | else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) | |
347 | { | |
348 | this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); | |
5d187bd2 MW |
349 | this->child_sa->destroy(this->child_sa); |
350 | this->child_sa = NULL; | |
a527a426 MW |
351 | } |
352 | else | |
353 | { | |
5d187bd2 | 354 | status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); |
a527a426 MW |
355 | if (status != SUCCESS) |
356 | { | |
357 | this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); | |
358 | return DELETE_ME; | |
359 | } | |
fb8aa445 | 360 | this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); |
a527a426 MW |
361 | } |
362 | ||
87a217f9 MW |
363 | /* create new state */ |
364 | this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); | |
365 | this->destroy_after_state_change(this); | |
366 | ||
16b9a73c MW |
367 | connection = this->ike_sa->get_connection(this->ike_sa); |
368 | my_host = connection->get_my_host(connection); | |
369 | other_host = connection->get_other_host(connection); | |
87a217f9 MW |
370 | this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", |
371 | my_host->get_address(my_host), other_host->get_address(other_host)); | |
ccf783d2 | 372 | |
d45ec1de MW |
373 | return SUCCESS; |
374 | } | |
375 | ||
ccf783d2 | 376 | /** |
6d0310e8 | 377 | * Implementation of private_ike_sa_init_responded_t.build_idr_payload. |
ccf783d2 | 378 | */ |
8d68033e | 379 | static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response,id_payload_t **response_idr) |
d45ec1de | 380 | { |
ccf783d2 | 381 | identification_t *other_id, *my_id = NULL; |
16b9a73c | 382 | connection_t *connection; |
ccf783d2 MW |
383 | id_payload_t *idr_response; |
384 | ||
eea35346 MW |
385 | connection = this->ike_sa->get_connection(this->ike_sa); |
386 | ||
387 | /* update adresses, as connection may contain wildcards, or wrong IDs */ | |
ccf783d2 MW |
388 | other_id = request_idi->get_identification(request_idi); |
389 | if (request_idr) | |
390 | { | |
391 | my_id = request_idr->get_identification(request_idr); | |
eea35346 MW |
392 | connection->update_my_id(connection, my_id); |
393 | } | |
394 | else | |
395 | { | |
396 | my_id = connection->get_my_id(connection); | |
ccf783d2 | 397 | } |
eea35346 | 398 | connection->update_other_id(connection, other_id); |
ccf783d2 MW |
399 | |
400 | /* build new sa config */ | |
16b9a73c MW |
401 | this->policy = charon->policies->get_policy(charon->policies, my_id, other_id); |
402 | if (this->policy == NULL) | |
283dbcc5 | 403 | { |
eea35346 MW |
404 | this->logger->log(this->logger, AUDIT, "We don't have a policy for IDs %s - %s. Deleting IKE_SA", |
405 | my_id->get_string(my_id), other_id->get_string(other_id)); | |
406 | return DELETE_ME; | |
283dbcc5 | 407 | } |
283dbcc5 | 408 | |
eea35346 | 409 | /* get my id from policy, which must contain a fully qualified valid id */ |
87a217f9 MW |
410 | my_id = this->policy->get_my_id(this->policy); |
411 | ||
412 | /* update others traffic selectors with actually used address */ | |
413 | this->policy->update_other_ts(this->policy, response->get_destination(response)); | |
7ef7c383 | 414 | |
16b9a73c MW |
415 | /* set policy in ike_sa for other states */ |
416 | this->ike_sa->set_policy(this->ike_sa, this->policy); | |
ccf783d2 MW |
417 | |
418 | /* build response */ | |
7ef7c383 | 419 | idr_response = id_payload_create_from_identification(FALSE, my_id); |
ccf783d2 | 420 | response->add_payload(response, (payload_t*)idr_response); |
8d68033e | 421 | *response_idr = idr_response; |
caa6b542 | 422 | |
c7dd2a7b MW |
423 | return SUCCESS; |
424 | } | |
425 | ||
ccf783d2 | 426 | /** |
6d0310e8 | 427 | * Implementation of private_ike_sa_init_responded_t.build_sa_payload. |
ccf783d2 MW |
428 | */ |
429 | static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response) | |
430 | { | |
ce461bbd | 431 | proposal_t *proposal, *proposal_tmp; |
93df94ac | 432 | linked_list_t *proposal_list; |
ccf783d2 | 433 | sa_payload_t *sa_response; |
fb8aa445 MW |
434 | chunk_t seed; |
435 | prf_plus_t *prf_plus; | |
436 | status_t status; | |
16b9a73c | 437 | connection_t *connection; |
ccf783d2 | 438 | |
c06dbbab | 439 | /* get proposals from request */ |
ce461bbd | 440 | proposal_list = request->get_proposals(request); |
c06dbbab | 441 | if (proposal_list->get_count(proposal_list) == 0) |
ccf783d2 | 442 | { |
c06dbbab MW |
443 | /* if the other side did not offer any proposals, we do not create child sa's */ |
444 | this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any proposals. No CHILD_SA created"); | |
f4d8999c JH |
445 | sa_response = sa_payload_create(); |
446 | response->add_payload(response, (payload_t*)sa_response); | |
dfa6e086 | 447 | proposal_list->destroy(proposal_list); |
c06dbbab | 448 | return SUCCESS; |
ccf783d2 | 449 | } |
93df94ac | 450 | |
c06dbbab | 451 | /* now select a proposal */ |
93df94ac | 452 | this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); |
16b9a73c | 453 | proposal = this->policy->select_proposal(this->policy, proposal_list); |
dfa6e086 MW |
454 | /* list is not needed anymore */ |
455 | while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) | |
456 | { | |
457 | proposal_tmp->destroy(proposal_tmp); | |
458 | } | |
459 | proposal_list->destroy(proposal_list); | |
460 | /* do we have a proposal */ | |
c06dbbab MW |
461 | if (proposal == NULL) |
462 | { | |
c06dbbab MW |
463 | this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA"); |
464 | this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); | |
465 | return DELETE_ME; | |
466 | } | |
467 | ||
fb8aa445 | 468 | /* set up child sa */ |
5113680f | 469 | seed = chunk_alloc(this->received_nonce.len + this->sent_nonce.len); |
fb8aa445 MW |
470 | memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); |
471 | memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len); | |
472 | prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); | |
5113680f | 473 | chunk_free(&seed); |
16b9a73c MW |
474 | |
475 | connection = this->ike_sa->get_connection(this->ike_sa); | |
476 | this->child_sa = child_sa_create(connection->get_my_host(connection), | |
477 | connection->get_other_host(connection)); | |
fb8aa445 MW |
478 | |
479 | status = this->child_sa->add(this->child_sa, proposal, prf_plus); | |
480 | prf_plus->destroy(prf_plus); | |
481 | if (status != SUCCESS) | |
482 | { | |
483 | this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); | |
484 | return DELETE_ME; | |
485 | } | |
30b5b412 MW |
486 | |
487 | /* create payload with selected propsal */ | |
488 | sa_response = sa_payload_create_from_proposal(proposal); | |
489 | response->add_payload(response, (payload_t*)sa_response); | |
fb8aa445 | 490 | proposal->destroy(proposal); |
c06dbbab | 491 | return SUCCESS; |
ccf783d2 MW |
492 | } |
493 | ||
494 | /** | |
6d0310e8 | 495 | * Implementation of private_ike_sa_init_responded_t.build_auth_payload. |
ccf783d2 | 496 | */ |
8d68033e | 497 | static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *auth_request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response) |
ccf783d2 | 498 | { |
0fdc3c7f | 499 | authenticator_t *authenticator; |
8d68033e JH |
500 | auth_payload_t *auth_reply; |
501 | status_t status; | |
ccf783d2 | 502 | |
0fdc3c7f | 503 | authenticator = authenticator_create(this->ike_sa); |
f6ba78c3 JH |
504 | status = authenticator->verify_auth_data(authenticator,auth_request, this->ike_sa_init_request_data,this->sent_nonce,other_id_payload,TRUE); |
505 | ||
8d68033e JH |
506 | if (status != SUCCESS) |
507 | { | |
283dbcc5 | 508 | this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA"); |
7fa8decb JH |
509 | this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER); |
510 | authenticator->destroy(authenticator); | |
6d0310e8 | 511 | return DELETE_ME; |
8d68033e | 512 | } |
f6ba78c3 | 513 | |
aebb38a0 | 514 | status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE); |
0fdc3c7f | 515 | authenticator->destroy(authenticator); |
8d68033e JH |
516 | if (status != SUCCESS) |
517 | { | |
283dbcc5 | 518 | this->logger->log(this->logger, AUDIT, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA"); |
6d0310e8 | 519 | return DELETE_ME; |
8d68033e JH |
520 | |
521 | } | |
a527a426 | 522 | |
8d68033e | 523 | response->add_payload(response, (payload_t *)auth_reply); |
ccf783d2 MW |
524 | return SUCCESS; |
525 | } | |
526 | ||
527 | /** | |
6d0310e8 | 528 | * Implementation of private_ike_sa_init_responded_t.build_ts_payload. |
ccf783d2 MW |
529 | */ |
530 | static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response) | |
531 | { | |
a527a426 MW |
532 | linked_list_t *ts_received, *ts_selected; |
533 | traffic_selector_t *ts; | |
ccf783d2 MW |
534 | status_t status = SUCCESS; |
535 | ts_payload_t *ts_response; | |
ccb37df2 | 536 | |
ccf783d2 | 537 | /* build a reply payload with selected traffic selectors */ |
a527a426 | 538 | ts_received = request->get_traffic_selectors(request); |
ccf783d2 MW |
539 | /* select ts depending on payload type */ |
540 | if (ts_initiator) | |
541 | { | |
16b9a73c | 542 | ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received); |
a527a426 | 543 | this->other_ts = ts_selected; |
ccf783d2 MW |
544 | } |
545 | else | |
546 | { | |
16b9a73c | 547 | ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received); |
a527a426 | 548 | this->my_ts = ts_selected; |
ccf783d2 MW |
549 | } |
550 | ||
a527a426 MW |
551 | ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected); |
552 | response->add_payload(response, (payload_t*)ts_response); | |
553 | ||
ccf783d2 | 554 | /* cleanup */ |
a527a426 | 555 | while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) |
ccf783d2 | 556 | { |
ccf783d2 MW |
557 | ts->destroy(ts); |
558 | } | |
a527a426 MW |
559 | ts_received->destroy(ts_received); |
560 | ||
ccf783d2 MW |
561 | return status; |
562 | } | |
563 | ||
283dbcc5 | 564 | static status_t process_notify_payload(private_ike_sa_init_responded_t *this, notify_payload_t *notify_payload) |
f6ba78c3 | 565 | { |
283dbcc5 | 566 | notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); |
f6ba78c3 | 567 | |
dec59822 MW |
568 | this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", |
569 | mapping_find(notify_message_type_m, notify_message_type)); | |
283dbcc5 | 570 | |
283dbcc5 | 571 | switch (notify_message_type) |
f6ba78c3 | 572 | { |
283dbcc5 MW |
573 | case SET_WINDOW_SIZE: |
574 | /* | |
575 | * TODO Increase window size. | |
576 | */ | |
577 | case INITIAL_CONTACT: | |
578 | /* | |
579 | * TODO Delete existing IKE_SA's with other Identity. | |
580 | */ | |
581 | default: | |
582 | { | |
583 | this->logger->log(this->logger, AUDIT, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type); | |
584 | } | |
f6ba78c3 | 585 | } |
283dbcc5 MW |
586 | |
587 | return SUCCESS; | |
f6ba78c3 JH |
588 | } |
589 | ||
c7dd2a7b | 590 | /** |
6d0310e8 | 591 | * Implementation of state_t.get_state. |
c7dd2a7b MW |
592 | */ |
593 | static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this) | |
594 | { | |
595 | return IKE_SA_INIT_RESPONDED; | |
596 | } | |
597 | ||
598 | /** | |
fb8aa445 | 599 | * Implementation of state_t.destroy. |
c7dd2a7b | 600 | */ |
df3c59d0 | 601 | static void destroy(private_ike_sa_init_responded_t *this) |
c7dd2a7b | 602 | { |
5113680f MW |
603 | chunk_free(&(this->received_nonce)); |
604 | chunk_free(&(this->sent_nonce)); | |
605 | chunk_free(&(this->ike_sa_init_response_data)); | |
606 | chunk_free(&(this->ike_sa_init_request_data)); | |
a527a426 MW |
607 | if (this->my_ts) |
608 | { | |
609 | traffic_selector_t *ts; | |
610 | while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) | |
611 | { | |
612 | ts->destroy(ts); | |
613 | } | |
614 | this->my_ts->destroy(this->my_ts); | |
615 | } | |
616 | if (this->other_ts) | |
617 | { | |
618 | traffic_selector_t *ts; | |
619 | while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) | |
620 | { | |
621 | ts->destroy(ts); | |
622 | } | |
623 | this->other_ts->destroy(this->other_ts); | |
624 | } | |
fb8aa445 | 625 | if (this->child_sa) |
a527a426 | 626 | { |
fb8aa445 MW |
627 | this->child_sa->destroy(this->child_sa); |
628 | } | |
629 | ||
5113680f | 630 | free(this); |
fb8aa445 MW |
631 | } |
632 | /** | |
633 | * Implementation of private_ike_sa_init_responded.destroy_after_state_change. | |
634 | */ | |
635 | static void destroy_after_state_change(private_ike_sa_init_responded_t *this) | |
636 | { | |
5113680f MW |
637 | chunk_free(&(this->received_nonce)); |
638 | chunk_free(&(this->sent_nonce)); | |
639 | chunk_free(&(this->ike_sa_init_response_data)); | |
640 | chunk_free(&(this->ike_sa_init_request_data)); | |
fb8aa445 MW |
641 | if (this->my_ts) |
642 | { | |
643 | traffic_selector_t *ts; | |
644 | while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) | |
645 | { | |
646 | ts->destroy(ts); | |
647 | } | |
648 | this->my_ts->destroy(this->my_ts); | |
649 | } | |
650 | if (this->other_ts) | |
651 | { | |
652 | traffic_selector_t *ts; | |
653 | while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) | |
654 | { | |
655 | ts->destroy(ts); | |
656 | } | |
657 | this->other_ts->destroy(this->other_ts); | |
a527a426 | 658 | } |
8d68033e | 659 | |
5113680f | 660 | free(this); |
c7dd2a7b MW |
661 | } |
662 | ||
663 | /* | |
664 | * Described in header. | |
665 | */ | |
8d68033e | 666 | ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce,chunk_t ike_sa_init_request_data, chunk_t ike_sa_init_response_data) |
c7dd2a7b | 667 | { |
5113680f | 668 | private_ike_sa_init_responded_t *this = malloc_thing(private_ike_sa_init_responded_t); |
c7dd2a7b MW |
669 | |
670 | /* interface functions */ | |
aad398a7 | 671 | this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; |
c7dd2a7b | 672 | this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; |
d048df5c | 673 | this->public.state_interface.destroy = (void (*) (state_t *)) destroy; |
c7dd2a7b | 674 | |
ccf783d2 MW |
675 | /* private functions */ |
676 | this->build_idr_payload = build_idr_payload; | |
677 | this->build_sa_payload = build_sa_payload; | |
678 | this->build_auth_payload = build_auth_payload; | |
679 | this->build_ts_payload = build_ts_payload; | |
283dbcc5 | 680 | this->process_notify_payload = process_notify_payload; |
fb8aa445 | 681 | this->destroy_after_state_change = destroy_after_state_change; |
ccf783d2 | 682 | |
c7dd2a7b MW |
683 | /* private data */ |
684 | this->ike_sa = ike_sa; | |
0fdc3c7f | 685 | this->received_nonce = received_nonce; |
8d68033e JH |
686 | this->sent_nonce = sent_nonce; |
687 | this->ike_sa_init_response_data = ike_sa_init_response_data; | |
688 | this->ike_sa_init_request_data = ike_sa_init_request_data; | |
a527a426 MW |
689 | this->my_ts = NULL; |
690 | this->other_ts = NULL; | |
fb8aa445 | 691 | this->child_sa = NULL; |
5113680f | 692 | this->logger = logger_manager->get_logger(logger_manager, IKE_SA); |
c7dd2a7b MW |
693 | |
694 | return &(this->public); | |
695 | } |