- comments
[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 /**
65 * process the IDr payload (check if other id is valid)
66 */
67 status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload);
68
69 /**
70 * process the SA payload (check if selected proposals are valid, setup child sa)
71 */
72 status_t (*process_sa_payload) (private_ike_auth_requested_t *this, sa_payload_t *sa_payload);
73
74 /**
75 * process the AUTH payload (check authenticity of message)
76 */
77 status_t (*process_auth_payload) (private_ike_auth_requested_t *this, auth_payload_t *auth_payload);
78
79 /**
80 * process the TS payload (check if selected traffic selectors are valid)
81 */
82 status_t (*process_ts_payload) (private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload);
83
84 };
85
86
87 /**
88 * Implements state_t.process_message
89 */
90 static status_t process_message(private_ike_auth_requested_t *this, message_t *request)
91 {
92 status_t status;
93 signer_t *signer;
94 crypter_t *crypter;
95 iterator_t *payloads;
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;
101
102 exchange_type = request->get_exchange_type(request);
103 if (exchange_type != IKE_AUTH)
104 {
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));
107 return FAILED;
108 }
109
110 if (request->get_request(request))
111 {
112 this->logger->log(this->logger, ERROR | MORE, "Only responses of type IKE_AUTH supported in state ike_auth_requested");
113 return FAILED;
114 }
115
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);
119
120 /* parse incoming message */
121 status = request->parse_body(request, crypter, signer);
122 if (status != SUCCESS)
123 {
124 this->logger->log(this->logger, ERROR | MORE, "Could not parse body of request message");
125 return status;
126 }
127
128 this->sa_config = this->ike_sa->get_sa_config(this->ike_sa);
129
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))
133 {
134 payload_t *payload;
135 payloads->current(payloads, (void**)&payload);
136
137 switch (payload->get_type(payload))
138 {
139 case AUTHENTICATION:
140 {
141 auth_payload = (auth_payload_t*)payload;
142 break;
143 }
144 case ID_RESPONDER:
145 {
146 idr_payload = (id_payload_t*)payload;
147 break;
148 }
149 case SECURITY_ASSOCIATION:
150 {
151 sa_payload = (sa_payload_t*)payload;
152 break;
153 }
154 case CERTIFICATE:
155 {
156 /* TODO handle cert payloads */
157 break;
158 }
159 case TRAFFIC_SELECTOR_INITIATOR:
160 {
161 tsi_payload = (ts_payload_t*)payload;
162 break;
163 }
164 case TRAFFIC_SELECTOR_RESPONDER:
165 {
166 tsr_payload = (ts_payload_t*)payload;
167 break;
168 }
169 default:
170 {
171 /* can't happen, since message is verified, notify's? */
172 break;
173 }
174 }
175 }
176 /* iterator can be destroyed */
177 payloads->destroy(payloads);
178
179 /* process all payloads */
180 status = this->process_idr_payload(this, idr_payload);
181 if (status != SUCCESS)
182 {
183 this->logger->log(this->logger, ERROR, "Processing idr payload failed");
184 return status;
185 }
186 status = this->process_sa_payload(this, sa_payload);
187 if (status != SUCCESS)
188 {
189 this->logger->log(this->logger, ERROR, "Processing sa payload failed");
190 return status;
191 }
192 status = this->process_auth_payload(this, auth_payload);
193 if (status != SUCCESS)
194 {
195 this->logger->log(this->logger, ERROR, "Processing auth payload failed");
196 return status;
197 }
198 status = this->process_ts_payload(this, TRUE, tsi_payload);
199 if (status != SUCCESS)
200 {
201 this->logger->log(this->logger, ERROR, "Processing tsi payload failed");
202 return status;
203 }
204 status = this->process_ts_payload(this, FALSE, tsr_payload);
205 if (status != SUCCESS)
206 {
207 this->logger->log(this->logger, ERROR, "Processing tsr payload failed");
208 return status;
209 }
210
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.");
213
214 /* create new state */
215 this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
216
217 this->public.state_interface.destroy(&(this->public.state_interface));
218 return SUCCESS;
219 }
220
221 /**
222 * Implements private_ike_auth_requested_t.process_idr_payload
223 */
224 static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload)
225 {
226 identification_t *other_id, *configured_other_id;
227
228 /* idr is optional */
229 if (idr_payload)
230 {
231 other_id = idr_payload->get_identification(idr_payload);
232
233 configured_other_id = this->sa_config->get_other_id(this->sa_config);
234 if (configured_other_id)
235 {
236 if (!other_id->equals(other_id, configured_other_id))
237 {
238 this->logger->log(this->logger, ERROR, "IKE_AUTH reply didn't contain requested id");
239 return FAILED;
240 }
241 }
242
243 other_id->destroy(other_id);
244 /* TODO do we have to store other_id somewhere ? */
245 }
246 return SUCCESS;
247 }
248
249 /**
250 * Implements private_ike_auth_requested_t.process_sa_payload
251 */
252 static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload)
253 {
254 child_proposal_t *proposals, *proposal_chosen;
255 size_t proposal_count;
256 status_t status;
257
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};
261
262 /* check selected proposal */
263 status = sa_payload->get_child_proposals(sa_payload, &proposals, &proposal_count);
264 if (status != SUCCESS)
265 {
266 this->logger->log(this->logger, ERROR, "responders sa payload contained no proposals");
267 return FAILED;
268 }
269 if (proposal_count > 1)
270 {
271 allocator_free(proposals);
272 this->logger->log(this->logger, ERROR, "responders sa payload contained more than one proposal");
273 return FAILED;
274 }
275
276 proposal_chosen = this->sa_config->select_proposal(this->sa_config, ah_spi, esp_spi, proposals, proposal_count);
277 if (proposal_chosen == NULL)
278 {
279 this->logger->log(this->logger, ERROR, "responder selected an not offered proposal");
280 allocator_free(proposals);
281 return FAILED;
282 }
283 else
284 {
285 allocator_free(proposal_chosen);
286 }
287
288 allocator_free(proposals);
289
290 return SUCCESS;
291 }
292
293 /**
294 * Implements private_ike_auth_requested_t.process_auth_payload
295 */
296 static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_payload_t *auth_payload)
297 {
298 /* TODO VERIFY auth here */
299 return SUCCESS;
300 }
301
302 /**
303 * Implements private_ike_auth_requested_t.process_ts_payload
304 */
305 static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload)
306 {
307 traffic_selector_t **ts_received, **ts_selected;
308 size_t ts_received_count, ts_selected_count;
309 status_t status = SUCCESS;
310
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 */
314 if (ts_initiator)
315 {
316 ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected);
317 }
318 else
319 {
320 ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected);
321 }
322 /* check if the responder selected valid proposals */
323 if (ts_selected_count != ts_received_count)
324 {
325 this->logger->log(this->logger, ERROR, "responder selected invalid traffic selectors");
326 status = FAILED;
327 }
328
329 /* cleanup */
330 while(ts_received_count--)
331 {
332 traffic_selector_t *ts = *ts_received + ts_received_count;
333 ts->destroy(ts);
334 }
335 allocator_free(ts_received);
336 while(ts_selected_count--)
337 {
338 traffic_selector_t *ts = *ts_selected + ts_selected_count;
339 ts->destroy(ts);
340 }
341 allocator_free(ts_selected);
342 return status;
343 }
344 /**
345 * Implements state_t.get_state
346 */
347 static ike_sa_state_t get_state(private_ike_auth_requested_t *this)
348 {
349 return IKE_AUTH_REQUESTED;
350 }
351
352 /**
353 * Implements state_t.get_state
354 */
355 static void destroy(private_ike_auth_requested_t *this)
356 {
357 allocator_free(this);
358 }
359
360 /*
361 * Described in header.
362 */
363 ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa)
364 {
365 private_ike_auth_requested_t *this = allocator_alloc_thing(private_ike_auth_requested_t);
366
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;
371
372 /* private functions */
373
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;
378
379 /* private data */
380 this->ike_sa = ike_sa;
381 this->logger = this->ike_sa->get_logger(this->ike_sa);
382
383 return &(this->public);
384 }