Subject: [Ietf-behave] TURN/STUN Interoperability Issues

From: Adam Roach <[email-masked]>
Date: Mon, 27 Mar 2006 15:56:17 -0800 (PST)

In trying to implement TURN and STUN, our engineers have discovered a
couple of places in the current set of drafts that could be clearer.
Below, I describe the ambiguities and propose clarifying text.

1. USERNAME AND PASSWORD LENGTHS
--------------------------------

RFC 3489 rather clearly constrained usernames and passwords to be
multiples of 4 [sections 11.2.6 and 11.2.7]. This was a perfectly
sensible constraint when they were temporary. 3489bis has removed the
sentences that specifically constrain usernames and passwords; however,
section 11 clearly states that the length of "attributes values MUST be
0 or a multiple of 4 bytes."

We assume that the removal of the constraint on username and password
lengths is to accommodate the fact that long-term, user-selected
usernames and passwords can't be reasonably constrained to multiples of
4 bytes. However, this removal creates an ambiguity in the
specification. There is similar ambiguity around REALM.

Specifically: If I want to encode a 5-byte username (e.g. "test1"), what
is this supposed to look like? With the current specification, there are
at least four incompatible encodings that reasonable designers could
implement after reading the specification:

  1. 00 06 00 08 74 65 73 74 31 00 00 00
  2. 00 06 00 08 74 65 73 74 31 20 20 20
  3. 00 06 00 05 74 65 73 74 31
  4. 00 06 00 05 74 65 73 74 31 00 00 00

Number 1 is based on null-padding of the name to fit into a multiple of
4. This kind of makes sense because C strings are null terminated, and
null padding just kind of "feels right."

Number 2 is based on the fact that reason phrases are padded with spaces
to be a multiple of 4. This is the only mechanism described in the
document that talks about *how* to pad fields to be a multiple of 4. It
is almost certainly not what we intend.

Number 3 kind of misses the point that attributes need to be a multiple
of 4; however, it is the encoding that TWO DIFFERENT, INDEPENDENT
implementation teams at two different companies implemented, based on
the current document.

Number 4 takes the BFCP approach of encoding the actual attribute
length, but padding out to an even multiple of 4 bytes.

I think all of these can work, but we need to pick one and make sure the
encoding is described in a clear way that cannot be misconstrued. My
personal vote is for method 1. An example would be useful here.

I would propose adding text to section 11, at the end of the paragraph
starting "In order to align attributes on word boundaries...", to the
effect of:

    In order to align attributes on word boundaries, the length of the
    all message attributes values MUST be 0 or a multiple of 4 bytes.
    Extensions to this specification MUST also follow this requirement.
    Variable-length fields, such as USERNAME and PASSWORD, MUST be
    padded with ASCII NUL (0x00) characters so as to be a multiple of
    four bytes in length. For example, a USERNAME of "test1" would be
    encoded as 00 06 00 08 74 65 73 74 31 00 00 00.

I would also put reminder text in the USERNAME, PASSWORD, and REALM
entries along the lines of:

    The value of USERNAME is a variable length opaque value. Like all
    variable-length fields, USERNAME must be padded with ASCII NUL
    (0x00) characters so as to be a multiple of four bytes in length.

2. FORMAL DEFINITION OF HMAC KEY CALCULATION
--------------------------------------------

Section 8.1.2 of the stun draft starts talking about HMAC key
calculation without first defining the syntax being used to define
things. While implementors familiar with RFC 2617 will probably
recognize the operations and tend to do something sensible, others are
likely to be confused.

In particular, the operation unq() isn't defined in the STUN draft, and
there's no explicit statement that implementors should look to RFC 2617
for its definition. Similarly, the use of quotes around the colons and
the implied string concatenation isn't particularly well defined in STUN.

Finally -- and this is causing *severe* headaches in our attempts to
interop with other implementations -- it is unclear whether the result
of hashing this string (to be fed into the HMAC as a key) is the raw
16-byte result of the MD5 hash, or whether it is the 32-byte text hex
representation of this hash. The former is a somewhat more obvious
implementation choice for people unfamiliar with RFC 2617, while the
latter is more consistent with RFC 2617 encoding (from which the TURN
draft obviously borrows the mechanism).

