diff options
author | Alexandre Erwin Ittner <alexandre@ittner.com.br> | 2014-09-21 11:37:49 -0300 |
---|---|---|
committer | Alexandre Erwin Ittner <alexandre@ittner.com.br> | 2014-09-21 11:37:49 -0300 |
commit | b52eb48c15a06fe198c7c5e0d765cfef8ff4fbdf (patch) | |
tree | b203648e6df5bd825461e8c09b45a10f874d55ae /docs | |
parent | 70b4018069c0bbfa7ac2cf907a76a693e78e2947 (diff) |
Remove chattiness from avatar data transfers
The chatty approach for the avatar data transfer was intended as a
security feature to add explicit delays to the transfer and prevent
amplification attacks among authenticated friends. This was deemed
unnecessary in the code review and, therefore, replaced by a simpler
approach that sends all data in a single burst.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Avatars.md | 81 |
1 files changed, 19 insertions, 62 deletions
diff --git a/docs/Avatars.md b/docs/Avatars.md index f0d7a1eb..97b65c10 100644 --- a/docs/Avatars.md +++ b/docs/Avatars.md | |||
@@ -474,19 +474,15 @@ types. | |||
474 | - Packet `PACKET_ID_AVATAR_DATA_CONTROL` have the format: | 474 | - Packet `PACKET_ID_AVATAR_DATA_CONTROL` have the format: |
475 | 475 | ||
476 | PACKET_ID_AVATAR_DATA_CONTROL (54) | 476 | PACKET_ID_AVATAR_DATA_CONTROL (54) |
477 | Packet data size: 5 bytes | 477 | Packet data size: 1 byte |
478 | [1: uint8_t op][1: uint32_t bytes_received] | 478 | [1: uint8_t op] |
479 | 479 | ||
480 | where 'op' is a code signaling both an operation request or a status | 480 | where 'op' is a code signaling both an operation request or a status |
481 | return, which semantics are explained bellow. The following values are | 481 | return, which semantics are explained bellow. The following values are |
482 | defined: | 482 | defined: |
483 | 483 | ||
484 | 0 = AVATARDATACONTROL_REQ | 484 | 0 = AVATARDATACONTROL_REQ |
485 | 1 = AVATARDATACONTROL_MORE | 485 | 1 = AVATARDATACONTROL_ERROR |
486 | 2 = AVATARDATACONTROL_ERROR | ||
487 | |||
488 | and 'bytes_received' is the number of bytes already received by the | ||
489 | client when the operation is `MORE` or zero otherwise. | ||
490 | 486 | ||
491 | 487 | ||
492 | - Packet `PACKET_ID_AVATAR_DATA_START` have the following format: | 488 | - Packet `PACKET_ID_AVATAR_DATA_START` have the following format: |
@@ -503,7 +499,9 @@ types. | |||
503 | 499 | ||
504 | 500 | ||
505 | - Packet `PACKET_ID_AVATAR_DATA_PUSH` have no format structure, just up | 501 | - Packet `PACKET_ID_AVATAR_DATA_PUSH` have no format structure, just up |
506 | to `AVATAR_DATA_MAX_CHUNK_SIZE` (56) bytes of raw avatar image data. | 502 | to `AVATAR_DATA_MAX_CHUNK_SIZE` bytes of raw avatar image data; this |
503 | value is defined according to the maximum amount of data a Tox crypted | ||
504 | packet can hold. | ||
507 | 505 | ||
508 | 506 | ||
509 | 507 | ||
@@ -513,8 +511,7 @@ from a client "B": | |||
513 | - "A" must initialize its control structures and mark its data transfer | 511 | - "A" must initialize its control structures and mark its data transfer |
514 | as not yet started. Then it requests avatar data from "B" by sending a | 512 | as not yet started. Then it requests avatar data from "B" by sending a |
515 | packet `PACKET_ID_AVATAR_DATA_CONTROL` with 'op' set to | 513 | packet `PACKET_ID_AVATAR_DATA_CONTROL` with 'op' set to |
516 | `AVATARDATACONTROL_REQ`. The field 'bytes_received' must be present, but | 514 | `AVATARDATACONTROL_REQ`. |
517 | should be set to zero and is ignored in this step. | ||
518 | 515 | ||
519 | - If "B" accepts this transfer, it answers by sending an | 516 | - If "B" accepts this transfer, it answers by sending an |
520 | `PACKET_ID_AVATAR_DATA_START` with the fields 'format', 'hash' and | 517 | `PACKET_ID_AVATAR_DATA_START` with the fields 'format', 'hash' and |
@@ -527,42 +524,21 @@ from a client "B": | |||
527 | `AVATARDATACONTROL_ERROR` or simply ignore this request. "A" must cope | 524 | `AVATARDATACONTROL_ERROR` or simply ignore this request. "A" must cope |
528 | with this. | 525 | with this. |
529 | 526 | ||
527 | If "B" have an avatar, it sends a variable number of | ||
528 | `PACKET_ID_AVATAR_DATA_PUSH` packets with the avatar data in a single | ||
529 | shot. | ||
530 | |||
530 | - Upon receiving a `PACKET_ID_AVATAR_DATA_START`, "A" checks if it | 531 | - Upon receiving a `PACKET_ID_AVATAR_DATA_START`, "A" checks if it |
531 | has sent a data request to "B". If not, just ignores the packet. | 532 | has sent a data request to "B". If not, just ignores the packet. |
532 | 533 | ||
533 | If "A" really sent a request to "B", checks if the request was already | 534 | If "A" really requested avatar data and the format is `AVATARFORMAT_NONE`, |
534 | started. If true, it is an error and it just ignores the request. | 535 | it triggers the avatar data callback, and clears all the temporary data, |
535 | 536 | finishing the process. For other formats, "A" just waits for packets | |
536 | Otherwise, "A" decodes the message data and checks if the avatar data | 537 | of type `PACKET_ID_AVATAR_DATA_PUSH`. |
537 | length stated in the field 'data_length' is acceptable (ie. less or | ||
538 | equal than `TOX_MAX_AVATAR_DATA_LENGTH`). If not, it replies with an | ||
539 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
540 | `AVATARDATACONTROL_ERROR` (or just ignores this, "A" holds no state). | ||
541 | |||
542 | If the size is acceptable, "A" marks the request as stated, stores the | ||
543 | format, hash, and data length in the local state for user "B", sets a | ||
544 | counter for the number of bytes received from the peer and replies with | ||
545 | a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
546 | `AVATARDATACONTROL_MORE` and 'bytes_received' set to zero (as no data | ||
547 | was received yet). | ||
548 | |||
549 | - Upon receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with op | ||
550 | `AVATARDATACONTROL_MORE`, "B" sends an `PACKET_ID_AVATAR_DATA_PUSH` | ||
551 | with up to `AVATAR_DATA_MAX_CHUNK_SIZE` bytes of data from the avatar, | ||
552 | starting from the offset stated in the field 'bytes_received'. | ||
553 | 538 | ||
554 | If the requested offset is invalid, "B" replies with a | 539 | - Upon receiving a `PACKET_ID_AVATAR_DATA_PUSH`, "A" checks if it really |
555 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | 540 | sent an avatar data request and if the `PACKET_ID_AVATAR_DATA_START` was |
556 | `AVATARDATACONTROL_ERROR`. | 541 | already received. If this conditions are valid, it checks if the total |
557 | |||
558 | "B" must have full control of the amount of data it sends to "A" and | ||
559 | may, at any time, abort the transfer by sending a | ||
560 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
561 | `AVATARDATACONTROL_ERROR`. This may happens, for example, if some limit | ||
562 | was hit or a network data usage throttle enabled. A rationale for this | ||
563 | procedures is available in section "Security considerations". | ||
564 | |||
565 | - Upon receiving a `PACKET_ID_AVATAR_DATA_PUSH`, "A" checks if the total | ||
566 | length of the data already stored in the receiving buffer plus the data | 542 | length of the data already stored in the receiving buffer plus the data |
567 | present in the push packet is still less or equal than | 543 | present in the push packet is still less or equal than |
568 | `TOX_MAX_AVATAR_DATA_LENGTH`. If invalid, it replies with a | 544 | `TOX_MAX_AVATAR_DATA_LENGTH`. If invalid, it replies with a |
@@ -582,22 +558,13 @@ from a client "B": | |||
582 | triggers the avatar data callback, and clears all the temporary data, | 558 | triggers the avatar data callback, and clears all the temporary data, |
583 | finishing the process. | 559 | finishing the process. |
584 | 560 | ||
585 | If not all data was received, "A" requests more data by sending a | 561 | If not all data was received, "A" simply waits for more data. |
586 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
587 | `AVATARDATACONTROL_MORE` and 'bytes_received' set to the new offset. | ||
588 | 562 | ||
589 | Client "A" is always responsible for controlling the transfer and | 563 | Client "A" is always responsible for controlling the transfer and |
590 | validating the data received. "B" don't need to keep any state for the | 564 | validating the data received. "B" don't need to keep any state for the |
591 | protocol, have full control over the data sent and should implement | 565 | protocol, have full control over the data sent and should implement |
592 | some transfer limit for the data it sends. | 566 | some transfer limit for the data it sends. |
593 | 567 | ||
594 | This "chatty" protocol mitigates a potential amplification attack, | ||
595 | i.e., a malicious friend sending a very small data packet that causes | ||
596 | another user to send a larger amount of data. The hash validation | ||
597 | ensures that the avatar data is correct even if "B" changed its avatar | ||
598 | data in the middle of the transfer. A rationale for this procedures is | ||
599 | available in section "Security considerations". | ||
600 | |||
601 | - Any peer receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' | 568 | - Any peer receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' |
602 | set to `AVATARDATACONTROL_ERROR` clears any existing control state and | 569 | set to `AVATARDATACONTROL_ERROR` clears any existing control state and |
603 | finishes sending or receiving data. | 570 | finishes sending or receiving data. |
@@ -624,12 +591,6 @@ The present proposal mitigates this situation by: | |||
624 | - Providing an alternate, smaller, message to cooperative users refresh | 591 | - Providing an alternate, smaller, message to cooperative users refresh |
625 | avatar information when nothing has changed (`PACKET_ID_AVATAR_INFO`); | 592 | avatar information when nothing has changed (`PACKET_ID_AVATAR_INFO`); |
626 | 593 | ||
627 | - Making the avatar data transfer chatty: The user requesting avatar data | ||
628 | can not force a peer to send large amounts of data in a single shot and | ||
629 | must request new chunks as needed. The sender will never send more that | ||
630 | 1 kB of data in a single push and have ultimate control over the amount | ||
631 | of data sent in a chunk; | ||
632 | |||
633 | - Having per-friend data transfer limit. As the current protocol still | 594 | - Having per-friend data transfer limit. As the current protocol still |
634 | allows an user to request an infinite data stream by asking the the | 595 | allows an user to request an infinite data stream by asking the the |
635 | same offset of the avatar again and again, the implementation limits | 596 | same offset of the avatar again and again, the implementation limits |
@@ -640,10 +601,6 @@ The present proposal mitigates this situation by: | |||
640 | - Making the requester responsible for storing partial data and state | 601 | - Making the requester responsible for storing partial data and state |
641 | information; | 602 | information; |
642 | 603 | ||
643 | - (currently not implemented) Treating avatar data transfers as a low | ||
644 | priority operation, handled only if no other packets are being | ||
645 | processed. | ||
646 | |||
647 | Another problem present in the avatars is the possibility of a friend send | 604 | Another problem present in the avatars is the possibility of a friend send |
648 | a maliciously crafted image intended to exploit vulnerabilities in image | 605 | a maliciously crafted image intended to exploit vulnerabilities in image |
649 | decoders. Without an intermediate server to recompress and validate and | 606 | decoders. Without an intermediate server to recompress and validate and |