-
Notifications
You must be signed in to change notification settings - Fork 400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File transfers #15
Comments
Wow, this is an old issue. It's about time to get this done. Let's talk about file transfers. This is partly requesting feedback, partly trying to convince myself, and partly a braindump, but hopefully it's useful. UXI see two broad types of use cases for file transfers. The active users are sending and receiving files during conversations, and expect the file to be part of their conversation. File drops are for an important minority of Ricochet users who want to stay online and be able to receive files at any time, even if they're not immediately active. Like most messaging applications, we want to do file transfers inline as part of the conversation, and they must not require using any other application (including a browser). Drag and drop of a file into a conversation is the normal way to send a file. Arguably, it could be easy to accidentally send a file this way. That could be mitigated by dropping the file into the message input box and allowing typing a message to go with it before sending, or more easily with a countdown before sending. There should be another visible UI method for sending files, like a button in the conversation header or near the message input. Offered files must expire after enough time to reasonably assume the user might've forgotten. Ricochet's threat model prohibits storing conversation data (including files) automatically. The threat model also sees contacts as potential exploitation adversaries, so we want to reduce the set of actions a contact can trigger without user approval. These suggest that we should require explicit accept by default for file transfers. The user has to explicitly choose where to save each file, unless they configure a default location. This is fine with the active user use case, but for file drops we will need an option to automatically save files (which could also be per-contact). Active offers or transfers must be easily noticable to both parties. In addition to showing progress on the transfer in the conversation, there should be progress in the conversation header (a transfers tab?) and/or global transfer status somewhere. This is particularly important because the conversation may move on while transfers are ongoing. When a transfer finishes, it should be moved to the end of the conversation. Completed transfers are opened by clicking, with a warning similar to the browser warning. Tor has been known to be unreliable, so the ability to resume will be important. We must reconnect and resume automatically whenever possible. If too much time has passed, or one of the clients has lost its history, resuming should still be possible by saving over an existing incomplete file. Future UXDisplaying images inline with conversations is a standard messaging feature. This is easy to do once we have file transfer in place, except that I don't trust image decoders. Once we find a robust and memory-safe decoder, or cross-platform seccomp-style sandboxing, this is worth doing. Someone pointed out that we could prefetch files, at least by building connections and buffering up to some in-memory limit, to make the transfer process seem faster. It would be nice to allow transferring batches of files or entire folders up to some reasonable limit. Having a way to automatically verify the hash of the downloaded file with the sending server would be nifty. ProtocolConnectionsFile data can't be sent over Ricochet's primary protocol connection. Even though we packetize data, because of the buffering properties for Tor streams, very large amounts of data will in queues when flooding a hidden service connection. This causes extreme (often 30s or more) latency for that stream. Any other form of rate control would have too much impact on transfer speeds. The simple answer is to open additional connections to the peer's service. These connections will be multiplexed by Tor onto the same circuit, but buffering behavior is significantly better. In casual testing there seems to not be significant impact on message latency when flooding data to another stream on the same circuit. We could also use circuit isolation options to force Tor to build new circuits for transfers. It's unclear whether this would be useful for throughput or latency, and it's unclear whether building additional concurrent circuits would have significant anonymity or traffic analysis impacts. Ricochet's protocol doesn't allow more than one authenticated connection per contact, because it would be ambiguous which connection should be used and could violate expectations on message ordering. If additional connections use Ricochet's protocol, they will need to authenticate differently to indicate that the connection is only used for data transfer. Because data transfer is happening over secondary connections, we're not required to package data with Ricochet's protocol. It's worth thinking through the options here. Option 1: Modified Ricochet protocolMy original thinking was to use Ricochet's protocol for file data transfer on additional connections. This isn't entirely straightforward. Benefits:
Downsides:
There's some older work on what this could look like from a WIP branch in FileTransferChannel.proto and FileTransferDataChannel.proto. Option 2: HTTP (my current preference)Ricochet clients could offer files over HTTP, using a simple internal server and unique URLs, similar to OnionShare. That server could be on a different (possibly randomized) port of the same hidden service, on new ephemeral services, or even share the same port using protocol detection. Benefits:
Downsides:
Server/client implementationThere is no need for a 100% feature-complete and spec-behavior-compatible HTTP client in Ricochet, because the use case here is very minimal. To keep the potential for bugs as low as possible, I'd limit the implementation to features we need, and not use (e.g.) chunked transfer encoding or esoteric options. We could even force Server behavior and URL formatI favor putting the HTTP server on a randomized port under the same hidden service. Bringing up new services is sometimes slow or unreliable, and involves many new circuits and distinguishable network activity. This also means we can require the same .onion hostname, which prevents peers from being able to force a connection to an arbitrary .onion. If the server is always running, it's possible for contacts and non-contacts to find at any time, though this shouldn't be of any value. If the server is only active when there are active file offers, that state may be detectable to contacts or non-contacts who can learn the port. There is no point or need to try to disguise as anything other than a Ricochet client. All well-formed requests that are not valid file requests should be rejected with a generic 404 error. I propose the following for download URLs:
File URLs are related to a specific transfer and are meant for one time use. Range requests must be supported to allow resume, and may be allowed for parallel downloading. Servers should stop offering a URL once they believe the recipient has a full copy. File offer protocolWe can package a file offer into an extended chat message:
Acknowledgement of this message also acknowledges the file offer. The URL may be immediately accessed to download the file. In addition to acknowledging the message normally, the recipient should send an additional This has the neat property of being entirely compatible with clients that don't implement file transfers; the user will see the URL, and can download it in a browser. This isn't especially meaningful, though. XXX There is no way defined here for the sender to indicate cancellation Next stepsI'd like to move forward on this pretty quickly, so I'm going to be aiming for nailing down the protocol and major UX decisions very soon. There's already a good chunk of code written, but it needs some fixing and will need changes based on the decisions here. Any thoughts? |
This looks good to me. I agree that the HTTP server direction feels like the right one. A couple of thoughts - in no particular order or priority:
|
Well, there is authentication by using a URL unique to the recipient and file. The concern is that it's transferrable: this authentication doesn't identify the recipient to anyone other than the sender (and that non-cryptographically), and doesn't contain any secret the recipient may wish to protect.
I think there isn't a DoS option, as long as we're limiting the number of connections per offered file. Since the intent is to share one file with one person once (allowing for resume and other issues), we can be strict about it. It could also be a good idea to set a minimum transfer rate, for usability also.
Interesting! I like this attack. There are weak defenses by changing the client authentication, but they really just discourage sharing URLs. I also like having these URLs not identify their intended recipient other than to the sender who generated them. To actually remove the cryptographic attribution, we'd have to serve files on ephemeral services. I'm not sure whether it also requires one ephemeral service per contact. Technically, Bob can convince Alice to send a dangerous file, Bob shares the address with Carol, and then Carol can separately get Alice to send an innocuous file, so that Carol can confirm that the dangerous URL came from Alice. The safest answer attribution-wise would be to use a unique ephemeral service per contact per session. My concerns with this are 1) service publication latency; 2) many more circuits required; 3) shows up more clearly to traffic analysis. I think I might be okay with using one ephemeral service for all file transfer in a session. It's at least still cryptographically distinct, reduces all of those impacts, and the case where it fails is contrived.
Content type is a MIME type, so no unicode issues there. For sanitizing filenames, I came up with some rules long ago, which will need some further thought. Must be very careful there.
Agree.
Without any response? Hmm. This makes it slightly more ambiguous for a ricochet client to tell if there was a network failure or if a URL is no longer valid. Otherwise I have no problem with that, and I'd like not sending anything back to unauthorized clients.
The precautions here would have to be the same as for opening any URL. I don't think this is necessarily a use case worth designing for -- I'm not sure it will end up staying in. |
Possibly already too large for this use case, but written with security in mind: https://github.com/reyk/httpd
I wonder why you would want to save an additional content-type apart from a user visible file name extension? Could that possibly lead to confusion on the receiver side either technically in which program to start, or non-technically in what a user expects?
Isn't the
👍
At the cost of client compatibility, would it be feasible to encrypt the contents of the file with the recipients public key or something of a session id? |
Hmm. I have two uses in mind:
Detecting these based on extension is at least as unreliable as having a (possibly wrong) content-type. You're right that there would need to be care on #2 to make sure that we don't show something as being an image when it will actually open as an executable. For that reason alone, maybe it's better to remove content-type and only detect by extension. Hmm..
It is only valid to send
Encrypting the file doesn't solve @s-rah's attribution attack: it only means that you need to provide a decryption key along with the URL. Common ways of encrypting to the recipient's public key have the same problem, because you're generally just wrapping the symmetric encryption key used for file data. It would be more useful to require the recipient to give up their identity private key in order to demonstrate that the sender is offering a file. For that, we just need to authenticate the connection with the recipient's public key prior to serving files -- but this doesn't map well into HTTP (no, no TLS). That would be a point in favor of using another protocol. A different approach entirely is to have the recipient host the server, with the sender acting as a client to upload data. This could work with HTTP or anything else, but it has some downsides in flexibility. There would be no attribution problem in that case. |
I'd like to express that I totally agree with your earlier statement:
My bad, I read "receiver" while it actually states "sender" :)
Sounds interesting, you have examples of other protocols doing this? Or how it could be setup? I guess the Noise framework could help here as noted in #72 (comment). |
If case anyone needs this asap, then you should use onionshare along with ricochet. |
-----BEGIN PGP SIGNED MESSAGE----- John Brooks:
It's unclear to me whether this is part of Ricochet's threat model, iQIcBAEBCgAGBQJYKlGYAAoJELPy0WV4bWVwu/gQAI/7bmPTKwbcsjEntuEjc03j |
Possible workaround: At least on Windows and Linux there's gpg4usb (gpg4usb.org), a self-contained GPG program that saves all files encrypted as text files: Output (open data.docx.asc in notepad): Pitfalls:
Update: This program uses an outdated version of GPG so while it's likely still functional as a workaround, it may not function with other recently updated GPG-compatible tools. |
Think to a not-so-loyal employee knowing of this mechanism and passing on a different channel (maybe even a second Ricochet IM chat without leaving any trace...) the URL to a third party as soon as he received it... The third party downloads the file, the employee downloads it too and pretend having done nothing wrong... In a system without any public/visible/copyable links, in which the only option he receives in the chat window is to download the file to his PC or refuse it, he is the only other person (other than the sender) having access to that file and if it leaks, then there is no excuse of it being due to any 'public http URL....
|
Being able to transfer files would be a useful feature, to enable whistleblowers, etc.
The text was updated successfully, but these errors were encountered: