Merge tag 'nfs-for-4.19-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
[sfrench/cifs-2.6.git] / net / sunrpc / auth_gss / auth_gss.c
index 3e192e25f27a3e8055f267b23c8171577a319c15..21c0aa0a0d1d4fde901aed91a51fc65481f72b7b 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;
@@ -456,18 +461,44 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
        buflen -= len;
        p += len;
        gss_msg->msg.len = len;
+
+       /*
+        * target= is a full service principal that names the remote
+        * identity that we are authenticating to.
+        */
        if (target_name) {
                len = scnprintf(p, buflen, "target=%s ", target_name);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;
        }
-       if (service_name != NULL) {
-               len = scnprintf(p, buflen, "service=%s ", service_name);
+
+       /*
+        * gssd uses service= and srchost= to select a matching key from
+        * the system's keytab to use as the source principal.
+        *
+        * service= is the service name part of the source principal,
+        * or "*" (meaning choose any).
+        *
+        * srchost= is the hostname part of the source principal. When
+        * not provided, gssd uses the local hostname.
+        */
+       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;
        }
+
        if (mech->gm_upcall_enctypes) {
                len = scnprintf(p, buflen, "enctypes=%s ",
                                mech->gm_upcall_enctypes);
@@ -517,7 +548,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
                err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
                if (err)
                        goto err_put_pipe_version;
-       };
+       }
        kref_get(&gss_auth->kref);
        return gss_msg;
 err_put_pipe_version: