diff options
Diffstat (limited to 'src/messenger/messenger_api_message.c')
-rw-r--r-- | src/messenger/messenger_api_message.c | 932 |
1 files changed, 0 insertions, 932 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c deleted file mode 100644 index 496c98dbf..000000000 --- a/src/messenger/messenger_api_message.c +++ /dev/null | |||
@@ -1,932 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2020--2021 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @author Tobias Frisch | ||
22 | * @file src/messenger/messenger_api_message.c | ||
23 | * @brief messenger api: client and service implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_message.h" | ||
27 | |||
28 | struct GNUNET_MESSENGER_MessageSignature | ||
29 | { | ||
30 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
31 | struct GNUNET_HashCode hash; | ||
32 | }; | ||
33 | |||
34 | struct GNUNET_MESSENGER_ShortMessage | ||
35 | { | ||
36 | enum GNUNET_MESSENGER_MessageKind kind; | ||
37 | struct GNUNET_MESSENGER_MessageBody body; | ||
38 | }; | ||
39 | |||
40 | struct GNUNET_MESSENGER_Message* | ||
41 | create_message (enum GNUNET_MESSENGER_MessageKind kind) | ||
42 | { | ||
43 | struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct GNUNET_MESSENGER_Message); | ||
44 | |||
45 | message->header.kind = kind; | ||
46 | |||
47 | switch (message->header.kind) | ||
48 | { | ||
49 | case GNUNET_MESSENGER_KIND_NAME: | ||
50 | message->body.name.name = NULL; | ||
51 | break; | ||
52 | case GNUNET_MESSENGER_KIND_TEXT: | ||
53 | message->body.text.text = NULL; | ||
54 | break; | ||
55 | case GNUNET_MESSENGER_KIND_FILE: | ||
56 | message->body.file.uri = NULL; | ||
57 | break; | ||
58 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
59 | message->body.privacy.length = 0; | ||
60 | message->body.privacy.data = NULL; | ||
61 | break; | ||
62 | default: | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | return message; | ||
67 | } | ||
68 | |||
69 | struct GNUNET_MESSENGER_Message* | ||
70 | copy_message (const struct GNUNET_MESSENGER_Message *message) | ||
71 | { | ||
72 | GNUNET_assert(message); | ||
73 | |||
74 | struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); | ||
75 | |||
76 | GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); | ||
77 | |||
78 | switch (message->header.kind) | ||
79 | { | ||
80 | case GNUNET_MESSENGER_KIND_NAME: | ||
81 | copy->body.name.name = GNUNET_strdup(message->body.name.name); | ||
82 | break; | ||
83 | case GNUNET_MESSENGER_KIND_TEXT: | ||
84 | copy->body.text.text = GNUNET_strdup(message->body.text.text); | ||
85 | break; | ||
86 | case GNUNET_MESSENGER_KIND_FILE: | ||
87 | copy->body.file.uri = GNUNET_strdup(message->body.file.uri); | ||
88 | break; | ||
89 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
90 | copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc(copy->body.privacy.length) : NULL; | ||
91 | |||
92 | if (copy->body.privacy.data) | ||
93 | { | ||
94 | GNUNET_memcpy(copy->body.privacy.data, message->body.privacy.data, copy->body.privacy.length); | ||
95 | } | ||
96 | |||
97 | break; | ||
98 | default: | ||
99 | break; | ||
100 | } | ||
101 | |||
102 | return copy; | ||
103 | } | ||
104 | |||
105 | static void | ||
106 | destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, | ||
107 | struct GNUNET_MESSENGER_MessageBody *body) | ||
108 | { | ||
109 | switch (kind) | ||
110 | { | ||
111 | case GNUNET_MESSENGER_KIND_NAME: | ||
112 | GNUNET_free(body->name.name); | ||
113 | break; | ||
114 | case GNUNET_MESSENGER_KIND_TEXT: | ||
115 | GNUNET_free(body->text.text); | ||
116 | break; | ||
117 | case GNUNET_MESSENGER_KIND_FILE: | ||
118 | GNUNET_free(body->file.uri); | ||
119 | break; | ||
120 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
121 | GNUNET_free(body->privacy.data); | ||
122 | break; | ||
123 | default: | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void | ||
129 | cleanup_message (struct GNUNET_MESSENGER_Message *message) | ||
130 | { | ||
131 | GNUNET_assert(message); | ||
132 | |||
133 | destroy_message_body (message->header.kind, &(message->body)); | ||
134 | } | ||
135 | |||
136 | void | ||
137 | destroy_message (struct GNUNET_MESSENGER_Message *message) | ||
138 | { | ||
139 | GNUNET_assert(message); | ||
140 | |||
141 | destroy_message_body (message->header.kind, &(message->body)); | ||
142 | |||
143 | GNUNET_free(message); | ||
144 | } | ||
145 | |||
146 | int | ||
147 | is_message_session_bound (const struct GNUNET_MESSENGER_Message *message) | ||
148 | { | ||
149 | GNUNET_assert(message); | ||
150 | |||
151 | if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) || | ||
152 | (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) || | ||
153 | (GNUNET_MESSENGER_KIND_NAME == message->header.kind) || | ||
154 | (GNUNET_MESSENGER_KIND_KEY == message->header.kind) || | ||
155 | (GNUNET_MESSENGER_KIND_ID == message->header.kind)) | ||
156 | return GNUNET_YES; | ||
157 | else | ||
158 | return GNUNET_NO; | ||
159 | } | ||
160 | |||
161 | static void | ||
162 | fold_short_message (const struct GNUNET_MESSENGER_Message *message, | ||
163 | struct GNUNET_MESSENGER_ShortMessage *shortened) | ||
164 | { | ||
165 | shortened->kind = message->header.kind; | ||
166 | |||
167 | GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody)); | ||
168 | } | ||
169 | |||
170 | static void | ||
171 | unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened, | ||
172 | struct GNUNET_MESSENGER_Message *message) | ||
173 | { | ||
174 | destroy_message_body (message->header.kind, &(message->body)); | ||
175 | |||
176 | message->header.kind = shortened->kind; | ||
177 | |||
178 | GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody)); | ||
179 | } | ||
180 | |||
181 | #define member_size(type, member) sizeof(((type*) NULL)->member) | ||
182 | |||
183 | static uint16_t | ||
184 | get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | ||
185 | { | ||
186 | uint16_t length = 0; | ||
187 | |||
188 | switch (kind) | ||
189 | { | ||
190 | case GNUNET_MESSENGER_KIND_INFO: | ||
191 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version); | ||
192 | break; | ||
193 | case GNUNET_MESSENGER_KIND_PEER: | ||
194 | length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); | ||
195 | break; | ||
196 | case GNUNET_MESSENGER_KIND_ID: | ||
197 | length += member_size(struct GNUNET_MESSENGER_Message, body.id.id); | ||
198 | break; | ||
199 | case GNUNET_MESSENGER_KIND_MISS: | ||
200 | length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer); | ||
201 | break; | ||
202 | case GNUNET_MESSENGER_KIND_MERGE: | ||
203 | length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous); | ||
204 | break; | ||
205 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
206 | length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash); | ||
207 | break; | ||
208 | case GNUNET_MESSENGER_KIND_INVITE: | ||
209 | length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door); | ||
210 | length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key); | ||
211 | break; | ||
212 | case GNUNET_MESSENGER_KIND_TEXT: | ||
213 | break; | ||
214 | case GNUNET_MESSENGER_KIND_FILE: | ||
215 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); | ||
216 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); | ||
217 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.name); | ||
218 | break; | ||
219 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
220 | length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key); | ||
221 | break; | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | return length; | ||
227 | } | ||
228 | |||
229 | typedef uint32_t kind_t; | ||
230 | |||
231 | uint16_t | ||
232 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind, | ||
233 | int include_header) | ||
234 | { | ||
235 | uint16_t length = 0; | ||
236 | |||
237 | if (GNUNET_YES == include_header) | ||
238 | { | ||
239 | length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); | ||
240 | length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); | ||
241 | length += member_size(struct GNUNET_MESSENGER_Message, header.previous); | ||
242 | } | ||
243 | |||
244 | length += sizeof(kind_t); | ||
245 | |||
246 | return length + get_message_body_kind_size (kind); | ||
247 | } | ||
248 | |||
249 | static uint16_t | ||
250 | get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, | ||
251 | const struct GNUNET_MESSENGER_MessageBody *body) | ||
252 | { | ||
253 | uint16_t length = 0; | ||
254 | |||
255 | switch (kind) | ||
256 | { | ||
257 | case GNUNET_MESSENGER_KIND_INFO: | ||
258 | length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key)); | ||
259 | break; | ||
260 | case GNUNET_MESSENGER_KIND_JOIN: | ||
261 | length += GNUNET_IDENTITY_key_get_length(&(body->join.key)); | ||
262 | break; | ||
263 | case GNUNET_MESSENGER_KIND_NAME: | ||
264 | length += (body->name.name ? strlen (body->name.name) : 0); | ||
265 | break; | ||
266 | case GNUNET_MESSENGER_KIND_KEY: | ||
267 | length += GNUNET_IDENTITY_key_get_length(&(body->key.key)); | ||
268 | break; | ||
269 | case GNUNET_MESSENGER_KIND_TEXT: | ||
270 | length += strlen (body->text.text); | ||
271 | break; | ||
272 | case GNUNET_MESSENGER_KIND_FILE: | ||
273 | length += strlen (body->file.uri); | ||
274 | break; | ||
275 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
276 | length += body->privacy.length; | ||
277 | break; | ||
278 | default: | ||
279 | break; | ||
280 | } | ||
281 | |||
282 | return length; | ||
283 | } | ||
284 | |||
285 | uint16_t | ||
286 | get_message_size (const struct GNUNET_MESSENGER_Message *message, | ||
287 | int include_header) | ||
288 | { | ||
289 | GNUNET_assert(message); | ||
290 | |||
291 | uint16_t length = 0; | ||
292 | |||
293 | if (GNUNET_YES == include_header) | ||
294 | length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature)); | ||
295 | |||
296 | length += get_message_kind_size (message->header.kind, include_header); | ||
297 | length += get_message_body_size (message->header.kind, &(message->body)); | ||
298 | |||
299 | return length; | ||
300 | } | ||
301 | |||
302 | static uint16_t | ||
303 | get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message, | ||
304 | int include_body) | ||
305 | { | ||
306 | const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t); | ||
307 | |||
308 | if (message) | ||
309 | return minimum_size + get_message_body_kind_size (message->kind) | ||
310 | + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0); | ||
311 | else | ||
312 | return minimum_size; | ||
313 | } | ||
314 | |||
315 | static uint16_t | ||
316 | calc_usual_padding () | ||
317 | { | ||
318 | uint16_t padding = 0; | ||
319 | uint16_t kind_size; | ||
320 | |||
321 | for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) { | ||
322 | kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, GNUNET_YES); | ||
323 | |||
324 | if (kind_size > padding) | ||
325 | padding = kind_size; | ||
326 | } | ||
327 | |||
328 | return padding + GNUNET_MESSENGER_PADDING_MIN; | ||
329 | } | ||
330 | |||
331 | #define max(x, y) (x > y? x : y) | ||
332 | |||
333 | static uint16_t | ||
334 | calc_padded_length (uint16_t length) | ||
335 | { | ||
336 | static uint16_t usual_padding = 0; | ||
337 | |||
338 | if (!usual_padding) | ||
339 | usual_padding = calc_usual_padding(); | ||
340 | |||
341 | const uint16_t padded_length = max( | ||
342 | length + GNUNET_MESSENGER_PADDING_MIN, | ||
343 | usual_padding | ||
344 | ); | ||
345 | |||
346 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0) | ||
347 | return GNUNET_MESSENGER_PADDING_LEVEL0; | ||
348 | |||
349 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1) | ||
350 | return GNUNET_MESSENGER_PADDING_LEVEL1; | ||
351 | |||
352 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2) | ||
353 | return GNUNET_MESSENGER_PADDING_LEVEL2; | ||
354 | |||
355 | return GNUNET_MESSENGER_MAX_MESSAGE_SIZE; | ||
356 | |||
357 | } | ||
358 | |||
359 | #define min(x, y) (x < y? x : y) | ||
360 | |||
361 | #define encode_step_ext(dst, offset, src, size) do { \ | ||
362 | GNUNET_memcpy(dst + offset, src, size); \ | ||
363 | offset += size; \ | ||
364 | } while (0) | ||
365 | |||
366 | #define encode_step(dst, offset, src) do { \ | ||
367 | encode_step_ext(dst, offset, src, sizeof(*src)); \ | ||
368 | } while (0) | ||
369 | |||
370 | #define encode_step_key(dst, offset, src, length) do { \ | ||
371 | ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \ | ||
372 | src, dst + offset, length - offset \ | ||
373 | ); \ | ||
374 | if (result < 0) \ | ||
375 | GNUNET_break (0); \ | ||
376 | else \ | ||
377 | offset += result; \ | ||
378 | } while (0) | ||
379 | |||
380 | #define encode_step_signature(dst, offset, src, length) do { \ | ||
381 | ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \ | ||
382 | src, dst + offset, length - offset \ | ||
383 | ); \ | ||
384 | if (result < 0) \ | ||
385 | GNUNET_break (0); \ | ||
386 | else \ | ||
387 | offset += result; \ | ||
388 | } while (0) | ||
389 | |||
390 | static void | ||
391 | encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, | ||
392 | const struct GNUNET_MESSENGER_MessageBody *body, | ||
393 | uint16_t length, | ||
394 | char *buffer, | ||
395 | uint16_t offset) | ||
396 | { | ||
397 | uint32_t version; | ||
398 | switch (kind) | ||
399 | { | ||
400 | case GNUNET_MESSENGER_KIND_INFO: | ||
401 | version = GNUNET_htobe32(body->info.messenger_version); | ||
402 | |||
403 | encode_step_key(buffer, offset, &(body->info.host_key), length); | ||
404 | encode_step(buffer, offset, &version); | ||
405 | break; | ||
406 | case GNUNET_MESSENGER_KIND_JOIN: | ||
407 | encode_step_key(buffer, offset, &(body->join.key), length); | ||
408 | break; | ||
409 | case GNUNET_MESSENGER_KIND_NAME: | ||
410 | if (body->name.name) | ||
411 | encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); | ||
412 | break; | ||
413 | case GNUNET_MESSENGER_KIND_KEY: | ||
414 | encode_step_key(buffer, offset, &(body->key.key), length); | ||
415 | break; | ||
416 | case GNUNET_MESSENGER_KIND_PEER: | ||
417 | encode_step(buffer, offset, &(body->peer.peer)); | ||
418 | break; | ||
419 | case GNUNET_MESSENGER_KIND_ID: | ||
420 | encode_step(buffer, offset, &(body->id.id)); | ||
421 | break; | ||
422 | case GNUNET_MESSENGER_KIND_MISS: | ||
423 | encode_step(buffer, offset, &(body->miss.peer)); | ||
424 | break; | ||
425 | case GNUNET_MESSENGER_KIND_MERGE: | ||
426 | encode_step(buffer, offset, &(body->merge.previous)); | ||
427 | break; | ||
428 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
429 | encode_step(buffer, offset, &(body->request.hash)); | ||
430 | break; | ||
431 | case GNUNET_MESSENGER_KIND_INVITE: | ||
432 | encode_step(buffer, offset, &(body->invite.door)); | ||
433 | encode_step(buffer, offset, &(body->invite.key)); | ||
434 | break; | ||
435 | case GNUNET_MESSENGER_KIND_TEXT: | ||
436 | encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text))); | ||
437 | break; | ||
438 | case GNUNET_MESSENGER_KIND_FILE: | ||
439 | encode_step(buffer, offset, &(body->file.key)); | ||
440 | encode_step(buffer, offset, &(body->file.hash)); | ||
441 | encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name)); | ||
442 | encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); | ||
443 | break; | ||
444 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
445 | encode_step(buffer, offset, &(body->privacy.key)); | ||
446 | encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length)); | ||
447 | break; | ||
448 | default: | ||
449 | break; | ||
450 | } | ||
451 | |||
452 | if (offset >= length) | ||
453 | return; | ||
454 | |||
455 | const uint16_t padding = length - offset; | ||
456 | const uint16_t used_padding = sizeof(padding) + sizeof(char); | ||
457 | |||
458 | GNUNET_assert(padding >= used_padding); | ||
459 | |||
460 | buffer[offset++] = '\0'; | ||
461 | |||
462 | if (padding > used_padding) | ||
463 | GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding); | ||
464 | |||
465 | GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding)); | ||
466 | } | ||
467 | |||
468 | void | ||
469 | encode_message (const struct GNUNET_MESSENGER_Message *message, | ||
470 | uint16_t length, | ||
471 | char *buffer, | ||
472 | int include_header) | ||
473 | { | ||
474 | GNUNET_assert((message) && (buffer)); | ||
475 | |||
476 | uint16_t offset = 0; | ||
477 | |||
478 | if (GNUNET_YES == include_header) | ||
479 | encode_step_signature(buffer, offset, &(message->header.signature), length); | ||
480 | |||
481 | const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind); | ||
482 | |||
483 | if (GNUNET_YES == include_header) | ||
484 | { | ||
485 | encode_step(buffer, offset, &(message->header.timestamp)); | ||
486 | encode_step(buffer, offset, &(message->header.sender_id)); | ||
487 | encode_step(buffer, offset, &(message->header.previous)); | ||
488 | } | ||
489 | |||
490 | encode_step(buffer, offset, &kind); | ||
491 | |||
492 | encode_message_body (message->header.kind, &(message->body), length, buffer, offset); | ||
493 | } | ||
494 | |||
495 | static void | ||
496 | encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, | ||
497 | uint16_t length, | ||
498 | char *buffer) | ||
499 | { | ||
500 | struct GNUNET_HashCode hash; | ||
501 | uint16_t offset = sizeof(hash); | ||
502 | |||
503 | const kind_t kind = GNUNET_htobe32((kind_t) message->kind); | ||
504 | |||
505 | encode_step(buffer, offset, &kind); | ||
506 | |||
507 | encode_message_body (message->kind, &(message->body), length, buffer, offset); | ||
508 | |||
509 | GNUNET_CRYPTO_hash( | ||
510 | buffer + sizeof(hash), | ||
511 | length - sizeof(hash), | ||
512 | &hash | ||
513 | ); | ||
514 | |||
515 | GNUNET_memcpy(buffer, &hash, sizeof(hash)); | ||
516 | } | ||
517 | |||
518 | #define decode_step_ext(src, offset, dst, size) do { \ | ||
519 | GNUNET_memcpy(dst, src + offset, size); \ | ||
520 | offset += size; \ | ||
521 | } while (0) | ||
522 | |||
523 | #define decode_step(src, offset, dst) do { \ | ||
524 | decode_step_ext(src, offset, dst, sizeof(*dst)); \ | ||
525 | } while (0) | ||
526 | |||
527 | #define decode_step_malloc(src, offset, dst, size, zero) do { \ | ||
528 | dst = GNUNET_malloc(size + zero); \ | ||
529 | if (zero) dst[size] = 0; \ | ||
530 | decode_step_ext(src, offset, dst, size); \ | ||
531 | } while (0) | ||
532 | |||
533 | #define decode_step_key(src, offset, dst, length) do { \ | ||
534 | ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \ | ||
535 | dst, src + offset, length - offset \ | ||
536 | ); \ | ||
537 | if (result < 0) \ | ||
538 | GNUNET_break(0); \ | ||
539 | else \ | ||
540 | offset += result; \ | ||
541 | } while (0) | ||
542 | |||
543 | static uint16_t | ||
544 | decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, | ||
545 | struct GNUNET_MESSENGER_MessageBody *body, | ||
546 | uint16_t length, | ||
547 | const char *buffer, | ||
548 | uint16_t offset) | ||
549 | { | ||
550 | uint16_t padding = 0; | ||
551 | |||
552 | GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding)); | ||
553 | |||
554 | if (padding > length - offset) | ||
555 | padding = 0; | ||
556 | |||
557 | const uint16_t end_zero = length - padding; | ||
558 | |||
559 | if ((padding) && (buffer[end_zero] != '\0')) | ||
560 | padding = 0; | ||
561 | |||
562 | length -= padding; | ||
563 | |||
564 | uint32_t version; | ||
565 | switch (*kind) | ||
566 | { | ||
567 | case GNUNET_MESSENGER_KIND_INFO: { | ||
568 | decode_step_key(buffer, offset, &(body->info.host_key), length); | ||
569 | decode_step(buffer, offset, &version); | ||
570 | |||
571 | body->info.messenger_version = GNUNET_be32toh(version); | ||
572 | break; | ||
573 | } case GNUNET_MESSENGER_KIND_JOIN: { | ||
574 | decode_step_key(buffer, offset, &(body->join.key), length); | ||
575 | break; | ||
576 | } case GNUNET_MESSENGER_KIND_NAME: | ||
577 | if (length - offset > 0) | ||
578 | decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); | ||
579 | else | ||
580 | body->name.name = NULL; | ||
581 | break; | ||
582 | case GNUNET_MESSENGER_KIND_KEY: | ||
583 | decode_step_key(buffer, offset, &(body->key.key), length); | ||
584 | break; | ||
585 | case GNUNET_MESSENGER_KIND_PEER: | ||
586 | decode_step(buffer, offset, &(body->peer.peer)); | ||
587 | break; | ||
588 | case GNUNET_MESSENGER_KIND_ID: | ||
589 | decode_step(buffer, offset, &(body->id.id)); | ||
590 | break; | ||
591 | case GNUNET_MESSENGER_KIND_MISS: | ||
592 | decode_step(buffer, offset, &(body->miss.peer)); | ||
593 | break; | ||
594 | case GNUNET_MESSENGER_KIND_MERGE: | ||
595 | decode_step(buffer, offset, &(body->merge.previous)); | ||
596 | break; | ||
597 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
598 | decode_step(buffer, offset, &(body->request.hash)); | ||
599 | break; | ||
600 | case GNUNET_MESSENGER_KIND_INVITE: | ||
601 | decode_step(buffer, offset, &(body->invite.door)); | ||
602 | decode_step(buffer, offset, &(body->invite.key)); | ||
603 | break; | ||
604 | case GNUNET_MESSENGER_KIND_TEXT: | ||
605 | decode_step_malloc(buffer, offset, body->text.text, length - offset, 1); | ||
606 | break; | ||
607 | case GNUNET_MESSENGER_KIND_FILE: | ||
608 | decode_step(buffer, offset, &(body->file.key)); | ||
609 | decode_step(buffer, offset, &(body->file.hash)); | ||
610 | decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name)); | ||
611 | decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); | ||
612 | break; | ||
613 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
614 | decode_step(buffer, offset, &(body->privacy.key)); | ||
615 | |||
616 | body->privacy.length = (length - offset); | ||
617 | decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0); | ||
618 | break; | ||
619 | default: | ||
620 | *kind = GNUNET_MESSENGER_KIND_UNKNOWN; | ||
621 | break; | ||
622 | } | ||
623 | |||
624 | return padding; | ||
625 | } | ||
626 | |||
627 | int | ||
628 | decode_message (struct GNUNET_MESSENGER_Message *message, | ||
629 | uint16_t length, | ||
630 | const char *buffer, | ||
631 | int include_header, | ||
632 | uint16_t *padding) | ||
633 | { | ||
634 | GNUNET_assert( | ||
635 | (message) && | ||
636 | (buffer) && | ||
637 | (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, include_header)) | ||
638 | ); | ||
639 | |||
640 | uint16_t offset = 0; | ||
641 | |||
642 | if (GNUNET_YES == include_header) | ||
643 | { | ||
644 | ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer( | ||
645 | &(message->header.signature), buffer, length - offset | ||
646 | ); | ||
647 | |||
648 | if (result < 0) | ||
649 | return GNUNET_NO; | ||
650 | else | ||
651 | offset += result; | ||
652 | } | ||
653 | |||
654 | const uint16_t count = length - offset; | ||
655 | |||
656 | if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, include_header)) | ||
657 | return GNUNET_NO; | ||
658 | |||
659 | kind_t kind; | ||
660 | |||
661 | if (GNUNET_YES == include_header) | ||
662 | { | ||
663 | decode_step(buffer, offset, &(message->header.timestamp)); | ||
664 | decode_step(buffer, offset, &(message->header.sender_id)); | ||
665 | decode_step(buffer, offset, &(message->header.previous)); | ||
666 | } | ||
667 | |||
668 | decode_step(buffer, offset, &kind); | ||
669 | |||
670 | message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind); | ||
671 | |||
672 | if (count < get_message_kind_size (message->header.kind, include_header)) | ||
673 | return GNUNET_NO; | ||
674 | |||
675 | const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); | ||
676 | |||
677 | if (padding) | ||
678 | *padding = result; | ||
679 | |||
680 | return GNUNET_YES; | ||
681 | } | ||
682 | |||
683 | static int | ||
684 | decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, | ||
685 | uint16_t length, | ||
686 | const char *buffer) | ||
687 | { | ||
688 | struct GNUNET_HashCode expected, hash; | ||
689 | uint16_t offset = sizeof(hash); | ||
690 | |||
691 | if (length < get_short_message_size (NULL, GNUNET_NO)) | ||
692 | return GNUNET_NO; | ||
693 | |||
694 | GNUNET_memcpy(&hash, buffer, sizeof(hash)); | ||
695 | |||
696 | GNUNET_CRYPTO_hash( | ||
697 | buffer + sizeof(hash), | ||
698 | length - sizeof(hash), | ||
699 | &expected | ||
700 | ); | ||
701 | |||
702 | if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected)) | ||
703 | return GNUNET_NO; | ||
704 | |||
705 | kind_t kind; | ||
706 | |||
707 | decode_step(buffer, offset, &kind); | ||
708 | |||
709 | message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind); | ||
710 | |||
711 | if (length < get_short_message_size (message, GNUNET_NO)) | ||
712 | return GNUNET_NO; | ||
713 | |||
714 | decode_message_body (&(message->kind), &(message->body), length, buffer, offset); | ||
715 | |||
716 | if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind) | ||
717 | return GNUNET_NO; | ||
718 | |||
719 | return GNUNET_YES; | ||
720 | } | ||
721 | |||
722 | void | ||
723 | hash_message (const struct GNUNET_MESSENGER_Message *message, | ||
724 | uint16_t length, | ||
725 | const char *buffer, | ||
726 | struct GNUNET_HashCode *hash) | ||
727 | { | ||
728 | GNUNET_assert((message) && (buffer) && (hash)); | ||
729 | |||
730 | const ssize_t offset = GNUNET_IDENTITY_signature_get_length( | ||
731 | &(message->header.signature) | ||
732 | ); | ||
733 | |||
734 | GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash); | ||
735 | } | ||
736 | |||
737 | void | ||
738 | sign_message (struct GNUNET_MESSENGER_Message *message, | ||
739 | uint16_t length, | ||
740 | char *buffer, | ||
741 | const struct GNUNET_HashCode *hash, | ||
742 | const struct GNUNET_MESSENGER_Ego *ego) | ||
743 | { | ||
744 | GNUNET_assert((message) && (buffer) && (hash) && (ego)); | ||
745 | |||
746 | struct GNUNET_MESSENGER_MessageSignature signature; | ||
747 | |||
748 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | ||
749 | signature.purpose.size = htonl (sizeof(signature)); | ||
750 | |||
751 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); | ||
752 | GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); | ||
753 | |||
754 | uint16_t offset = 0; | ||
755 | encode_step_signature(buffer, offset, &(message->header.signature), length); | ||
756 | } | ||
757 | |||
758 | int | ||
759 | verify_message (const struct GNUNET_MESSENGER_Message *message, | ||
760 | const struct GNUNET_HashCode *hash, | ||
761 | const struct GNUNET_IDENTITY_PublicKey *key) | ||
762 | { | ||
763 | GNUNET_assert((message) && (hash) && (key)); | ||
764 | |||
765 | if (ntohl (key->type) != ntohl (message->header.signature.type)) | ||
766 | return GNUNET_SYSERR; | ||
767 | |||
768 | struct GNUNET_MESSENGER_MessageSignature signature; | ||
769 | |||
770 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | ||
771 | signature.purpose.size = htonl (sizeof(signature)); | ||
772 | |||
773 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); | ||
774 | |||
775 | return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature, | ||
776 | &(message->header.signature), key); | ||
777 | } | ||
778 | |||
779 | int | ||
780 | encrypt_message (struct GNUNET_MESSENGER_Message *message, | ||
781 | const struct GNUNET_IDENTITY_PublicKey *key) | ||
782 | { | ||
783 | GNUNET_assert((message) && (key)); | ||
784 | |||
785 | struct GNUNET_MESSENGER_ShortMessage shortened; | ||
786 | |||
787 | fold_short_message (message, &shortened); | ||
788 | |||
789 | const uint16_t length = get_short_message_size (&shortened, GNUNET_YES); | ||
790 | const uint16_t padded_length = calc_padded_length(length); | ||
791 | |||
792 | message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; | ||
793 | message->body.privacy.data = GNUNET_malloc(padded_length); | ||
794 | message->body.privacy.length = padded_length; | ||
795 | |||
796 | encode_short_message (&shortened, padded_length, message->body.privacy.data); | ||
797 | |||
798 | if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key, | ||
799 | &(message->body.privacy.key), | ||
800 | message->body.privacy.data)) | ||
801 | { | ||
802 | destroy_message_body (shortened.kind, &(shortened.body)); | ||
803 | return GNUNET_YES; | ||
804 | } | ||
805 | else | ||
806 | { | ||
807 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n"); | ||
808 | |||
809 | unfold_short_message (&shortened, message); | ||
810 | return GNUNET_NO; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | int | ||
815 | decrypt_message (struct GNUNET_MESSENGER_Message *message, | ||
816 | const struct GNUNET_IDENTITY_PrivateKey *key) | ||
817 | { | ||
818 | GNUNET_assert((message) && (key)); | ||
819 | |||
820 | if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length, | ||
821 | key, &(message->body.privacy.key), | ||
822 | message->body.privacy.data)) | ||
823 | { | ||
824 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n"); | ||
825 | |||
826 | return GNUNET_NO; | ||
827 | } | ||
828 | |||
829 | struct GNUNET_MESSENGER_ShortMessage shortened; | ||
830 | |||
831 | if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data)) | ||
832 | { | ||
833 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n"); | ||
834 | |||
835 | return GNUNET_NO; | ||
836 | } | ||
837 | |||
838 | unfold_short_message (&shortened, message); | ||
839 | |||
840 | return GNUNET_YES; | ||
841 | } | ||
842 | |||
843 | struct GNUNET_MQ_Envelope* | ||
844 | pack_message (struct GNUNET_MESSENGER_Message *message, | ||
845 | struct GNUNET_HashCode *hash, | ||
846 | const struct GNUNET_MESSENGER_Ego *ego, | ||
847 | int mode) | ||
848 | { | ||
849 | GNUNET_assert(message); | ||
850 | |||
851 | if (ego) | ||
852 | message->header.signature.type = ego->priv.type; | ||
853 | |||
854 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n", | ||
855 | message->header.kind, GNUNET_sh2s(&(message->header.sender_id))); | ||
856 | |||
857 | struct GNUNET_MessageHeader *header; | ||
858 | |||
859 | const uint16_t length = get_message_size (message, GNUNET_YES); | ||
860 | const uint16_t padded_length = calc_padded_length(length); | ||
861 | |||
862 | struct GNUNET_MQ_Envelope *env; | ||
863 | char *buffer; | ||
864 | |||
865 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) | ||
866 | { | ||
867 | env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI); | ||
868 | |||
869 | buffer = (char*) &(header[1]); | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | env = NULL; | ||
874 | |||
875 | buffer = GNUNET_malloc(padded_length); | ||
876 | } | ||
877 | |||
878 | encode_message (message, padded_length, buffer, GNUNET_YES); | ||
879 | |||
880 | if (hash) | ||
881 | { | ||
882 | hash_message (message, length, buffer, hash); | ||
883 | |||
884 | if (ego) | ||
885 | sign_message (message, length, buffer, hash, ego); | ||
886 | } | ||
887 | |||
888 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode) | ||
889 | GNUNET_free(buffer); | ||
890 | |||
891 | return env; | ||
892 | } | ||
893 | |||
894 | int | ||
895 | filter_message_sending (const struct GNUNET_MESSENGER_Message *message) | ||
896 | { | ||
897 | switch (message->header.kind) | ||
898 | { | ||
899 | case GNUNET_MESSENGER_KIND_INFO: | ||
900 | return GNUNET_SYSERR; // Reserved for connection handling only! | ||
901 | case GNUNET_MESSENGER_KIND_JOIN: | ||
902 | return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead! | ||
903 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
904 | return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead! | ||
905 | case GNUNET_MESSENGER_KIND_NAME: | ||
906 | return GNUNET_YES; | ||
907 | case GNUNET_MESSENGER_KIND_KEY: | ||
908 | return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead! | ||
909 | case GNUNET_MESSENGER_KIND_PEER: | ||
910 | return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead! | ||
911 | case GNUNET_MESSENGER_KIND_ID: | ||
912 | return GNUNET_SYSERR; // Reserved for member id handling only! | ||
913 | case GNUNET_MESSENGER_KIND_MISS: | ||
914 | return GNUNET_SYSERR; // Reserved for connection handling only! | ||
915 | case GNUNET_MESSENGER_KIND_MERGE: | ||
916 | return GNUNET_YES; | ||
917 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
918 | return GNUNET_YES; | ||
919 | case GNUNET_MESSENGER_KIND_INVITE: | ||
920 | return GNUNET_YES; | ||
921 | case GNUNET_MESSENGER_KIND_TEXT: | ||
922 | return GNUNET_YES; | ||
923 | case GNUNET_MESSENGER_KIND_FILE: | ||
924 | return GNUNET_YES; | ||
925 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
926 | return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead! | ||
927 | case GNUNET_MESSENGER_KIND_DELETE: | ||
928 | return GNUNET_YES; | ||
929 | default: | ||
930 | return GNUNET_SYSERR; | ||
931 | } | ||
932 | } | ||