sunrpc: Enable the kernel to specify the hostname part of service principals
authorChuck Lever <chuck.lever@oracle.com>
Thu, 16 Aug 2018 16:05:54 +0000 (12:05 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 22 Aug 2018 22:32:07 +0000 (18:32 -0400)
A multi-homed NFS server may have more than one "nfs" key in its
keytab. Enable the kernel to pick the key it wants as a machine
credential when establishing a GSS context.

This is useful for GSS-protected NFSv4.0 callbacks, which are
required by RFC 7530 S3.3.3 to use the same principal as the service
principal the client used when establishing its lease.

A complementary modification to rpc.gssd is required to fully enable
this feature.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/auth_gss/auth_gss.c

index be8f103d22fdb7e439bb3ae610aaa3726a4b8332..1943e11988043c7a41df1d4e85f7e69a2e96fa3b 100644 (file)
@@ -284,7 +284,12 @@ err:
        return p;
 }
 
-#define UPCALL_BUF_LEN 128
+/* XXX: Need some documentation about why UPCALL_BUF_LEN is so small.
+ *     Is user space expecting no more than UPCALL_BUF_LEN bytes?
+ *     Note that there are now _two_ NI_MAXHOST sized data items
+ *     being passed in this string.
+ */
+#define UPCALL_BUF_LEN 256
 
 struct gss_upcall_msg {
        refcount_t count;
@@ -462,8 +467,17 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
                p += len;
                gss_msg->msg.len += len;
        }
-       if (service_name != NULL) {
-               len = scnprintf(p, buflen, "service=%s ", service_name);
+       if (service_name) {
+               char *c = strchr(service_name, '@');
+
+               if (!c)
+                       len = scnprintf(p, buflen, "service=%s ",
+                                       service_name);
+               else
+                       len = scnprintf(p, buflen,
+                                       "service=%.*s srchost=%s ",
+                                       (int)(c - service_name),
+                                       service_name, c + 1);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;