diff options
Diffstat (limited to 'src/messenger/messenger_api_message.c')
-rw-r--r-- | src/messenger/messenger_api_message.c | 423 |
1 files changed, 346 insertions, 77 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c index fdab60eef..d88859186 100644 --- a/src/messenger/messenger_api_message.c +++ b/src/messenger/messenger_api_message.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2020 GNUnet e.V. | 3 | Copyright (C) 2020--2021 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 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 | 6 | under the terms of the GNU Affero General Public License as published |
@@ -69,6 +69,8 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind) | |||
69 | struct GNUNET_MESSENGER_Message* | 69 | struct GNUNET_MESSENGER_Message* |
70 | copy_message (const struct GNUNET_MESSENGER_Message *message) | 70 | copy_message (const struct GNUNET_MESSENGER_Message *message) |
71 | { | 71 | { |
72 | GNUNET_assert(message); | ||
73 | |||
72 | struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); | 74 | struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); |
73 | 75 | ||
74 | GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); | 76 | GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); |
@@ -125,11 +127,28 @@ destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESS | |||
125 | void | 127 | void |
126 | destroy_message (struct GNUNET_MESSENGER_Message *message) | 128 | destroy_message (struct GNUNET_MESSENGER_Message *message) |
127 | { | 129 | { |
130 | GNUNET_assert(message); | ||
131 | |||
128 | destroy_message_body (message->header.kind, &(message->body)); | 132 | destroy_message_body (message->header.kind, &(message->body)); |
129 | 133 | ||
130 | GNUNET_free(message); | 134 | GNUNET_free(message); |
131 | } | 135 | } |
132 | 136 | ||
137 | int | ||
138 | is_message_session_bound (const struct GNUNET_MESSENGER_Message *message) | ||
139 | { | ||
140 | GNUNET_assert(message); | ||
141 | |||
142 | if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) || | ||
143 | (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) || | ||
144 | (GNUNET_MESSENGER_KIND_NAME == message->header.kind) || | ||
145 | (GNUNET_MESSENGER_KIND_KEY == message->header.kind) || | ||
146 | (GNUNET_MESSENGER_KIND_ID == message->header.kind)) | ||
147 | return GNUNET_YES; | ||
148 | else | ||
149 | return GNUNET_NO; | ||
150 | } | ||
151 | |||
133 | static void | 152 | static void |
134 | fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) | 153 | fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) |
135 | { | 154 | { |
@@ -158,18 +177,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | |||
158 | switch (kind) | 177 | switch (kind) |
159 | { | 178 | { |
160 | case GNUNET_MESSENGER_KIND_INFO: | 179 | case GNUNET_MESSENGER_KIND_INFO: |
161 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.host_key); | 180 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version); |
162 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.unique_id); | ||
163 | break; | ||
164 | case GNUNET_MESSENGER_KIND_JOIN: | ||
165 | length += member_size(struct GNUNET_MESSENGER_Message, body.join.key); | ||
166 | break; | ||
167 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
168 | break; | ||
169 | case GNUNET_MESSENGER_KIND_NAME: | ||
170 | break; | ||
171 | case GNUNET_MESSENGER_KIND_KEY: | ||
172 | length += member_size(struct GNUNET_MESSENGER_Message, body.key.key); | ||
173 | break; | 181 | break; |
174 | case GNUNET_MESSENGER_KIND_PEER: | 182 | case GNUNET_MESSENGER_KIND_PEER: |
175 | length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); | 183 | length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); |
@@ -195,7 +203,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | |||
195 | case GNUNET_MESSENGER_KIND_FILE: | 203 | case GNUNET_MESSENGER_KIND_FILE: |
196 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); | 204 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); |
197 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); | 205 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); |
198 | length += NAME_MAX; | 206 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.name); |
199 | break; | 207 | break; |
200 | case GNUNET_MESSENGER_KIND_PRIVATE: | 208 | case GNUNET_MESSENGER_KIND_PRIVATE: |
201 | length += member_size(struct GNUNET_MESSENGER_Message, body.private.key); | 209 | length += member_size(struct GNUNET_MESSENGER_Message, body.private.key); |
@@ -207,16 +215,17 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | |||
207 | return length; | 215 | return length; |
208 | } | 216 | } |
209 | 217 | ||
218 | typedef uint32_t kind_t; | ||
219 | |||
210 | uint16_t | 220 | uint16_t |
211 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | 221 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) |
212 | { | 222 | { |
213 | uint16_t length = 0; | 223 | uint16_t length = 0; |
214 | 224 | ||
215 | length += member_size(struct GNUNET_MESSENGER_Message, header.signature); | ||
216 | length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); | 225 | length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); |
217 | length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); | 226 | length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); |
218 | length += member_size(struct GNUNET_MESSENGER_Message, header.previous); | 227 | length += member_size(struct GNUNET_MESSENGER_Message, header.previous); |
219 | length += member_size(struct GNUNET_MESSENGER_Message, header.kind); | 228 | length += sizeof(kind_t); |
220 | 229 | ||
221 | return length + get_message_body_kind_size (kind); | 230 | return length + get_message_body_kind_size (kind); |
222 | } | 231 | } |
@@ -228,8 +237,17 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN | |||
228 | 237 | ||
229 | switch (kind) | 238 | switch (kind) |
230 | { | 239 | { |
240 | case GNUNET_MESSENGER_KIND_INFO: | ||
241 | length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key)); | ||
242 | break; | ||
243 | case GNUNET_MESSENGER_KIND_JOIN: | ||
244 | length += GNUNET_IDENTITY_key_get_length(&(body->join.key)); | ||
245 | break; | ||
231 | case GNUNET_MESSENGER_KIND_NAME: | 246 | case GNUNET_MESSENGER_KIND_NAME: |
232 | length += (body->name.name? strlen (body->name.name) : 0); | 247 | length += (body->name.name ? strlen (body->name.name) : 0); |
248 | break; | ||
249 | case GNUNET_MESSENGER_KIND_KEY: | ||
250 | length += GNUNET_IDENTITY_key_get_length(&(body->key.key)); | ||
233 | break; | 251 | break; |
234 | case GNUNET_MESSENGER_KIND_TEXT: | 252 | case GNUNET_MESSENGER_KIND_TEXT: |
235 | length += strlen (body->text.text); | 253 | length += strlen (body->text.text); |
@@ -248,19 +266,76 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN | |||
248 | } | 266 | } |
249 | 267 | ||
250 | uint16_t | 268 | uint16_t |
251 | get_message_size (const struct GNUNET_MESSENGER_Message *message) | 269 | get_message_size (const struct GNUNET_MESSENGER_Message *message, |
270 | int include_signature) | ||
252 | { | 271 | { |
253 | return get_message_kind_size (message->header.kind) + get_message_body_size (message->header.kind, &(message->body)); | 272 | GNUNET_assert(message); |
273 | |||
274 | uint16_t length = 0; | ||
275 | |||
276 | if (GNUNET_YES == include_signature) | ||
277 | length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature)); | ||
278 | |||
279 | length += get_message_kind_size (message->header.kind); | ||
280 | length += get_message_body_size (message->header.kind, &(message->body)); | ||
281 | |||
282 | return length; | ||
254 | } | 283 | } |
255 | 284 | ||
256 | static uint16_t | 285 | static uint16_t |
257 | get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) | 286 | get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message, int include_body) |
258 | { | 287 | { |
288 | const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t); | ||
289 | |||
259 | if (message) | 290 | if (message) |
260 | return sizeof(message->kind) + get_message_body_kind_size (message->kind) | 291 | return minimum_size + get_message_body_kind_size (message->kind) |
261 | + get_message_body_size (message->kind, &(message->body)); | 292 | + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0); |
262 | else | 293 | else |
263 | return sizeof(message->kind); | 294 | return minimum_size; |
295 | } | ||
296 | |||
297 | static uint16_t | ||
298 | calc_usual_padding () | ||
299 | { | ||
300 | uint16_t padding = 0; | ||
301 | uint16_t kind_size; | ||
302 | |||
303 | for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) { | ||
304 | kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i); | ||
305 | |||
306 | if (kind_size > padding) | ||
307 | padding = kind_size; | ||
308 | } | ||
309 | |||
310 | return padding + GNUNET_MESSENGER_PADDING_MIN; | ||
311 | } | ||
312 | |||
313 | #define max(x, y) (x > y? x : y) | ||
314 | |||
315 | static uint16_t | ||
316 | calc_padded_length (uint16_t length) | ||
317 | { | ||
318 | static uint16_t usual_padding = 0; | ||
319 | |||
320 | if (!usual_padding) | ||
321 | usual_padding = calc_usual_padding(); | ||
322 | |||
323 | const uint16_t padded_length = max( | ||
324 | length + GNUNET_MESSENGER_PADDING_MIN, | ||
325 | usual_padding | ||
326 | ); | ||
327 | |||
328 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0) | ||
329 | return GNUNET_MESSENGER_PADDING_LEVEL0; | ||
330 | |||
331 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1) | ||
332 | return GNUNET_MESSENGER_PADDING_LEVEL1; | ||
333 | |||
334 | if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2) | ||
335 | return GNUNET_MESSENGER_PADDING_LEVEL2; | ||
336 | |||
337 | return GNUNET_MESSENGER_MAX_MESSAGE_SIZE; | ||
338 | |||
264 | } | 339 | } |
265 | 340 | ||
266 | #define min(x, y) (x < y? x : y) | 341 | #define min(x, y) (x < y? x : y) |
@@ -272,7 +347,27 @@ get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) | |||
272 | 347 | ||
273 | #define encode_step(dst, offset, src) do { \ | 348 | #define encode_step(dst, offset, src) do { \ |
274 | encode_step_ext(dst, offset, src, sizeof(*src)); \ | 349 | encode_step_ext(dst, offset, src, sizeof(*src)); \ |
275 | } while(0) | 350 | } while (0) |
351 | |||
352 | #define encode_step_key(dst, offset, src, length) do { \ | ||
353 | ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \ | ||
354 | src, dst + offset, length - offset \ | ||
355 | ); \ | ||
356 | if (result < 0) \ | ||
357 | GNUNET_break (0); \ | ||
358 | else \ | ||
359 | offset += result; \ | ||
360 | } while (0) | ||
361 | |||
362 | #define encode_step_signature(dst, offset, src, length) do { \ | ||
363 | ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \ | ||
364 | src, dst + offset, length - offset \ | ||
365 | ); \ | ||
366 | if (result < 0) \ | ||
367 | GNUNET_break (0); \ | ||
368 | else \ | ||
369 | offset += result; \ | ||
370 | } while (0) | ||
276 | 371 | ||
277 | static void | 372 | static void |
278 | encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, | 373 | encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, |
@@ -281,20 +376,18 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET | |||
281 | switch (kind) | 376 | switch (kind) |
282 | { | 377 | { |
283 | case GNUNET_MESSENGER_KIND_INFO: | 378 | case GNUNET_MESSENGER_KIND_INFO: |
284 | encode_step(buffer, offset, &(body->info.host_key)); | 379 | encode_step_key(buffer, offset, &(body->info.host_key), length); |
285 | encode_step(buffer, offset, &(body->info.unique_id)); | 380 | encode_step(buffer, offset, &(body->info.messenger_version)); |
286 | break; | 381 | break; |
287 | case GNUNET_MESSENGER_KIND_JOIN: | 382 | case GNUNET_MESSENGER_KIND_JOIN: |
288 | encode_step(buffer, offset, &(body->join.key)); | 383 | encode_step_key(buffer, offset, &(body->join.key), length); |
289 | break; | ||
290 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
291 | break; | 384 | break; |
292 | case GNUNET_MESSENGER_KIND_NAME: | 385 | case GNUNET_MESSENGER_KIND_NAME: |
293 | if (body->name.name) | 386 | if (body->name.name) |
294 | encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); | 387 | encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); |
295 | break; | 388 | break; |
296 | case GNUNET_MESSENGER_KIND_KEY: | 389 | case GNUNET_MESSENGER_KIND_KEY: |
297 | encode_step(buffer, offset, &(body->key.key)); | 390 | encode_step_key(buffer, offset, &(body->key.key), length); |
298 | break; | 391 | break; |
299 | case GNUNET_MESSENGER_KIND_PEER: | 392 | case GNUNET_MESSENGER_KIND_PEER: |
300 | encode_step(buffer, offset, &(body->peer.peer)); | 393 | encode_step(buffer, offset, &(body->peer.peer)); |
@@ -321,7 +414,7 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET | |||
321 | case GNUNET_MESSENGER_KIND_FILE: | 414 | case GNUNET_MESSENGER_KIND_FILE: |
322 | encode_step(buffer, offset, &(body->file.key)); | 415 | encode_step(buffer, offset, &(body->file.key)); |
323 | encode_step(buffer, offset, &(body->file.hash)); | 416 | encode_step(buffer, offset, &(body->file.hash)); |
324 | encode_step_ext(buffer, offset, body->file.name, NAME_MAX); | 417 | encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name)); |
325 | encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); | 418 | encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); |
326 | break; | 419 | break; |
327 | case GNUNET_MESSENGER_KIND_PRIVATE: | 420 | case GNUNET_MESSENGER_KIND_PRIVATE: |
@@ -331,18 +424,40 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET | |||
331 | default: | 424 | default: |
332 | break; | 425 | break; |
333 | } | 426 | } |
427 | |||
428 | if (offset >= length) | ||
429 | return; | ||
430 | |||
431 | const uint16_t padding = length - offset; | ||
432 | const uint16_t used_padding = sizeof(padding) + sizeof(char); | ||
433 | |||
434 | GNUNET_assert(padding >= used_padding); | ||
435 | |||
436 | buffer[offset++] = '\0'; | ||
437 | |||
438 | if (padding > used_padding) | ||
439 | GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding); | ||
440 | |||
441 | GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding)); | ||
334 | } | 442 | } |
335 | 443 | ||
336 | void | 444 | void |
337 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer) | 445 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, |
446 | int include_signature) | ||
338 | { | 447 | { |
448 | GNUNET_assert((message) && (buffer)); | ||
449 | |||
339 | uint16_t offset = 0; | 450 | uint16_t offset = 0; |
340 | 451 | ||
341 | encode_step(buffer, offset, &(message->header.signature)); | 452 | if (GNUNET_YES == include_signature) |
453 | encode_step_signature(buffer, offset, &(message->header.signature), length); | ||
454 | |||
455 | const kind_t kind = (kind_t) message->header.kind; | ||
456 | |||
342 | encode_step(buffer, offset, &(message->header.timestamp)); | 457 | encode_step(buffer, offset, &(message->header.timestamp)); |
343 | encode_step(buffer, offset, &(message->header.sender_id)); | 458 | encode_step(buffer, offset, &(message->header.sender_id)); |
344 | encode_step(buffer, offset, &(message->header.previous)); | 459 | encode_step(buffer, offset, &(message->header.previous)); |
345 | encode_step(buffer, offset, &(message->header.kind)); | 460 | encode_step(buffer, offset, &kind); |
346 | 461 | ||
347 | encode_message_body (message->header.kind, &(message->body), length, buffer, offset); | 462 | encode_message_body (message->header.kind, &(message->body), length, buffer, offset); |
348 | } | 463 | } |
@@ -350,11 +465,22 @@ encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, | |||
350 | static void | 465 | static void |
351 | encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) | 466 | encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) |
352 | { | 467 | { |
353 | uint16_t offset = 0; | 468 | struct GNUNET_HashCode hash; |
469 | uint16_t offset = sizeof(hash); | ||
354 | 470 | ||
355 | encode_step(buffer, offset, &(message->kind)); | 471 | const kind_t kind = (kind_t) message->kind; |
472 | |||
473 | encode_step(buffer, offset, &kind); | ||
356 | 474 | ||
357 | encode_message_body (message->kind, &(message->body), length, buffer, offset); | 475 | encode_message_body (message->kind, &(message->body), length, buffer, offset); |
476 | |||
477 | GNUNET_CRYPTO_hash( | ||
478 | buffer + sizeof(hash), | ||
479 | length - sizeof(hash), | ||
480 | &hash | ||
481 | ); | ||
482 | |||
483 | GNUNET_memcpy(buffer, &hash, sizeof(hash)); | ||
358 | } | 484 | } |
359 | 485 | ||
360 | #define decode_step_ext(src, offset, dst, size) do { \ | 486 | #define decode_step_ext(src, offset, dst, size) do { \ |
@@ -372,29 +498,51 @@ encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint1 | |||
372 | decode_step_ext(src, offset, dst, size); \ | 498 | decode_step_ext(src, offset, dst, size); \ |
373 | } while (0) | 499 | } while (0) |
374 | 500 | ||
375 | static void | 501 | #define decode_step_key(src, offset, dst, length) do { \ |
502 | ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \ | ||
503 | dst, src + offset, length - offset \ | ||
504 | ); \ | ||
505 | if (result < 0) \ | ||
506 | GNUNET_break(0); \ | ||
507 | else \ | ||
508 | offset += result; \ | ||
509 | } while (0) | ||
510 | |||
511 | static uint16_t | ||
376 | decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, | 512 | decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, |
377 | uint16_t length, const char *buffer, uint16_t offset) | 513 | uint16_t length, const char *buffer, uint16_t offset) |
378 | { | 514 | { |
515 | uint16_t padding = 0; | ||
516 | |||
517 | GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding)); | ||
518 | |||
519 | if (padding > length - offset) | ||
520 | padding = 0; | ||
521 | |||
522 | const uint16_t end_zero = length - padding; | ||
523 | |||
524 | if ((padding) && (buffer[end_zero] != '\0')) | ||
525 | padding = 0; | ||
526 | |||
527 | length -= padding; | ||
528 | |||
379 | switch (*kind) | 529 | switch (*kind) |
380 | { | 530 | { |
381 | case GNUNET_MESSENGER_KIND_INFO: | 531 | case GNUNET_MESSENGER_KIND_INFO: { |
382 | decode_step(buffer, offset, &(body->info.host_key)); | 532 | decode_step_key(buffer, offset, &(body->info.host_key), length); |
383 | decode_step(buffer, offset, &(body->info.unique_id)); | 533 | decode_step(buffer, offset, &(body->info.messenger_version)); |
384 | break; | 534 | break; |
385 | case GNUNET_MESSENGER_KIND_JOIN: | 535 | } case GNUNET_MESSENGER_KIND_JOIN: { |
386 | decode_step(buffer, offset, &(body->join.key)); | 536 | decode_step_key(buffer, offset, &(body->join.key), length); |
387 | break; | ||
388 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
389 | break; | 537 | break; |
390 | case GNUNET_MESSENGER_KIND_NAME: | 538 | } case GNUNET_MESSENGER_KIND_NAME: |
391 | if (length - offset > 0) | 539 | if (length - offset > 0) |
392 | decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); | 540 | decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); |
393 | else | 541 | else |
394 | body->name.name = NULL; | 542 | body->name.name = NULL; |
395 | break; | 543 | break; |
396 | case GNUNET_MESSENGER_KIND_KEY: | 544 | case GNUNET_MESSENGER_KIND_KEY: |
397 | decode_step(buffer, offset, &(body->key.key)); | 545 | decode_step_key(buffer, offset, &(body->key.key), length); |
398 | break; | 546 | break; |
399 | case GNUNET_MESSENGER_KIND_PEER: | 547 | case GNUNET_MESSENGER_KIND_PEER: |
400 | decode_step(buffer, offset, &(body->peer.peer)); | 548 | decode_step(buffer, offset, &(body->peer.peer)); |
@@ -421,7 +569,7 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS | |||
421 | case GNUNET_MESSENGER_KIND_FILE: | 569 | case GNUNET_MESSENGER_KIND_FILE: |
422 | decode_step(buffer, offset, &(body->file.key)); | 570 | decode_step(buffer, offset, &(body->file.key)); |
423 | decode_step(buffer, offset, &(body->file.hash)); | 571 | decode_step(buffer, offset, &(body->file.hash)); |
424 | decode_step_ext(buffer, offset, body->file.name, NAME_MAX); | 572 | decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name)); |
425 | decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); | 573 | decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); |
426 | break; | 574 | break; |
427 | case GNUNET_MESSENGER_KIND_PRIVATE: | 575 | case GNUNET_MESSENGER_KIND_PRIVATE: |
@@ -434,26 +582,51 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS | |||
434 | *kind = GNUNET_MESSENGER_KIND_UNKNOWN; | 582 | *kind = GNUNET_MESSENGER_KIND_UNKNOWN; |
435 | break; | 583 | break; |
436 | } | 584 | } |
585 | |||
586 | return padding; | ||
437 | } | 587 | } |
438 | 588 | ||
439 | int | 589 | int |
440 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer) | 590 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, |
591 | int include_signature, uint16_t *padding) | ||
441 | { | 592 | { |
593 | GNUNET_assert((message) && (buffer)); | ||
594 | |||
442 | uint16_t offset = 0; | 595 | uint16_t offset = 0; |
443 | 596 | ||
444 | if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN)) | 597 | if (GNUNET_YES == include_signature) |
598 | { | ||
599 | ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer( | ||
600 | &(message->header.signature), buffer, length - offset | ||
601 | ); | ||
602 | |||
603 | if (result < 0) | ||
604 | return GNUNET_NO; | ||
605 | else | ||
606 | offset += result; | ||
607 | } | ||
608 | |||
609 | const uint16_t count = length - offset; | ||
610 | |||
611 | if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN)) | ||
445 | return GNUNET_NO; | 612 | return GNUNET_NO; |
446 | 613 | ||
447 | decode_step(buffer, offset, &(message->header.signature)); | 614 | kind_t kind; |
615 | |||
448 | decode_step(buffer, offset, &(message->header.timestamp)); | 616 | decode_step(buffer, offset, &(message->header.timestamp)); |
449 | decode_step(buffer, offset, &(message->header.sender_id)); | 617 | decode_step(buffer, offset, &(message->header.sender_id)); |
450 | decode_step(buffer, offset, &(message->header.previous)); | 618 | decode_step(buffer, offset, &(message->header.previous)); |
451 | decode_step(buffer, offset, &(message->header.kind)); | 619 | decode_step(buffer, offset, &kind); |
452 | 620 | ||
453 | if (length < get_message_kind_size (message->header.kind)) | 621 | message->header.kind = (enum GNUNET_MESSENGER_MessageKind) kind; |
622 | |||
623 | if (count < get_message_kind_size (message->header.kind)) | ||
454 | return GNUNET_NO; | 624 | return GNUNET_NO; |
455 | 625 | ||
456 | decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); | 626 | const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); |
627 | |||
628 | if (padding) | ||
629 | *padding = result; | ||
457 | 630 | ||
458 | return GNUNET_YES; | 631 | return GNUNET_YES; |
459 | } | 632 | } |
@@ -461,47 +634,80 @@ decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const | |||
461 | static int | 634 | static int |
462 | decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) | 635 | decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) |
463 | { | 636 | { |
464 | uint16_t offset = 0; | 637 | struct GNUNET_HashCode expected, hash; |
638 | uint16_t offset = sizeof(hash); | ||
639 | |||
640 | if (length < get_short_message_size (NULL, GNUNET_NO)) | ||
641 | return GNUNET_NO; | ||
642 | |||
643 | GNUNET_memcpy(&hash, buffer, sizeof(hash)); | ||
644 | |||
645 | GNUNET_CRYPTO_hash( | ||
646 | buffer + sizeof(hash), | ||
647 | length - sizeof(hash), | ||
648 | &expected | ||
649 | ); | ||
465 | 650 | ||
466 | if (length < get_short_message_size (NULL)) | 651 | if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected)) |
467 | return GNUNET_NO; | 652 | return GNUNET_NO; |
468 | 653 | ||
469 | decode_step(buffer, offset, &(message->kind)); | 654 | kind_t kind; |
470 | 655 | ||
471 | if (length < get_short_message_size (message)) | 656 | decode_step(buffer, offset, &kind); |
657 | |||
658 | message->kind = (enum GNUNET_MESSENGER_MessageKind) kind; | ||
659 | |||
660 | if (length < get_short_message_size (message, GNUNET_NO)) | ||
472 | return GNUNET_NO; | 661 | return GNUNET_NO; |
473 | 662 | ||
474 | decode_message_body (&(message->kind), &(message->body), length, buffer, offset); | 663 | decode_message_body (&(message->kind), &(message->body), length, buffer, offset); |
475 | 664 | ||
665 | if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind) | ||
666 | return GNUNET_NO; | ||
667 | |||
476 | return GNUNET_YES; | 668 | return GNUNET_YES; |
477 | } | 669 | } |
478 | 670 | ||
479 | void | 671 | void |
480 | hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash) | 672 | hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, |
673 | struct GNUNET_HashCode *hash) | ||
481 | { | 674 | { |
482 | GNUNET_CRYPTO_hash (buffer + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), | 675 | GNUNET_assert((message) && (buffer) && (hash)); |
483 | length - sizeof(struct GNUNET_CRYPTO_EcdsaSignature), hash); | 676 | |
677 | const ssize_t offset = GNUNET_IDENTITY_signature_get_length( | ||
678 | &(message->header.signature) | ||
679 | ); | ||
680 | |||
681 | GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash); | ||
484 | } | 682 | } |
485 | 683 | ||
486 | void | 684 | void |
487 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, | 685 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, |
488 | const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego) | 686 | const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego) |
489 | { | 687 | { |
688 | GNUNET_assert((message) && (buffer) && (hash) && (ego)); | ||
689 | |||
490 | struct GNUNET_MESSENGER_MessageSignature signature; | 690 | struct GNUNET_MESSENGER_MessageSignature signature; |
491 | 691 | ||
492 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | 692 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); |
493 | signature.purpose.size = htonl (sizeof(signature)); | 693 | signature.purpose.size = htonl (sizeof(signature)); |
494 | 694 | ||
495 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); | 695 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); |
496 | |||
497 | GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); | 696 | GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); |
498 | GNUNET_memcpy(buffer, &(message->header.signature), sizeof(struct GNUNET_CRYPTO_EcdsaSignature)); | 697 | |
698 | uint16_t offset = 0; | ||
699 | encode_step_signature(buffer, offset, &(message->header.signature), length); | ||
499 | } | 700 | } |
500 | 701 | ||
501 | int | 702 | int |
502 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, | 703 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, |
503 | const struct GNUNET_IDENTITY_PublicKey *key) | 704 | const struct GNUNET_IDENTITY_PublicKey *key) |
504 | { | 705 | { |
706 | GNUNET_assert((message) && (hash) && (key)); | ||
707 | |||
708 | if (ntohl (key->type) != ntohl (message->header.signature.type)) | ||
709 | return GNUNET_SYSERR; | ||
710 | |||
505 | struct GNUNET_MESSENGER_MessageSignature signature; | 711 | struct GNUNET_MESSENGER_MessageSignature signature; |
506 | 712 | ||
507 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | 713 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); |
@@ -516,26 +722,32 @@ verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNU | |||
516 | int | 722 | int |
517 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) | 723 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) |
518 | { | 724 | { |
725 | GNUNET_assert((message) && (key)); | ||
726 | |||
519 | struct GNUNET_MESSENGER_ShortMessage shortened; | 727 | struct GNUNET_MESSENGER_ShortMessage shortened; |
520 | 728 | ||
521 | fold_short_message (message, &shortened); | 729 | fold_short_message (message, &shortened); |
522 | 730 | ||
523 | const uint16_t length = get_short_message_size (&shortened); | 731 | const uint16_t length = get_short_message_size (&shortened, GNUNET_YES); |
732 | const uint16_t padded_length = calc_padded_length(length); | ||
524 | 733 | ||
525 | message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; | 734 | message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; |
526 | message->body.private.data = GNUNET_malloc(length); | 735 | message->body.private.data = GNUNET_malloc(padded_length); |
736 | message->body.private.length = padded_length; | ||
527 | 737 | ||
528 | encode_short_message (&shortened, length, message->body.private.data); | 738 | encode_short_message (&shortened, padded_length, message->body.private.data); |
529 | 739 | ||
530 | if (GNUNET_IDENTITY_encrypt (message->body.private.data, length, key, &(message->body.private.key), | 740 | if (padded_length == GNUNET_IDENTITY_encrypt (message->body.private.data, padded_length, key, |
531 | message->body.private.data) | 741 | &(message->body.private.key), |
532 | == length) | 742 | message->body.private.data)) |
533 | { | 743 | { |
534 | destroy_message_body (shortened.kind, &(shortened.body)); | 744 | destroy_message_body (shortened.kind, &(shortened.body)); |
535 | return GNUNET_YES; | 745 | return GNUNET_YES; |
536 | } | 746 | } |
537 | else | 747 | else |
538 | { | 748 | { |
749 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n"); | ||
750 | |||
539 | unfold_short_message (&shortened, message); | 751 | unfold_short_message (&shortened, message); |
540 | return GNUNET_NO; | 752 | return GNUNET_NO; |
541 | } | 753 | } |
@@ -544,18 +756,28 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_I | |||
544 | int | 756 | int |
545 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) | 757 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) |
546 | { | 758 | { |
547 | if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, | 759 | GNUNET_assert((message) && (key)); |
548 | message->body.private.length, key, | 760 | |
549 | &(message->body.private.key), | 761 | if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, message->body.private.length, |
762 | key, &(message->body.private.key), | ||
550 | message->body.private.data)) | 763 | message->body.private.data)) |
764 | { | ||
765 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n"); | ||
766 | |||
551 | return GNUNET_NO; | 767 | return GNUNET_NO; |
768 | } | ||
552 | 769 | ||
553 | struct GNUNET_MESSENGER_ShortMessage shortened; | 770 | struct GNUNET_MESSENGER_ShortMessage shortened; |
554 | 771 | ||
555 | if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data)) | 772 | if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data)) |
773 | { | ||
774 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n"); | ||
775 | |||
556 | return GNUNET_NO; | 776 | return GNUNET_NO; |
777 | } | ||
557 | 778 | ||
558 | unfold_short_message (&shortened, message); | 779 | unfold_short_message (&shortened, message); |
780 | |||
559 | return GNUNET_YES; | 781 | return GNUNET_YES; |
560 | } | 782 | } |
561 | 783 | ||
@@ -563,18 +785,25 @@ struct GNUNET_MQ_Envelope* | |||
563 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | 785 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, |
564 | const struct GNUNET_MESSENGER_Ego *ego, int mode) | 786 | const struct GNUNET_MESSENGER_Ego *ego, int mode) |
565 | { | 787 | { |
566 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message: %u\n", message->header.kind); | 788 | GNUNET_assert(message); |
789 | |||
790 | if (ego) | ||
791 | message->header.signature.type = ego->priv.type; | ||
792 | |||
793 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n", | ||
794 | message->header.kind, GNUNET_sh2s(&(message->header.sender_id))); | ||
567 | 795 | ||
568 | struct GNUNET_MessageHeader *header; | 796 | struct GNUNET_MessageHeader *header; |
569 | 797 | ||
570 | uint16_t length = get_message_size (message); | 798 | const uint16_t length = get_message_size (message, GNUNET_YES); |
799 | const uint16_t padded_length = calc_padded_length(length); | ||
571 | 800 | ||
572 | struct GNUNET_MQ_Envelope *env; | 801 | struct GNUNET_MQ_Envelope *env; |
573 | char *buffer; | 802 | char *buffer; |
574 | 803 | ||
575 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) | 804 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) |
576 | { | 805 | { |
577 | env = GNUNET_MQ_msg_extra(header, length, GNUNET_MESSAGE_TYPE_CADET_CLI); | 806 | env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI); |
578 | 807 | ||
579 | buffer = (char*) &(header[1]); | 808 | buffer = (char*) &(header[1]); |
580 | } | 809 | } |
@@ -582,14 +811,14 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode * | |||
582 | { | 811 | { |
583 | env = NULL; | 812 | env = NULL; |
584 | 813 | ||
585 | buffer = GNUNET_malloc(length); | 814 | buffer = GNUNET_malloc(padded_length); |
586 | } | 815 | } |
587 | 816 | ||
588 | encode_message (message, length, buffer); | 817 | encode_message (message, padded_length, buffer, GNUNET_YES); |
589 | 818 | ||
590 | if (hash) | 819 | if (hash) |
591 | { | 820 | { |
592 | hash_message (length, buffer, hash); | 821 | hash_message (message, length, buffer, hash); |
593 | 822 | ||
594 | if (ego) | 823 | if (ego) |
595 | sign_message (message, length, buffer, hash, ego); | 824 | sign_message (message, length, buffer, hash, ego); |
@@ -600,3 +829,43 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode * | |||
600 | 829 | ||
601 | return env; | 830 | return env; |
602 | } | 831 | } |
832 | |||
833 | int | ||
834 | filter_message_sending (const struct GNUNET_MESSENGER_Message *message) | ||
835 | { | ||
836 | switch (message->header.kind) | ||
837 | { | ||
838 | case GNUNET_MESSENGER_KIND_INFO: | ||
839 | return GNUNET_SYSERR; // Reserved for connection handling only! | ||
840 | case GNUNET_MESSENGER_KIND_JOIN: | ||
841 | return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead! | ||
842 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
843 | return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead! | ||
844 | case GNUNET_MESSENGER_KIND_NAME: | ||
845 | return GNUNET_YES; | ||
846 | case GNUNET_MESSENGER_KIND_KEY: | ||
847 | return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead! | ||
848 | case GNUNET_MESSENGER_KIND_PEER: | ||
849 | return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead! | ||
850 | case GNUNET_MESSENGER_KIND_ID: | ||
851 | return GNUNET_SYSERR; // Reserved for member id handling only! | ||
852 | case GNUNET_MESSENGER_KIND_MISS: | ||
853 | return GNUNET_SYSERR; // Reserved for connection handling only! | ||
854 | case GNUNET_MESSENGER_KIND_MERGE: | ||
855 | return GNUNET_YES; | ||
856 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
857 | return GNUNET_YES; | ||
858 | case GNUNET_MESSENGER_KIND_INVITE: | ||
859 | return GNUNET_YES; | ||
860 | case GNUNET_MESSENGER_KIND_TEXT: | ||
861 | return GNUNET_YES; | ||
862 | case GNUNET_MESSENGER_KIND_FILE: | ||
863 | return GNUNET_YES; | ||
864 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
865 | return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead! | ||
866 | case GNUNET_MESSENGER_KIND_DELETE: | ||
867 | return GNUNET_YES; | ||
868 | default: | ||
869 | return GNUNET_SYSERR; | ||
870 | } | ||
871 | } | ||