Subject: Re: [nfsv4] one more try at RFC3530 internationalization.

From: Mike Kupfer <[email-masked]>
Date: Tue, 10 Sep 2013 11:56:22 -0700

Mike Kupfer wrote:

> Noveck, David wrote:
> 
> > I understand that there are lots of things people might like to see,
> > but right now I'd like people to focus on chapter 12 of
> > draft-ietf-nfsv4-rfc3530bis-27.  If you have specific changes that
> > you'd like to see in future drafts, please suggest the wording changes
> > you want.  On the other hand, if you don't think this is a reasonable
> > basis to go forward with in the rfc3530bis time frame, please say so
> > and draft a replacement chapter.
> 
> Okay, I'll work on some specific replacement text.  It may take a few
> weeks, as I will have to juggle this with other tasks.

Here's a stab at replacement text for Chapter 12, with change bars.

High-level overview: I reorganized the chapter into 2 main sections
(in addition to the introduction).

Section 12.2 discusses component names and symbolic links.  On a
technical level, it is radically different from what's in rev 27, but I
think it's more accurate in describing actual implementation practice.
If we think that this moves the spec in the right direction, I think
we'll also want to change the rpcgen declarations elsewhere in the spec
to reflect the change from UTF-8 to opaque byte string.

Section 12.3 discusses other strings and reuses most of the text from
rev 27.  I'm not particularly confident of the Section 12.3 text, for
two reasons.  First, I'm not familiar with how this code is implemented
in Solaris.  Second, I'm not aware of any testing in this area at our
testing events.  Still, I don't have anything better to suggest.

mike

--8<---------------cut here---------------start------------->8---
12.  Internationalization

12.1.  Introduction

   This section describes NFSv4.0 internationalization as implemented by
   existing clients and servers.  As a result, the keywords "MUST",
   "SHOULD", and "MAY", even though they retain their normal meanings,
   reflect patterns of existing implementation:

   o  Behavior implemented by all existing clients or servers is
      described using "MUST", since new implementations need to follow
      existing ones to be assured of interoperability.

   o  Behavior implemented by no existing clients or servers is
      described using "MUST NOT", if such behavior poses
      interoperability problems.

   o  Behavior implemented by most existing clients or servers, where
      that behavior is more desirable than any alternative is described
      using "SHOULD", since new implementations need to follow that
      existing practice unless there are strong reasons to do otherwise.
      This also holds for "SHOULD NOT".

   o  Behavior implemented by some not all existing clients or servers,
      is described using "MAY", indicating that new implementations have
      a choice as to whether they will behave in that way.

   o  Behavior implemented by all existing clients or servers, so far as
      is known, but where there remains some uncertainty as to details
      is described using "should".  Such cases primary concern details
      of error returns.  New implementations should follow existing
      practice even though such situations generally do not affect
      interoperability.

  Strings are used in the NFS protocol is the following contexts: as	    |
  component names, as the contents of symbolic links, as user and	    |
  group identifiers, and as hostnames.  The requirements for component	    |
  names and symbolic links will be discussed first, followed by a	    |
  discussion of the other strings.					    |
									    |
12.2.  Encoding of Component Names and Symbolic Link Text		    |
									    |
  The preferred over-the-wire encoding of strings is UTF-8 [RFC2279].	    |
  Unfortunately, the architecture of many NFS implementations is such	    |
  that they cannot guarantee that UTF-8 is used for component names or	    |
  the contents of a symbolic link.  On the client, the application	    |
  process may control the encoding, and the encoding is not		    |
  necessarily known at the NFS layer.  On the server, the encoding	    |
  used by the local filesystem implementation may not be known;		    |
  indeed, multiple encodings may be in use.				    |
									    |
  To avoid possible corruption of component names or symbolic links,	    |
  an implementation MUST NOT attempt a conversion to UTF-8 if the	    |
  original encoding is not known.  Furthermore, when receiving a	    |
  component name or symbolic link contents from another host, an	    |
  implementation MUST NOT make any assumptions about the encoding.	    |
  Note that just because a string is valid when interpreted as UTF-8,	    |
  that does not mean that the string's encoding is actually UTF-8.	    |
									    |
  The net result is that implementations SHOULD treat component names	    |
  and symbolic link text as opaque byte strings.			    |
									    |
12.3.  Encoding of Other Strings					    |
									    |
   For strings whose form is defined by other internet standards, most	    |
   notably host and domain names, non-ASCII characters MUST be		    |
   represented using the UTF-8 encoding of Unicode.  In addition other	    |
   sorts of restrictions defined by those standards need to be
   addressed.  See section 12.3.2 for details.				    |
									    |
   For other sorts of strings, any non-ASCII characters SHOULD be
   represented using the UTF-8 encoding of Unicode.

