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!
64 status_t (*process_idr_payload
) (private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
);
65 status_t (*process_sa_payload
) (private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
);
66 status_t (*process_auth_payload
) (private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
);
67 status_t (*process_ts_payload
) (private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
);
73 * Implements state_t.process_message
75 static status_t
process_message(private_ike_auth_requested_t
*this, message_t
*request
)
81 exchange_type_t exchange_type
;
82 id_payload_t
*idr_payload
= NULL
;
83 auth_payload_t
*auth_payload
;
84 sa_payload_t
*sa_payload
;
85 ts_payload_t
*tsi_payload
, *tsr_payload
;
87 exchange_type
= request
->get_exchange_type(request
);
88 if (exchange_type
!= IKE_AUTH
)
90 this->logger
->log(this->logger
, ERROR
| MORE
, "Message of type %s not supported in state ike_auth_requested",
91 mapping_find(exchange_type_m
,exchange_type
));
95 if (request
->get_request(request
))
97 this->logger
->log(this->logger
, ERROR
| MORE
, "Only responses of type IKE_AUTH supported in state ike_auth_requested");
101 /* get signer for verification and crypter for decryption */
102 signer
= this->ike_sa
->get_signer_responder(this->ike_sa
);
103 crypter
= this->ike_sa
->get_crypter_responder(this->ike_sa
);
105 /* parse incoming message */
106 status
= request
->parse_body(request
, crypter
, signer
);
107 if (status
!= SUCCESS
)
109 this->logger
->log(this->logger
, ERROR
| MORE
, "Could not parse body of request message");
113 this->sa_config
= this->ike_sa
->get_sa_config(this->ike_sa
);
115 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
116 payloads
= request
->get_payload_iterator(request
);
117 while (payloads
->has_next(payloads
))
120 payloads
->current(payloads
, (void**)&payload
);
122 switch (payload
->get_type(payload
))
126 auth_payload
= (auth_payload_t
*)payload
;
131 idr_payload
= (id_payload_t
*)payload
;
134 case SECURITY_ASSOCIATION
:
136 sa_payload
= (sa_payload_t
*)payload
;
141 /* TODO handle cert payloads */
144 case TRAFFIC_SELECTOR_INITIATOR
:
146 tsi_payload
= (ts_payload_t
*)payload
;
149 case TRAFFIC_SELECTOR_RESPONDER
:
151 tsr_payload
= (ts_payload_t
*)payload
;
156 /* can't happen, since message is verified, notify's? */
161 /* iterator can be destroyed */
162 payloads
->destroy(payloads
);
164 /* add payloads to it */
165 status
= this->process_idr_payload(this, idr_payload
);
166 if (status
!= SUCCESS
)
168 this->logger
->log(this->logger
, ERROR
, "Processing idr payload failed");
171 status
= this->process_sa_payload(this, sa_payload
);
172 if (status
!= SUCCESS
)
174 this->logger
->log(this->logger
, ERROR
, "Processing sa payload failed");
177 status
= this->process_auth_payload(this, auth_payload
);
178 if (status
!= SUCCESS
)
180 this->logger
->log(this->logger
, ERROR
, "Processing auth payload failed");
183 status
= this->process_ts_payload(this, TRUE
, tsi_payload
);
184 if (status
!= SUCCESS
)
186 this->logger
->log(this->logger
, ERROR
, "Processing tsi payload failed");
189 status
= this->process_ts_payload(this, FALSE
, tsr_payload
);
190 if (status
!= SUCCESS
)
192 this->logger
->log(this->logger
, ERROR
, "Processing tsr payload failed");
196 this->ike_sa
->set_last_replied_message_id(this->ike_sa
,request
->get_message_id(request
));
197 this->logger
->log(this->logger
, CONTROL
| MORE
, "IKE_AUTH response successfully handled. IKE_SA established.");
199 /* create new state */
200 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
202 this->public.state_interface
.destroy(&(this->public.state_interface
));
207 * Implements private_ike_auth_requested_t.build_idr_payload
209 static status_t
process_idr_payload(private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
)
211 identification_t
*other_id
, *configured_other_id
;
213 /* idr is optional */
216 other_id
= idr_payload
->get_identification(idr_payload
);
218 configured_other_id
= this->sa_config
->get_other_id(this->sa_config
);
219 if (configured_other_id
)
221 if (!other_id
->equals(other_id
, configured_other_id
))
223 this->logger
->log(this->logger
, ERROR
, "IKE_AUTH reply didn't contain requested id");
228 other_id
->destroy(other_id
);
229 /* TODO do we have to store other_id somewhere ? */
235 * Implements private_ike_auth_requested_t.build_sa_payload
237 static status_t
process_sa_payload(private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
)
239 child_proposal_t
*proposals
, *proposal_chosen
;
240 size_t proposal_count
;
243 /* dummy spis, until we have a child sa to request them */
244 u_int8_t ah_spi
[4] = {0x01, 0x02, 0x03, 0x04};
245 u_int8_t esp_spi
[4] = {0x05, 0x06, 0x07, 0x08};
247 /* check selected proposal */
248 status
= sa_payload
->get_child_proposals(sa_payload
, &proposals
, &proposal_count
);
249 if (status
!= SUCCESS
)
251 this->logger
->log(this->logger
, ERROR
, "responders sa payload contained no proposals");
254 if (proposal_count
> 1)
256 allocator_free(proposals
);
257 this->logger
->log(this->logger
, ERROR
, "responders sa payload contained more than one proposal");
261 proposal_chosen
= this->sa_config
->select_proposal(this->sa_config
, ah_spi
, esp_spi
, proposals
, proposal_count
);
262 if (proposal_chosen
== NULL
)
264 this->logger
->log(this->logger
, ERROR
, "responder selected an not offered proposal");
265 allocator_free(proposals
);
270 allocator_free(proposal_chosen
);
273 allocator_free(proposals
);
279 * Implements private_ike_auth_requested_t.build_auth_payload
281 static status_t
process_auth_payload(private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
)
283 /* TODO VERIFY auth here */
288 * Implements private_ike_auth_requested_t.build_ts_payload
290 static status_t
process_ts_payload(private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
)
292 traffic_selector_t
**ts_received
, **ts_selected
;
293 size_t ts_received_count
, ts_selected_count
;
294 status_t status
= SUCCESS
;
296 /* get ts form payload */
297 ts_received_count
= ts_payload
->get_traffic_selectors(ts_payload
, &ts_received
);
298 /* select ts depending on payload type */
301 ts_selected_count
= this->sa_config
->select_traffic_selectors_initiator(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
305 ts_selected_count
= this->sa_config
->select_traffic_selectors_responder(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
307 /* check if the responder selected valid proposals */
308 if (ts_selected_count
!= ts_received_count
)
310 this->logger
->log(this->logger
, ERROR
, "responder selected invalid traffic selectors");
315 while(ts_received_count
--)
317 traffic_selector_t
*ts
= *ts_received
+ ts_received_count
;
320 allocator_free(ts_received
);
321 while(ts_selected_count
--)
323 traffic_selector_t
*ts
= *ts_selected
+ ts_selected_count
;
326 allocator_free(ts_selected
);
330 * Implements state_t.get_state
332 static ike_sa_state_t
get_state(private_ike_auth_requested_t
*this)
334 return IKE_AUTH_REQUESTED
;
338 * Implements state_t.get_state
340 static void destroy(private_ike_auth_requested_t
*this)
342 allocator_free(this);
346 * Described in header.
348 ike_auth_requested_t
*ike_auth_requested_create(protected_ike_sa_t
*ike_sa
)
350 private_ike_auth_requested_t
*this = allocator_alloc_thing(private_ike_auth_requested_t
);
352 /* interface functions */
353 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
354 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
355 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
357 /* private functions */
359 this->process_idr_payload
= process_idr_payload
;
360 this->process_sa_payload
= process_sa_payload
;
361 this->process_auth_payload
= process_auth_payload
;
362 this->process_ts_payload
= process_ts_payload
;
365 this->ike_sa
= ike_sa
;
366 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
368 return &(this->public);