2 * @file ike_auth_requested.c
4 * @brief Implementation of ike_auth_requested_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "ike_auth_requested.h"
26 #include <utils/allocator.h>
27 #include <encoding/payloads/ts_payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/auth_payload.h>
31 #include <transforms/signers/signer.h>
32 #include <transforms/crypters/crypter.h>
33 #include <sa/states/ike_sa_established.h>
35 typedef struct private_ike_auth_requested_t private_ike_auth_requested_t
;
38 * Private data of a ike_auth_requested_t object.
41 struct private_ike_auth_requested_t
{
43 * methods of the state_t interface
45 ike_auth_requested_t
public;
50 protected_ike_sa_t
*ike_sa
;
53 * SA config, just a copy of the one stored in the ike_sa
55 sa_config_t
*sa_config
;
58 * Logger used to log data
60 * Is logger of ike_sa!
65 * process the IDr payload (check if other id is valid)
67 status_t (*process_idr_payload
) (private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
);
70 * process the SA payload (check if selected proposals are valid, setup child sa)
72 status_t (*process_sa_payload
) (private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
);
75 * process the AUTH payload (check authenticity of message)
77 status_t (*process_auth_payload
) (private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
);
80 * process the TS payload (check if selected traffic selectors are valid)
82 status_t (*process_ts_payload
) (private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
);
88 * Implements state_t.process_message
90 static status_t
process_message(private_ike_auth_requested_t
*this, message_t
*request
)
96 exchange_type_t exchange_type
;
97 id_payload_t
*idr_payload
= NULL
;
98 auth_payload_t
*auth_payload
;
99 sa_payload_t
*sa_payload
;
100 ts_payload_t
*tsi_payload
, *tsr_payload
;
102 exchange_type
= request
->get_exchange_type(request
);
103 if (exchange_type
!= IKE_AUTH
)
105 this->logger
->log(this->logger
, ERROR
| MORE
, "Message of type %s not supported in state ike_auth_requested",
106 mapping_find(exchange_type_m
,exchange_type
));
110 if (request
->get_request(request
))
112 this->logger
->log(this->logger
, ERROR
| MORE
, "Only responses of type IKE_AUTH supported in state ike_auth_requested");
116 /* get signer for verification and crypter for decryption */
117 signer
= this->ike_sa
->get_signer_responder(this->ike_sa
);
118 crypter
= this->ike_sa
->get_crypter_responder(this->ike_sa
);
120 /* parse incoming message */
121 status
= request
->parse_body(request
, crypter
, signer
);
122 if (status
!= SUCCESS
)
124 this->logger
->log(this->logger
, ERROR
| MORE
, "Could not parse body of request message");
128 this->sa_config
= this->ike_sa
->get_sa_config(this->ike_sa
);
130 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
131 payloads
= request
->get_payload_iterator(request
);
132 while (payloads
->has_next(payloads
))
135 payloads
->current(payloads
, (void**)&payload
);
137 switch (payload
->get_type(payload
))
141 auth_payload
= (auth_payload_t
*)payload
;
146 idr_payload
= (id_payload_t
*)payload
;
149 case SECURITY_ASSOCIATION
:
151 sa_payload
= (sa_payload_t
*)payload
;
156 /* TODO handle cert payloads */
159 case TRAFFIC_SELECTOR_INITIATOR
:
161 tsi_payload
= (ts_payload_t
*)payload
;
164 case TRAFFIC_SELECTOR_RESPONDER
:
166 tsr_payload
= (ts_payload_t
*)payload
;
171 /* can't happen, since message is verified, notify's? */
176 /* iterator can be destroyed */
177 payloads
->destroy(payloads
);
179 /* process all payloads */
180 status
= this->process_idr_payload(this, idr_payload
);
181 if (status
!= SUCCESS
)
183 this->logger
->log(this->logger
, ERROR
, "Processing idr payload failed");
186 status
= this->process_sa_payload(this, sa_payload
);
187 if (status
!= SUCCESS
)
189 this->logger
->log(this->logger
, ERROR
, "Processing sa payload failed");
192 status
= this->process_auth_payload(this, auth_payload
);
193 if (status
!= SUCCESS
)
195 this->logger
->log(this->logger
, ERROR
, "Processing auth payload failed");
198 status
= this->process_ts_payload(this, TRUE
, tsi_payload
);
199 if (status
!= SUCCESS
)
201 this->logger
->log(this->logger
, ERROR
, "Processing tsi payload failed");
204 status
= this->process_ts_payload(this, FALSE
, tsr_payload
);
205 if (status
!= SUCCESS
)
207 this->logger
->log(this->logger
, ERROR
, "Processing tsr payload failed");
211 this->ike_sa
->set_last_replied_message_id(this->ike_sa
,request
->get_message_id(request
));
212 this->logger
->log(this->logger
, CONTROL
| MORE
, "IKE_AUTH response successfully handled. IKE_SA established.");
214 /* create new state */
215 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
217 this->public.state_interface
.destroy(&(this->public.state_interface
));
222 * Implements private_ike_auth_requested_t.process_idr_payload
224 static status_t
process_idr_payload(private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
)
226 identification_t
*other_id
, *configured_other_id
;
228 /* idr is optional */
231 other_id
= idr_payload
->get_identification(idr_payload
);
233 configured_other_id
= this->sa_config
->get_other_id(this->sa_config
);
234 if (configured_other_id
)
236 if (!other_id
->equals(other_id
, configured_other_id
))
238 this->logger
->log(this->logger
, ERROR
, "IKE_AUTH reply didn't contain requested id");
243 other_id
->destroy(other_id
);
244 /* TODO do we have to store other_id somewhere ? */
250 * Implements private_ike_auth_requested_t.process_sa_payload
252 static status_t
process_sa_payload(private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
)
254 child_proposal_t
*proposals
, *proposal_chosen
;
255 size_t proposal_count
;
258 /* dummy spis, until we have a child sa to request them */
259 u_int8_t ah_spi
[4] = {0x01, 0x02, 0x03, 0x04};
260 u_int8_t esp_spi
[4] = {0x05, 0x06, 0x07, 0x08};
262 /* check selected proposal */
263 status
= sa_payload
->get_child_proposals(sa_payload
, &proposals
, &proposal_count
);
264 if (status
!= SUCCESS
)
266 this->logger
->log(this->logger
, ERROR
, "responders sa payload contained no proposals");
269 if (proposal_count
> 1)
271 allocator_free(proposals
);
272 this->logger
->log(this->logger
, ERROR
, "responders sa payload contained more than one proposal");
276 proposal_chosen
= this->sa_config
->select_proposal(this->sa_config
, ah_spi
, esp_spi
, proposals
, proposal_count
);
277 if (proposal_chosen
== NULL
)
279 this->logger
->log(this->logger
, ERROR
, "responder selected an not offered proposal");
280 allocator_free(proposals
);
285 allocator_free(proposal_chosen
);
288 allocator_free(proposals
);
294 * Implements private_ike_auth_requested_t.process_auth_payload
296 static status_t
process_auth_payload(private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
)
298 /* TODO VERIFY auth here */
303 * Implements private_ike_auth_requested_t.process_ts_payload
305 static status_t
process_ts_payload(private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
)
307 traffic_selector_t
**ts_received
, **ts_selected
;
308 size_t ts_received_count
, ts_selected_count
;
309 status_t status
= SUCCESS
;
311 /* get ts form payload */
312 ts_received_count
= ts_payload
->get_traffic_selectors(ts_payload
, &ts_received
);
313 /* select ts depending on payload type */
316 ts_selected_count
= this->sa_config
->select_traffic_selectors_initiator(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
320 ts_selected_count
= this->sa_config
->select_traffic_selectors_responder(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
322 /* check if the responder selected valid proposals */
323 if (ts_selected_count
!= ts_received_count
)
325 this->logger
->log(this->logger
, ERROR
, "responder selected invalid traffic selectors");
330 while(ts_received_count
--)
332 traffic_selector_t
*ts
= *ts_received
+ ts_received_count
;
335 allocator_free(ts_received
);
336 while(ts_selected_count
--)
338 traffic_selector_t
*ts
= *ts_selected
+ ts_selected_count
;
341 allocator_free(ts_selected
);
345 * Implements state_t.get_state
347 static ike_sa_state_t
get_state(private_ike_auth_requested_t
*this)
349 return IKE_AUTH_REQUESTED
;
353 * Implements state_t.get_state
355 static void destroy(private_ike_auth_requested_t
*this)
357 allocator_free(this);
361 * Described in header.
363 ike_auth_requested_t
*ike_auth_requested_create(protected_ike_sa_t
*ike_sa
)
365 private_ike_auth_requested_t
*this = allocator_alloc_thing(private_ike_auth_requested_t
);
367 /* interface functions */
368 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
369 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
370 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
372 /* private functions */
374 this->process_idr_payload
= process_idr_payload
;
375 this->process_sa_payload
= process_sa_payload
;
376 this->process_auth_payload
= process_auth_payload
;
377 this->process_ts_payload
= process_ts_payload
;
380 this->ike_sa
= ike_sa
;
381 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
383 return &(this->public);