12.3.1  Normalization							    |

   The client and server operating environments may differ in their
   policies and operational methods with respect to character
   normalization (See [Unicode1] for a discussion of normalization
   forms).  This difference may also exist between applications on the
   same client.  This adds to the difficulty of providing a single
   normalization policy for the protocol that allows for maximal
   interoperability.  This issue is similar to the character case issues
   where the server may or may not support case insensitive file name
   matching and may or may not preserve the character case when storing
   file names.  The protocol does not mandate a particular behavior but
   allows for a range of useful behaviors.

   The NFS version 4 protocol does not mandate the use of a particular
   normalization form at this time.  A subsequent minor version of the
   NFSv4 protocol might specify a particular normalization form.
   Therefore, the server and client can expect that they may receive
   unnormalized characters within protocol requests and responses.  If
   the operating environment requires normalization, then the
   implementation must normalize the various UTF-8 encoded strings
   within the protocol before presenting the information to an
   application (at the client) or local file system (at the server).
   Implementations MAY also perform normalization-insensitive string	    |
   comparisons without modifying the name to match a particular		    |
   normalization form.							    |
									    |
12.3.2  Types with Processing Defined by Other Internet Areas		    |

   There are two types of strings which NFSv4 deals with whose
   processing is defined by other Internet standards, and where issues
   related to different handling choices by server operating systems or
   server file systems do not apply.

   These are as follows:

   o  Server names as they appear in the fs_locations attribute.  Note
      that for most purposes, such server names will only be sent by the
      server to the client.  The exception is use of the fs_locations
      attribute in a VERIFY or NVERIFY operation.

   o  Principal suffixes which are used to denote sets of users and
      groups, and are in the form of domain names.

   The general rules for handling all of these domain-related strings
   are similar and independent of role the of the sender or receiver as
   client or server although the consequences of failure to obey these
   rules may be different for client or server.  The server can report
   errors when it is sent invalid strings, whereas the client will
   simply ignore invalid string or use a default value in their place.

   The string sent SHOULD be in the form of a U-label although it MAY be
   in the form of an A-label or a UTF-8 string that would not map to
   itself when canonicalized by applying ToUnicode(ToASCII(...)).  The
   receiver needs to be able to accept domain and server names in any of
   the formats allowed.  The server MUST reject, using the error
   NFS4ERR_INVAL, a string which is not valid UTF-8 or which begins with
   "xn--" and violates the rules for a valid A-label.

   When a domain string is part of id@domain or group@domain, the server
   SHOULD map domain strings which are A-labels or are UTF-8 domain
   names which are not U-labels, to the corresponding U-label, using
   ToUnicode(domain) or ToUnicode(ToASCII(domain)).  As a result, the
   domain name returned within a userid on a GETATTR may not match that
   sent when the userid is set using SETATTR, although when this
   happens, the domain will be in the form of a U-label.  When the
   server does not map domain strings which are not U-labels into a
   U-label, which it MAY do, it MUST NOT modify the domain and the
   domain returned on a GETATTR of the userid MUST be the same as that
   used when setting the userid by the SETATTR.

   The server MAY implement VERIFY and NVERIFY without translating
   internal state to a string form, so that, for example, a user
   principal which represents a specific numeric user id, will match a
   different principal string which represents the same numeric user id.

12.3.3.  UTF-8 Related Errors						    |

   Where the client sends an invalid UTF-8 string, the server SHOULD
   return an NFS4ERR_INVAL error.  This includes cases in which
   inappropriate prefixes are detected and where the count includes
   trailing bytes that do not constitute a full UCS character.

   Where the client-supplied string is not rejected with NFS4ERR_INVAL	    |
   but contains characters that are not supported by the server as a
   value for that string (e.g. names containing characters that have
   more than two octets on a file system that supports Unicode
   characters only), the server should return an NFS4ERR_BADCHAR error.
									    |
--8<---------------cut here---------------end--------------->8---

---

From: "Noveck, David" <[email-masked]>
Date: Tue, 10 Sep 2013 20:26:55 -0400

Let me start by giving you what I understand to be overall framework for this discussion.

I'll invite Spencer, David Black, and Martin to correct me if I've got something wrong.

We want to get RFC3530bis approved by the IESG, and right now the favored approach is to present the IESG with something that can be fairly described as reflecting current implementation practice and ask for it to be approved on that basis.  The Chapter 12 in the current rfc3530bis draft was intended to be a baseline for that effort and I'm primarily interested in cases where I got it wrong.  I know of a few and I'll summarize those in a bit.  My current expectation is that those, plus any that anyone points out to me will be the basis for the next rfc3530bis draft.

If the working group wants to follow a different path, that's up to them.

