fef2949d31faa04b8f7b12a172efe21e642e91e3
[strongswan.git] / src / libcharon / encoding / payloads / notify_payload.c
1 /*
2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2006-2008 Tobias Brunner
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * Hochschule fuer Technik Rapperswil
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20 #include <stddef.h>
21
22 #include "notify_payload.h"
23
24 #include <daemon.h>
25 #include <encoding/payloads/encodings.h>
26 #include <crypto/hashers/hasher.h>
27
28 ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
29 "UNSUPPORTED_CRITICAL_PAYLOAD");
30 ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
31 "INVALID_IKE_SPI",
32 "INVALID_MAJOR_VERSION");
33 ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
34 "INVALID_SYNTAX");
35 ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
36 "INVALID_MESSAGE_ID");
37 ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
38 "INVALID_SPI");
39 ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
40 "NO_PROPOSAL_CHOSEN");
41 ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
42 "INVALID_KE_PAYLOAD");
43 ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
44 "AUTHENTICATION_FAILED");
45 ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
46 "SINGLE_PAIR_REQUIRED",
47 "NO_ADDITIONAL_SAS",
48 "INTERNAL_ADDRESS_FAILURE",
49 "FAILED_CP_REQUIRED",
50 "TS_UNACCEPTABLE",
51 "INVALID_SELECTORS",
52 "UNACCEPTABLE_ADDRESSES",
53 "UNEXPECTED_NAT_DETECTED",
54 "USE_ASSIGNED_HoA",
55 "TEMPORARY_FAILURE",
56 "CHILD_SA_NOT_FOUND");
57 ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_FOUND,
58 "ME_CONNECT_FAILED");
59 ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
60 "MS_NOTIFY_STATUS");
61 ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
62 "INITIAL_CONTACT",
63 "SET_WINDOW_SIZE",
64 "ADDITIONAL_TS_POSSIBLE",
65 "IPCOMP_SUPPORTED",
66 "NAT_DETECTION_SOURCE_IP",
67 "NAT_DETECTION_DESTINATION_IP",
68 "COOKIE",
69 "USE_TRANSPORT_MODE",
70 "HTTP_CERT_LOOKUP_SUPPORTED",
71 "REKEY_SA",
72 "ESP_TFC_PADDING_NOT_SUPPORTED",
73 "NON_FIRST_FRAGMENTS_ALSO",
74 "MOBIKE_SUPPORTED",
75 "ADDITIONAL_IP4_ADDRESS",
76 "ADDITIONAL_IP6_ADDRESS",
77 "NO_ADDITIONAL_ADDRESSES",
78 "UPDATE_SA_ADDRESSES",
79 "COOKIE2",
80 "NO_NATS_ALLOWED",
81 "AUTH_LIFETIME",
82 "MULTIPLE_AUTH_SUPPORTED",
83 "ANOTHER_AUTH_FOLLOWS",
84 "REDIRECT_SUPPORTED",
85 "REDIRECT",
86 "REDIRECTED_FROM",
87 "TICKET_LT_OPAQUE",
88 "TICKET_REQUEST",
89 "TICKET_ACK",
90 "TICKET_NACK",
91 "TICKET_OPAQUE",
92 "LINK_ID",
93 "USE_WESP_MODE",
94 "ROHC_SUPPORTED",
95 "EAP_ONLY_AUTHENTICATION",
96 "CHILDLESS_IKEV2_SUPPORTED",
97 "QUICK_CRASH_DETECTION",
98 "IKEV2_MESSAGE_ID_SYNC_SUPPORTED",
99 "IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
100 "IKEV2_MESSAGE_ID_SYNC",
101 "IPSEC_REPLAY_COUNTER_SYNC");
102 ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC,
103 "USE_BEET_MODE");
104 ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
105 "ME_MEDIATION",
106 "ME_ENDPOINT",
107 "ME_CALLBACK",
108 "ME_CONNECTID",
109 "ME_CONNECTKEY",
110 "ME_CONNECTAUTH",
111 "ME_RESPONSE",
112 "RADIUS_ATTRIBUTE",);
113 ENUM_END(notify_type_names, RADIUS_ATTRIBUTE);
114
115
116 ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
117 "CRIT");
118 ENUM_NEXT(notify_type_short_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
119 "INVAL_IKE_SPI",
120 "INVAL_MAJOR");
121 ENUM_NEXT(notify_type_short_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
122 "INVAL_SYN");
123 ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
124 "INVAL_MID");
125 ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
126 "INVAL_SPI");
127 ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
128 "NO_PROP");
129 ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
130 "INVAL_KE");
131 ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
132 "AUTH_FAILED");
133 ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
134 "SINGLE_PAIR",
135 "NO_ADD_SAS",
136 "INT_ADDR_FAIL",
137 "FAIL_CP_REQ",
138 "TS_UNACCEPT",
139 "INVAL_SEL",
140 "UNACCEPT_ADDR",
141 "UNEXPECT_NAT",
142 "ASSIGNED_HoA",
143 "TEMP_FAIL",
144 "NO_CHILD_SA");
145 ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_FOUND,
146 "ME_CONN_FAIL");
147 ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
148 "MS_STATUS");
149 ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTIFY_STATUS,
150 "INIT_CONTACT",
151 "SET_WINSIZE",
152 "ADD_TS_POSS",
153 "IPCOMP_SUP",
154 "NATD_S_IP",
155 "NATD_D_IP",
156 "COOKIE",
157 "USE_TRANSP",
158 "HTTP_CERT_LOOK",
159 "REKEY_SA",
160 "ESP_TFC_PAD_N",
161 "NON_FIRST_FRAG",
162 "MOBIKE_SUP",
163 "ADD_4_ADDR",
164 "ADD_6_ADDR",
165 "NO_ADD_ADDR",
166 "UPD_SA_ADDR",
167 "COOKIE2",
168 "NO_NATS",
169 "AUTH_LFT",
170 "MULT_AUTH",
171 "AUTH_FOLLOWS",
172 "REDIR_SUP",
173 "REDIR",
174 "REDIR_FROM",
175 "TKT_LT_OPAK",
176 "TKT_REQ",
177 "TKT_ACK",
178 "TKT_NACK",
179 "TKT_OPAK",
180 "LINK_ID",
181 "WESP_MODE",
182 "ROHC_SUP",
183 "EAP_ONLY",
184 "CHDLESS_SUP",
185 "CRASH_DET",
186 "MSG_ID_SYN_SUP",
187 "RPL_CTR_SYN_SUP",
188 "MSG_ID_SYN",
189 "RPL_CTR_SYN");
190 ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC,
191 "BEET_MODE");
192 ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
193 "ME_MED",
194 "ME_EP",
195 "ME_CB",
196 "ME_CID",
197 "ME_CKEY",
198 "ME_CAUTH",
199 "ME_R",
200 "RADIUS");
201 ENUM_END(notify_type_short_names, RADIUS_ATTRIBUTE);
202
203
204 typedef struct private_notify_payload_t private_notify_payload_t;
205
206 /**
207 * Private data of an notify_payload_t object.
208 */
209 struct private_notify_payload_t {
210
211 /**
212 * Public notify_payload_t interface.
213 */
214 notify_payload_t public;
215
216 /**
217 * Next payload type.
218 */
219 u_int8_t next_payload;
220
221 /**
222 * Critical flag.
223 */
224 bool critical;
225
226 /**
227 * reserved bits
228 */
229 bool reserved[7];
230
231 /**
232 * Length of this payload.
233 */
234 u_int16_t payload_length;
235
236 /**
237 * Protocol id.
238 */
239 u_int8_t protocol_id;
240
241 /**
242 * Spi size.
243 */
244 u_int8_t spi_size;
245
246 /**
247 * Notify message type.
248 */
249 u_int16_t notify_type;
250
251 /**
252 * Security parameter index (spi).
253 */
254 chunk_t spi;
255
256 /**
257 * Notification data.
258 */
259 chunk_t notification_data;
260 };
261
262 /**
263 * Encoding rules to parse or generate a IKEv2-Notify Payload.
264 *
265 * The defined offsets are the positions in a object of type
266 * private_notify_payload_t.
267 */
268 encoding_rule_t notify_payload_encodings[] = {
269 /* 1 Byte next payload type, stored in the field next_payload */
270 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
271 /* the critical bit */
272 { FLAG, offsetof(private_notify_payload_t, critical) },
273 /* 7 Bit reserved bits, nowhere stored */
274 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
275 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
276 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
277 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
278 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
279 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
280 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
281 /* Length of the whole payload*/
282 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
283 /* Protocol ID as 8 bit field*/
284 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
285 /* SPI Size as 8 bit field*/
286 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
287 /* Notify message type as 16 bit field*/
288 { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
289 /* SPI as variable length field*/
290 { SPI, offsetof(private_notify_payload_t, spi) },
291 /* Key Exchange Data is from variable size */
292 { NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) }
293 };
294
295 /*
296 1 2 3
297 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
298 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
299 ! Next Payload !C! RESERVED ! Payload Length !
300 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
301 ! Protocol ID ! SPI Size ! Notify Message Type !
302 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303 ! !
304 ~ Security Parameter Index (SPI) ~
305 ! !
306 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307 ! !
308 ~ Notification Data ~
309 ! !
310 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311 */
312
313 METHOD(payload_t, verify, status_t,
314 private_notify_payload_t *this)
315 {
316 bool bad_length = FALSE;
317
318 switch (this->protocol_id)
319 {
320 case PROTO_NONE:
321 case PROTO_IKE:
322 case PROTO_AH:
323 case PROTO_ESP:
324 break;
325 default:
326 DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
327 return FAILED;
328 }
329
330 switch (this->notify_type)
331 {
332 case INVALID_KE_PAYLOAD:
333 {
334 if (this->notification_data.len != 2)
335 {
336 bad_length = TRUE;
337 }
338 break;
339 }
340 case NAT_DETECTION_SOURCE_IP:
341 case NAT_DETECTION_DESTINATION_IP:
342 case ME_CONNECTAUTH:
343 {
344 if (this->notification_data.len != HASH_SIZE_SHA1)
345 {
346 bad_length = TRUE;
347 }
348 break;
349 }
350 case INVALID_SYNTAX:
351 case INVALID_MAJOR_VERSION:
352 case NO_PROPOSAL_CHOSEN:
353 {
354 if (this->notification_data.len != 0)
355 {
356 bad_length = TRUE;
357 }
358 break;
359 }
360 case ADDITIONAL_IP4_ADDRESS:
361 {
362 if (this->notification_data.len != 4)
363 {
364 bad_length = TRUE;
365 }
366 break;
367 }
368 case ADDITIONAL_IP6_ADDRESS:
369 {
370 if (this->notification_data.len != 16)
371 {
372 bad_length = TRUE;
373 }
374 break;
375 }
376 case AUTH_LIFETIME:
377 {
378 if (this->notification_data.len != 4)
379 {
380 bad_length = TRUE;
381 }
382 break;
383 }
384 case IPCOMP_SUPPORTED:
385 {
386 if (this->notification_data.len != 3)
387 {
388 bad_length = TRUE;
389 }
390 break;
391 }
392 case ME_ENDPOINT:
393 if (this->notification_data.len != 8 &&
394 this->notification_data.len != 12 &&
395 this->notification_data.len != 24)
396 {
397 bad_length = TRUE;
398 }
399 break;
400 case ME_CONNECTID:
401 if (this->notification_data.len < 4 ||
402 this->notification_data.len > 16)
403 {
404 bad_length = TRUE;
405 }
406 break;
407 case ME_CONNECTKEY:
408 if (this->notification_data.len < 16 ||
409 this->notification_data.len > 32)
410 {
411 bad_length = TRUE;
412 }
413 break;
414 default:
415 /* TODO: verify */
416 break;
417 }
418 if (bad_length)
419 {
420 DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
421 notify_type_names, this->notify_type,
422 this->notification_data.len);
423 return FAILED;
424 }
425 return SUCCESS;
426 }
427
428 METHOD(payload_t, get_encoding_rules, void,
429 private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
430 {
431 *rules = notify_payload_encodings;
432 *rule_count = countof(notify_payload_encodings);
433 }
434
435 METHOD(payload_t, get_type, payload_type_t,
436 private_notify_payload_t *this)
437 {
438 return NOTIFY;
439 }
440
441 METHOD(payload_t, get_next_type, payload_type_t,
442 private_notify_payload_t *this)
443 {
444 return this->next_payload;
445 }
446
447 METHOD(payload_t, set_next_type, void,
448 private_notify_payload_t *this, payload_type_t type)
449 {
450 this->next_payload = type;
451 }
452
453 /**
454 * recompute the payloads length.
455 */
456 static void compute_length (private_notify_payload_t *this)
457 {
458 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
459
460 if (this->notification_data.ptr != NULL)
461 {
462 length += this->notification_data.len;
463 }
464 if (this->spi.ptr != NULL)
465 {
466 length += this->spi.len;
467 }
468 this->payload_length = length;
469 }
470
471 METHOD(payload_t, get_length, size_t,
472 private_notify_payload_t *this)
473 {
474 return this->payload_length;
475 }
476
477 METHOD(notify_payload_t, get_protocol_id, u_int8_t,
478 private_notify_payload_t *this)
479 {
480 return this->protocol_id;
481 }
482
483 METHOD(notify_payload_t, set_protocol_id, void,
484 private_notify_payload_t *this, u_int8_t protocol_id)
485 {
486 this->protocol_id = protocol_id;
487 }
488
489 METHOD(notify_payload_t, get_notify_type, notify_type_t,
490 private_notify_payload_t *this)
491 {
492 return this->notify_type;
493 }
494
495 METHOD(notify_payload_t, set_notify_type, void,
496 private_notify_payload_t *this, notify_type_t notify_type)
497 {
498 this->notify_type = notify_type;
499 }
500
501 METHOD(notify_payload_t, get_spi, u_int32_t,
502 private_notify_payload_t *this)
503 {
504 switch (this->protocol_id)
505 {
506 case PROTO_AH:
507 case PROTO_ESP:
508 if (this->spi.len == 4)
509 {
510 return *((u_int32_t*)this->spi.ptr);
511 }
512 default:
513 break;
514 }
515 return 0;
516 }
517
518 METHOD(notify_payload_t, set_spi, void,
519 private_notify_payload_t *this, u_int32_t spi)
520 {
521 chunk_free(&this->spi);
522 switch (this->protocol_id)
523 {
524 case PROTO_AH:
525 case PROTO_ESP:
526 this->spi = chunk_alloc(4);
527 *((u_int32_t*)this->spi.ptr) = spi;
528 break;
529 default:
530 break;
531 }
532 this->spi_size = this->spi.len;
533 compute_length(this);
534 }
535
536 METHOD(notify_payload_t, get_notification_data, chunk_t,
537 private_notify_payload_t *this)
538 {
539 return this->notification_data;
540 }
541
542 METHOD(notify_payload_t, set_notification_data, void,
543 private_notify_payload_t *this, chunk_t data)
544 {
545 free(this->notification_data.ptr);
546 this->notification_data = chunk_clone(data);
547 compute_length(this);
548 }
549
550 METHOD2(payload_t, notify_payload_t, destroy, void,
551 private_notify_payload_t *this)
552 {
553 free(this->notification_data.ptr);
554 free(this->spi.ptr);
555 free(this);
556 }
557
558 /*
559 * Described in header
560 */
561 notify_payload_t *notify_payload_create()
562 {
563 private_notify_payload_t *this;
564
565 INIT(this,
566 .public = {
567 .payload_interface = {
568 .verify = _verify,
569 .get_encoding_rules = _get_encoding_rules,
570 .get_length = _get_length,
571 .get_next_type = _get_next_type,
572 .set_next_type = _set_next_type,
573 .get_type = _get_type,
574 .destroy = _destroy,
575 },
576 .get_protocol_id = _get_protocol_id,
577 .set_protocol_id = _set_protocol_id,
578 .get_notify_type = _get_notify_type,
579 .set_notify_type = _set_notify_type,
580 .get_spi = _get_spi,
581 .set_spi = _set_spi,
582 .get_notification_data = _get_notification_data,
583 .set_notification_data = _set_notification_data,
584 .destroy = _destroy,
585 },
586 .next_payload = NO_PAYLOAD,
587 .payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH,
588 );
589 return &this->public;
590 }
591
592 /*
593 * Described in header.
594 */
595 notify_payload_t *notify_payload_create_from_protocol_and_type(
596 protocol_id_t protocol_id, notify_type_t notify_type)
597 {
598 notify_payload_t *notify = notify_payload_create();
599
600 notify->set_notify_type(notify, notify_type);
601 notify->set_protocol_id(notify, protocol_id);
602
603 return notify;
604 }