DBG1 level for 'peer supports MOBIKE' debug message
[strongswan.git] / src / charon / encoding / payloads / notify_payload.c
1 /**
2 * @file notify_payload.c
3 *
4 * @brief Implementation of notify_payload_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <stddef.h>
26
27 #include "notify_payload.h"
28
29 #include <daemon.h>
30 #include <encoding/payloads/encodings.h>
31 #include <crypto/hashers/hasher.h>
32
33 ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
34 "UNSUPPORTED_CRITICAL_PAYLOAD");
35 ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
36 "INVALID_IKE_SPI",
37 "INVALID_MAJOR_VERSION");
38 ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
39 "INVALID_SYNTAX");
40 ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
41 "INVALID_MESSAGE_ID");
42 ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
43 "INVALID_SPI");
44 ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
45 "NO_PROPOSAL_CHOSEN");
46 ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
47 "INVALID_KE_PAYLOAD");
48 ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
49 "AUTHENTICATION_FAILED");
50 ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED, AUTHENTICATION_FAILED,
51 "SINGLE_PAIR_REQUIRED",
52 "NO_ADDITIONAL_SAS",
53 "INTERNAL_ADDRESS_FAILURE",
54 "FAILED_CP_REQUIRED",
55 "TS_UNACCEPTABLE",
56 "INVALID_SELECTORS",
57 "UNACCEPTABLE_ADDRESSES",
58 "UNEXPECTED_NAT_DETECTED");
59 ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, UNEXPECTED_NAT_DETECTED,
60 "INITIAL_CONTACT",
61 "SET_WINDOW_SIZE",
62 "ADDITIONAL_TS_POSSIBLE",
63 "IPCOMP_SUPPORTED",
64 "NAT_DETECTION_SOURCE_IP",
65 "NAT_DETECTION_DESTINATION_IP",
66 "COOKIE",
67 "USE_TRANSPORT_MODE",
68 "HTTP_CERT_LOOKUP_SUPPORTED",
69 "REKEY_SA",
70 "ESP_TFC_PADDING_NOT_SUPPORTED",
71 "NON_FIRST_FRAGMENTS_ALSO",
72 "MOBIKE_SUPPORTED",
73 "ADDITIONAL_IP4_ADDRESS",
74 "ADDITIONAL_IP6_ADDRESS",
75 "NO_ADDITIONAL_ADDRESSES",
76 "UPDATE_SA_ADDRESSES",
77 "COOKIE2",
78 "NO_NATS_ALLOWED",
79 "AUTH_LIFETIME");
80 ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, AUTH_LIFETIME,
81 "EAP_ONLY_AUTHENTICATION");
82 ENUM_END(notify_type_names, EAP_ONLY_AUTHENTICATION);
83
84 typedef struct private_notify_payload_t private_notify_payload_t;
85
86 /**
87 * Private data of an notify_payload_t object.
88 *
89 */
90 struct private_notify_payload_t {
91 /**
92 * Public notify_payload_t interface.
93 */
94 notify_payload_t public;
95
96 /**
97 * Next payload type.
98 */
99 u_int8_t next_payload;
100
101 /**
102 * Critical flag.
103 */
104 bool critical;
105
106 /**
107 * Length of this payload.
108 */
109 u_int16_t payload_length;
110
111 /**
112 * Protocol id.
113 */
114 u_int8_t protocol_id;
115
116 /**
117 * Spi size.
118 */
119 u_int8_t spi_size;
120
121 /**
122 * Notify message type.
123 */
124 u_int16_t notify_type;
125
126 /**
127 * Security parameter index (spi).
128 */
129 chunk_t spi;
130
131 /**
132 * Notification data.
133 */
134 chunk_t notification_data;
135 };
136
137 /**
138 * Encoding rules to parse or generate a IKEv2-Notify Payload.
139 *
140 * The defined offsets are the positions in a object of type
141 * private_notify_payload_t.
142 *
143 */
144 encoding_rule_t notify_payload_encodings[] = {
145 /* 1 Byte next payload type, stored in the field next_payload */
146 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
147 /* the critical bit */
148 { FLAG, offsetof(private_notify_payload_t, critical) },
149 /* 7 Bit reserved bits, nowhere stored */
150 { RESERVED_BIT, 0 },
151 { RESERVED_BIT, 0 },
152 { RESERVED_BIT, 0 },
153 { RESERVED_BIT, 0 },
154 { RESERVED_BIT, 0 },
155 { RESERVED_BIT, 0 },
156 { RESERVED_BIT, 0 },
157 /* Length of the whole payload*/
158 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
159 /* Protocol ID as 8 bit field*/
160 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
161 /* SPI Size as 8 bit field*/
162 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
163 /* Notify message type as 16 bit field*/
164 { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
165 /* SPI as variable length field*/
166 { SPI, offsetof(private_notify_payload_t, spi) },
167 /* Key Exchange Data is from variable size */
168 { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
169 };
170
171 /*
172 1 2 3
173 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
174 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 ! Next Payload !C! RESERVED ! Payload Length !
176 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 ! Protocol ID ! SPI Size ! Notify Message Type !
178 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 ! !
180 ~ Security Parameter Index (SPI) ~
181 ! !
182 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183 ! !
184 ~ Notification Data ~
185 ! !
186 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187 */
188
189 /**
190 * Implementation of payload_t.verify.
191 */
192 static status_t verify(private_notify_payload_t *this)
193 {
194 bool bad_length = FALSE;
195
196 switch (this->protocol_id)
197 {
198 case PROTO_NONE:
199 case PROTO_IKE:
200 case PROTO_AH:
201 case PROTO_ESP:
202 break;
203 default:
204 DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
205 return FAILED;
206 }
207
208 switch (this->notify_type)
209 {
210 case INVALID_KE_PAYLOAD:
211 {
212 if (this->notification_data.len != 2)
213 {
214 bad_length = TRUE;
215 }
216 break;
217 }
218 case NAT_DETECTION_SOURCE_IP:
219 case NAT_DETECTION_DESTINATION_IP:
220 {
221 if (this->notification_data.len != HASH_SIZE_SHA1)
222 {
223 bad_length = TRUE;
224 }
225 break;
226 }
227 case INVALID_SYNTAX:
228 case INVALID_MAJOR_VERSION:
229 case NO_PROPOSAL_CHOSEN:
230 {
231 if (this->notification_data.len != 0)
232 {
233 bad_length = TRUE;
234 }
235 break;
236 }
237 case ADDITIONAL_IP4_ADDRESS:
238 {
239 if (this->notification_data.len != 4)
240 {
241 bad_length = TRUE;
242 }
243 break;
244 }
245 case ADDITIONAL_IP6_ADDRESS:
246 {
247 if (this->notification_data.len != 16)
248 {
249 bad_length = TRUE;
250 }
251 break;
252 }
253 default:
254 /* TODO: verify */
255 break;
256 }
257 if (bad_length)
258 {
259 DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
260 notify_type_names, this->notify_type,
261 this->notification_data.len);
262 return FAILED;
263 }
264 return SUCCESS;
265 }
266
267 /**
268 * Implementation of payload_t.get_encoding_rules.
269 */
270 static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
271 {
272 *rules = notify_payload_encodings;
273 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
274 }
275
276 /**
277 * Implementation of payload_t.get_type.
278 */
279 static payload_type_t get_type(private_notify_payload_t *this)
280 {
281 return NOTIFY;
282 }
283
284 /**
285 * Implementation of payload_t.get_next_type.
286 */
287 static payload_type_t get_next_type(private_notify_payload_t *this)
288 {
289 return (this->next_payload);
290 }
291
292 /**
293 * Implementation of payload_t.set_next_type.
294 */
295 static void set_next_type(private_notify_payload_t *this,payload_type_t type)
296 {
297 this->next_payload = type;
298 }
299
300 /**
301 * recompute the payloads length.
302 */
303 static void compute_length (private_notify_payload_t *this)
304 {
305 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
306 if (this->notification_data.ptr != NULL)
307 {
308 length += this->notification_data.len;
309 }
310 if (this->spi.ptr != NULL)
311 {
312 length += this->spi.len;
313 }
314 this->payload_length = length;
315 }
316
317 /**
318 * Implementation of payload_t.get_length.
319 */
320 static size_t get_length(private_notify_payload_t *this)
321 {
322 compute_length(this);
323 return this->payload_length;
324 }
325
326 /**
327 * Implementation of notify_payload_t.get_protocol_id.
328 */
329 static u_int8_t get_protocol_id(private_notify_payload_t *this)
330 {
331 return this->protocol_id;
332 }
333
334 /**
335 * Implementation of notify_payload_t.set_protocol_id.
336 */
337 static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
338 {
339 this->protocol_id = protocol_id;
340 }
341
342 /**
343 * Implementation of notify_payload_t.get_notify_type.
344 */
345 static notify_type_t get_notify_type(private_notify_payload_t *this)
346 {
347 return this->notify_type;
348 }
349
350 /**
351 * Implementation of notify_payload_t.set_notify_type.
352 */
353 static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
354 {
355 this->notify_type = notify_type;
356 }
357
358 /**
359 * Implementation of notify_payload_t.get_spi.
360 */
361 static u_int32_t get_spi(private_notify_payload_t *this)
362 {
363 switch (this->protocol_id)
364 {
365 case PROTO_AH:
366 case PROTO_ESP:
367 if (this->spi.len == 4)
368 {
369 return *((u_int32_t*)this->spi.ptr);
370 }
371 default:
372 break;
373 }
374 return 0;
375 }
376
377 /**
378 * Implementation of notify_payload_t.set_spi.
379 */
380 static void set_spi(private_notify_payload_t *this, u_int32_t spi)
381 {
382 chunk_free(&this->spi);
383 switch (this->protocol_id)
384 {
385 case PROTO_AH:
386 case PROTO_ESP:
387 this->spi = chunk_alloc(4);
388 *((u_int32_t*)this->spi.ptr) = spi;
389 break;
390 default:
391 break;
392 }
393 this->spi_size = this->spi.len;
394 compute_length(this);
395 }
396
397 /**
398 * Implementation of notify_payload_t.get_notification_data.
399 */
400 static chunk_t get_notification_data(private_notify_payload_t *this)
401 {
402 return (this->notification_data);
403 }
404
405 /**
406 * Implementation of notify_payload_t.set_notification_data.
407 */
408 static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
409 {
410 chunk_free(&this->notification_data);
411 if (notification_data.len > 0)
412 {
413 this->notification_data = chunk_clone(notification_data);
414 }
415 compute_length(this);
416 return SUCCESS;
417 }
418
419 /**
420 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
421 */
422 static status_t destroy(private_notify_payload_t *this)
423 {
424 chunk_free(&this->notification_data);
425 chunk_free(&this->spi);
426 free(this);
427 return SUCCESS;
428 }
429
430 /*
431 * Described in header
432 */
433 notify_payload_t *notify_payload_create()
434 {
435 private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
436
437 /* interface functions */
438 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
439 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
440 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
441 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
442 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
443 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
444 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
445
446 /* public functions */
447 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
448 this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
449 this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
450 this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
451 this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
452 this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
453 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
454 this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
455 this->public.destroy = (void (*) (notify_payload_t *)) destroy;
456
457 /* set default values of the fields */
458 this->critical = FALSE;
459 this->next_payload = NO_PAYLOAD;
460 this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
461 this->protocol_id = 0;
462 this->notify_type = 0;
463 this->spi.ptr = NULL;
464 this->spi.len = 0;
465 this->spi_size = 0;
466 this->notification_data.ptr = NULL;
467 this->notification_data.len = 0;
468
469 return &this->public;
470 }
471
472 /*
473 * Described in header.
474 */
475 notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
476 {
477 notify_payload_t *notify = notify_payload_create();
478
479 notify->set_notify_type(notify,notify_type);
480 notify->set_protocol_id(notify,protocol_id);
481
482 return notify;
483 }