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