Red Hat Bugzilla – Bug 334931
Add Kerberos support to CIFS mounts
Last modified: 2008-12-04 08:11:59 EST
This bug is for tracking work on the userspace component for handling SPNEGO
upcalls from CIFS. The kernel piece is being tracked in bug #334931. My guess is
that we'll want to integrate this new program with samba (similar to how
mount.cifs is integrated). Much of the code to do SPNEGO handling seems to
already be in libsmbclient, so I'm hoping this program will be fairly small.
My thinking is that the flow should be something like this:
Negotiate Protocol Request (with extended security bit set)
NegProt Response (with SPNEGO blob)
- client sends SPNEGO blob plus some other info to userspace via request_key
- client gets back new SPNEGO blob (plus maybe some state info)
Session Setup Request (using new SPNEGO blob received from userspace)
Session Setup Response (with new SPNEGO blob)
- do we need to send this to userspace?
After that, I presume we should have a signing key and we won't need to involve
userspace unless we need to reconnect. Obviously this is the simple case, we'll
also need to determine how to handle it if the negotiation needs to go back and
forth a few times (shouldn't be too tough, but that's why we'll likely need to
send state info back and forth).
The mechanism I'm planning to use is simple request_key calls. The encoding I'm
using for callout_data should allow for us to send large enough blobs to
userspace. If it turns out not to be big enough then we can look at other
options for it. I'd prefer not to do that unless we have to, and only after we
have something working for smaller blobs.
Created attachment 229111 [details]
sample request-key callout program
This program is what I've been using to do simple testing with the current
kernel work. It just attaches whatever blob was sent from the kernel to the
key. It should serve as an skeleton example of what sort of program we'll need.
The current kernel patch uniquely identifies the key with a description string
The callout_data consists of the SPNEGO blob that came in from the Negotiate
Protocol reply. So currently you have the linux_uid of the session and the
server's IP address.
I can easily make it so that we send more in the callout_data if needed, but
we'll need to determine a format. We can also change the key description if
need be (which we may want to do if there is more than one upcall per mount). I
estimate that we should try to limit the amount of data sent from the kernel to
~100k. Anything more than that and we'll start bumping up against ARG_MAX
(we're limited to 128k for ARG_MAX total, and that includes all program
arguments + environment vars).
The last thing the program does is a keyctl_instantiate, with the data that we
want to send back to the kernel. For now, that's just a struct with fixed
length fields that's followed by the SPNEGO blob, but we can add other fields
to send back to the kernel if need be. The data restriction there is less
stringent -- we have an absolute max of 1M, but we still want to keep it as
small as possible.
You'll probably want to have a look at the keyutils* packages since they have
the docs for how to use the API.
For now, my big questions are:
1) what other info do we need to send from the kernel to this program in order
to get the SPNEGO blob for session setup?
2) Once the session setup reply comes back, what do we need to send to
3) how and when do we generate the session signing key?
Simo, I've been chatting with David H today and he's got some patches that allow
us to send the callout data as a blob and a length rather than a string. I'm
going to respin the kernel patches to take advantage of that. That will mean a
lot less copying of data within the kernel and should make it so that we don't
need to encode anything.
Created attachment 232751 [details]
sample request-key callout program
This program is a request-key callout program intended for use with the latest
patch in bug 315311. That patch takes advantage of some patches propsed by
David Howells so that we can call request_key_with_auxdata() and pass in a
binary blob as callout_info.
This program also uses a different scheme for getting the callout_info. It no
longer has to be passed in on the command line, so this removes the ARG_MAX
limitation that the other program had.
With this scheme we should be able to deal with blobs up to 1M in size, and
will not need to encode/decode them before sending them off to userspace.
Again, this program just attaches the callout_info as-is to the key payload,
but it should serve as an example of what sort of program we'd need. The
request-key.conf line for it looks like this:
#OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ...
#====== ======= =============== =============== ===============================
create cifs.spnego * * /usr/local/bin/cifskey %k
I've just sent working krb5 support patch to the linux-cifs-client mail list.
Waiting for comments...
Some newer code has been posted to the linux-cifs-client mailing list. Igor
posted his userspace program, and I've posted a patch to that that allows it to
work with my kernel patch.
At this point, this is the main blocker for getting this implemented. Igor's
program basically works:
1) I think it might make sense to integrate it with the samba sources. For
Fedora/RHEL that would make it easy to put it in the same package as the
mount.cifs program. smbclient needs to roll up SPNEGO blobs too, so it might
make sense to share some of that code with the request-key callout.
2) The program needs to deal with multiple UID's. For now I suggest we have the
program get the description string via keyctl_describe and pull the key uid out
of that. This will be important for multisession mounts.
3) some work needs to go into finalizing how we actually get the hostname
portion of the cifs/servername principal. The kernel patch currently passes the
hostname portion of the UNC to userspace in the description. Between that and
the IP address, the callout will need to determine the hostname string to use.
This will need to be clearly documented to save us pain later.
I'm sure there's plenty of other stuff that I haven't considered as well ;-)
Relevant kernel code has been committed upstream and we've got it enabled in
rawhide. Latest upstream samba has a cifs.spnego program.
We're hoping to have all of this in F9. The main part that's missing at this
point is to make sure that Fedora's samba-client package has the cifs.spnego
This support is now upstream and in Fedora 9+. Closing bug.