]>
Commit | Line | Data |
---|---|---|
c7dd2a7b MW |
1 | /** |
2 | * @file ike_sa_init_requested.c | |
3 | * | |
df3c59d0 | 4 | * @brief Implementation of ike_sa_init_requested_t. |
c7dd2a7b MW |
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_sa_init_requested.h" | |
24 | ||
0e96f7d8 | 25 | #include <daemon.h> |
c7dd2a7b MW |
26 | #include <utils/allocator.h> |
27 | #include <encoding/payloads/sa_payload.h> | |
28 | #include <encoding/payloads/ke_payload.h> | |
29 | #include <encoding/payloads/nonce_payload.h> | |
f890d8fe | 30 | #include <encoding/payloads/id_payload.h> |
c7dd2a7b MW |
31 | #include <transforms/diffie_hellman.h> |
32 | ||
5796aa16 MW |
33 | |
34 | typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t; | |
35 | ||
c7dd2a7b MW |
36 | /** |
37 | * Private data of a ike_sa_init_requested_t object. | |
38 | * | |
39 | */ | |
5796aa16 | 40 | struct private_ike_sa_init_requested_t { |
c7dd2a7b MW |
41 | /** |
42 | * methods of the state_t interface | |
43 | */ | |
44 | ike_sa_init_requested_t public; | |
45 | ||
46 | /** | |
47 | * Assigned IKE_SA | |
48 | */ | |
49 | protected_ike_sa_t *ike_sa; | |
50 | ||
51 | /** | |
52 | * Diffie Hellman object used to compute shared secret | |
53 | */ | |
54 | diffie_hellman_t *diffie_hellman; | |
55 | ||
56 | /** | |
57 | * Shared secret of successful exchange | |
58 | */ | |
59 | chunk_t shared_secret; | |
60 | ||
61 | /** | |
62 | * Sent nonce value | |
63 | */ | |
64 | chunk_t sent_nonce; | |
65 | ||
66 | /** | |
67 | * Received nonce | |
68 | */ | |
69 | chunk_t received_nonce; | |
70 | ||
71 | /** | |
72 | * DH group priority used to get dh_group_number from configuration manager. | |
73 | * | |
74 | * Currently uused but usable if informational messages of unsupported dh group number are processed. | |
75 | */ | |
76 | u_int16_t dh_group_priority; | |
77 | ||
78 | /** | |
79 | * Logger used to log data | |
80 | * | |
81 | * Is logger of ike_sa! | |
82 | */ | |
83 | logger_t *logger; | |
f890d8fe JH |
84 | |
85 | /** | |
86 | * Builds the IKE_SA_AUTH request message. | |
87 | * | |
88 | * @param this calling object | |
89 | * @param message the created message will be stored at this location | |
90 | */ | |
91 | void (*build_ike_auth_request) (private_ike_sa_init_requested_t *this, message_t **message); | |
92 | ||
93 | /** | |
94 | * Builds the id payload for this state. | |
95 | * | |
96 | * @param this calling object | |
97 | * @param payload The generated payload object of type id_payload_t is | |
98 | * stored at this location. | |
99 | */ | |
100 | void (*build_id_payload) (private_ike_sa_init_requested_t *this, payload_t **payload); | |
101 | ||
c7dd2a7b MW |
102 | }; |
103 | ||
104 | /** | |
105 | * Implements state_t.get_state | |
106 | */ | |
d440fe6d | 107 | static status_t process_message(private_ike_sa_init_requested_t *this, message_t *reply) |
c7dd2a7b | 108 | { |
aad398a7 JH |
109 | status_t status; |
110 | iterator_t *payloads; | |
111 | exchange_type_t exchange_type; | |
f890d8fe JH |
112 | message_t *request; |
113 | packet_t *packet; | |
aad398a7 JH |
114 | u_int64_t responder_spi; |
115 | ike_sa_id_t *ike_sa_id; | |
116 | ||
c7dd2a7b | 117 | |
d440fe6d | 118 | exchange_type = reply->get_exchange_type(reply); |
c7dd2a7b MW |
119 | if (exchange_type != IKE_SA_INIT) |
120 | { | |
121 | this->logger->log(this->logger, ERROR | MORE, "Message of type %s not supported in state ike_sa_init_requested",mapping_find(exchange_type_m,exchange_type)); | |
122 | return FAILED; | |
123 | } | |
124 | ||
d440fe6d | 125 | if (reply->get_request(reply)) |
c7dd2a7b MW |
126 | { |
127 | this->logger->log(this->logger, ERROR | MORE, "Only responses of type IKE_SA_INIT supported in state ike_sa_init_requested"); | |
128 | return FAILED; | |
129 | } | |
130 | ||
131 | /* parse incoming message */ | |
d440fe6d | 132 | status = reply->parse_body(reply, NULL, NULL); |
c7dd2a7b MW |
133 | if (status != SUCCESS) |
134 | { | |
135 | this->logger->log(this->logger, ERROR | MORE, "Could not parse body"); | |
136 | return status; | |
137 | } | |
138 | ||
d440fe6d | 139 | responder_spi = reply->get_responder_spi(reply); |
aad398a7 JH |
140 | ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); |
141 | ike_sa_id->set_responder_spi(ike_sa_id,responder_spi); | |
c7dd2a7b MW |
142 | |
143 | /* iterate over incoming payloads */ | |
d440fe6d | 144 | payloads = reply->get_payload_iterator(reply); |
c7dd2a7b MW |
145 | while (payloads->has_next(payloads)) |
146 | { | |
147 | payload_t *payload; | |
148 | payloads->current(payloads, (void**)&payload); | |
149 | ||
150 | this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload))); | |
151 | switch (payload->get_type(payload)) | |
152 | { | |
153 | case SECURITY_ASSOCIATION: | |
154 | { | |
b9d9f188 JH |
155 | sa_payload_t *sa_payload = (sa_payload_t*)payload; |
156 | iterator_t *suggested_proposals; | |
157 | proposal_substructure_t *suggested_proposal; | |
158 | bool valid; | |
aad398a7 JH |
159 | |
160 | ||
c7dd2a7b | 161 | /* get the list of suggested proposals */ |
a0753941 | 162 | suggested_proposals = sa_payload->create_proposal_substructure_iterator(sa_payload, TRUE); |
d048df5c | 163 | |
c7dd2a7b | 164 | |
b9d9f188 JH |
165 | /* now let the configuration-manager check the selected proposals*/ |
166 | this->logger->log(this->logger, CONTROL | MOST, "Check suggested proposals"); | |
0e96f7d8 | 167 | status = charon->configuration_manager->check_selected_proposals_for_host(charon->configuration_manager, |
b9d9f188 | 168 | this->ike_sa->get_other_host(this->ike_sa), suggested_proposals,&valid); |
c7dd2a7b MW |
169 | if (status != SUCCESS) |
170 | { | |
b9d9f188 | 171 | this->logger->log(this->logger, ERROR | MORE, "Could not check suggested proposals!"); |
c7dd2a7b MW |
172 | suggested_proposals->destroy(suggested_proposals); |
173 | payloads->destroy(payloads); | |
174 | return status; | |
175 | } | |
b9d9f188 JH |
176 | |
177 | if (!valid) | |
178 | { | |
179 | this->logger->log(this->logger, ERROR | MORE, "Suggested proposals not accepted!"); | |
180 | payloads->destroy(payloads); | |
181 | return status; | |
182 | } | |
183 | ||
184 | ||
185 | /* let the ike_sa create their own transforms from proposal informations */ | |
186 | suggested_proposals->reset(suggested_proposals); | |
187 | /* TODO check for true*/ | |
188 | suggested_proposals->has_next(suggested_proposals); | |
189 | status = suggested_proposals->current(suggested_proposals,(void **)&suggested_proposal); | |
c7dd2a7b | 190 | suggested_proposals->destroy(suggested_proposals); |
b9d9f188 | 191 | if (status != SUCCESS) |
c7dd2a7b | 192 | { |
b9d9f188 | 193 | this->logger->log(this->logger, ERROR | MORE, "Could not get first proposal"); |
c7dd2a7b | 194 | payloads->destroy(payloads); |
b9d9f188 JH |
195 | return status; |
196 | } | |
197 | ||
198 | status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,suggested_proposal); | |
199 | if (status != SUCCESS) | |
200 | { | |
201 | this->logger->log(this->logger, ERROR | MORE, "Transform objects could not be created from selected proposal"); | |
202 | payloads->destroy(payloads); | |
203 | return status; | |
c7dd2a7b MW |
204 | } |
205 | ||
206 | ||
207 | /* ok, we have what we need for sa_payload */ | |
208 | break; | |
209 | } | |
210 | case KEY_EXCHANGE: | |
211 | { | |
212 | ke_payload_t *ke_payload = (ke_payload_t*)payload; | |
d048df5c MW |
213 | |
214 | this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload)); | |
c7dd2a7b MW |
215 | |
216 | /* shared secret is computed AFTER processing of all payloads... */ | |
217 | break; | |
218 | } | |
219 | case NONCE: | |
220 | { | |
221 | nonce_payload_t *nonce_payload = (nonce_payload_t*)payload; | |
c7dd2a7b | 222 | |
d048df5c MW |
223 | allocator_free(this->received_nonce.ptr); |
224 | this->received_nonce = CHUNK_INITIALIZER; | |
225 | ||
226 | nonce_payload->get_nonce(nonce_payload, &(this->received_nonce)); | |
c7dd2a7b MW |
227 | break; |
228 | } | |
229 | default: | |
230 | { | |
d048df5c | 231 | this->logger->log(this->logger, ERROR, "Payload type not supported!!!!"); |
c7dd2a7b MW |
232 | payloads->destroy(payloads); |
233 | return FAILED; | |
234 | } | |
235 | ||
236 | } | |
237 | ||
238 | } | |
239 | payloads->destroy(payloads); | |
d048df5c MW |
240 | |
241 | allocator_free(this->shared_secret.ptr); | |
242 | this->shared_secret = CHUNK_INITIALIZER; | |
243 | ||
c7dd2a7b MW |
244 | /* store shared secret */ |
245 | this->logger->log(this->logger, CONTROL | MOST, "Retrieve shared secret and store it"); | |
246 | status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &(this->shared_secret)); | |
247 | this->logger->log_chunk(this->logger, PRIVATE, "Shared secret", &this->shared_secret); | |
248 | ||
d048df5c | 249 | this->ike_sa->compute_secrets(this->ike_sa,this->shared_secret,this->sent_nonce, this->received_nonce); |
c7dd2a7b | 250 | |
d440fe6d | 251 | /* build the complete IKE_AUTH request */ |
f890d8fe JH |
252 | this->build_ike_auth_request (this,&request); |
253 | ||
254 | /* generate packet */ | |
255 | this->logger->log(this->logger, CONTROL|MOST, "generate packet from message"); | |
256 | ||
257 | status = request->generate(request, this->ike_sa->get_crypter_initiator(this->ike_sa), this->ike_sa->get_signer_initiator(this->ike_sa), &packet); | |
258 | if (status != SUCCESS) | |
259 | { | |
260 | this->logger->log(this->logger, ERROR, "could not generate packet from message"); | |
d440fe6d | 261 | reply->destroy(reply); |
f890d8fe JH |
262 | return status; |
263 | } | |
264 | ||
265 | this->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue"); | |
266 | charon->send_queue->add(charon->send_queue, packet); | |
267 | ||
268 | ||
d440fe6d JH |
269 | /* last message can now be set */ |
270 | status = this->ike_sa->set_last_requested_message(this->ike_sa, request); | |
271 | ||
272 | if (status != SUCCESS) | |
273 | { | |
274 | this->logger->log(this->logger, ERROR, "Could not set last requested message"); | |
275 | // (next_state->state_interface).destroy(&(next_state->state_interface)); | |
276 | request->destroy(request); | |
277 | return status; | |
278 | } | |
279 | ||
f890d8fe | 280 | |
c7dd2a7b MW |
281 | /**************************** |
282 | * | |
283 | * TODO | |
284 | * | |
c7dd2a7b MW |
285 | * Send IKE_SA_AUTH request |
286 | * | |
aad398a7 JH |
287 | * Make state change |
288 | * | |
c7dd2a7b MW |
289 | ****************************/ |
290 | ||
291 | ||
292 | /* set up the reply */ | |
293 | // status = this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response); | |
294 | // if (status != SUCCESS) | |
295 | // { | |
296 | // return status; | |
297 | // } | |
298 | ||
299 | // response->destroy(response); | |
300 | ||
c7dd2a7b MW |
301 | |
302 | return SUCCESS; | |
303 | } | |
304 | ||
f890d8fe JH |
305 | /** |
306 | * implements private_ike_sa_init_requested_t.build_ike_auth_request | |
307 | */ | |
308 | static void build_ike_auth_request (private_ike_sa_init_requested_t *this, message_t **request) | |
309 | { | |
310 | payload_t *payload; | |
311 | message_t *message; | |
312 | ||
313 | /* going to build message */ | |
314 | this->logger->log(this->logger, CONTROL|MOST, "Going to build empty message"); | |
315 | this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &message); | |
316 | ||
317 | ||
318 | /* build id payload */ | |
319 | this->build_id_payload(this, &payload); | |
320 | this->logger->log(this->logger, CONTROL|MOST, "add id payload to message"); | |
321 | message->add_payload(message, payload); | |
322 | ||
323 | *request = message; | |
324 | } | |
325 | ||
326 | static void build_id_payload (private_ike_sa_init_requested_t *this, payload_t **payload) | |
327 | { | |
328 | id_payload_t *id_payload; | |
329 | chunk_t email; | |
330 | ||
331 | /* create IDi */ | |
332 | id_payload = id_payload_create(TRUE); | |
333 | /* TODO special functions on id payload */ | |
334 | /* TODO configuration manager request */ | |
335 | id_payload->set_id_type(id_payload,ID_RFC822_ADDR); | |
336 | email.ptr = "moerdi@hsr.ch"; | |
337 | email.len = strlen(email.ptr); | |
338 | this->logger->log_chunk(this->logger, CONTROL, "Moerdi",&email); | |
339 | id_payload->set_data(id_payload,email); | |
340 | ||
341 | *payload = (payload_t *) id_payload; | |
342 | } | |
343 | ||
c7dd2a7b MW |
344 | /** |
345 | * Implements state_t.get_state | |
346 | */ | |
347 | static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this) | |
348 | { | |
349 | return IKE_SA_INIT_REQUESTED; | |
350 | } | |
351 | ||
352 | /** | |
353 | * Implements state_t.get_state | |
354 | */ | |
d048df5c | 355 | static void destroy(private_ike_sa_init_requested_t *this) |
c7dd2a7b MW |
356 | { |
357 | this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t"); | |
358 | ||
359 | this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object"); | |
360 | this->diffie_hellman->destroy(this->diffie_hellman); | |
c7dd2a7b | 361 | |
d048df5c MW |
362 | allocator_free(this->sent_nonce.ptr); |
363 | allocator_free(this->received_nonce.ptr); | |
364 | allocator_free(this->shared_secret.ptr); | |
c7dd2a7b | 365 | allocator_free(this); |
c7dd2a7b MW |
366 | } |
367 | ||
368 | /* | |
369 | * Described in header. | |
370 | */ | |
371 | ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa,u_int16_t dh_group_priority, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce) | |
372 | { | |
373 | private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t); | |
374 | ||
c7dd2a7b | 375 | /* interface functions */ |
aad398a7 | 376 | this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; |
c7dd2a7b | 377 | this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; |
d048df5c | 378 | this->public.state_interface.destroy = (void (*) (state_t *)) destroy; |
c7dd2a7b | 379 | |
f890d8fe JH |
380 | /* private functions */ |
381 | this->build_ike_auth_request = build_ike_auth_request; | |
382 | this->build_id_payload = build_id_payload; | |
383 | ||
c7dd2a7b MW |
384 | /* private data */ |
385 | this->ike_sa = ike_sa; | |
d048df5c MW |
386 | this->received_nonce = CHUNK_INITIALIZER; |
387 | this->shared_secret = CHUNK_INITIALIZER; | |
aad398a7 | 388 | this->logger = this->ike_sa->get_logger(this->ike_sa); |
c7dd2a7b MW |
389 | this->diffie_hellman = diffie_hellman; |
390 | this->sent_nonce = sent_nonce; | |
391 | this->dh_group_priority = dh_group_priority; | |
392 | ||
393 | return &(this->public); | |
394 | } |