]> git.ipfire.org Git - thirdparty/strongswan.git/blob - programs/charon/charon/encoding/payloads/notify_payload.c
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / charon / 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) 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
23 #include <stddef.h>
24
25 #include "notify_payload.h"
26
27 #include <daemon.h>
28 #include <encoding/payloads/encodings.h>
29
30 /**
31 * String mappings for notify_message_type_t.
32 */
33 mapping_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"},
38 {INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"},
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"},
49 {INITIAL_CONTACT, "INITIAL_CONTACT"},
50 {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"},
51 {MAPPING_END, NULL}
52 };
53
54 typedef struct private_notify_payload_t private_notify_payload_t;
55
56 /**
57 * Private data of an notify_payload_t object.
58 *
59 */
60 struct private_notify_payload_t {
61 /**
62 * Public notify_payload_t interface.
63 */
64 notify_payload_t public;
65
66 /**
67 * Next payload type.
68 */
69 u_int8_t next_payload;
70
71 /**
72 * Critical flag.
73 */
74 bool critical;
75
76 /**
77 * Length of this payload.
78 */
79 u_int16_t payload_length;
80
81 /**
82 * Protocol id.
83 */
84 u_int8_t protocol_id;
85
86 /**
87 * Spi size.
88 */
89 u_int8_t spi_size;
90
91 /**
92 * Notify message type.
93 */
94 u_int16_t notify_message_type;
95
96 /**
97 * Security parameter index (spi).
98 */
99 chunk_t spi;
100
101 /**
102 * Notification data.
103 */
104 chunk_t notification_data;
105
106 /**
107 * Assigned logger
108 */
109 logger_t *logger;
110
111 /**
112 * @brief Computes the length of this payload.
113 *
114 * @param this calling private_ke_payload_t object
115 */
116 void (*compute_length) (private_notify_payload_t *this);
117 };
118
119 /**
120 * Encoding rules to parse or generate a IKEv2-Notify Payload.
121 *
122 * The defined offsets are the positions in a object of type
123 * private_notify_payload_t.
124 *
125 */
126 encoding_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
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 /**
172 * Implementation of payload_t.verify.
173 */
174 static status_t verify(private_notify_payload_t *this)
175 {
176 if (this->protocol_id > 3)
177 {
178 /* reserved for future use */
179 return FAILED;
180 }
181
182 /* TODO: Check all kinds of notify */
183
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));
193 switch (dh_group)
194 {
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;
207 }
208 }
209 return SUCCESS;
210 }
211
212 /**
213 * Implementation of payload_t.get_encoding_rules.
214 */
215 static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
216 {
217 *rules = notify_payload_encodings;
218 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
219 }
220
221 /**
222 * Implementation of payload_t.get_type.
223 */
224 static payload_type_t get_type(private_notify_payload_t *this)
225 {
226 return NOTIFY;
227 }
228
229 /**
230 * Implementation of payload_t.get_next_type.
231 */
232 static payload_type_t get_next_type(private_notify_payload_t *this)
233 {
234 return (this->next_payload);
235 }
236
237 /**
238 * Implementation of payload_t.set_next_type.
239 */
240 static void set_next_type(private_notify_payload_t *this,payload_type_t type)
241 {
242 this->next_payload = type;
243 }
244
245 /**
246 * Implementation of payload_t.get_length.
247 */
248 static size_t get_length(private_notify_payload_t *this)
249 {
250 this->compute_length(this);
251 return this->payload_length;
252 }
253
254 /**
255 * Implementation of private_notify_payload_t.compute_length.
256 */
257 static void compute_length (private_notify_payload_t *this)
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;
270
271 }
272
273 /**
274 * Implementation of notify_payload_t.get_protocol_id.
275 */
276 static u_int8_t get_protocol_id(private_notify_payload_t *this)
277 {
278 return this->protocol_id;
279 }
280
281 /**
282 * Implementation of notify_payload_t.set_protocol_id.
283 */
284 static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
285 {
286 this->protocol_id = protocol_id;
287 }
288
289 /**
290 * Implementation of notify_payload_t.get_notify_message_type.
291 */
292 static u_int16_t get_notify_message_type(private_notify_payload_t *this)
293 {
294 return this->notify_message_type;
295 }
296
297 /**
298 * Implementation of notify_payload_t.set_notify_message_type.
299 */
300 static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
301 {
302 this->notify_message_type = notify_message_type;
303 }
304
305 /**
306 * Implementation of notify_payload_t.get_spi.
307 */
308 static chunk_t get_spi(private_notify_payload_t *this)
309 {
310 return (this->spi);
311 }
312
313 /**
314 * Implementation of notify_payload_t.set_spi.
315 */
316 static void set_spi(private_notify_payload_t *this, chunk_t spi)
317 {
318 /* destroy existing data first */
319 if (this->spi.ptr != NULL)
320 {
321 /* free existing value */
322 free(this->spi.ptr);
323 this->spi.ptr = NULL;
324 this->spi.len = 0;
325
326 }
327
328 this->spi.ptr = clalloc(spi.ptr,spi.len);
329
330 this->spi.len = spi.len;
331 this->spi_size = spi.len;
332 this->compute_length(this);
333
334 }
335
336 /**
337 * Implementation of notify_payload_t.get_notification_data.
338 */
339 static chunk_t get_notification_data(private_notify_payload_t *this)
340 {
341 return (this->notification_data);
342 }
343
344 /**
345 * Implementation of notify_payload_t.set_notification_data.
346 */
347 static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
348 {
349 /* destroy existing data first */
350 if (this->notification_data.ptr != NULL)
351 {
352 /* free existing value */
353 free(this->notification_data.ptr);
354 this->notification_data.ptr = NULL;
355 this->notification_data.len = 0;
356
357 }
358
359 this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len);
360 this->notification_data.len = notification_data.len;
361 this->compute_length(this);
362
363 return SUCCESS;
364 }
365
366 /**
367 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
368 */
369 static status_t destroy(private_notify_payload_t *this)
370 {
371 if (this->notification_data.ptr != NULL)
372 {
373 free(this->notification_data.ptr);
374 }
375 if (this->spi.ptr != NULL)
376 {
377 free(this->spi.ptr);
378 }
379
380 free(this);
381 return SUCCESS;
382 }
383
384 /*
385 * Described in header
386 */
387 notify_payload_t *notify_payload_create()
388 {
389 private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
390
391 /* interface functions */
392 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
393 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
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;
396 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
397 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
398 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
399
400 /* public functions */
401 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
402 this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
403 this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
404 this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
405 this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
406 this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi;
407 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
408 this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
409 this->public.destroy = (void (*) (notify_payload_t *)) destroy;
410
411 /* private functions */
412 this->compute_length = compute_length;
413
414 /* set default values of the fields */
415 this->critical = FALSE;
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;
422 this->spi_size = 0;
423 this->notification_data.ptr = NULL;
424 this->notification_data.len = 0;
425 this->logger = logger_manager->get_logger(logger_manager, PAYLOAD);
426
427 return (&(this->public));
428 }
429
430 /*
431 * Described in header.
432 */
433 notify_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 }