There is also an expectation that there will be a subsequent document describing internationalization within a précis-based framework.  The current  intention is that it describe internationalization for all NFSv4 minor versions, be implementable, and be acceptable to the IESG.   Not much thought has been given to the possibility that those three conditions might not simultaneously satisfiable.

Now to details.

>> Also, servers that support NFSv4 and CIFS access to the same
>> filesystem have to make some sort of assumptions about what the NFSv4
>> component strings mean.

> Why?

Because, if I call a file StuffForPrécis in CIFS, and give you the name, you'd like to be able to look it up using NFSv4.  The only way that a server can do that is to assume that it knows how "é" is represented by an NFSv4 client.

>  So, I suppose the spec could say that if a string is syntactically valid as UTF-8, then an implementation may treat it
> as UTF-8 (and do normalization-independent comparison), but warn that applications may see unexpected behavior
> if they use a non-UTF-8 encoding.

I think we agree on the principle, which is that UTF-8 is the preferred encoding.

I'd say "SHOULD treat it as UTF-8 and MAY do normalization-independent comparison"

> If the client receives a string from the server that isn't syntactically valid as UTF-8, it should (MUST?) treat the string as an opaque byte string.

I don't see what exactly it is that the client MUST do.

> If the server receives a string from the client that isn't syntactically valid as UTF-8, the server SHOULD treat it as an opaque byte string but MAY reject it with NFS4ERR_INVAL.

Ultimately, I'd switch the SHOULD and MAY, but as an explanation of current behavior, "MAY reject it with NFS4ERR_INVAL" sounds right, but I'm not aware of anything that existing servers do with non-UTF-8 strings other than treat them as opaque.

> Does that sound any better?

It sounds like we are converging, although there are occasional discordant notes.

-----Original Message-----
From: Mike Kupfer [mailto:[email-masked]]
Sent: Tuesday, September 10, 2013 5:24 PM
To: Noveck, David
Subject: Re: [nfsv4] one more try at RFC3530 internationalization.

Noveck, David wrote:

> So are you saying that, if a server-filesystem combination  implements
> normalization-insensitive LOOKUP's, then it is doing something wrong?

Well, I suspect it's doing something wrong.  I'd certainly be happy to see evidence to the contrary (e.g., an implementation that's deployed in a multi-vendor environment where normalization is relevant to the language being used).  If the applications are using UTF-8, then it could all work by happy accident.

> You can't do normalization-insensitive LOOKUP's without assuming that
> you are receiving UTF-8.

Indeed.

> Also, servers that support NFSv4 and CIFS access to the same
> filesystem have to make some sort of assumptions about what the NFSv4
> component strings mean.

Why?

> It gets worse.  A filesystem that rejects CREATE of ".'" and ".." is
> making some assumptions about the encoding, even if they are very
> limited assumptions.
>
> I think a "MUST NOT" like this does not reflect overall implementation
> practice.

Yes, good point.  We seem to be using ASCII as a baseline, so I guess an implementation can assume that if a string is all 7-bit characters, it's ASCII.

The reason I resisted saying that an implementation may assume UTF-8 is that I don't have a good handle on the failure scenarios that are possible when a string is treated as UTF-8 but that wasn't its original encoding.  But I'm willing to back off from that stance.

So, I suppose the spec could say that if a string is syntactically valid as UTF-8, then an implementation may treat it as UTF-8 (and do normalization-independent comparison), but warn that applications may see unexpected behavior if they use a non-UTF-8 encoding.

If the client receives a string from the server that isn't syntactically valid as UTF-8, it should (MUST?) treat the string as an opaque byte string.

If the server receives a string from the client that isn't syntactically valid as UTF-8, the server SHOULD treat it as an opaque byte string but MAY reject it with NFS4ERR_INVAL.

Does that sound any better?

mike

---

From: Nico Williams <[email-masked]>
Date: Tue, 10 Sep 2013 22:27:29 -0500

On Tuesday, September 10, 2013, Noveck, David wrote:

> We want to get RFC3530bis approved by the IESG, and right now the favored
> approach is to present the IESG with something that can be fairly described
> as reflecting current implementation practice and ask for it to be approved
> on that basis.  The Chapter 12 in the current rfc3530bis draft was intended
> to be a baseline for that effort and I'm primarily interested in cases
> where I got it wrong.  I know of a few and I'll summarize those in a bit.
> My current expectation is that those, plus any that anyone points out to me
> will be the basis for the next rfc3530bis draft.
>
> There is also an expectation that there will be a subsequent document
> describing internationalization within a précis-based framework.  The
> current  intention is that it describe internationalization for all NFSv4
> minor versions, be implementable, and be acceptable to the IESG.   Not much
> thought has been given to the possibility that those three conditions might
> not simultaneously satisfiable.
>

Heh, sure, it may not be possible.  It may even not be possible to describe
reality in a non-contradictory way.

Now to details.
> Because, if I call a file StuffForPrécis in CIFS, and give you the name,
> you'd like to be able to look it up using NFSv4.  The only way that a
> server can do that is to assume that it knows how “é” is represented by an
> NFSv4 client.
>

But two protocols could interop at the filesystem if a) the server
just-uses-8 and b) the clients all use UTF-8 (in the same form).  So a
no-assumptions implementation is possible.  And it's even getting more and
more likely to interop just on account of the growing use of UTF-8 locales.
 Now if one fs protocol requires UTF-16 and the other could be
