]>
Commit | Line | Data |
---|---|---|
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 | */ | |
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"}, | |
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 | |
54 | typedef 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 | 60 | struct 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 | */ | |
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 | ||
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 | */ |
174 | static 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 | 215 | static 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 | */ |
224 | static 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 | */ |
232 | static 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 | 240 | static 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 | */ |
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 | /** | |
3fe05870 | 255 | * Implementation of private_notify_payload_t.compute_length. |
8166bcec | 256 | */ |
3fe05870 | 257 | static 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 | 276 | static 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 | 284 | static 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 | 292 | static 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 | 300 | static 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 | 308 | static 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 | 316 | static 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 | 339 | static 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 | 347 | static 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 | */ |
369 | static 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 | */ | |
387 | notify_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 | */ | |
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 | } |