]>
Commit | Line | Data |
---|---|---|
cb5c6cc7 JH |
1 | /** |
2 | * @file message.c | |
79538669 | 3 | * |
27e43205 | 4 | * @brief Implementation of message_t. |
79538669 | 5 | * |
cb5c6cc7 JH |
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 | ||
ca6dd4f6 | 23 | #include <stdlib.h> |
ca6dd4f6 | 24 | |
b85d20d1 MW |
25 | #include "message.h" |
26 | ||
021c2322 | 27 | #include <types.h> |
0e96f7d8 | 28 | #include <daemon.h> |
96f79ff1 | 29 | #include <sa/ike_sa_id.h> |
4a962238 MW |
30 | #include <encoding/generator.h> |
31 | #include <encoding/parser.h> | |
021c2322 MW |
32 | #include <utils/linked_list.h> |
33 | #include <utils/allocator.h> | |
34 | #include <utils/logger_manager.h> | |
4a962238 MW |
35 | #include <encoding/payloads/encodings.h> |
36 | #include <encoding/payloads/payload.h> | |
81796a52 | 37 | #include <encoding/payloads/encryption_payload.h> |
668f9fcb | 38 | #include <encoding/payloads/unknown_payload.h> |
110dc83a | 39 | |
f6ba78c3 JH |
40 | /** |
41 | * Max number of notify payloads per IKEv2 Message | |
42 | */ | |
43 | #define MAX_NOTIFY_PAYLOADS 10 | |
44 | ||
9da406cf | 45 | |
668f9fcb | 46 | typedef struct payload_rule_t payload_rule_t; |
95c61cb9 | 47 | |
9da406cf | 48 | /** |
668f9fcb MW |
49 | * A payload rule defines the rules for a payload |
50 | * in a specific message rule. It defines if and how | |
51 | * many times a payload must/can occur in a message | |
52 | * and if it must be encrypted. | |
9da406cf | 53 | */ |
668f9fcb | 54 | struct payload_rule_t { |
9da406cf | 55 | /** |
27e43205 | 56 | * Payload type. |
9da406cf JH |
57 | */ |
58 | payload_type_t payload_type; | |
59 | ||
60 | /** | |
27e43205 | 61 | * Minimal occurence of this payload. |
9da406cf JH |
62 | */ |
63 | size_t min_occurence; | |
64 | ||
65 | /** | |
27e43205 | 66 | * Max occurence of this payload. |
9da406cf JH |
67 | */ |
68 | size_t max_occurence; | |
f890d8fe JH |
69 | |
70 | /** | |
668f9fcb | 71 | * TRUE if payload must be encrypted |
f890d8fe JH |
72 | */ |
73 | bool encrypted; | |
ae3012a0 JH |
74 | |
75 | /** | |
668f9fcb MW |
76 | * If this payload occurs, the message rule is |
77 | * fullfilled in any case. This applies e.g. to | |
78 | * notify_payloads. | |
ae3012a0 | 79 | */ |
668f9fcb | 80 | bool sufficient; |
9da406cf JH |
81 | }; |
82 | ||
95c61cb9 JH |
83 | typedef struct message_rule_t message_rule_t; |
84 | ||
9da406cf | 85 | /** |
668f9fcb MW |
86 | * A message rule defines the kind of a message, |
87 | * if it has encrypted contents and a list | |
88 | * of payload rules. | |
9da406cf JH |
89 | * |
90 | */ | |
95c61cb9 | 91 | struct message_rule_t { |
9da406cf | 92 | /** |
27e43205 | 93 | * Type of message. |
9da406cf JH |
94 | */ |
95 | exchange_type_t exchange_type; | |
96 | ||
97 | /** | |
27e43205 | 98 | * Is message a request or response. |
9da406cf JH |
99 | */ |
100 | bool is_request; | |
d440fe6d JH |
101 | |
102 | /** | |
103 | * Message contains encrypted content. | |
104 | */ | |
105 | bool encrypted_content; | |
106 | ||
668f9fcb MW |
107 | /** |
108 | * Number of payload rules which will follow | |
109 | */ | |
110 | size_t payload_rule_count; | |
d440fe6d | 111 | |
9da406cf | 112 | /** |
668f9fcb | 113 | * Pointer to first payload rule |
9da406cf | 114 | */ |
668f9fcb | 115 | payload_rule_t *payload_rules; |
9da406cf JH |
116 | }; |
117 | ||
e0d60939 | 118 | /** |
27e43205 | 119 | * Message rule for IKE_SA_INIT from initiator. |
e0d60939 | 120 | */ |
668f9fcb | 121 | static payload_rule_t ike_sa_init_i_payload_rules[] = { |
f6ba78c3 | 122 | {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,FALSE}, |
ae3012a0 JH |
123 | {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, |
124 | {KEY_EXCHANGE,1,1,FALSE,FALSE}, | |
125 | {NONCE,1,1,FALSE,FALSE}, | |
9da406cf JH |
126 | }; |
127 | ||
e0d60939 | 128 | /** |
27e43205 | 129 | * Message rule for IKE_SA_INIT from responder. |
e0d60939 | 130 | */ |
668f9fcb | 131 | static payload_rule_t ike_sa_init_r_payload_rules[] = { |
f6ba78c3 | 132 | {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,TRUE}, |
ae3012a0 JH |
133 | {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, |
134 | {KEY_EXCHANGE,1,1,FALSE,FALSE}, | |
135 | {NONCE,1,1,FALSE,FALSE}, | |
9da406cf JH |
136 | }; |
137 | ||
f890d8fe JH |
138 | /** |
139 | * Message rule for IKE_AUTH from initiator. | |
140 | */ | |
668f9fcb | 141 | static payload_rule_t ike_auth_i_payload_rules[] = { |
f6ba78c3 | 142 | {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, |
ae3012a0 JH |
143 | {ID_INITIATOR,1,1,TRUE,FALSE}, |
144 | {CERTIFICATE,0,1,TRUE,FALSE}, | |
145 | {CERTIFICATE_REQUEST,0,1,TRUE,FALSE}, | |
146 | {ID_RESPONDER,0,1,TRUE,FALSE}, | |
147 | {AUTHENTICATION,1,1,TRUE,FALSE}, | |
148 | {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, | |
149 | {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, | |
150 | {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, | |
668f9fcb | 151 | {CONFIGURATION,0,1,TRUE,FALSE}, |
f890d8fe JH |
152 | }; |
153 | ||
154 | /** | |
155 | * Message rule for IKE_AUTH from responder. | |
156 | */ | |
668f9fcb | 157 | static payload_rule_t ike_auth_r_payload_rules[] = { |
f6ba78c3 | 158 | {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, |
ae3012a0 | 159 | {CERTIFICATE,0,1,TRUE,FALSE}, |
01de2f3c | 160 | {ID_RESPONDER,1,1,TRUE,FALSE}, |
ae3012a0 JH |
161 | {AUTHENTICATION,1,1,TRUE,FALSE}, |
162 | {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, | |
163 | {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, | |
164 | {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, | |
668f9fcb | 165 | {CONFIGURATION,0,1,TRUE,FALSE}, |
f890d8fe | 166 | }; |
e0d60939 MW |
167 | |
168 | /** | |
27e43205 | 169 | * Message rules, defines allowed payloads. |
e0d60939 | 170 | */ |
93a9a115 | 171 | static message_rule_t message_rules[] = { |
668f9fcb MW |
172 | {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, |
173 | {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, | |
174 | {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, | |
175 | {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules} | |
110dc83a JH |
176 | }; |
177 | ||
ca6dd4f6 | 178 | |
5796aa16 MW |
179 | typedef struct private_message_t private_message_t; |
180 | ||
ca6dd4f6 | 181 | /** |
27e43205 | 182 | * Private data of an message_t object. |
ca6dd4f6 | 183 | */ |
5796aa16 | 184 | struct private_message_t { |
ca6dd4f6 JH |
185 | |
186 | /** | |
27e43205 | 187 | * Public part of a message_t object. |
ca6dd4f6 JH |
188 | */ |
189 | message_t public; | |
79538669 | 190 | |
9da406cf | 191 | /** |
27e43205 | 192 | * Minor version of message. |
9da406cf JH |
193 | */ |
194 | u_int8_t major_version; | |
195 | ||
196 | /** | |
27e43205 | 197 | * Major version of message. |
9da406cf JH |
198 | */ |
199 | u_int8_t minor_version; | |
200 | ||
201 | /** | |
27e43205 | 202 | * First Payload in message. |
9da406cf JH |
203 | */ |
204 | payload_type_t first_payload; | |
205 | ||
110dc83a | 206 | /** |
27e43205 | 207 | * Assigned exchange type. |
110dc83a | 208 | */ |
523526ec | 209 | exchange_type_t exchange_type; |
3a8f9f44 | 210 | |
110dc83a | 211 | /** |
668f9fcb | 212 | * TRUE if message is a request, FALSE if a reply. |
110dc83a JH |
213 | */ |
214 | bool is_request; | |
c64d7032 | 215 | |
525250c6 | 216 | /** |
27e43205 | 217 | * Message ID of this message. |
525250c6 JH |
218 | */ |
219 | u_int32_t message_id; | |
220 | ||
221 | /** | |
27e43205 | 222 | * ID of assigned IKE_SA. |
525250c6 JH |
223 | */ |
224 | ike_sa_id_t *ike_sa_id; | |
225 | ||
c64d7032 | 226 | /** |
668f9fcb | 227 | * Assigned UDP packet, stores incoming packet or last generated one. |
c64d7032 | 228 | */ |
523526ec | 229 | packet_t *packet; |
c64d7032 | 230 | |
523526ec | 231 | /** |
27e43205 | 232 | * Linked List where payload data are stored in. |
523526ec | 233 | */ |
c64d7032 | 234 | linked_list_t *payloads; |
523526ec | 235 | |
91443667 | 236 | /** |
27e43205 | 237 | * Assigned parser to parse Header and Body of this message. |
91443667 JH |
238 | */ |
239 | parser_t *parser; | |
240 | ||
668f9fcb MW |
241 | /** |
242 | * The message rule for this message instance | |
243 | */ | |
244 | message_rule_t *message_rule; | |
245 | ||
523526ec | 246 | /** |
27e43205 | 247 | * Assigned logger. |
523526ec MW |
248 | */ |
249 | logger_t *logger; | |
250 | ||
93a9a115 | 251 | /** |
668f9fcb MW |
252 | * Sets the private message_rule member to the rule which |
253 | * applies to this message. Must be called before get_payload_rule(). | |
93a9a115 | 254 | * |
f6039334 | 255 | * @param this calling object |
27e43205 | 256 | * @return |
f6039334 | 257 | * - SUCCESS |
668f9fcb | 258 | * - NOT_FOUND if no message rule applies to this message. |
93a9a115 | 259 | */ |
668f9fcb | 260 | status_t (*set_message_rule) (private_message_t *this); |
f6039334 JH |
261 | |
262 | /** | |
668f9fcb | 263 | * Gets the payload_rule_t for a specific message_rule_t and payload type. |
f6039334 JH |
264 | * |
265 | * @param this calling object | |
f6039334 | 266 | * @param payload_type payload type |
668f9fcb | 267 | * @param[out] payload_rule returned payload_rule_t |
f6039334 JH |
268 | * @return |
269 | * - SUCCESS | |
668f9fcb MW |
270 | * - NOT_FOUND if payload not defined in current message rule |
271 | * - INVALID_STATE if message rule is not set via set_message_rule() | |
f6039334 | 272 | */ |
668f9fcb | 273 | status_t (*get_payload_rule) (private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule); |
93a9a115 | 274 | |
f890d8fe JH |
275 | /** |
276 | * Encrypts all payloads which has to get encrypted. | |
277 | * | |
f6039334 JH |
278 | * Can also be called with messages not containing encrypted content. |
279 | * | |
280 | * @param this calling object | |
d440fe6d JH |
281 | * @param crypter crypter_t object |
282 | * @param signer signer_t object | |
668f9fcb MW |
283 | * @return |
284 | * - SUCCESS | |
285 | * - INVALID_STATE if no crypter/signer supplied but needed | |
f890d8fe JH |
286 | */ |
287 | status_t (*encrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); | |
288 | ||
d440fe6d | 289 | /** |
668f9fcb | 290 | * Decrypts encrypted contents, and checks if a payload is encrypted if it has to be. |
d440fe6d JH |
291 | * |
292 | * @param this calling object | |
293 | * @param crypter crypter_t object | |
294 | * @param signer signer_t object | |
668f9fcb MW |
295 | * @return |
296 | * - SUCCESS | |
297 | * - FAILED if decryption not successfull | |
298 | * - INVALID_STATE if no crypter/signer supplied but needed | |
299 | */ | |
300 | status_t (*decrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); | |
301 | ||
302 | /** | |
303 | * Verifies the message. Checks for payloads count. | |
304 | * | |
305 | * @param calling object | |
306 | * @return | |
307 | * - SUCCESS if message valid, or | |
308 | * - FAILED if message does not align with message rules. | |
d440fe6d | 309 | */ |
668f9fcb | 310 | status_t (*verify) (private_message_t *this); |
ca6dd4f6 JH |
311 | }; |
312 | ||
93a9a115 | 313 | /** |
668f9fcb | 314 | * Implementation of private_message_t.set_message_rule. |
93a9a115 | 315 | */ |
668f9fcb | 316 | static status_t set_message_rule(private_message_t *this) |
93a9a115 JH |
317 | { |
318 | int i; | |
d440fe6d | 319 | |
93a9a115 JH |
320 | for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++) |
321 | { | |
d440fe6d JH |
322 | if ((this->exchange_type == message_rules[i].exchange_type) && |
323 | (this->is_request == message_rules[i].is_request)) | |
93a9a115 JH |
324 | { |
325 | /* found rule for given exchange_type*/ | |
668f9fcb | 326 | this->message_rule = &(message_rules[i]); |
93a9a115 JH |
327 | return SUCCESS; |
328 | } | |
93a9a115 | 329 | } |
668f9fcb | 330 | this->message_rule = NULL; |
d440fe6d JH |
331 | return NOT_FOUND; |
332 | } | |
333 | ||
f6039334 | 334 | /** |
668f9fcb | 335 | * Implementation of private_message_t.get_payload_rule. |
f6039334 | 336 | */ |
668f9fcb | 337 | static status_t get_payload_rule(private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule) |
d440fe6d JH |
338 | { |
339 | int i; | |
340 | ||
668f9fcb | 341 | for (i = 0; i < this->message_rule->payload_rule_count;i++) |
d440fe6d | 342 | { |
668f9fcb | 343 | if (this->message_rule->payload_rules[i].payload_type == payload_type) |
d440fe6d | 344 | { |
668f9fcb | 345 | *payload_rule = &(this->message_rule->payload_rules[i]); |
d440fe6d JH |
346 | return SUCCESS; |
347 | } | |
348 | } | |
349 | ||
668f9fcb | 350 | *payload_rule = NULL; |
93a9a115 JH |
351 | return NOT_FOUND; |
352 | } | |
525250c6 JH |
353 | |
354 | /** | |
27e43205 | 355 | * Implementation of message_t.set_ike_sa_id. |
525250c6 | 356 | */ |
27e43205 | 357 | static void set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id) |
525250c6 | 358 | { |
d048df5c | 359 | this->ike_sa_id = ike_sa_id->clone(ike_sa_id); |
525250c6 JH |
360 | } |
361 | ||
362 | /** | |
27e43205 | 363 | * Implementation of message_t.get_ike_sa_id. |
525250c6 JH |
364 | */ |
365 | static status_t get_ike_sa_id (private_message_t *this,ike_sa_id_t **ike_sa_id) | |
366 | { | |
525250c6 JH |
367 | if (this->ike_sa_id == NULL) |
368 | { | |
369 | return FAILED; | |
370 | } | |
d048df5c | 371 | *ike_sa_id = this->ike_sa_id->clone(this->ike_sa_id); |
27e43205 | 372 | return SUCCESS; |
525250c6 JH |
373 | } |
374 | ||
525250c6 | 375 | /** |
27e43205 | 376 | * Implementation of message_t.set_message_id. |
525250c6 | 377 | */ |
27e43205 | 378 | static void set_message_id (private_message_t *this,u_int32_t message_id) |
525250c6 JH |
379 | { |
380 | this->message_id = message_id; | |
525250c6 JH |
381 | } |
382 | ||
525250c6 | 383 | /** |
27e43205 | 384 | * Implementation of message_t.get_message_id. |
525250c6 JH |
385 | */ |
386 | static u_int32_t get_message_id (private_message_t *this) | |
387 | { | |
388 | return this->message_id; | |
389 | } | |
390 | ||
21981473 | 391 | /** |
27e43205 | 392 | * Implementation of message_t.get_responder_spi. |
21981473 JH |
393 | */ |
394 | static u_int64_t get_responder_spi (private_message_t *this) | |
395 | { | |
396 | return (this->ike_sa_id->get_responder_spi(this->ike_sa_id)); | |
397 | } | |
398 | ||
9da406cf | 399 | /** |
27e43205 | 400 | * Implementation of message_t.set_major_version. |
9da406cf | 401 | */ |
27e43205 | 402 | static void set_major_version (private_message_t *this,u_int8_t major_version) |
9da406cf JH |
403 | { |
404 | this->major_version = major_version; | |
9da406cf JH |
405 | } |
406 | ||
407 | ||
408 | /** | |
27e43205 | 409 | * Implementation of message_t.set_major_version. |
9da406cf JH |
410 | */ |
411 | static u_int8_t get_major_version (private_message_t *this) | |
412 | { | |
413 | return this->major_version; | |
414 | } | |
415 | ||
416 | /** | |
27e43205 | 417 | * Implementation of message_t.set_minor_version. |
9da406cf | 418 | */ |
27e43205 | 419 | static void set_minor_version (private_message_t *this,u_int8_t minor_version) |
9da406cf JH |
420 | { |
421 | this->minor_version = minor_version; | |
9da406cf JH |
422 | } |
423 | ||
9da406cf | 424 | /** |
27e43205 | 425 | * Implementation of message_t.get_minor_version. |
9da406cf JH |
426 | */ |
427 | static u_int8_t get_minor_version (private_message_t *this) | |
428 | { | |
429 | return this->minor_version; | |
430 | } | |
525250c6 | 431 | |
110dc83a | 432 | /** |
27e43205 | 433 | * Implementation of message_t.set_exchange_type. |
110dc83a | 434 | */ |
27e43205 | 435 | static void set_exchange_type (private_message_t *this,exchange_type_t exchange_type) |
110dc83a JH |
436 | { |
437 | this->exchange_type = exchange_type; | |
110dc83a JH |
438 | } |
439 | ||
110dc83a | 440 | /** |
27e43205 | 441 | * Implementation of message_t.get_exchange_type. |
110dc83a JH |
442 | */ |
443 | static exchange_type_t get_exchange_type (private_message_t *this) | |
444 | { | |
445 | return this->exchange_type; | |
446 | } | |
447 | ||
110dc83a | 448 | /** |
27e43205 | 449 | * Implementation of message_t.set_request. |
110dc83a | 450 | */ |
27e43205 | 451 | static void set_request (private_message_t *this,bool request) |
110dc83a JH |
452 | { |
453 | this->is_request = request; | |
110dc83a JH |
454 | } |
455 | ||
456 | /** | |
27e43205 | 457 | * Implementation of message_t.get_request. |
110dc83a JH |
458 | */ |
459 | static exchange_type_t get_request (private_message_t *this) | |
460 | { | |
461 | return this->is_request; | |
462 | } | |
463 | ||
27e43205 JH |
464 | /** |
465 | * Implementation of message_t.add_payload. | |
466 | */ | |
467 | static void add_payload(private_message_t *this, payload_t *payload) | |
523526ec | 468 | { |
7b3d1389 | 469 | payload_t *last_payload; |
27e43205 | 470 | if (this->payloads->get_count(this->payloads) > 0) |
7b3d1389 | 471 | { |
27e43205 | 472 | this->payloads->get_last(this->payloads,(void **) &last_payload); |
ee29afd4 | 473 | last_payload->set_next_type(last_payload, payload->get_type(payload)); |
7b3d1389 MW |
474 | } |
475 | else | |
476 | { | |
ee29afd4 | 477 | this->first_payload = payload->get_type(payload); |
7b3d1389 | 478 | } |
ee29afd4 MW |
479 | payload->set_next_type(payload, NO_PAYLOAD); |
480 | this->payloads->insert_last(this->payloads, (void*)payload); | |
481 | ||
f6039334 JH |
482 | this->logger->log(this->logger, CONTROL|MORE, "Added payload of type %s to message", |
483 | mapping_find(payload_type_m, payload->get_type(payload))); | |
523526ec MW |
484 | } |
485 | ||
27e43205 JH |
486 | /** |
487 | * Implementation of message_t.set_source. | |
488 | */ | |
489 | static void set_source(private_message_t *this, host_t *host) | |
523526ec MW |
490 | { |
491 | if (this->packet->source != NULL) | |
492 | { | |
493 | this->packet->source->destroy(this->packet->source); | |
494 | } | |
495 | this->packet->source = host; | |
523526ec MW |
496 | } |
497 | ||
27e43205 JH |
498 | /** |
499 | * Implementation of message_t.set_destination. | |
500 | */ | |
501 | static void set_destination(private_message_t *this, host_t *host) | |
523526ec MW |
502 | { |
503 | if (this->packet->destination != NULL) | |
504 | { | |
505 | this->packet->destination->destroy(this->packet->destination); | |
506 | } | |
507 | this->packet->destination = host; | |
523526ec MW |
508 | } |
509 | ||
27e43205 JH |
510 | /** |
511 | * Implementation of message_t.get_source. | |
512 | */ | |
f6039334 | 513 | static host_t* get_source(private_message_t *this) |
523526ec | 514 | { |
f6039334 | 515 | return this->packet->source; |
523526ec MW |
516 | } |
517 | ||
27e43205 JH |
518 | /** |
519 | * Implementation of message_t.get_destination. | |
520 | */ | |
f6039334 | 521 | static host_t * get_destination(private_message_t *this) |
523526ec | 522 | { |
f6039334 | 523 | return this->packet->destination; |
523526ec MW |
524 | } |
525 | ||
27e43205 JH |
526 | /** |
527 | * Implementation of message_t.get_destination. | |
528 | */ | |
a0753941 | 529 | static iterator_t *get_payload_iterator(private_message_t *this) |
501a41b9 | 530 | { |
a0753941 | 531 | return this->payloads->create_iterator(this->payloads, TRUE); |
501a41b9 MW |
532 | } |
533 | ||
534 | ||
110dc83a | 535 | /** |
27e43205 | 536 | * Implementation of message_t.generate. |
110dc83a | 537 | */ |
81796a52 | 538 | static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* signer, packet_t **packet) |
110dc83a | 539 | { |
523526ec MW |
540 | generator_t *generator; |
541 | ike_header_t *ike_header; | |
542 | payload_t *payload, *next_payload; | |
bdb141cb | 543 | iterator_t *iterator; |
523526ec MW |
544 | status_t status; |
545 | ||
f6039334 JH |
546 | this->logger->log(this->logger, CONTROL, "Generating message of type %s, contains %d payloads", |
547 | mapping_find(exchange_type_m,this->exchange_type), | |
548 | this->payloads->get_count(this->payloads)); | |
e0d60939 | 549 | |
523526ec MW |
550 | if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) |
551 | { | |
668f9fcb MW |
552 | this->logger->log(this->logger, ERROR | MORE, "Exchange type %s is not defined", |
553 | mapping_find(exchange_type_m,this->exchange_type)); | |
523526ec MW |
554 | return INVALID_STATE; |
555 | } | |
556 | ||
557 | if (this->packet->source == NULL || | |
558 | this->packet->destination == NULL) | |
559 | { | |
668f9fcb MW |
560 | this->logger->log(this->logger, ERROR|MORE, "%s not defined", |
561 | !this->packet->source ? "source" : "destination"); | |
523526ec MW |
562 | return INVALID_STATE; |
563 | } | |
564 | ||
668f9fcb MW |
565 | /* set the rules for this messge */ |
566 | status = this->set_message_rule(this); | |
567 | if (status != SUCCESS) | |
568 | { | |
569 | this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", | |
570 | mapping_find(exchange_type_m,this->exchange_type), | |
571 | this->is_request ? "request" : "response"); | |
572 | return NOT_SUPPORTED; | |
573 | } | |
574 | ||
575 | ||
f6039334 | 576 | /* going to encrypt all content which have to be encrypted */ |
668f9fcb | 577 | status = this->encrypt_payloads(this, crypter, signer); |
f890d8fe JH |
578 | if (status != SUCCESS) |
579 | { | |
f6039334 | 580 | this->logger->log(this->logger, ERROR | MORE, "Could not encrypt payloads"); |
f890d8fe JH |
581 | return status; |
582 | } | |
583 | ||
81796a52 | 584 | /* build ike header */ |
523526ec | 585 | ike_header = ike_header_create(); |
27e43205 | 586 | |
523526ec | 587 | ike_header->set_exchange_type(ike_header, this->exchange_type); |
523526ec MW |
588 | ike_header->set_message_id(ike_header, this->message_id); |
589 | ike_header->set_response_flag(ike_header, !this->is_request); | |
7b3d1389 MW |
590 | ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); |
591 | ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id)); | |
592 | ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id)); | |
f890d8fe | 593 | |
523526ec MW |
594 | generator = generator_create(); |
595 | ||
596 | payload = (payload_t*)ike_header; | |
597 | ||
27e43205 | 598 | |
668f9fcb MW |
599 | /* generate every payload expect last one, this is doen later*/ |
600 | iterator = this->payloads->create_iterator(this->payloads, TRUE); | |
523526ec | 601 | while(iterator->has_next(iterator)) |
110dc83a | 602 | { |
523526ec MW |
603 | iterator->current(iterator, (void**)&next_payload); |
604 | payload->set_next_type(payload, next_payload->get_type(next_payload)); | |
0f30f568 | 605 | generator->generate_payload(generator, payload); |
523526ec | 606 | payload = next_payload; |
110dc83a | 607 | } |
523526ec MW |
608 | iterator->destroy(iterator); |
609 | ||
f6039334 | 610 | /* last payload has no next payload*/ |
523526ec | 611 | payload->set_next_type(payload, NO_PAYLOAD); |
f890d8fe | 612 | |
0f30f568 | 613 | generator->generate_payload(generator, payload); |
f6039334 | 614 | |
523526ec | 615 | ike_header->destroy(ike_header); |
81796a52 MW |
616 | |
617 | /* build packet */ | |
523526ec MW |
618 | if (this->packet->data.ptr != NULL) |
619 | { | |
f6039334 | 620 | this->logger->log(this->logger, CONTROL | MOST, "Replace last generated packet data"); |
523526ec MW |
621 | allocator_free(this->packet->data.ptr); |
622 | } | |
0f30f568 | 623 | generator->write_to_chunk(generator, &(this->packet->data)); |
81796a52 | 624 | generator->destroy(generator); |
523526ec | 625 | |
f6039334 | 626 | /* if last payload is of type encrypted, integrity checksum if necessary */ |
81796a52 MW |
627 | if (payload->get_type(payload) == ENCRYPTED) |
628 | { | |
f6039334 | 629 | this->logger->log(this->logger, CONTROL | MORE, "Build signature on whole message"); |
81796a52 MW |
630 | encryption_payload_t *encryption_payload = (encryption_payload_t*)payload; |
631 | status = encryption_payload->build_signature(encryption_payload, this->packet->data); | |
632 | if (status != SUCCESS) | |
633 | { | |
634 | return status; | |
635 | } | |
636 | } | |
e0d60939 | 637 | |
df3c59d0 MW |
638 | /* clone packet for caller */ |
639 | *packet = this->packet->clone(this->packet); | |
e0d60939 | 640 | |
668f9fcb MW |
641 | this->logger->log(this->logger, CONTROL, "Message of type %s generated successfully", |
642 | mapping_find(exchange_type_m,this->exchange_type)); | |
110dc83a JH |
643 | return SUCCESS; |
644 | } | |
645 | ||
5534ee84 JH |
646 | /** |
647 | * Implementation of message_t.get_packet. | |
648 | */ | |
649 | static packet_t *get_packet (private_message_t *this) | |
650 | { | |
651 | return this->packet->clone(this->packet); | |
652 | } | |
653 | ||
8d68033e JH |
654 | /** |
655 | * Implementation of message_t.get_packet_data. | |
656 | */ | |
657 | static chunk_t get_packet_data (private_message_t *this) | |
658 | { | |
659 | return allocator_clone_chunk(this->packet->data); | |
660 | } | |
661 | ||
91443667 | 662 | /** |
f6039334 | 663 | * Implementation of message_t.parse_header. |
91443667 | 664 | */ |
e0d60939 | 665 | static status_t parse_header(private_message_t *this) |
91443667 JH |
666 | { |
667 | ike_header_t *ike_header; | |
668 | status_t status; | |
669 | ||
e0d60939 | 670 | |
25c41f4d | 671 | this->logger->log(this->logger, CONTROL|MORE, "parsing Header of message"); |
e0d60939 | 672 | |
91443667 JH |
673 | this->parser->reset_context(this->parser); |
674 | status = this->parser->parse_payload(this->parser,HEADER,(payload_t **) &ike_header); | |
675 | if (status != SUCCESS) | |
676 | { | |
f6039334 | 677 | this->logger->log(this->logger, ERROR | MORE, "Header could not be parsed"); |
91443667 JH |
678 | return status; |
679 | ||
680 | } | |
2dbc3168 JH |
681 | |
682 | /* verify payload */ | |
683 | status = ike_header->payload_interface.verify(&(ike_header->payload_interface)); | |
684 | if (status != SUCCESS) | |
685 | { | |
f6039334 | 686 | this->logger->log(this->logger, ERROR | MORE, "Header verification failed"); |
b6b83651 | 687 | ike_header->destroy(ike_header); |
2dbc3168 JH |
688 | return status; |
689 | } | |
690 | ||
28c734d7 JH |
691 | if (this->ike_sa_id != NULL) |
692 | { | |
693 | this->ike_sa_id->destroy(this->ike_sa_id); | |
694 | } | |
28c734d7 | 695 | |
3a8f9f44 MW |
696 | this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header), |
697 | ike_header->get_responder_spi(ike_header), | |
e0d60939 | 698 | ike_header->get_initiator_flag(ike_header)); |
27e43205 | 699 | |
28c734d7 JH |
700 | this->exchange_type = ike_header->get_exchange_type(ike_header); |
701 | this->message_id = ike_header->get_message_id(ike_header); | |
93a9a115 | 702 | this->is_request = (!(ike_header->get_response_flag(ike_header))); |
9da406cf JH |
703 | this->major_version = ike_header->get_maj_version(ike_header); |
704 | this->minor_version = ike_header->get_min_version(ike_header); | |
705 | this->first_payload = ike_header->payload_interface.get_next_type(&(ike_header->payload_interface)); | |
706 | ||
668f9fcb MW |
707 | this->logger->log(this->logger, CONTROL, "Parsed a %s %s", |
708 | mapping_find(exchange_type_m, this->exchange_type), | |
25c41f4d | 709 | this->is_request ? "request" : "response"); |
e0d60939 | 710 | |
668f9fcb MW |
711 | ike_header->destroy(ike_header); |
712 | ||
713 | /* get the rules for this messge */ | |
714 | status = this->set_message_rule(this); | |
715 | if (status != SUCCESS) | |
716 | { | |
717 | this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", | |
718 | mapping_find(exchange_type_m,this->exchange_type), | |
719 | this->is_request ? "request" : "response"); | |
720 | } | |
721 | ||
722 | return status; | |
9da406cf JH |
723 | } |
724 | ||
725 | /** | |
f6039334 | 726 | * Implementation of message_t.parse_body. |
9da406cf | 727 | */ |
81796a52 | 728 | static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t *signer) |
9da406cf | 729 | { |
daa1c00e | 730 | status_t status = SUCCESS; |
668f9fcb MW |
731 | payload_type_t current_payload_type; |
732 | ||
733 | current_payload_type = this->first_payload; | |
e0d60939 | 734 | |
25c41f4d | 735 | this->logger->log(this->logger, CONTROL|MORE, "Parsing body of message, first payload %s", |
f6039334 | 736 | mapping_find(payload_type_m, current_payload_type)); |
d440fe6d | 737 | |
668f9fcb | 738 | /* parse payload for payload, while there are more available */ |
d440fe6d | 739 | while ((current_payload_type != NO_PAYLOAD)) |
28c734d7 | 740 | { |
9da406cf | 741 | payload_t *current_payload; |
be230691 | 742 | |
25c41f4d | 743 | this->logger->log(this->logger, CONTROL|MOST, "Start parsing payload of type %s", |
e0d60939 | 744 | mapping_find(payload_type_m, current_payload_type)); |
9da406cf | 745 | |
668f9fcb | 746 | /* parse current payload */ |
9da406cf | 747 | status = this->parser->parse_payload(this->parser,current_payload_type,(payload_t **) ¤t_payload); |
93a9a115 JH |
748 | if (status != SUCCESS) |
749 | { | |
f6039334 | 750 | this->logger->log(this->logger, ERROR, "Payload type %s could not be parsed",mapping_find(payload_type_m,current_payload_type)); |
81796a52 | 751 | return status; |
93a9a115 | 752 | } |
f6039334 JH |
753 | |
754 | this->logger->log(this->logger, CONTROL|MOST, "Verify payload of type %s", | |
755 | mapping_find(payload_type_m, current_payload_type)); | |
9da406cf | 756 | |
668f9fcb | 757 | /* verify it, stop parsig if its invalid */ |
2dbc3168 | 758 | status = current_payload->verify(current_payload); |
93a9a115 JH |
759 | if (status != SUCCESS) |
760 | { | |
f6039334 | 761 | this->logger->log(this->logger, ERROR, "Payload type %s could not be verified",mapping_find(payload_type_m,current_payload_type)); |
346af6f3 | 762 | current_payload->destroy(current_payload); |
2dbc3168 | 763 | status = VERIFY_ERROR; |
81796a52 MW |
764 | return status; |
765 | } | |
766 | ||
f6039334 JH |
767 | this->logger->log(this->logger, CONTROL|MOST, "Payload verified. Adding to payload list", |
768 | mapping_find(payload_type_m, current_payload_type)); | |
d048df5c | 769 | this->payloads->insert_last(this->payloads,current_payload); |
bc788302 | 770 | |
668f9fcb | 771 | /* an encryption payload is the last one, so STOP here. decryption is done later */ |
bc788302 MW |
772 | if (current_payload_type == ENCRYPTED) |
773 | { | |
f6039334 JH |
774 | this->logger->log(this->logger, CONTROL|MOST, "Payload of type encrypted found. Stop parsing.", |
775 | mapping_find(payload_type_m, current_payload_type)); | |
bc788302 MW |
776 | break; |
777 | } | |
778 | ||
779 | /* get next payload type */ | |
780 | current_payload_type = current_payload->get_next_type(current_payload); | |
28c734d7 | 781 | } |
25c41f4d MW |
782 | |
783 | this->logger->log(this->logger, CONTROL, "Message a %s %s contains %d payloads", | |
784 | mapping_find(exchange_type_m, this->exchange_type), | |
785 | this->is_request ? "request" : "response", | |
786 | this->payloads->get_count(this->payloads)); | |
f6039334 | 787 | |
668f9fcb MW |
788 | /* */ |
789 | if (current_payload_type == ENCRYPTED) | |
790 | status = this->decrypt_payloads(this,crypter,signer); | |
d440fe6d JH |
791 | if (status != SUCCESS) |
792 | { | |
668f9fcb | 793 | this->logger->log(this->logger, ERROR, "Could not decrypt payloads"); |
d440fe6d JH |
794 | return status; |
795 | } | |
796 | ||
668f9fcb MW |
797 | status = this->verify(this); |
798 | if (status != SUCCESS) | |
799 | { | |
800 | this->logger->log(this->logger, ERROR, "Verification of message failed"); | |
801 | } | |
802 | return status; | |
81796a52 MW |
803 | } |
804 | ||
805 | /** | |
668f9fcb | 806 | * Implementation of private_message_t.verify. |
81796a52 MW |
807 | */ |
808 | static status_t verify(private_message_t *this) | |
809 | { | |
81796a52 | 810 | int i; |
d440fe6d | 811 | iterator_t *iterator; |
ae3012a0 | 812 | size_t total_found_payloads = 0; |
81796a52 | 813 | |
f6039334 | 814 | this->logger->log(this->logger, CONTROL|MORE, "Verifying message structure"); |
ae3012a0 | 815 | |
a0753941 | 816 | iterator = this->payloads->create_iterator(this->payloads,TRUE); |
81796a52 | 817 | /* check for payloads with wrong count*/ |
668f9fcb | 818 | for (i = 0; i < this->message_rule->payload_rule_count;i++) |
81796a52 | 819 | { |
81796a52 | 820 | size_t found_payloads = 0; |
93a9a115 | 821 | |
f6039334 | 822 | /* check all payloads for specific rule */ |
81796a52 | 823 | iterator->reset(iterator); |
668f9fcb | 824 | |
81796a52 MW |
825 | while(iterator->has_next(iterator)) |
826 | { | |
827 | payload_t *current_payload; | |
668f9fcb MW |
828 | payload_type_t current_payload_type; |
829 | ||
27e43205 | 830 | iterator->current(iterator,(void **)¤t_payload); |
668f9fcb | 831 | current_payload_type = current_payload->get_type(current_payload); |
a0753941 | 832 | |
668f9fcb MW |
833 | if (current_payload_type == UNKNOWN_PAYLOAD) |
834 | { | |
835 | /* unknown payloads are ignored, IF they are not critical */ | |
836 | unknown_payload_t *unknown_payload = (unknown_payload_t*)current_payload; | |
837 | if (unknown_payload->is_critical(unknown_payload)) | |
838 | { | |
839 | this->logger->log(this->logger, ERROR, "%s (%d) is not supported, but its critical!", | |
840 | mapping_find(payload_type_m, current_payload_type), current_payload_type); | |
841 | iterator->destroy(iterator); | |
842 | return NOT_SUPPORTED; | |
843 | } | |
844 | } | |
845 | else if (current_payload_type == this->message_rule->payload_rules[i].payload_type) | |
93a9a115 | 846 | { |
81796a52 | 847 | found_payloads++; |
ae3012a0 | 848 | total_found_payloads++; |
bc788302 | 849 | this->logger->log(this->logger, CONTROL | MOST, "Found payload of type %s", |
668f9fcb MW |
850 | mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type)); |
851 | ||
f6039334 | 852 | /* as soon as ohe payload occures more then specified, the verification fails */ |
668f9fcb | 853 | if (found_payloads > this->message_rule->payload_rules[i].max_occurence) |
81796a52 MW |
854 | { |
855 | this->logger->log(this->logger, ERROR, "Payload of type %s more than %d times (%d) occured in current message", | |
668f9fcb MW |
856 | mapping_find(payload_type_m, current_payload_type), |
857 | this->message_rule->payload_rules[i].max_occurence, found_payloads); | |
93a9a115 | 858 | iterator->destroy(iterator); |
668f9fcb | 859 | return FAILED; |
81796a52 | 860 | } |
93a9a115 | 861 | } |
93a9a115 | 862 | } |
668f9fcb MW |
863 | |
864 | if (found_payloads < this->message_rule->payload_rules[i].min_occurence) | |
81796a52 | 865 | { |
f6039334 | 866 | this->logger->log(this->logger, ERROR, "Payload of type %s not occured %d times (%d)", |
668f9fcb MW |
867 | mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type), |
868 | this->message_rule->payload_rules[i].min_occurence, found_payloads); | |
81796a52 | 869 | iterator->destroy(iterator); |
668f9fcb | 870 | return FAILED; |
81796a52 | 871 | } |
668f9fcb | 872 | if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads)) |
ae3012a0 JH |
873 | { |
874 | iterator->destroy(iterator); | |
875 | return SUCCESS; | |
876 | } | |
93a9a115 | 877 | } |
81796a52 | 878 | iterator->destroy(iterator); |
81796a52 | 879 | return SUCCESS; |
91443667 JH |
880 | } |
881 | ||
882 | ||
f6039334 JH |
883 | /** |
884 | * Implementation of private_message_t.decrypt_and_verify_payloads. | |
885 | */ | |
668f9fcb | 886 | static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, signer_t* signer) |
d440fe6d JH |
887 | { |
888 | bool current_payload_was_encrypted = FALSE; | |
668f9fcb | 889 | payload_t *previous_payload = NULL; |
d440fe6d | 890 | int payload_number = 1; |
f6039334 JH |
891 | iterator_t *iterator; |
892 | status_t status; | |
d440fe6d JH |
893 | |
894 | iterator = this->payloads->create_iterator(this->payloads,TRUE); | |
895 | ||
f6039334 | 896 | /* process each payload and decrypt a encryption payload */ |
d440fe6d JH |
897 | while(iterator->has_next(iterator)) |
898 | { | |
668f9fcb | 899 | payload_rule_t *payload_rule; |
bc788302 | 900 | payload_type_t current_payload_type; |
f6039334 | 901 | payload_t *current_payload; |
d440fe6d JH |
902 | |
903 | /* get current payload */ | |
904 | iterator->current(iterator,(void **)¤t_payload); | |
905 | ||
f6039334 | 906 | /* needed to check */ |
bc788302 MW |
907 | current_payload_type = current_payload->get_type(current_payload); |
908 | ||
f6039334 | 909 | this->logger->log(this->logger, CONTROL | MOST, "Process payload of type %s",mapping_find(payload_type_m,current_payload_type)); |
63bfd6cc | 910 | |
bc788302 | 911 | if (current_payload_type == ENCRYPTED) |
d440fe6d JH |
912 | { |
913 | encryption_payload_t *encryption_payload; | |
d440fe6d | 914 | payload_t *current_encrypted_payload; |
bc788302 | 915 | |
668f9fcb | 916 | encryption_payload = (encryption_payload_t*)current_payload; |
bc788302 MW |
917 | |
918 | this->logger->log(this->logger, CONTROL | MORE, "Found an encryption payload"); | |
668f9fcb | 919 | |
d440fe6d JH |
920 | if (payload_number != this->payloads->get_count(this->payloads)) |
921 | { | |
668f9fcb | 922 | /* encrypted payload is not last one */ |
f6039334 | 923 | this->logger->log(this->logger, ERROR | MORE, "Encrypted payload is not last payload"); |
d440fe6d | 924 | iterator->destroy(iterator); |
d440fe6d JH |
925 | return FAILED; |
926 | } | |
668f9fcb | 927 | /* decrypt */ |
d440fe6d | 928 | encryption_payload->set_transforms(encryption_payload, crypter, signer); |
f6039334 | 929 | this->logger->log(this->logger, CONTROL | MORE, "Verify signature of encryption payload"); |
d440fe6d JH |
930 | status = encryption_payload->verify_signature(encryption_payload, this->packet->data); |
931 | if (status != SUCCESS) | |
932 | { | |
f6039334 | 933 | this->logger->log(this->logger, ERROR | MORE, "encryption payload signature invalid"); |
d440fe6d JH |
934 | iterator->destroy(iterator); |
935 | return status; | |
936 | } | |
f6039334 | 937 | this->logger->log(this->logger, CONTROL | MORE, "Decrypt content of encryption payload"); |
d440fe6d JH |
938 | status = encryption_payload->decrypt(encryption_payload); |
939 | if (status != SUCCESS) | |
940 | { | |
ccf783d2 MW |
941 | this->logger->log(this->logger, ERROR | MORE, "Encrypted payload could not be decrypted and parsed: %s", |
942 | mapping_find(status_m, status)); | |
d440fe6d JH |
943 | iterator->destroy(iterator); |
944 | return status; | |
945 | } | |
946 | ||
668f9fcb | 947 | /* needed later to find out if a payload was encrypted */ |
d440fe6d | 948 | current_payload_was_encrypted = TRUE; |
668f9fcb MW |
949 | |
950 | /* check if there are payloads contained in the encryption payload */ | |
bc788302 | 951 | if (encryption_payload->get_payload_count(encryption_payload) == 0) |
d440fe6d | 952 | { |
668f9fcb MW |
953 | this->logger->log(this->logger, CONTROL | MOST, "Encrypted payload is empty"); |
954 | /* remove the encryption payload, is not needed anymore */ | |
d440fe6d | 955 | iterator->remove(iterator); |
f6039334 | 956 | /* encrypted payload contains no other payload */ |
bc788302 | 957 | current_payload_type = NO_PAYLOAD; |
d440fe6d | 958 | } |
668f9fcb MW |
959 | else |
960 | { | |
961 | this->logger->log(this->logger, CONTROL | MOST, "Encrypted payload is not empty"); | |
962 | /* encryption_payload is replaced with first payload contained in encryption_payload */ | |
963 | encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); | |
964 | iterator->replace(iterator,NULL,(void *) current_encrypted_payload); | |
965 | current_payload_type = current_encrypted_payload->get_type(current_encrypted_payload); | |
966 | } | |
bc788302 | 967 | |
668f9fcb MW |
968 | /* is the current paylad the first in the message? */ |
969 | if (previous_payload == NULL) | |
bc788302 | 970 | { |
668f9fcb | 971 | /* yes, set the first payload type of the message to the current type */ |
bc788302 MW |
972 | this->first_payload = current_payload_type; |
973 | } | |
974 | else | |
975 | { | |
668f9fcb MW |
976 | /* no, set the next_type of the previous payload to the current type */ |
977 | previous_payload->set_next_type(previous_payload, current_payload_type); | |
bc788302 | 978 | } |
d440fe6d JH |
979 | |
980 | /* all encrypted payloads are added to the payload list */ | |
bc788302 | 981 | while (encryption_payload->get_payload_count(encryption_payload) > 0) |
d440fe6d | 982 | { |
bc788302 | 983 | encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); |
f8c6d7e4 | 984 | this->logger->log(this->logger, CONTROL | MORE, "Insert unencrypted payload of type %s at end of list.",mapping_find(payload_type_m,current_encrypted_payload->get_type(current_encrypted_payload))); |
d440fe6d JH |
985 | this->payloads->insert_last(this->payloads,current_encrypted_payload); |
986 | } | |
987 | ||
668f9fcb MW |
988 | /* encryption payload is processed, payloads are moved. Destroy it. */ |
989 | encryption_payload->destroy(encryption_payload); | |
d440fe6d JH |
990 | } |
991 | ||
668f9fcb MW |
992 | /* we allow unknown payloads of any type and don't bother if it was encrypted. Not our problem. */ |
993 | if (current_payload_type != UNKNOWN_PAYLOAD) | |
d440fe6d | 994 | { |
668f9fcb MW |
995 | /* get the ruleset for found payload */ |
996 | status = this->get_payload_rule(this, current_payload_type, &payload_rule); | |
997 | if (status != SUCCESS) | |
998 | { | |
999 | /* payload is not allowed */ | |
1000 | this->logger->log(this->logger, ERROR | MORE, "Payload type %s not allowed",mapping_find(payload_type_m,current_payload_type)); | |
1001 | iterator->destroy(iterator); | |
1002 | return status; | |
1003 | } | |
1004 | ||
1005 | /* check if the payload was encrypted, and if it should been have encrypted */ | |
1006 | if (payload_rule->encrypted != current_payload_was_encrypted) | |
1007 | { | |
1008 | /* payload was not encrypted, but should have been. or vice-versa */ | |
1009 | this->logger->log(this->logger, ERROR | MORE, "Payload type %s should be %s!", | |
1010 | mapping_find(payload_type_m,current_payload_type), | |
1011 | (payload_rule->encrypted) ? "encrypted": "not encrypted"); | |
1012 | iterator->destroy(iterator); | |
1013 | return FAILED; | |
1014 | } | |
d440fe6d | 1015 | } |
668f9fcb | 1016 | /* advance to the next payload */ |
d440fe6d | 1017 | payload_number++; |
f6039334 | 1018 | /* is stored to set next payload in case of found encryption payload */ |
668f9fcb | 1019 | previous_payload = current_payload; |
d440fe6d JH |
1020 | } |
1021 | iterator->destroy(iterator); | |
668f9fcb | 1022 | return SUCCESS; |
d440fe6d JH |
1023 | } |
1024 | ||
f6039334 JH |
1025 | /** |
1026 | * Implementation of private_message_t.encrypt_payloads. | |
1027 | */ | |
f890d8fe JH |
1028 | static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) |
1029 | { | |
f890d8fe | 1030 | encryption_payload_t *encryption_payload = NULL; |
f6039334 | 1031 | status_t status; |
d440fe6d | 1032 | linked_list_t *all_payloads; |
f890d8fe | 1033 | |
668f9fcb | 1034 | if (!this->message_rule->encrypted_content) |
d440fe6d | 1035 | { |
b09e85f9 | 1036 | this->logger->log(this->logger, CONTROL | MORE, "Message doesn't have to be encrypted"); |
d440fe6d JH |
1037 | /* message contains no content to encrypt */ |
1038 | return SUCCESS; | |
1039 | } | |
1040 | ||
f6039334 | 1041 | this->logger->log(this->logger, CONTROL | MOST, "Copy all payloads to a temporary list"); |
d440fe6d JH |
1042 | all_payloads = linked_list_create(); |
1043 | ||
f890d8fe JH |
1044 | /* first copy all payloads in a temporary list */ |
1045 | while (this->payloads->get_count(this->payloads) > 0) | |
1046 | { | |
1047 | void *current_payload; | |
1048 | this->payloads->remove_first(this->payloads,¤t_payload); | |
1049 | all_payloads->insert_last(all_payloads,current_payload); | |
1050 | } | |
f6039334 JH |
1051 | |
1052 | this->logger->log(this->logger, CONTROL | MOST, "Check each payloads if they have to get encrypted"); | |
f890d8fe JH |
1053 | while (all_payloads->get_count(all_payloads) > 0) |
1054 | { | |
668f9fcb | 1055 | payload_rule_t *payload_rule; |
f890d8fe JH |
1056 | payload_t *current_payload; |
1057 | bool to_encrypt = FALSE; | |
1058 | ||
1059 | all_payloads->remove_first(all_payloads,(void **)¤t_payload); | |
f6039334 | 1060 | this->logger->log(this->logger, CONTROL | MOST, "Get rule for payload %s", mapping_find(payload_type_m,current_payload->get_type(current_payload))); |
f890d8fe | 1061 | |
668f9fcb | 1062 | status = this->get_payload_rule(this,current_payload->get_type(current_payload),&payload_rule); |
d440fe6d JH |
1063 | /* for payload types which are not found in supported payload list, it is presumed |
1064 | * that they don't have to be encrypted */ | |
668f9fcb | 1065 | if ((status == SUCCESS) && (payload_rule->encrypted)) |
f890d8fe | 1066 | { |
f6039334 JH |
1067 | this->logger->log(this->logger, CONTROL | MOST, "Payload %s has to get encrypted", |
1068 | mapping_find(payload_type_m,current_payload->get_type(current_payload))); | |
d440fe6d | 1069 | to_encrypt = TRUE; |
f890d8fe | 1070 | } |
f6039334 JH |
1071 | else if (status != SUCCESS) |
1072 | { | |
1073 | this->logger->log(this->logger, CONTROL | MOST, "Payload %s not defined for exchange type %s. Handle it anyway", | |
1074 | mapping_find(payload_type_m,current_payload->get_type(current_payload)), | |
1075 | mapping_find(exchange_type_m,this->exchange_type)); | |
1076 | } | |
f890d8fe JH |
1077 | |
1078 | if (to_encrypt) | |
1079 | { | |
1080 | if (encryption_payload == NULL) | |
1081 | { | |
1082 | encryption_payload = encryption_payload_create(); | |
1083 | } | |
f6039334 JH |
1084 | this->logger->log(this->logger, CONTROL | MOST, "Insert payload %s to encryption payload", |
1085 | mapping_find(payload_type_m,current_payload->get_type(current_payload))); | |
1086 | ||
f890d8fe JH |
1087 | encryption_payload->add_payload(encryption_payload,current_payload); |
1088 | } | |
1089 | else | |
1090 | { | |
f6039334 JH |
1091 | this->logger->log(this->logger, CONTROL | MOST, "Insert payload %s as payload wich does not have to be encrypted", |
1092 | mapping_find(payload_type_m,current_payload->get_type(current_payload))); | |
bc788302 | 1093 | this->public.add_payload(&(this->public), (payload_t*)encryption_payload); |
f890d8fe JH |
1094 | } |
1095 | } | |
1096 | ||
1097 | status = SUCCESS; | |
1098 | if (encryption_payload != NULL) | |
1099 | { | |
f6039334 | 1100 | this->logger->log(this->logger, CONTROL | MOST, "Set transforms for encryption payload "); |
f890d8fe | 1101 | encryption_payload->set_transforms(encryption_payload,crypter,signer); |
f6039334 | 1102 | this->logger->log(this->logger, CONTROL | MORE, "Encrypt all payloads of encrypted payload"); |
f890d8fe | 1103 | status = encryption_payload->encrypt(encryption_payload); |
f6039334 | 1104 | this->logger->log(this->logger, CONTROL | MOST, "Add encrypted payload to payload list"); |
ee29afd4 | 1105 | this->public.add_payload(&(this->public), (payload_t*)encryption_payload); |
f890d8fe JH |
1106 | } |
1107 | ||
1108 | all_payloads->destroy(all_payloads); | |
1109 | ||
1110 | return status; | |
1111 | } | |
1112 | ||
f6039334 | 1113 | |
ca6dd4f6 | 1114 | /** |
f6039334 | 1115 | * Implementation of message_t.destroy. |
ca6dd4f6 | 1116 | */ |
27e43205 | 1117 | static void destroy (private_message_t *this) |
ca6dd4f6 | 1118 | { |
bdb141cb | 1119 | iterator_t *iterator; |
523526ec | 1120 | |
668f9fcb | 1121 | this->logger->log(this->logger, CONTROL|ALL, "Going to destroy message_t object"); |
f6039334 | 1122 | |
55f90b5d JH |
1123 | this->packet->destroy(this->packet); |
1124 | ||
525250c6 JH |
1125 | if (this->ike_sa_id != NULL) |
1126 | { | |
1127 | this->ike_sa_id->destroy(this->ike_sa_id); | |
1128 | } | |
523526ec | 1129 | |
a0753941 | 1130 | iterator = this->payloads->create_iterator(this->payloads, TRUE); |
523526ec MW |
1131 | while (iterator->has_next(iterator)) |
1132 | { | |
1133 | payload_t *payload; | |
1134 | iterator->current(iterator, (void**)&payload); | |
668f9fcb | 1135 | this->logger->log(this->logger, CONTROL|ALL, "Destroying payload of type %s", |
e0d60939 | 1136 | mapping_find(payload_type_m, payload->get_type(payload))); |
523526ec MW |
1137 | payload->destroy(payload); |
1138 | } | |
1139 | iterator->destroy(iterator); | |
c64d7032 | 1140 | this->payloads->destroy(this->payloads); |
9da406cf | 1141 | this->parser->destroy(this->parser); |
0e96f7d8 | 1142 | charon->logger_manager->destroy_logger(charon->logger_manager, this->logger); |
93a9a115 | 1143 | |
31332efa | 1144 | allocator_free(this); |
ca6dd4f6 JH |
1145 | } |
1146 | ||
1147 | /* | |
1148 | * Described in Header-File | |
1149 | */ | |
c64d7032 | 1150 | message_t *message_create_from_packet(packet_t *packet) |
ca6dd4f6 | 1151 | { |
6c4b815f | 1152 | private_message_t *this = allocator_alloc_thing(private_message_t); |
79538669 | 1153 | |
c64d7032 | 1154 | /* public functions */ |
27e43205 | 1155 | this->public.set_major_version = (void(*)(message_t*, u_int8_t))set_major_version; |
9da406cf | 1156 | this->public.get_major_version = (u_int8_t(*)(message_t*))get_major_version; |
27e43205 | 1157 | this->public.set_minor_version = (void(*)(message_t*, u_int8_t))set_minor_version; |
9da406cf | 1158 | this->public.get_minor_version = (u_int8_t(*)(message_t*))get_minor_version; |
27e43205 | 1159 | this->public.set_message_id = (void(*)(message_t*, u_int32_t))set_message_id; |
525250c6 | 1160 | this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id; |
21981473 | 1161 | this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi; |
27e43205 | 1162 | this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id; |
525250c6 | 1163 | this->public.get_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t **))get_ike_sa_id; |
27e43205 | 1164 | this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type; |
110dc83a | 1165 | this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type; |
27e43205 | 1166 | this->public.set_request = (void(*)(message_t*, bool))set_request; |
110dc83a | 1167 | this->public.get_request = (bool(*)(message_t*))get_request; |
27e43205 | 1168 | this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload; |
81796a52 | 1169 | this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate; |
27e43205 | 1170 | this->public.set_source = (void (*) (message_t*,host_t*)) set_source; |
f6039334 | 1171 | this->public.get_source = (host_t * (*) (message_t*)) get_source; |
27e43205 | 1172 | this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination; |
f6039334 | 1173 | this->public.get_destination = (host_t * (*) (message_t*)) get_destination; |
a0753941 | 1174 | this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator; |
81796a52 MW |
1175 | this->public.parse_header = (status_t (*) (message_t *)) parse_header; |
1176 | this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body; | |
5534ee84 | 1177 | this->public.get_packet = (packet_t * (*) (message_t*)) get_packet; |
8d68033e | 1178 | this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data; |
27e43205 | 1179 | this->public.destroy = (void(*)(message_t*))destroy; |
110dc83a | 1180 | |
f890d8fe | 1181 | /* private values */ |
523526ec | 1182 | this->exchange_type = EXCHANGE_TYPE_UNDEFINED; |
110dc83a | 1183 | this->is_request = TRUE; |
525250c6 | 1184 | this->ike_sa_id = NULL; |
9da406cf | 1185 | this->first_payload = NO_PAYLOAD; |
525250c6 | 1186 | this->message_id = 0; |
ca6dd4f6 | 1187 | |
93a9a115 | 1188 | /* private functions */ |
668f9fcb MW |
1189 | this->set_message_rule = set_message_rule; |
1190 | this->get_payload_rule = get_payload_rule; | |
f890d8fe | 1191 | this->encrypt_payloads = encrypt_payloads; |
668f9fcb MW |
1192 | this->decrypt_payloads = decrypt_payloads; |
1193 | this->verify = verify; | |
93a9a115 | 1194 | |
c64d7032 | 1195 | /* private values */ |
523526ec MW |
1196 | if (packet == NULL) |
1197 | { | |
1198 | packet = packet_create(); | |
1199 | } | |
668f9fcb | 1200 | this->message_rule = NULL; |
c64d7032 JH |
1201 | this->packet = packet; |
1202 | this->payloads = linked_list_create(); | |
91443667 JH |
1203 | |
1204 | /* parser is created from data of packet */ | |
1205 | this->parser = parser_create(this->packet->data); | |
523526ec | 1206 | |
0e96f7d8 | 1207 | this->logger = charon->logger_manager->create_logger(charon->logger_manager, MESSAGE, NULL); |
79538669 JH |
1208 | |
1209 | return (&this->public); | |
ca6dd4f6 | 1210 | } |
c64d7032 JH |
1211 | |
1212 | /* | |
f6039334 | 1213 | * Described in Header. |
c64d7032 JH |
1214 | */ |
1215 | message_t *message_create() | |
1216 | { | |
1217 | return message_create_from_packet(NULL); | |
1218 | } | |
f6ba78c3 JH |
1219 | |
1220 | /* | |
1221 | * Described in Header. | |
1222 | */ | |
1223 | message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type) | |
1224 | { | |
1225 | message_t *message = message_create_from_packet(NULL); | |
1226 | notify_payload_t *payload; | |
1227 | ||
1228 | message->set_source(message, source->clone(source)); | |
1229 | message->set_destination(message, destination->clone(destination)); | |
1230 | message->set_exchange_type(message, exchange_type); | |
1231 | message->set_request(message, FALSE); | |
1232 | message->set_message_id(message,0); | |
1233 | message->set_ike_sa_id(message, ike_sa_id); | |
1234 | ||
1235 | payload = notify_payload_create_from_protocol_and_type(IKE,notify_type); | |
1236 | message->add_payload(message,(payload_t *) payload); | |
1237 | ||
1238 | return message; | |
1239 | } |