[OpenAFS-devel] crypto backend and integration for rxgk

Benjamin Kaduk kaduk@MIT.EDU
Thu, 2 May 2013 16:58:32 -0400 (EDT)


On Wed, 1 May 2013, Simon Wilkinson wrote:

>
> On 1 May 2013, at 17:24, Benjamin Kaduk wrote:
>
>> As such, it seems like we should have the ability for an rxgk-using 
>> tool/utility/etc. to use either hcrypto or libkrb5 for its crypto 
>> backend. This would also leave open the possibility of using an OS 
>> kernel's crypto implementation instead of hcrypto, though that would 
>> require per-OS work and is not needed for an initial implementation.
>
> I think you actually need to split things up more than this. You've got 
> the library that provides the RFC3961 functionality, and then the 
> library that provides the raw crypto operations. I think it's really 
> important to consider the non-krb5 use cases. People will want to link 
> against non-krb5 GSSAPI libraries, and we have to make that possible 
> without requiring that they bring in a large amount of krb5 baggage with 
> them.

Let me check that I'm reading this correctly: the idea is that OpenAFS has 
an interal "rfc3961 library" which exposes an API for the RFC 3961 crypto 
operations (and this API happens to look like the heimdal API for 
historical reasons).  rxgk would link against libafsrfc3961, but what 
libafsrfc3961 uses as a backend is configurable, and could be the in-tree 
hcrypto, an out-of-tree krb5 solution, the kernel's crypto layer, etc.
Hmm, using a different crypto backend for libafsrfc3961 in the kernel and 
in userland could be annoying with the current build system; I'm not sure 
how that would work.

In my dev work, I went with something intended to be minimally invasive to 
the rest of the tree (to make a future API change easier), namely define 
an "rxgk rfc3961 crypto api" with things like mic_in_key(), 
encrypt_in_key(), etc..  Those are obviously not final names, but one 
reason I started this thread is to decide whether they should be renamed 
to rxgk_mic_in_key() or calls to them should be replaced by something 
else, such as this purpoted rfc3961 library.

> My original goal, which is partially implemented in the OpenAFS tree was 
> to provide hcrypto as a general purpose crypto library, which could be 
> replaced by anything which provides a compatible interface (OpenSSL is 
> the obvious candidate here, although I believe that there are also shims 
> which would allow NSS to be used to). We then layer on top of this a 
> rfc3961 krb5_crypto library, which at the moment is only used in kernel 
> space. The way the code is structured, you can also swap this out for a 
> compatible (Heimdal) libkrb5 if you so wish.
>
> I didn't really consider the MIT code because at that point the MIT 
> crypto code was an unholy mess, and my main priority was to have 
> something that could be loaded into the kernel with as little bother as 
> possible. So the whole implementation, both kernel and userspace was 
> built around the Heimdal krb5_crypto API. I still think this makes sense 
> - base your implementation around the kernel API, and support userspace 
> MIT through a shim layer if required.

Yeah, the MIT crypto code is not usable in the kernal yet.  It's a goal 
for us, but I don't think there's a particular timescale for it yet.

It does seem to make sense to fix a kernel (as in core, not OS kernel) 
"rfc3961 API" and use a shim to other backends as desired, yes.

