]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/charon/encoding/payloads/notify_payload.c
(no commit message)
[people/ms/strongswan.git] / src / charon / encoding / payloads / notify_payload.c
CommitLineData
8166bcec
JH
1/**
2 * @file notify_payload.c
3 *
3fe05870 4 * @brief Implementation of notify_payload_t.
8166bcec
JH
5 *
6 */
7
8/*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
5113680f 22
8166bcec
JH
23#include <stddef.h>
24
25#include "notify_payload.h"
26
dec59822 27#include <daemon.h>
4a962238 28#include <encoding/payloads/encodings.h>
8166bcec 29
ae3012a0
JH
30/**
31 * String mappings for notify_message_type_t.
32 */
33mapping_t notify_message_type_m[] = {
34 {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
35 {INVALID_IKE_SPI, "INVALID_IKE_SPI"},
36 {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
37 {INVALID_SYNTAX, "INVALID_SYNTAX"},
f6ba78c3 38 {INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"},
ae3012a0
JH
39 {INVALID_SPI, "INVALID_SPI"},
40 {NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"},
41 {INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"},
42 {AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"},
43 {SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"},
44 {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
45 {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
46 {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
47 {TS_UACCEPTABLE, "TS_UACCEPTABLE"},
48 {INVALID_SELECTORS, "INVALID_SELECTORS"},
f6ba78c3
JH
49 {INITIAL_CONTACT, "INITIAL_CONTACT"},
50 {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"},
ae3012a0
JH
51 {MAPPING_END, NULL}
52};
95c61cb9
JH
53
54typedef struct private_notify_payload_t private_notify_payload_t;
55
8166bcec 56/**
3fe05870 57 * Private data of an notify_payload_t object.
8166bcec
JH
58 *
59 */
95c61cb9 60struct private_notify_payload_t {
8166bcec 61 /**
3fe05870 62 * Public notify_payload_t interface.
8166bcec
JH
63 */
64 notify_payload_t public;
65
66 /**
3fe05870 67 * Next payload type.
8166bcec
JH
68 */
69 u_int8_t next_payload;
70
71 /**
3fe05870 72 * Critical flag.
8166bcec
JH
73 */
74 bool critical;
75
76 /**
3fe05870 77 * Length of this payload.
8166bcec
JH
78 */
79 u_int16_t payload_length;
80
81 /**
3fe05870 82 * Protocol id.
8166bcec
JH
83 */
84 u_int8_t protocol_id;
85
86 /**
3fe05870 87 * Spi size.
8166bcec
JH
88 */
89 u_int8_t spi_size;
90
91 /**
3fe05870 92 * Notify message type.
8166bcec
JH
93 */
94 u_int16_t notify_message_type;
95
96 /**
3fe05870 97 * Security parameter index (spi).
8166bcec
JH
98 */
99 chunk_t spi;
100
101 /**
3fe05870 102 * Notification data.
8166bcec
JH
103 */
104 chunk_t notification_data;
105
dec59822
MW
106 /**
107 * Assigned logger
108 */
109 logger_t *logger;
110
8166bcec
JH
111 /**
112 * @brief Computes the length of this payload.
113 *
114 * @param this calling private_ke_payload_t object
8166bcec 115 */
3fe05870 116 void (*compute_length) (private_notify_payload_t *this);
8166bcec
JH
117};
118
119/**
3fe05870 120 * Encoding rules to parse or generate a IKEv2-Notify Payload.
8166bcec
JH
121 *
122 * The defined offsets are the positions in a object of type
123 * private_notify_payload_t.
124 *
125 */
126encoding_rule_t notify_payload_encodings[] = {
127 /* 1 Byte next payload type, stored in the field next_payload */
128 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
129 /* the critical bit */
130 { FLAG, offsetof(private_notify_payload_t, critical) },
131 /* 7 Bit reserved bits, nowhere stored */
132 { RESERVED_BIT, 0 },
133 { RESERVED_BIT, 0 },
134 { RESERVED_BIT, 0 },
135 { RESERVED_BIT, 0 },
136 { RESERVED_BIT, 0 },
137 { RESERVED_BIT, 0 },
138 { RESERVED_BIT, 0 },
139 /* Length of the whole payload*/
140 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
141 /* Protocol ID as 8 bit field*/
142 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
143 /* SPI Size as 8 bit field*/
144 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
145 /* Notify message type as 16 bit field*/
146 { U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
147 /* SPI as variable length field*/
148 { SPI, offsetof(private_notify_payload_t, spi) },
149 /* Key Exchange Data is from variable size */
150 { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
151};
152
e31eb71e
JH
153/*
154 1 2 3
155 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
156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 ! Next Payload !C! RESERVED ! Payload Length !
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 ! Protocol ID ! SPI Size ! Notify Message Type !
160 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 ! !
162 ~ Security Parameter Index (SPI) ~
163 ! !
164 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 ! !
166 ~ Notification Data ~
167 ! !
168 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169*/
170
171/**
3fe05870 172 * Implementation of payload_t.verify.
e31eb71e
JH
173 */
174static status_t verify(private_notify_payload_t *this)
175{
e31eb71e
JH
176 if (this->protocol_id > 3)
177 {
178 /* reserved for future use */
179 return FAILED;
180 }
181
ce461bbd 182 /* TODO: Check all kinds of notify */
e31eb71e 183
ce461bbd
MW
184 if (this->notify_message_type == INVALID_KE_PAYLOAD)
185 {
186 /* check notification data */
187 diffie_hellman_group_t dh_group;
188 if (this->notification_data.len != 2)
189 {
190 return FAILED;
191 }
192 dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
dec59822 193 switch (dh_group)
ce461bbd 194 {
dec59822
MW
195 case MODP_768_BIT:
196 case MODP_1024_BIT:
197 case MODP_1536_BIT:
198 case MODP_2048_BIT:
199 case MODP_3072_BIT:
200 case MODP_4096_BIT:
201 case MODP_6144_BIT:
202 case MODP_8192_BIT:
203 break;
204 default:
205 this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group);
206 return FAILED;
ce461bbd
MW
207 }
208 }
e31eb71e
JH
209 return SUCCESS;
210}
211
8166bcec 212/**
3fe05870 213 * Implementation of payload_t.get_encoding_rules.
8166bcec 214 */
3fe05870 215static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
8166bcec
JH
216{
217 *rules = notify_payload_encodings;
218 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
8166bcec
JH
219}
220
221/**
3fe05870 222 * Implementation of payload_t.get_type.
8166bcec
JH
223 */
224static payload_type_t get_type(private_notify_payload_t *this)
225{
ae3012a0 226 return NOTIFY;
8166bcec
JH
227}
228
229/**
3fe05870 230 * Implementation of payload_t.get_next_type.
8166bcec
JH
231 */
232static payload_type_t get_next_type(private_notify_payload_t *this)
233{
234 return (this->next_payload);
235}
236
237/**
3fe05870 238 * Implementation of payload_t.set_next_type.
8166bcec 239 */
3fe05870 240static void set_next_type(private_notify_payload_t *this,payload_type_t type)
8166bcec
JH
241{
242 this->next_payload = type;
8166bcec
JH
243}
244
245/**
3fe05870 246 * Implementation of payload_t.get_length.
8166bcec
JH
247 */
248static size_t get_length(private_notify_payload_t *this)
249{
250 this->compute_length(this);
251 return this->payload_length;
252}
253
254/**
3fe05870 255 * Implementation of private_notify_payload_t.compute_length.
8166bcec 256 */
3fe05870 257static void compute_length (private_notify_payload_t *this)
8166bcec
JH
258{
259 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
260 if (this->notification_data.ptr != NULL)
261 {
262 length += this->notification_data.len;
263 }
264 if (this->spi.ptr != NULL)
265 {
266 length += this->spi.len;
267 }
268
269 this->payload_length = length;
8166bcec 270
3fe05870 271}
8166bcec
JH
272
273/**
3fe05870 274 * Implementation of notify_payload_t.get_protocol_id.
8166bcec 275 */
3fe05870 276static u_int8_t get_protocol_id(private_notify_payload_t *this)
8166bcec
JH
277{
278 return this->protocol_id;
279}
280
281/**
3fe05870 282 * Implementation of notify_payload_t.set_protocol_id.
8166bcec 283 */
3fe05870 284static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
8166bcec
JH
285{
286 this->protocol_id = protocol_id;
8166bcec
JH
287}
288
289/**
3fe05870 290 * Implementation of notify_payload_t.get_notify_message_type.
8166bcec 291 */
3fe05870 292static u_int16_t get_notify_message_type(private_notify_payload_t *this)
8166bcec
JH
293{
294 return this->notify_message_type;
295}
296
297/**
3fe05870 298 * Implementation of notify_payload_t.set_notify_message_type.
8166bcec 299 */
3fe05870 300static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
8166bcec
JH
301{
302 this->notify_message_type = notify_message_type;
8166bcec
JH
303}
304
305/**
3fe05870 306 * Implementation of notify_payload_t.get_spi.
8166bcec 307 */
3fe05870 308static chunk_t get_spi(private_notify_payload_t *this)
8166bcec
JH
309{
310 return (this->spi);
311}
312
313/**
3fe05870 314 * Implementation of notify_payload_t.set_spi.
8166bcec 315 */
3fe05870 316static void set_spi(private_notify_payload_t *this, chunk_t spi)
8166bcec
JH
317{
318 /* destroy existing data first */
319 if (this->spi.ptr != NULL)
320 {
321 /* free existing value */
5113680f 322 free(this->spi.ptr);
8166bcec
JH
323 this->spi.ptr = NULL;
324 this->spi.len = 0;
325
326 }
327
5113680f 328 this->spi.ptr = clalloc(spi.ptr,spi.len);
3fe05870 329
8166bcec
JH
330 this->spi.len = spi.len;
331 this->spi_size = spi.len;
332 this->compute_length(this);
8166bcec 333
3fe05870 334}
8166bcec
JH
335
336/**
3fe05870 337 * Implementation of notify_payload_t.get_notification_data.
8166bcec 338 */
3fe05870 339static chunk_t get_notification_data(private_notify_payload_t *this)
8166bcec
JH
340{
341 return (this->notification_data);
342}
343
344/**
3fe05870 345 * Implementation of notify_payload_t.set_notification_data.
8166bcec 346 */
3fe05870 347static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
8166bcec
JH
348{
349 /* destroy existing data first */
350 if (this->notification_data.ptr != NULL)
351 {
352 /* free existing value */
5113680f 353 free(this->notification_data.ptr);
8166bcec
JH
354 this->notification_data.ptr = NULL;
355 this->notification_data.len = 0;
356
357 }
358
5113680f 359 this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len);
8166bcec
JH
360 this->notification_data.len = notification_data.len;
361 this->compute_length(this);
362
363 return SUCCESS;
364}
365
723b6664 366/**
3fe05870 367 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
723b6664
JH
368 */
369static status_t destroy(private_notify_payload_t *this)
370{
371 if (this->notification_data.ptr != NULL)
372 {
5113680f 373 free(this->notification_data.ptr);
723b6664
JH
374 }
375 if (this->spi.ptr != NULL)
376 {
5113680f 377 free(this->spi.ptr);
723b6664
JH
378 }
379
5113680f 380 free(this);
723b6664
JH
381 return SUCCESS;
382}
383
8166bcec
JH
384/*
385 * Described in header
386 */
387notify_payload_t *notify_payload_create()
388{
5113680f 389 private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
3fe05870 390
8166bcec 391 /* interface functions */
e31eb71e 392 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
3fe05870 393 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
8166bcec
JH
394 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
395 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
3fe05870 396 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
8166bcec 397 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
3fe05870 398 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
8166bcec
JH
399
400 /* public functions */
401 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
3fe05870 402 this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
8166bcec 403 this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
3fe05870 404 this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
8166bcec 405 this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
3fe05870 406 this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi;
8166bcec 407 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
3fe05870
JH
408 this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
409 this->public.destroy = (void (*) (notify_payload_t *)) destroy;
8166bcec
JH
410
411 /* private functions */
412 this->compute_length = compute_length;
413
414 /* set default values of the fields */
dec59822 415 this->critical = FALSE;
8166bcec
JH
416 this->next_payload = NO_PAYLOAD;
417 this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
418 this->protocol_id = 0;
419 this->notify_message_type = 0;
420 this->spi.ptr = NULL;
421 this->spi.len = 0;
6db4e80b 422 this->spi_size = 0;
8166bcec
JH
423 this->notification_data.ptr = NULL;
424 this->notification_data.len = 0;
5113680f 425 this->logger = logger_manager->get_logger(logger_manager, PAYLOAD);
8166bcec
JH
426
427 return (&(this->public));
428}
429
ae3012a0
JH
430/*
431 * Described in header.
432 */
433notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
434{
435 notify_payload_t *notify = notify_payload_create();
436
437 notify->set_notify_message_type(notify,notify_message_type);
438 notify->set_protocol_id(notify,protocol_id);
439
440 return notify;
441}