- added notify message handling to ike_sa_init_requested_t and
[strongswan.git] / Source / 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 /* offsetof macro */
24 #include <stddef.h>
25
26 #include "notify_payload.h"
27
28 #include <encoding/payloads/encodings.h>
29 #include <utils/allocator.h>
30
31 /**
32 * String mappings for notify_message_type_t.
33 */
34 mapping_t notify_message_type_m[] = {
35 {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
36 {INVALID_IKE_SPI, "INVALID_IKE_SPI"},
37 {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
38 {INVALID_SYNTAX, "INVALID_SYNTAX"},
39 {INVALID_MESSAGE_ID, "MODP_2048_BIT"},
40 {INVALID_SPI, "INVALID_SPI"},
41 {NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"},
42 {INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"},
43 {AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"},
44 {SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"},
45 {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
46 {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
47 {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
48 {TS_UACCEPTABLE, "TS_UACCEPTABLE"},
49 {INVALID_SELECTORS, "INVALID_SELECTORS"},
50 {MAPPING_END, NULL}
51 };
52
53 typedef struct private_notify_payload_t private_notify_payload_t;
54
55 /**
56 * Private data of an notify_payload_t object.
57 *
58 */
59 struct private_notify_payload_t {
60 /**
61 * Public notify_payload_t interface.
62 */
63 notify_payload_t public;
64
65 /**
66 * Next payload type.
67 */
68 u_int8_t next_payload;
69
70 /**
71 * Critical flag.
72 */
73 bool critical;
74
75 /**
76 * Length of this payload.
77 */
78 u_int16_t payload_length;
79
80 /**
81 * Protocol id.
82 */
83 u_int8_t protocol_id;
84
85 /**
86 * Spi size.
87 */
88 u_int8_t spi_size;
89
90 /**
91 * Notify message type.
92 */
93 u_int16_t notify_message_type;
94
95 /**
96 * Security parameter index (spi).
97 */
98 chunk_t spi;
99
100 /**
101 * Notification data.
102 */
103 chunk_t notification_data;
104
105 /**
106 * @brief Computes the length of this payload.
107 *
108 * @param this calling private_ke_payload_t object
109 */
110 void (*compute_length) (private_notify_payload_t *this);
111 };
112
113 /**
114 * Encoding rules to parse or generate a IKEv2-Notify Payload.
115 *
116 * The defined offsets are the positions in a object of type
117 * private_notify_payload_t.
118 *
119 */
120 encoding_rule_t notify_payload_encodings[] = {
121 /* 1 Byte next payload type, stored in the field next_payload */
122 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
123 /* the critical bit */
124 { FLAG, offsetof(private_notify_payload_t, critical) },
125 /* 7 Bit reserved bits, nowhere stored */
126 { RESERVED_BIT, 0 },
127 { RESERVED_BIT, 0 },
128 { RESERVED_BIT, 0 },
129 { RESERVED_BIT, 0 },
130 { RESERVED_BIT, 0 },
131 { RESERVED_BIT, 0 },
132 { RESERVED_BIT, 0 },
133 /* Length of the whole payload*/
134 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
135 /* Protocol ID as 8 bit field*/
136 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
137 /* SPI Size as 8 bit field*/
138 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
139 /* Notify message type as 16 bit field*/
140 { U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
141 /* SPI as variable length field*/
142 { SPI, offsetof(private_notify_payload_t, spi) },
143 /* Key Exchange Data is from variable size */
144 { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
145 };
146
147 /*
148 1 2 3
149 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
150 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 ! Next Payload !C! RESERVED ! Payload Length !
152 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 ! Protocol ID ! SPI Size ! Notify Message Type !
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 ! !
156 ~ Security Parameter Index (SPI) ~
157 ! !
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 ! !
160 ~ Notification Data ~
161 ! !
162 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 */
164
165 /**
166 * Implementation of payload_t.verify.
167 */
168 static status_t verify(private_notify_payload_t *this)
169 {
170 if (this->critical)
171 {
172 /* critical bit is set! */
173 return FAILED;
174 }
175 if (this->protocol_id > 3)
176 {
177 /* reserved for future use */
178 return FAILED;
179 }
180
181 /* notify message types and data is not getting checked in here */
182
183 return SUCCESS;
184 }
185
186 /**
187 * Implementation of payload_t.get_encoding_rules.
188 */
189 static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
190 {
191 *rules = notify_payload_encodings;
192 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
193 }
194
195 /**
196 * Implementation of payload_t.get_type.
197 */
198 static payload_type_t get_type(private_notify_payload_t *this)
199 {
200 return NOTIFY;
201 }
202
203 /**
204 * Implementation of payload_t.get_next_type.
205 */
206 static payload_type_t get_next_type(private_notify_payload_t *this)
207 {
208 return (this->next_payload);
209 }
210
211 /**
212 * Implementation of payload_t.set_next_type.
213 */
214 static void set_next_type(private_notify_payload_t *this,payload_type_t type)
215 {
216 this->next_payload = type;
217 }
218
219 /**
220 * Implementation of payload_t.get_length.
221 */
222 static size_t get_length(private_notify_payload_t *this)
223 {
224 this->compute_length(this);
225 return this->payload_length;
226 }
227
228 /**
229 * Implementation of private_notify_payload_t.compute_length.
230 */
231 static void compute_length (private_notify_payload_t *this)
232 {
233 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
234 if (this->notification_data.ptr != NULL)
235 {
236 length += this->notification_data.len;
237 }
238 if (this->spi.ptr != NULL)
239 {
240 length += this->spi.len;
241 }
242
243 this->payload_length = length;
244
245 }
246
247 /**
248 * Implementation of notify_payload_t.get_protocol_id.
249 */
250 static u_int8_t get_protocol_id(private_notify_payload_t *this)
251 {
252 return this->protocol_id;
253 }
254
255 /**
256 * Implementation of notify_payload_t.set_protocol_id.
257 */
258 static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
259 {
260 this->protocol_id = protocol_id;
261 }
262
263 /**
264 * Implementation of notify_payload_t.get_notify_message_type.
265 */
266 static u_int16_t get_notify_message_type(private_notify_payload_t *this)
267 {
268 return this->notify_message_type;
269 }
270
271 /**
272 * Implementation of notify_payload_t.set_notify_message_type.
273 */
274 static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
275 {
276 this->notify_message_type = notify_message_type;
277 }
278
279 /**
280 * Implementation of notify_payload_t.get_spi.
281 */
282 static chunk_t get_spi(private_notify_payload_t *this)
283 {
284 return (this->spi);
285 }
286
287 /**
288 * Implementation of notify_payload_t.set_spi.
289 */
290 static void set_spi(private_notify_payload_t *this, chunk_t spi)
291 {
292 /* destroy existing data first */
293 if (this->spi.ptr != NULL)
294 {
295 /* free existing value */
296 allocator_free(this->spi.ptr);
297 this->spi.ptr = NULL;
298 this->spi.len = 0;
299
300 }
301
302 this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
303
304 this->spi.len = spi.len;
305 this->spi_size = spi.len;
306 this->compute_length(this);
307
308 }
309
310 /**
311 * Implementation of notify_payload_t.get_notification_data.
312 */
313 static chunk_t get_notification_data(private_notify_payload_t *this)
314 {
315 return (this->notification_data);
316 }
317
318 /**
319 * Implementation of notify_payload_t.set_notification_data.
320 */
321 static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
322 {
323 /* destroy existing data first */
324 if (this->notification_data.ptr != NULL)
325 {
326 /* free existing value */
327 allocator_free(this->notification_data.ptr);
328 this->notification_data.ptr = NULL;
329 this->notification_data.len = 0;
330
331 }
332
333 this->notification_data.ptr = allocator_clone_bytes(notification_data.ptr,notification_data.len);
334 this->notification_data.len = notification_data.len;
335 this->compute_length(this);
336
337 return SUCCESS;
338 }
339
340 /**
341 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
342 */
343 static status_t destroy(private_notify_payload_t *this)
344 {
345 if (this->notification_data.ptr != NULL)
346 {
347 allocator_free(this->notification_data.ptr);
348 }
349 if (this->spi.ptr != NULL)
350 {
351 allocator_free(this->spi.ptr);
352 }
353
354 allocator_free(this);
355 return SUCCESS;
356 }
357
358 /*
359 * Described in header
360 */
361 notify_payload_t *notify_payload_create()
362 {
363 private_notify_payload_t *this = allocator_alloc_thing(private_notify_payload_t);
364
365 /* interface functions */
366 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
367 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
368 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
369 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
370 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
371 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
372 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
373
374 /* public functions */
375 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
376 this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
377 this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
378 this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
379 this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
380 this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi;
381 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
382 this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
383 this->public.destroy = (void (*) (notify_payload_t *)) destroy;
384
385 /* private functions */
386 this->compute_length = compute_length;
387
388 /* set default values of the fields */
389 this->critical = NOTIFY_PAYLOAD_CRITICAL_FLAG;
390 this->next_payload = NO_PAYLOAD;
391 this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
392 this->protocol_id = 0;
393 this->notify_message_type = 0;
394 this->spi.ptr = NULL;
395 this->spi.len = 0;
396 this->notification_data.ptr = NULL;
397 this->notification_data.len = 0;
398
399 return (&(this->public));
400 }
401
402 /*
403 * Described in header.
404 */
405 notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
406 {
407 notify_payload_t *notify = notify_payload_create();
408
409 notify->set_notify_message_type(notify,notify_message_type);
410 notify->set_protocol_id(notify,protocol_id);
411
412 return notify;
413 }