9fe7b1b9ffc4d9ea4f0575c09e728d936103e75d
[strongswan.git] / Source / charon / sa / states / ike_auth_requested.c
1 /**
2 * @file ike_auth_requested.c
3 *
4 * @brief Implementation of ike_auth_requested_t.
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 */
22
23 #include "ike_auth_requested.h"
24
25 #include <daemon.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>
34
35 typedef struct private_ike_auth_requested_t private_ike_auth_requested_t;
36
37 /**
38 * Private data of a ike_auth_requested_t object.
39 *
40 */
41 struct private_ike_auth_requested_t {
42 /**
43 * methods of the state_t interface
44 */
45 ike_auth_requested_t public;
46
47 /**
48 * Assigned IKE_SA
49 */
50 protected_ike_sa_t *ike_sa;
51
52 /**
53 * SA config, just a copy of the one stored in the ike_sa
54 */
55 sa_config_t *sa_config;
56
57 /**
58 * Logger used to log data
59 *
60 * Is logger of ike_sa!
61 */
62 logger_t *logger;
63
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);
68
69 };
70
71
72 /**
73 * Implements state_t.process_message
74 */
75 static status_t process_message(private_ike_auth_requested_t *this, message_t *request)
76 {
77 status_t status;
78 signer_t *signer;
79 crypter_t *crypter;
80 iterator_t *payloads;
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;
86
87 exchange_type = request->get_exchange_type(request);
88 if (exchange_type != IKE_AUTH)
89 {
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));
92 return FAILED;
93 }
94
95 if (request->get_request(request))
96 {
97 this->logger->log(this->logger, ERROR | MORE, "Only responses of type IKE_AUTH supported in state ike_auth_requested");
98 return FAILED;
99 }
100
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);
104
105 /* parse incoming message */
106 status = request->parse_body(request, crypter, signer);
107 if (status != SUCCESS)
108 {
109 this->logger->log(this->logger, ERROR | MORE, "Could not parse body of request message");
110 return status;
111 }
112
113 this->sa_config = this->ike_sa->get_sa_config(this->ike_sa);
114
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))
118 {
119 payload_t *payload;
120 payloads->current(payloads, (void**)&payload);
121
122 switch (payload->get_type(payload))
123 {
124 case AUTHENTICATION:
125 {
126 auth_payload = (auth_payload_t*)payload;
127 break;
128 }
129 case ID_RESPONDER:
130 {
131 idr_payload = (id_payload_t*)payload;
132 break;
133 }
134 case SECURITY_ASSOCIATION:
135 {
136 sa_payload = (sa_payload_t*)payload;
137 break;
138 }
139 case CERTIFICATE:
140 {
141 /* TODO handle cert payloads */
142 break;
143 }
144 case TRAFFIC_SELECTOR_INITIATOR:
145 {
146 tsi_payload = (ts_payload_t*)payload;
147 break;
148 }
149 case TRAFFIC_SELECTOR_RESPONDER:
150 {
151 tsr_payload = (ts_payload_t*)payload;
152 break;
153 }
154 default:
155 {
156 /* can't happen, since message is verified, notify's? */
157 break;
158 }
159 }
160 }
161 /* iterator can be destroyed */
162 payloads->destroy(payloads);
163
164 /* add payloads to it */
165 status = this->process_idr_payload(this, idr_payload);
166 if (status != SUCCESS)
167 {
168 this->logger->log(this->logger, ERROR, "Processing idr payload failed");
169 return status;
170 }
171 status = this->process_sa_payload(this, sa_payload);
172 if (status != SUCCESS)
173 {
174 this->logger->log(this->logger, ERROR, "Processing sa payload failed");
175 return status;
176 }
177 status = this->process_auth_payload(this, auth_payload);
178 if (status != SUCCESS)
179 {
180 this->logger->log(this->logger, ERROR, "Processing auth payload failed");
181 return status;
182 }
183 status = this->process_ts_payload(this, TRUE, tsi_payload);
184 if (status != SUCCESS)
185 {
186 this->logger->log(this->logger, ERROR, "Processing tsi payload failed");
187 return status;
188 }
189 status = this->process_ts_payload(this, FALSE, tsr_payload);
190 if (status != SUCCESS)
191 {
192 this->logger->log(this->logger, ERROR, "Processing tsr payload failed");
193 return status;
194 }
195
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.");
198
199 /* create new state */
200 this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
201
202 this->public.state_interface.destroy(&(this->public.state_interface));
203 return SUCCESS;
204 }
205
206 /**
207 * Implements private_ike_auth_requested_t.build_idr_payload
208 */
209 static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload)
210 {
211 identification_t *other_id, *configured_other_id;
212
213 /* idr is optional */
214 if (idr_payload)
215 {
216 other_id = idr_payload->get_identification(idr_payload);
217
218 configured_other_id = this->sa_config->get_other_id(this->sa_config);
219 if (configured_other_id)
220 {
221 if (!other_id->equals(other_id, configured_other_id))
222 {
223 this->logger->log(this->logger, ERROR, "IKE_AUTH reply didn't contain requested id");
224 return FAILED;
225 }
226 }
227
228 other_id->destroy(other_id);
229 /* TODO do we have to store other_id somewhere ? */
230 }
231 return SUCCESS;
232 }
233
234 /**
235 * Implements private_ike_auth_requested_t.build_sa_payload
236 */
237 static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload)
238 {
239 child_proposal_t *proposals, *proposal_chosen;
240 size_t proposal_count;
241 status_t status;
242
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};
246
247 /* check selected proposal */
248 status = sa_payload->get_child_proposals(sa_payload, &proposals, &proposal_count);
249 if (status != SUCCESS)
250 {
251 this->logger->log(this->logger, ERROR, "responders sa payload contained no proposals");
252 return FAILED;
253 }
254 if (proposal_count > 1)
255 {
256 allocator_free(proposals);
257 this->logger->log(this->logger, ERROR, "responders sa payload contained more than one proposal");
258 return FAILED;
259 }
260
261 proposal_chosen = this->sa_config->select_proposal(this->sa_config, ah_spi, esp_spi, proposals, proposal_count);
262 if (proposal_chosen == NULL)
263 {
264 this->logger->log(this->logger, ERROR, "responder selected an not offered proposal");
265 allocator_free(proposals);
266 return FAILED;
267 }
268 else
269 {
270 allocator_free(proposal_chosen);
271 }
272
273 allocator_free(proposals);
274
275 return SUCCESS;
276 }
277
278 /**
279 * Implements private_ike_auth_requested_t.build_auth_payload
280 */
281 static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_payload_t *auth_payload)
282 {
283 /* TODO VERIFY auth here */
284 return SUCCESS;
285 }
286
287 /**
288 * Implements private_ike_auth_requested_t.build_ts_payload
289 */
290 static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload)
291 {
292 traffic_selector_t **ts_received, **ts_selected;
293 size_t ts_received_count, ts_selected_count;
294 status_t status = SUCCESS;
295
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 */
299 if (ts_initiator)
300 {
301 ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected);
302 }
303 else
304 {
305 ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected);
306 }
307 /* check if the responder selected valid proposals */
308 if (ts_selected_count != ts_received_count)
309 {
310 this->logger->log(this->logger, ERROR, "responder selected invalid traffic selectors");
311 status = FAILED;
312 }
313
314 /* cleanup */
315 while(ts_received_count--)
316 {
317 traffic_selector_t *ts = *ts_received + ts_received_count;
318 ts->destroy(ts);
319 }
320 allocator_free(ts_received);
321 while(ts_selected_count--)
322 {
323 traffic_selector_t *ts = *ts_selected + ts_selected_count;
324 ts->destroy(ts);
325 }
326 allocator_free(ts_selected);
327 return status;
328 }
329 /**
330 * Implements state_t.get_state
331 */
332 static ike_sa_state_t get_state(private_ike_auth_requested_t *this)
333 {
334 return IKE_AUTH_REQUESTED;
335 }
336
337 /**
338 * Implements state_t.get_state
339 */
340 static void destroy(private_ike_auth_requested_t *this)
341 {
342 allocator_free(this);
343 }
344
345 /*
346 * Described in header.
347 */
348 ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa)
349 {
350 private_ike_auth_requested_t *this = allocator_alloc_thing(private_ike_auth_requested_t);
351
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;
356
357 /* private functions */
358
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;
363
364 /* private data */
365 this->ike_sa = ike_sa;
366 this->logger = this->ike_sa->get_logger(this->ike_sa);
367
368 return &(this->public);
369 }