>> There is also the question of GSS integration for key negotiation.  I 
>> have the impression that, just as we currently try to limit the 
>> exposure of libkrb5 to aklog and asetkey and similar, we will want to 
>> limit the exposure of the GSS-API library in the tree.  (That is, we 
>> don't want to link every executable we build against a gssapi library.)
>
> That would be the ideal, yes. Whether it is practical or not, with our 
> current library structure, is another matter. We don't really have any 
> separation between client libraries and server libraries, so it is very 
> easy for something that is required on the server to end up also being 
> required on the client just through library dependencies. This is more 
> of an issue for things like extended authentication names, and support 
> in the UserList, and so on, than for core rxgk.

Indeed, the extended names are what I worry about the most.  I think for 
rxgk server executables, we could have a separate rxgk_gssapi.lo object 
which is linked in directly but not included in the rxgk library itself 
(or a separate library for the negotiation protocol and the security 
class, or something) if we need to.

>> The question of which keys go where is a pretty big one.
>> At a glance, keys to worry about include:
>> GSS acceptor creds for the vlserver
>> GSS acceptor creds for bosserver
>> GSS acceptor creds for other non-dbserver, non-fileserver bits
>
> These all live in the default gss acceptor location. Doing anything else 
> makes your binary mechanism dependent, which it would be best to avoid.

I want to hear from jhutz, but the argument of having 
mechanism-independent binaries is fairly persuasive.  Of course, it feels 
less so when the MIT distribution's general gssapi library is called 
libgssapi_krb5.so...

>> cell-wide shared key (need not be the vlserver acceptor creds)
> KeyFileExt

Right.

>> per-fileserver key
>
> Custom location, private to the fileserver

I'm not sure this is best; we already have the KeyFileExt infrastructure 
for storing general key types, and it would seem to make sense to reuse it 
if we can.

My thinking was that a given server would either be a "departmental" 
fileserver with its own key (or a per-department key), or it would be a 
central fileserver running on the same machine as the dbservers. 
(Centrally managed fileservers without colocated dbservers are also 
possible, of course.)  In that framework, we could have the fileserver 
always look in the KeyFileExt for its key -- for a departmental 
fileserver, the departmental key would be in the KeyFileExt; on a 
centrally managed server, it would just reuse the cell-wide key that's 
already in the KeyFileExt.

>> [key for securing extended callbacks, which may or may not be able to 
>> just live in memory]
>
> Private to the fileserver. If you're serialising callback state to disk, 
> then you also need to serialise these keys to disk.

Yup.  There is again the argument for reusing the KeyFileExt 
infrastructure, but the way to do so is less clear to me here.

>> Simon had some thoughts on Jabber a couple weeks ago (2013-04-18.txt); 
>> in particular the idea that the GSS acceptor creds (e.g., the 
>> afs-rxgk/_afs.cellname krb5 keytab) can be different than the cell-wide 
>> shared key.
>
> This is really important. You need this in order to be able to support 
> non-krb5 GSS mechanisms. Bear in mind that for some mechanisms (GSI, for 
> example), the acceptor credential does not contain a symmetric 
> encryption key - so you have to provide a mechanism through which such a 
> key can be obtained.

Yes, I am quite convinced.

>> This is probably fine, it just solidifies the implementation detail 
>> that the per-server key for a fileserver located on the same machine as 
>> a dbserver will be the same key as the cell-wide shared key.
>
> There's no reason why such a fileserver should use the cell-wide shared 
> key, so I'm not sure where this implementation detail has come from. The 
> location of a fileserver is immaterial when it comes to the keys that it 
> uses.

If the fileserver is going to use the KeyFileExt for its key, then this 
implementation detail follows.  Apparently this mindset is not universal, 
though...

>> The KeyFileExt format has 32 bits of integer for the key type; I wonder 
>> if we want to get more specific than "afsconf_rxgk" and go to 
>> "afsconf_rxgk_cellwide", "afsconf_rxgk_fileserver", etc., it could end 
>> up simplifying some things.
>
> I would rather not store these within KeyFileEx. My intent had always 
> been that KeyFileEx would be used in a similar way to the way in which 
> KeyFile is used today - so it would get copied around machines with 
> equal privilege. Fileserver keys are private to the fileserver - they 
> should be stored somewhere that only the fileserver (and volserver, but 
> that really is an implementation detail) can gain access to them.

I don't see how having the fileserver use KeyFileExt for its key is 
inconsistent with the KeyFileExt getting copied around to machines with 
equal privilege.  Departmental fileservers in the same department can have 
the same key, and are of equal privilege; machines with the cell-wide key 
are centrally managed and also of equal privilege.  It's just that not all 
KeyFileExts are created alike, and they can have different levels of 
privilege.

This (my) proposal does not allow for fine-grained privilege separation 
between dbserver and fileserver, of course.  Do we think there is demand 
for this?  I know Derrick has talked about various ways of doing privilege 
separation so that an "AFS server" runs as a dedicated non-root user as an 
ordinary userland program, but I don't remember getting a sense that 
separating dbserver and fileserver privilege was desired.

>> There's also the question of where to put the GSS acceptor credentials. 
>> I'm not sure that I like the idea of using the mechanism default (for 
>> kerberos, the system's krb5.keytab, but we are not limited to the krb5 
>> mechanism); if we did stay with that, I would want to have each 
>> acceptor specify which name it is accepting as.  My preference would be 
>> to have a separate credentials store for each service/acceptor, but not 
>> specify a name within that credentials store.  This does have the 
>> drawback of using mechanism-specific functionality (e.g., 
>> krb5_gss_register_acceptor_identity) which would need to be 
>> conditionalized somehow, probably at build time.
>
> I think we want to be able to use the same binaries with different GSS 
> mechanisms - so I think you need to use the mechanism default. I also 
> can't see any reason for not specifying the acceptor name - what to use 
> is clearly defined, in particular for the AFS-3 acceptor, so I can't see 
> any value at all in blindy accepting anything that's in a particular 
> keytab.

What if a cell wants to accept credentials from two different kerberos 
realms that do not have a cross-realm trust with each other?
This is currently supported (albeit in an ugly way), but I am not sure 
whether GSS implementations will do the right thing if credentials for 
afs-rxgk/_afs.cell@A and afs-rxgk/_afs.cell@B are both present in the same 
keytab.

I feel like there are lots of cases where ugly real-world realities cause 
administrators to need to have multiple identities in a single keytab used 
by an acceptor, even if in principle it should not be necessary.

-Ben