[AFS3-std] rxgk implementation notes

Benjamin Kaduk kaduk@MIT.EDU
Thu, 28 Feb 2013 17:05:07 -0500 (EST)


I've got a partial implementation of rxgk, just enough to perform the 
negotiation exchange to get a token and then use that token to "secure" 
an RXGK_LEVEL_CLEAR connection which is used to perform another 
token negotiation exchange.  (This implementation is using the token 
format &c. from the rxgk-afs document.)

As a result of this, I have a few comments about the rxgk document 
implementation experience:

We still have some places that refer to or imply an ordering of security 
levels, such as "this MUST NOT be less than the security level originally 
negotiated"; the OpenAFS rxkad implementation has this sort of assumption 
baked in, in that the client and server track a "minimum security level" 
in the security object private data, and make numeric comparisons against 
that value.  We used to have a channel-bound security level, and 
conceivably one may get added in the future.  It would be nice to either 
settle on "a token only supports exactly the level it was negotiated for" 
or some better ordering on the values of security levels.  Having the 
client and server explicitly track all allowable security levels would be 
somewhat annoying.

Having a mixture of RXGK_Data and plain XDR opaque types gets a bit 
annoying; in some places I end up having one variable of each type that 
alias the same storage.

It's hard to get the logic right for when to terminate a GSS negotiation 
loop, especially when the same C variable is used to hold major/minor 
status information from both the client and server calls.  I still owe us 
an update to the text in the document on this matter.

Having publicly-visible routines that take a gssapi context or other 
gssapi type is pretty annoying for the code structure, as it makes 
gssapi.h a prerequisite for the rxgk header.  This is rather inevitable, 
but it may prove convenient to split that stuff off into a separate 
header/library only used by the negotiation service.

Additionally, the gssapi libraries shipped with some OSes do not support 
the pseudo-random functions that we need.  This is just something that 
implementations will have to deal with.

It takes a fair amount of code to prepare the several structures that we 
specify as opaque or RXGK_Data typed objects that are the XDR encoding of 
some more detailed type.  Manually specifying bit layouts would be 
differently annoying though, I'm sure.

Relatedly, there's not an obvious error code to return when such encoding 
fails or we can't allocate memory for the new object.  I've been using, 
e.g., RXGEN_SS_MARSHAL for now, but I wonder if there are more RXGK error 
codes waiting to be added, here.  There's also some temptation to make 
things like BADLEVEL apply to the authentication step as well as just 
token negotiation; that would probably warrant changing the associated 
error string.

We say "rxgk challenges simply contain some versioning information and a 
random nonce selected by the server", though the current RPC-L is just a 
nonce.  It sort of seems like it may be worth adding a version field in 
case the challenge/response protocol ever needs to be rev'd.

The transport key is derived from the master key and a few pieces of 
information that are sent from client to server in the clear; it therefore 
seems that the utility of the transport key for avoiding key sharing 
mostly comes into play when large quantities of data are being conveyed. 
It is still useful as a mechanism for rekeying after lifetime or bytelife, 
though.  (I think, at least -- I haven't implemented rekeying yet.)

Endianness conversion routines for 64-bit quantities (i.e., rxgkTime) do 
not seem to be universally available; an incorrect hand-rolled 
implementation could lead to interoperability issues.

It's a bit awkward to include call number information in the authenticator 
(read: feels like a layering violation), and it's not clear to me what 
benefit is gained from doing so.  I vaguely remember seeing some 
discussion of this in an archive somewhere, but can't find it now.  All I 
see looking nowis discussion of using the maxcalls information as a way to 
migrate to having more than 4 calls per connection, which doesn't sound 
familiar.
We also don't mention whether call numbers in use are checked as part of 
verifying the authenticator -- I do not currently do so.


Strictly speaking, this affects the rxgk-afs document, but including the 
client UUID in the authenticator's appdata field is pretty awkward.  This 
field "contains the UUID of the client", which sounds like it should be 
the cache manager's idea of the UUID, but getting that from the rx layer 
seems to be a layering violation, and we may have situations (e.g., bos) 
where an rxgk client is not running a cache manager.  At the moment I just 
generate a fresh one and don't store it anywhere, which seems 
counterproductive.

-Ben