either just-use-8 or UTF-8 then yes, the server must assume it's UTF-8.
 Your point, I think, is that one's hand can be forced, yes?

Yes.  The server can't warn applications either (docs can warn users).

> So, I suppose the spec could say that if a string is syntactically valid
> as UTF-8, then an implementation may treat it

> > If the client receives a string from the server that isn't syntactically
> valid as UTF-8, it should (MUST?) treat the string as an opaque byte string.
>
> I don’t see what exactly it is that the client MUST do.
>

I think the client has more choices.  Once more I think the boundaries are
important: if we're talking about a POSIX readdir()-type interface the I
think the client MUST just-use-8 when the server's READDIR results include
non-UTF-8, but if we're talking about an application (that might be using
readdir()) then I think we might prefer it to display undisplayable
codepoints as '?' or similar.  But we can't mandate application behavior!
 How could we when the vast majority of NFSv4 implementations are below a
POSIX-like layer?  We can't.  But it feels wrong to prevent an application
from handling undisplayable (because invalid/non-sensical) codepoints as it
wishes -- that would be the effect of saying that the client must do
anything other than just-use-8.  Therefore i agree with Dave, we can't
really require any particular behavior as to non-UTF-8 in READDIR results.

> > If the server receives a string from the client that isn't syntactically
> valid as UTF-8, the server SHOULD treat it as an opaque byte string but MAY
> reject it with NFS4ERR_INVAL.
>
> Ultimately, I’d switch the SHOULD and MAY, but as an explanation of
> current behavior, “MAY reject it with NFS4ERR_INVAL” sounds right, but I’m
> not aware of anything that existing servers do with non-UTF-8 strings other
> than treat them as opaque.
>

I think this MUST be configurable if the server is to accept non-UTF-8 at
all.  I don't care what the default SHOULD be.

> It sounds like we are converging, although there are occasional discordant

I have that sense as well.

> From: Mike Kupfer [mailto:[email-masked] <javascript:_e({},
> 'cvml', [email-masked]');>]
> Well, I suspect it's doing something wrong.  I'd certainly be happy to see
> evidence to the contrary (e.g., an implementation that's deployed in a
> multi-vendor environment where normalization is relevant to the language
> being used).  If the applications are using UTF-8, then it could all work
> by happy accident.
>

Normalization is not just about language/script (though it is for
Korean/Hangul).  I blogged long ago about interop problems with HFS+ (which
normalizes on CREATE, to NFD).  My example was contrived, involving
cut-n-paste.  Later it happened for realz when Apple was porting ZFS to OS
X and they made it normalize on CREATE to match HFS+ behavior, and someone
reported a live interop problem where the symptoms involved git failures.
 I remember this vividly because it caused Linus Torvalds to rant about ZFS
being broken, but it wasn't ZFS, it was Apple's port -- I had fought for
n-i behavior in ZFS at Sun, so I was flabbergasted and annoyed and
overjoyed (that the theoretical problem was real and that we'd avoided it
correctly at Sun) all at once.

> > You can't do normalization-insensitive LOOKUP's without assuming that

But it's a mostly harmless assumption.  It creates some aliasing that i
most cases will not be noticed.  There is a security consideration though:
access controls based on listing file names might allow equivalent forms
through

.

> Yes, good point.  We seem to be using ASCII as a baseline, so I guess an
> implementation can assume that if a string is all 7-bit characters, it's
> ASCII.
>
> The reason I resisted saying that an implementation may assume UTF-8 is
> that I don't have a good handle on the failure scenarios that are possible
> when a string is treated as UTF-8 but that wasn't its original encoding.
> But I'm willing to back off from that stance.
>
> So, I suppose the spec could say that if a string is syntactically valid
> as UTF-8, then an implementation may treat it as UTF-8 (and do
> normalization-independent comparison), but warn that applications may see
> unexpected behavior if they use a non-UTF-8 encoding.
>
> If the client receives a string from the server that isn't syntactically
> valid as UTF-8, it should (MUST?) treat the string as an opaque byte string.
>

The failure scenarios for n-i behavior are about aliasing.  I think they
are mostly harmless.

We already have some of that when you think of filenames with embedded
backslashes in them (ok, i'm stretching a bit here).

Nico
--