I would propose removing the final sentence of the first item #3 in
section 8.1.2, and replacing it with:

    The 16-byte key for the MESSAGE-INTEGRITY HMAC is formed by taking
    the MD5 hash of the result of concatenating the following five fields:

        - The username, with any trailing nulls removed
        - A single colon
        - The realm, with any quotes and trailing nulls removed
        - A single colon
        - The password, with any trailing nulls removed

    For example, if the USERNAME field were 'user', the REALM field were
    '"realm"', and the PASSWORD field were 'pass', then the 16-byte HMAC
    key would be the result of performing an MD5 hash on the string
    'user:realm:pass', or 0x8493fbc53ba582fb4c044c456bdc40eb.

I would also strike the text in section 9.1.1 that re-specifies how to
perform the hash, and instead refer to the earlier description:

    If the USERNAME attribute was present, the server computes the HMAC
    over the request as described in Section 11.8. The HMAC key is
    computed as described in section 8.1.2. If the server does not have
    a record for that username within that realm, the server generates
    an error response.  That error response MUST include an ERROR-CODE
    attribute with a response code of 436.  That error response MUST
    include a NONCE attribute and a REALM attribute.

/a

---

From: Marc Petit-Huguenin <[email-masked]>
Date: Mon, 27 Mar 2006 16:57:46 -0800 (PST)

For issue #1, my understanding after the BEHAVE meeting (see slide 11 of
the TURN slides) is that the length is the real length of the value of
the attribute, but the attribute itself is padded to be a multiple of
four. This means that the number of bytes to skip when reading an
unknown attribute is (((((int)length) + 3) / 4) * 4), and not ((int)length).

This means that in fact the byte value used for padding is irrelevant. I
never understood why the attributes had to be 32 bit aligned, now it
makes sense.

All the implementations I know of, mine and Ethereal included, are
incorrect.

Adam Roach wrote:
> _______________________________________________
> Ietf-behave mailing list
> Ietf-behave@xxxxxxxxxxxxxxxxxxx
> https://list.sipfoundry.org/mailman/listinfo/ietf-behave
> 
> 

- --
Marc Petit-Huguenin
Home: marc@xxxxxxxxxxxxxxxxxx
Work: marc@xxxxxxx

-- 
Marc Petit-Huguenin
Home: marc@xxxxxxxxxxxxxxxxxx
Work: marc@xxxxxxx

---

From: "Derek MacDonald" <[email-masked]>
Date: Mon, 27 Mar 2006 16:58:24 -0800 (PST)

See Inline.

> -----Original Message-----
> From: ietf-behave-bounces@xxxxxxxxxxxxxxxxxxx [mailto:ietf-behave-
> bounces@xxxxxxxxxxxxxxxxxxx] On Behalf Of Adam Roach
> Sent: Monday, March 27, 2006 3:56 PM
> To: Behave; Jonathan Rosenberg; Christian Huitema; Rohan Mahy; Dan Wing
> Cc: Robert Sparks
> Subject: [Ietf-behave] TURN/STUN Interoperability Issues
> 

I also vote for method 1.

> 2. FORMAL DEFINITION OF HMAC KEY CALCULATION

After talking to Adam, I have been swayed to the 16-byte HMAC key camp.

---

From: Justin Uberti <[email-masked]>
Date: Mon, 27 Mar 2006 18:30:38 -0800 (PST)

Hi,

Thanks for the clarification; should it be the case that a multiple of 4 
bytes is read for every attribute (not just unknown ones)?

Also, I assume the requirement for 4-byte alignment is a performance 
optimization for CPUs that require integers to be aligned - is this correct?

Thanks,
--justin
petithug@xxxxxxx wrote:

---

From: Marc Petit-Huguenin <[email-masked]>
Date: Tue, 28 Mar 2006 03:14:47 -0800 (PST)

> bytes is read for every attribute (not just unknown ones)?

Yes. This was just an example.

> optimization for CPUs that require integers to be aligned - is this

I do not know.

> 
> Thanks,
> --justin
> 
> petithug@xxxxxxx wrote:
> 
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>

---

From: "Pete Cordell" <[email-masked]>
Date: Tue, 28 Mar 2006 06:44:04 -0800 (PST)

----- Original Message ----- 
From: "Justin Uberti" <juberti@xxxxxxx>

Also, I assume the requirement for 4-byte alignment is a performance 
optimization for CPUs that require integers to be aligned - is this 
correct?
It seems that IETF binary protocols are historically done that way (see IP,
TCP etc.).  It helps processors such as 68000 and maybe Sparc and maybe ARM
etc.  Mind you, even the 68020 could read integers starting at non-aligned
boundaries.  As a colleague once told me, "It's an optimization for a
minority architecture!"  (e.g. in some cases you can use the trick of
crafting a C struct that overlays the actual message bytes.)  Personally,
for portability I'd recommend treating such messages as byte streams but I
may be in the minority!
The only real advantage of it now is that it potentially makes the ASCII art
pictures of messages more precise.
HTH,

Pete.
--
=============================================
Pete Cordell
Tech-Know-Ware Ltd
                        for XML to C++ data binding visit
                        http://www.tech-know-ware.com/lmx
                        (or http://www.xml2cpp.com)
=============================================

---

From: Adam Roach <[email-masked]>
Date: Tue, 28 Mar 2006 09:08:43 -0800 (PST)

Pete Cordell wrote:

> ----- Original Message ----- From: "Justin Uberti" <juberti@xxxxxxx>
>
>
> minority architecture!"

Minority perhaps, but not antiquated (as you imply). Even modern
ultrasparc processors will SIGBUS if you try to access a 32-bit value
that isn't 32-bit aligned. Without backing data, I would be hesitant to
construe the use of Sun servers in data centers as a minority. I would
guess they make up a nontrivial fraction of such servers, in fact.

/a

---

From: Jonathan Rosenberg <[email-masked]>
Date: Wed, 29 Mar 2006 11:03:37 -0800 (PST)

To be clear, on the first issue, we discussed this at IETF and agreed on 
approach 4, which says that the attribute length value encodes the 
length of the actual data, but it is padded out when placed into the 
packet in order to equal a multiple of 32 bits. In such a case, the 
value of the pad is irrelevant. Unless someone says this gives them real 
heartburn I plan on proceeding with that approach.

On the second issue, thanks for pointing out this (big) ambiguity. I am 
fine with the 16 byte binary value and am happy to incorporate your 
proposed text. Thanks much for sending it.

-Jonathan R.

Rohan Mahy wrote:

Hi Adam,

Personally I like #3 and would be happy to abandon alignment in general, 
however I do not feel strongly about this.  If we insist on preserving 
alignment, I vote for #4.  I think this is much "safer" should someone 
send an embedded null in the middle of a value.

thanks,
-rohan
On Mar 27, 2006, at 15:56, Adam Roach wrote:

    the MD5 hash of the result of concatenating the following five 
fields:

--
Jonathan D. Rosenberg, Ph.D.                   600 Lanidex Plaza
Cisco Fellow                                   Parsippany, NJ 07054-2711
Cisco Systems
jdrosen@xxxxxxxxx                              FAX:   (973) 952-5050
http://www.jdrosen.net                         PHONE: (973) 952-5000
http://www.cisco.com

---

From: Adam Roach <[email-masked]>
Date: Wed, 29 Mar 2006 13:40:55 -0800 (PST)

Jonathan Rosenberg wrote:

> To be clear, on the first issue, we discussed this at IETF and agreed
> on approach 4, which says that the attribute length value encodes the
> value of the pad is irrelevant. Unless someone says this gives them
> real heartburn I plan on proceeding with that approach.

Perhaps I'm just confused, but won't this cause Really Bad Things to
happen if an old-style TURN server receives a new-style TURN message? At
least with approach 1, it will be able to skip over the padding
successfully. If the length no longer means "number of bytes to skip to
get to the next attribute," then old-style STUN servers are likely to
choke badly.

/a

---

From: Marc Petit-Huguenin <[email-masked]>
Date: Wed, 29 Mar 2006 17:34:34 -0800 (PST)

> get to the next attribute," then old-style STUN servers are likely to

I perhaps missed something but I cannot find a case where it can happen:

Here is the list of attributes that can have a variable length content:

ERROR-CODE
UNKNOWN-ATTRIBUTES
SERVER
PASSWORD
NONCE
REALM
DATA
USERNAME

We can remove ERROR-CODE, UNKNOWN-ATTRIBUTES, SERVER and PASSWORD from
the list, because there are sent only in response messages, so an
old-style STUN/TURN server will send them padded.

NONCE, REALM and DATA are used only with a TURN server. As the service
part of the SRV RR is different (_turn and _stun-relay), the client
knowns how to send this attributes. Same thing when the USERNAME is used
with an old-style TURN server.

USERNAME sent to an old-style STUN server is also not a problem as an
old-style STUN server will return it already padded in the
SHARED-SECRET-RESPONSE and it will be sent as it is to the
BINDING-REQUEST, i.e. already padded.

- --
Marc Petit-Huguenin