On Thu Jun 28 23:12:25 2007, Joe Hildebrand wrote:
The current spec could absolutely be used for this. The hardest part is spec'ing how to generate a string that has all of the capabilities, so that you can run the hash. Canonical XML is massive overkill, but, for example, if we just said:

- For all sorting, use the Unicode Collation Algorithm (http:// www.unicode.org/unicode/reports/tr10/)

Feh. UTF-8 encode then i;octet - much faster, just as stable, and a heck of a lot simpler to implement, especially given that namespaces will be us-ascii anyway (hence UTF-8). RFC4790 defines this. (i;basic uses TR10, but ISTR it's not yet ready).


- Initialize an empty string E
- sort the identities by category, then type
- for each identity, append the category, then the type (if it exists) to E (note: any information inside an identity will be ignored)

I'd propose something mildly more structured here, really such that it's simpler to view by eye to ensure the formatting and ordering is correct. This has no security impact, it's just easier to implement. Something like:

For each identity, append the following production:

cat-line = cat-tag SP category [SP type] CRLF
        ;; Note that type MUST be present if it exists.
cat-tag = %43 %41 %54
        ;; "CAT", case insensitively.


- sort the features by URI
- for each feature, append the URI to E (note: any information inside a feature will be ignored)

Similarly:

feat-line = feat-tag SP feat-uri CRLF
feat-tag = %46 %45 %41 %54
        ;; "FEAT" case insensitively.


- calculate the MD5 sum for E

MD5 has a bad reputation, but note that the stricter the input formatting, the less likely it is to be forged (ie, the less likely it is that someone could find a colliding input that makes semantic sense.)

For better security, we could use HMAC, and/or a different hash function. One option would be that, if H is the result of the hash/hmac function, then V, the version string, is formed by prepending its algorithm and a $, something like:

E = *(cat-line) *(feat-line)
H = <hash/hmac of E>
V = hash-func-name "$" H
hash-func-name = hash-name / "HMAC-" hash-name
hash-name = "MD5" / "SHA1" / "SHA-256"

We mandate that HMAC-MD5 is used, but a future specification MAY change this requirement. MD5 does have the minor advantage of being smaller.


- use this for the version number or extension name


(Given my suggestion above, we'd use V, rather than Hash(E)).


Example (adapted from XEP-115, example 2):

<presence from='[EMAIL PROTECTED]/home'>
  <c xmlns='http://jabber.org/protocol/caps'
     node='http://exodus.jabberstudio.org/caps'
     ver='730c80b442e150dd5e19a31f8edfa8b1'
ext='d6224a352df544cfde1fbce177301c67 d0ef9e8327acf5873d16fe083b4d3f3f'/>
</presence>


This example would have the same form, roughly:

ver='HMAC-MD5$[...]'
ext='HMAC-MD5$[...] HMAC-MD5$[...]'


The receiving client SHOULD check the hashes, after doing the IQ/gets:

md5(clientpchttp://jabber.org/protocol/disco#infohttp://jabber.org/ protocol/disco#itemshttp://jabber.org/protocol/feature-neghttp:// jabber.org/protocol/muc) = 730c80b442e150dd5e19a31f8edfa8b1

This one becomes (using literal whitespace for clarification, not syntax):

Hash("
CAT client pc\r\n
FEAT http://jabber.org/protocol/disco#info\r\n
FEAT http://jabber.org/protocol/disco#items\r\n
FEAT http://jabber.org/protocol/feature-neg\r\n
FEAT http://jabber.org/protocol/muc\r\n
")

I'll skip the remaining examples, but presumably you get the notion.

If the receiving client detects an inconsistency, it MUST NOT use the information it received, and SHOULD show an error of some kind.

For backwards-compatibility, any version number that is not 32 octets long consisting only of [0-9a-f] MUST be treated as if it does not implement MD5 checking.


We've got slightly better error checking if we explicitly tag the data with the prefix defined by the V ABNF production above.


Analysis:
- Existing entities, both sending and receiving, should work fine
- Over time, we can phase in entities that send md5 versions and ext's - Receiving clients that care about security can start checking MD5 hashes of the features to check for poisoning.
- Downside: more bytes in presence than today.

We send these out, currently, with every presence update, correct? Is it worth looking at an alternate mechanism, or a generalized presence-delta? (After all, I'm pretty sure that this data won't change as often as my status).

I have to admit, I have an odd feeling that combining all extensions together might generate a better result, too, but that's nothing more than a gut feeling.


- Assertion: anything else we do will be at least this bad if not worse.

If we add these bits to -115, will everyone agree to never bring up changing caps again, and to all agree on that the next time a n00b comes around?

I hate to say never, but I can't see how we can get much better than this.

Dave.
--
Dave Cridland - mailto:[EMAIL PROTECTED] - xmpp:[EMAIL PROTECTED]
 - acap://acap.dave.cridland.net/byowner/user/dwd/bookmarks/
 - http://dave.cridland.net/
Infotrope Polymer - ACAP, IMAP, ESMTP, and Lemonade

Reply via email to