]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/gssd/gssd_proc.c
statd: Replace note() with xlog() in rpc.statd
[nfs-utils.git] / utils / gssd / gssd_proc.c
index 5897ae6ac13074a09d019922ca7ddf2449e8fb0f..33a31c3c3c5b1c018ea8a7408bba34863569053b 100644 (file)
@@ -883,7 +883,8 @@ int create_auth_rpc_client(struct clnt_info *clp,
  * context on behalf of the kernel
  */
 static void
-process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd)
+process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+                   char *service)
 {
        CLIENT                  *rpc_clnt = NULL;
        AUTH                    *auth = NULL;
@@ -896,11 +897,41 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd)
 
        printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
 
+       if (tgtname) {
+               if (clp->servicename) {
+                       free(clp->servicename);
+                       clp->servicename = strdup(tgtname);
+               }
+       }
        token.length = 0;
        token.value = NULL;
        memset(&pd, 0, sizeof(struct authgss_private_data));
 
-       if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) {
+       /*
+        * If "service" is specified, then the kernel is indicating that
+        * we must use machine credentials for this request.  (Regardless
+        * of the uid value or the setting of root_uses_machine_creds.)
+        * If the service value is "*", then any service name can be used.
+        * Otherwise, it specifies the service name that should be used.
+        * (For now, the values of service will only be "*" or "nfs".)
+        *
+        * Restricting gssd to use "nfs" service name is needed for when
+        * the NFS server is doing a callback to the NFS client.  In this
+        * case, the NFS server has to authenticate itself as "nfs" --
+        * even if there are other service keys such as "host" or "root"
+        * in the keytab.
+        *
+        * Another case when the kernel may specify the service attribute
+        * is when gssd is being asked to create the context for a
+        * SETCLIENT_ID operation.  In this case, machine credentials
+        * must be used for the authentication.  However, the service name
+        * used for this case is not important.
+        *
+        */
+       printerr(2, "%s: service is '%s'\n", __func__,
+                service ? service : "<null>");
+       if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+                               service == NULL)) {
                /* Tell krb5 gss which credentials cache to use */
                for (dirname = ccachesearch; *dirname != NULL; dirname++) {
                        if (gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname) == 0)
@@ -911,12 +942,13 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd)
                }
        }
        if (create_resp != 0) {
-               if (uid == 0 && root_uses_machine_creds == 1) {
+               if (uid == 0 && (root_uses_machine_creds == 1 ||
+                               service != NULL)) {
                        int nocache = 0;
                        int success = 0;
                        do {
                                gssd_refresh_krb5_machine_credential(clp->servername,
-                                                                    NULL, nocache);
+                                                                    NULL, service);
                                /*
                                 * Get a list of credential cache names and try each
                                 * of them until one works or we've tried them all
@@ -1060,7 +1092,7 @@ handle_krb5_upcall(struct clnt_info *clp)
                return;
        }
 
-       return process_krb5_upcall(clp, uid, clp->krb5_fd);
+       return process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
 }
 
 void
@@ -1085,6 +1117,8 @@ handle_gssd_upcall(struct clnt_info *clp)
        int                     lbuflen = 0;
        char                    *p;
        char                    *mech = NULL;
+       char                    *target = NULL;
+       char                    *service = NULL;
 
        printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
 
@@ -1128,9 +1162,43 @@ handle_gssd_upcall(struct clnt_info *clp)
                goto out;
        }
 
+       /* read target name */
+       if ((p = strstr(lbuf, "target=")) != NULL) {
+               target = malloc(lbuflen);
+               if (!target)
+                       goto out;
+               if (sscanf(p, "target=%s", target) != 1) {
+                       printerr(0, "WARNING: handle_gssd_upcall: "
+                                   "failed to parse target name "
+                                   "in upcall string '%s'\n", lbuf);
+                       goto out;
+               }
+       }
+
+       /*
+        * read the service name
+        *
+        * The presence of attribute "service=" indicates that machine
+        * credentials should be used for this request.  If the value
+        * is "*", then any machine credentials available can be used.
+        * If the value is anything else, then machine credentials for
+        * the specified service name (always "nfs" for now) should be
+        * used.
+        */
+       if ((p = strstr(lbuf, "service=")) != NULL) {
+               service = malloc(lbuflen);
+               if (!service)
+                       goto out;
+               if (sscanf(p, "service=%s", service) != 1) {
+                       printerr(0, "WARNING: handle_gssd_upcall: "
+                                   "failed to parse service type "
+                                   "in upcall string '%s'\n", lbuf);
+                       goto out;
+               }
+       }
 
        if (strcmp(mech, "krb5") == 0)
-               process_krb5_upcall(clp, uid, clp->gssd_fd);
+               process_krb5_upcall(clp, uid, clp->gssd_fd, target, service);
        else if (strcmp(mech, "spkm3") == 0)
                process_spkm3_upcall(clp, uid, clp->gssd_fd);
        else
@@ -1140,6 +1208,8 @@ handle_gssd_upcall(struct clnt_info *clp)
 out:
        free(lbuf);
        free(mech);
+       free(target);
+       free(service);
        return; 
 }