-
Notifications
You must be signed in to change notification settings - Fork 2
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
Compliant use of tokens in blockwise transfer (RFC7959) #29
Comments
I think it's rather clear that this is not how requests are supposed to be matched; IIRC there was wide agreement on that in the last interim. While clients are free to reuse the tokens, the server can not rely on it. Given we are seeing evidence that people start relying on this just because it works with the one or two peers they are testing it, I'd recommend that clients start mixing up their block numbers just to keep their servers from relying on the pattern. (It's sad we have to resort to this, but apparently either people don't read the specs or the specs are not written well enough). If there is any property of its interactions a server can only obtain when exchanging with peers that do use those constant-over-the-body tokens, please point me to it, but I'm very confident that the tools we have allow doing it properly. (That is not to say that 7959+9175 are perfect, far from it -- just that everything that can be done relying on constant tokens can also be done without). |
In some cases the people want to improve the specs. I remember converting RFC7641 into time series. For blockwise it was to support concurrent transfers of changed resources. |
Let me try to put up an example that might help to you to see what problems I'm seeing. In LwM2M, a device holds multiple "objects" and those can have "resources" and all those are accessed using their CoAP URI path. In LwM2M, you can send a query for a single or multiple resources. So for example, if you send query to path Now as you can see, one of the resource is "Current Time". So as you can expect, this changes as often as what is the accuracy of the system clock. Once a second, or once a millisecond. So the problems, as I see it:
-- |
Regarding the security, I'm thinking that as long as the same pair of URI-path & block number does not get reused within the same token, I don't consider it as reusing of token. But if you store one response packet, it will not match any further transfers as the token has already been used. |
So far, that's a pretty common thing. Quote from 7959To avoid [changing ETags] happening all the time for a fast-changing resource, a server MAY try to keep a cache around for a specific client for a short amount of time. The expectation here is that the lifetime for such a cache can be kept short, on the order of a few expected round-trip times, counting from the previous block transferred."
None at all. If a later request for a later block comes in before your stored version expires, you send the stored version.
If you get any request with Block2:0/-/x (or without a Block2), you can do either, and either should work. The difference will just be that if a client requests the same thing all over, not regenerating gives the client a stale view, so you'd need to be careful in picking that "short amount of time". Or, what I'd recommend, just regenerate. On being "similar" (vs. "identical"), 7959 didn't have a good term, so I introduced "matchable" in RFC79175. You can only serve from the stored version if the request is "matchable" to the original one (which you can reasonably check by storing a hash of the client's address and the relevant option values). If the request is not matchable, you must not use that stored version. What you do precisely depends on how you store them -- you may have just a single "active transfer", or you may have a bunch of them, in which case keying them by that hash is a good option.
Note that Request-Tag is not in any way special to the server. The rules for being "matchable" ("same endpoint pair, have the same code, and have the same set of options, with the exception that elective NoCacheKey options and options involved in block-wise transfer (Block1, Block2, and Request-Tag) need not be the same") make them an exception because it simplified phrasing the document for the client -- but on the server side, you just build a hash of the endpoint, code, and options unless NoCacheKey or Block1/Block2, and that's what needs to match. Also, the URI is not special there -- Uri-Path, Uri-Query and Accept are all options that need to match.
It is not an error, it is just recommended that the client fetches them in order. As long as the rest is good, you can just send the block they requested.
Just because out-of-order is fine doesn't mean you have to go out of your way to accommodate it. But having sent the last block is also not a reliable indicator to free things, because you usually don't get an acknowledgement for the block. How smart you have to be depends on your constraints and requirements. Having one global "last transaction" block and a single timeout (that gets refreshed every time a request matches it) and overwriting it if anything else comes in requiring block-wise is fine. Having a small number of slots in an LRU cache is also fine and a bit better. If you have different authorization levels, some slots in the LRU may be reserved for admins. If your timeout is large, it may make sense to not go full LRU, but also consider whether you have transmitted the last block in an entry, and evict that even before it expires. But these are all optimizations that just modify when and to whom the error cases occur, and the error cases boil down to one situation: The state which the client expected to continue with was overwritten. The client detects that using the ETag, and starts over.
The issue I'm taking with making this a token thing is not about security, it's about layering. The token is on the request/response layer, but block-wise happens in the application visible options, on top of that. |
In the scope of LwM2M, a question about the usage of the token in relation with a blockwise transfer occurred.
Is it valid to use the client's token to relation a server side state to the request? In particular, to make it mandatory, that follow up requests of an blockwise transfer MUST use the same token?
For more background information, please read the comment in
Eclipse/Californium
and
Eclipse/Leshan
The text was updated successfully, but these errors were encountered: