RFC 2755

Security Negotiation for WebNFS

πŸ“… published January 2000, from ietf

RFC 2755: Security Negotiation for WebNFS ✨

Okay bestie, let's dig into this one. RFC 2755 is an Informational doc (so it's sharing info, not setting an Internet standard 🫢). It was written in January 2000 by A. Chiu, M. Eisler, and B. Callaghan from Sun Microsystems. The title block doesn't list anything it obsoletes or updates, so it's standing on its own πŸ’….


Status of this Memo πŸ“œ

This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.

Copyright (C) The Internet Society (2000). All Rights Reserved.

Abstract 🌸

This doc describes a protocol that lets a WebNFS client [RFC2054] negotiate which security mechanism it wants with a WebNFS server [RFC2055]. This all happens before the WebNFS client falls back to the MOUNT v3 protocol [RFC1813]. It's written so people can build implementations that work together 🧚.

Table of Contents πŸ—‚οΈ

   1. Introduction ..............................................  2
   2. Security Negotiation Multi-component LOOKUP ...............  3
   3  Overloaded Filehandle .....................................  4
   3.1  Overloaded NFS Version 2 Filehandle .....................  5
   3.2  Overloaded NFS Version 3 Filehandle .....................  6
   4. WebNFS Security Negotiation ...............................  6
   5. Security Considerations ................................... 10
   6. References ................................................ 10
   7. Acknowledgements .......................................... 10
   8. Authors' Addresses ........................................ 11
   9. Full Copyright Statement .................................. 12

1. Introduction πŸŽ€

Okay so the MOUNT protocol is how an NFS client gets the filehandle it needs for accessing data πŸ—οΈ. MOUNT versions 1 and 2 [RFC1094] hand back NFS version 2 filehandles, but MOUNT version 3 [RFC1813] gives you NFS version 3 filehandles.

Here's the tea: out of all the MOUNT versions, only MOUNT v3 has an RPC procedure (MOUNTPROC3_MNT) that helps an NFS v3 client and an NFS v3 server negotiate security πŸ”. When that procedure works (MNT3_OK), the server sends back an array of the security mechanisms it supports for the pathname you asked about, plus an NFS v3 filehandle. Iconic behaviour, honestly πŸ‘‘.

A security mechanism in this doc is a generalized security flavor. It can be an RPC authentication flavor [RFC1831] or a flavor from the RPCSEC_GSS protocol [RFC2203]. Each security mechanism is stored as a four-octet integer πŸ”’.

No RPC procedures for security negotiation exist in versions 1 or 2 of the MOUNT protocol πŸ™ˆ.

The NFS mount command has a sec= option, which lets an NFS client pick the security mechanism it wants for NFS transactions πŸ’–. If you don't specify that option, here's what happens: over NFS v2 mounts, it uses the default security mechanism. Over NFS v3 mounts, it negotiates a mechanism through MOUNTPROC3_MNT on MOUNT v3 and then uses that. In the NFS v3 case, the client grabs the first mechanism in the server's array that the client also supports. Simple but effective ✨.

As RFC 2054 says, a WebNFS client first assumes the server supports WebNFS. It uses the public filehandle as its starting filehandle for data access, which means it doesn't need MOUNT at all πŸ¦‹. If the server doesn't support WebNFS, the WebNFS client falls back to MOUNT.

Because a WebNFS client doesn't use MOUNT at the start, MOUNTPROC3_MNT isn't around for security negotiation until the client falls back to MOUNT 😭. So we need a brand new way for WebNFS clients to negotiate security mechanisms with the server when MOUNTPROC3_MNT isn't an option. That's the whole point of this doc πŸ’….

The WebNFS security negotiation protocol has to hit these requirements:

  • Must work seamlessly with NFS v2 and v3, and the WebNFS protocols
  • Must be backward compatible with servers that do not support this negotiation
  • Minimum number of network turnarounds (latency)

This doc describes the WebNFS security negotiation protocol that Sun Microsystems, Inc. developed. It uses terminology and definitions from RFCs 2054 and 2055, so you should already know those docs. Bestie, go read them first πŸ“šπŸ«Ά.

2. Security Negotiation Multi-component LOOKUP πŸ”

The big goal of WebNFS security negotiation is this: a WebNFS client should be able to find a security mechanism that the WebNFS server uses to protect a given path, and that the client also supports 🎯. Here's how it goes. The client starts by sending the server the path. The server replies with the array of security mechanisms it uses to protect that path. The client then picks the first one in that array that it also supports. Clean and iconic πŸ’œ.

The cool part is that there's no new WebNFS request. Instead, the negotiation works by modifying the request and response of the existing multi-component LOOKUP (MCL) operation [RFC2055] 🧠. The MCL operation runs through the LOOKUP procedure (NFSPROC3_LOOKUP for NFS v3, and NFSPROC_LOOKUP for NFS v2). This section and the next ones explain how the MCL request and response get modified to make WebNFS security negotiation work ✨.

To keep things easy to refer to, the modified MCL request is called the SNEGO-MCL (security negotiation multi-component LOOKUP) request πŸŽ€.

A multi-component LOOKUP request [RFC2055] has two parts: a public filehandle and a multi-component path. Here's what it looks like:

        For Canonical Path:

                LOOKUP FH=0x0, "/a/b/c"

        For Native Path:

                LOOKUP FH=0x0, 0x80 "a:b:c"

A multi-component path is either an ASCII string of slash-separated components, or the 0x80 character followed by a native path. Also, a multi-component LOOKUP always uses the public filehandle in the LOOKUP 🌈.

A SNEGO-MCL request is like an MCL request in that it has a public filehandle and a pathname. The difference is that its pathname is built in a special way, as described below, so it can't be confused with other pathnames πŸ¦‹.

Here's the deal with the SNEGO-MCL pathname: it's the regular WebNFS multi-component path with two octets stuck on the front πŸ’…. The first one is the 0x81 non-ASCII character. It's kind of like 0x80, which is used for native paths, but this one means "the client wants to negotiate security mechanisms" πŸ”. The second one is the security index octet. It holds the current position in the array of security mechanisms the server will send back. The security index always starts at one and goes up as the negotiation continues πŸ“ˆ. After those two octets comes the pathname itself, which is either an ASCII string of slash-separated canonical components, or 0x80 followed by a native path.

A security negotiation MCL request looks like this:

        For Canonical Path:

                LOOKUP FH=0x0, 0x81 <sec-index> "/a/b/c"

        For Native Path:

                LOOKUP FH=0x0, 0x81 <sec-index> 0x80 "a:b:c"

Next up, we'll see how the MCL response gets modified for WebNFS security negotiation 🫢✨.


Part 1 of 2. Part 2 picks up with Section 3 (Overloaded Filehandle) and keeps going from there πŸ’–.

4. WebNFS Security Negotiation ✨

Okay so now the fun part πŸŽ€ Once you've got the SNEGO-MCL request and the overloaded NFS v2 and v3 filehandles, the whole WebNFS security negotiation protocol looks like this πŸ‘‡

    Client                                      Server
    ------                                      ------

        LOOKUP FH=0x0, 0x81 <sec-index> "path"
                        ----------->
                        <-----------
                            FH: length, status, {sec_1  sec_2 ... sec_n}

Here's what everything in there means πŸ’…

  • 0x81 is the client saying "hey, I want to negotiate security mechanisms with you" πŸ™‹β€β™€οΈ
  • path is either an ASCII string of slash separated components, or 0x80 followed by a native path πŸ—ΊοΈ
  • sec-index, one octet, is the index into the array of security mechanisms the server uses to protect the specified path πŸ”
  • status, one octet, tells you whether there are more security mechanisms (1 means yes, 0 means no) that need another SNEGO-MCL to get them πŸ“
  • length (one octet for NFS v2 and four octets for NFS v3) tells you how many valid octets come after it πŸ“
  • {sec_1 sec_2 ... sec_n} is the array of security mechanisms. As noted earlier, each security mechanism is a four-octet integer 🧚

Okay so here's an NFS v2 example 🌸 Say the server shares /export with 10 security mechanisms {0x3900 0x3901 0x3902 ... 0x3909} on the export. You'd need two SNEGO-MCL requests to get the full security info, bestie 😭

LOOKUP FH=0x0, 0x81 0x01 "/export"
                    ----------->
                    <-----------
    0x1c, 0x01, {0x3900 0x3901 0x3902 0x3903 0x3904 0x3905 0x3906}

LOOKUP FH=0x0, 0x81 0x08 "/export"
                    ----------->
                    <-----------
    0x0c, 0x00, {0x3907 0x3908 0x3909}

The order of the security mechanisms in an overloaded filehandle tells you the preferences. The ones at the front are more recommended than the ones after them πŸ₯‡ And that ordering is the same as what comes back from the MOUNT v3 protocol πŸ¦‹


Now the typical scenario 🎬 This is how WebNFS security negotiation actually goes down when you're accessing publicly shared filesystems ✨

Normally, a WebNFS client starts with a regular multi-component LOOKUP using the public filehandle, to get the filehandle for the path it wants. The client has zero prior knowledge about how the server protects that path, so the default security mechanism gets used in this first multi-component LOOKUP. If the default mechanism doesn't meet the server's requirements, the server replies with the AUTH_TOOWEAK RPC authentication error. That basically means "the default isn't valid, go get a stronger one" πŸ’€

When the client gets AUTH_TOOWEAK, it wants to figure out which security mechanisms the path requires. So it sends a SNEGO-qMCL request, using the default security mechanism πŸ”

If the SNEGO-MCL request works, the server responds with the filehandle overloaded with the array of security mechanisms required for that path. If the server doesn't support WebNFS security negotiation at all, the SNEGO-MCL request fails with NFSERR_IO for NFS v2 or NFS3ERR_IO for NFS v3 [RFC2055] πŸ™ˆ

Depending on how big the array of security mechanisms is, the WebNFS client might have to make more SNEGO-MCL requests to get the complete array πŸ“š

For successful SNEGO-MCL requests, the WebNFS client pulls the array of security mechanisms out of the overloaded filehandle, picks one that works, and sends a regular multi-component LOOKUP using that selected mechanism to get the filehandle πŸ’–

After that, all subsequent NFS requests use the selected security mechanism and the filehandle. Main character energy πŸ‘‘

Here's the whole scenario in action πŸŽ€ It's assumed that the server shares /export/home like this:

share -o sec=sec_1:sec_2:sec_3,public /export/home

and AUTH_SYS is the client's default security mechanism, and it is not one of {sec_1, sec_2, sec_3}.

    Client                                          Server
    ------                                          ------

        LOOKUP FH=0x0, "/export/home"
                                 AUTH_SYS
                                ----------->
                                <-----------
                                                    AUTH_TOOWEAK

        LOOKUP FH=0x0, 0x81 0x01 "/export/home"
                                 AUTH_SYS
                                ----------->
                                <-----------
                 overloaded FH: length, status, {sec_1 sec_2 sec_3}

        LOOKUP FH=0x0, "/export/home"
                                    sec_n
                                ----------->
                                <-----------
                                                    FH = 0x01

        NFS request with FH=0x01
                                    sec_n
                                ----------->
                                <-----------
                                                    ...

So in the scenario above, the first request is a regular multi-component LOOKUP, and it fails with AUTH_TOOWEAK. The client then sends a SNEGO-MCL request to get the security info 🧠

Some WebNFS implementations let the public filehandle work with NFS protocol procedures other than LOOKUP 🧩 For those implementations, if the first request is not a regular multi-component LOOKUP and it fails with AUTH_TOOWEAK, the client should issue a SNEGO-MCL with the following as the path to get the security information:

    0x81 0x01 "."

5. Security Considerations 🚨

Okay this section is serious, so listen up 🫢

The reader may note that no mandatory security mechanisms are specified in the protocol that the client must use in making SNEGO-MCL requests. Normally, the client uses the default security mechanism configured on its system in the first SNEGO-MCL request. If the default security mechanism is not valid, the server replies with the AUTH_TOOWEAK error. In this case the server does not return the array of security mechanisms to the client. The client can then make another SNEGO-MCL request using a stronger security mechanism. This keeps going until the client hits a valid one or has run out of all the supported security mechanisms πŸ”₯


6. References πŸ“–


7. Acknowledgements 🫢

This specification was extensively brainstormed and reviewed by the NFS group of Solaris Software Division. The whole squad showed up πŸ’œ


8. Authors' Addresses πŸ’Œ

Alex Chiu
Sun Microsystems, Inc.
901 San Antonio Road
Palo Alto, CA 94303

Phone: +1 (650) 786-6465
EMail: alex.chiu@Eng.sun.com


Mike Eisler
Sun Microsystems, Inc.
901 San Antonio Road
Palo Alto, CA 94303

Phone: +1 (719) 599-9026
EMail: michael.eisler@Eng.sun.com


Brent Callaghan
Sun Microsystems, Inc.
901 San Antonio Road
Palo Alto, CA 94303

Phone: +1 (650) 786-5067
EMail: brent.callaghan@Eng.sun.com

Copyright (C) The Internet Society (2000). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Acknowledgement πŸ’–

Funding for the RFC Editor function is currently provided by the Internet Society. Thank you for reading, bestie πŸ¦‹βœ¨

πŸ“¦ where this page comes from