]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/gssd/gssd_proc.c
Add option to allow root to use credentials other than machine credentials
[nfs-utils.git] / utils / gssd / gssd_proc.c
index 75a04f5ba23744af9c0a347db1d9447cd5d60da3..04de4e676683c96010be6c6ebc0e6e1884b7d7cf 100644 (file)
@@ -47,6 +47,7 @@
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
+#include <sys/fsuid.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -493,13 +494,13 @@ int create_auth_rpc_client(struct clnt_info *clp,
 
        /* Create the context as the user (not as root) */
        save_uid = geteuid();
-       if (seteuid(uid) != 0) {
-               printerr(0, "WARNING: Failed to seteuid for "
+       if (setfsuid(uid) != 0) {
+               printerr(0, "WARNING: Failed to setfsuid for "
                            "user with uid %d\n", uid);
                goto out_fail;
        }
-       printerr(2, "creating context using euid %d (save_uid %d)\n",
-                       geteuid(), save_uid);
+       printerr(2, "creating context using fsuid %d (save_uid %d)\n",
+                       uid, save_uid);
 
        sec.qop = GSS_C_QOP_DEFAULT;
        sec.svc = RPCSEC_GSS_SVC_NONE;
@@ -646,9 +647,9 @@ int create_auth_rpc_client(struct clnt_info *clp,
                gss_release_cred(&min_stat, &sec.cred);
        if (a != NULL) freeaddrinfo(a);
        /* Restore euid to original value */
-       if ((save_uid != -1) && (seteuid(save_uid) != 0)) {
-               printerr(0, "WARNING: Failed to restore euid"
-                           " to uid %d\n", save_uid);
+       if ((save_uid != -1) && (setfsuid(save_uid) != uid)) {
+               printerr(0, "WARNING: Failed to restore fsuid"
+                           " to uid %d from %d\n", save_uid, uid);
        }
        return retval;
 
@@ -674,6 +675,7 @@ handle_krb5_upcall(struct clnt_info *clp)
        gss_buffer_desc         token;
        char                    **credlist = NULL;
        char                    **ccname;
+       int                     create_resp = -1;
 
        printerr(1, "handling krb5 upcall\n");
 
@@ -687,49 +689,52 @@ handle_krb5_upcall(struct clnt_info *clp)
                goto out;
        }
 
-       if (uid == 0) {
-               int success = 0;
-
-               /*
-                * Get a list of credential cache names and try each
-                * of them until one works or we've tried them all
-                */
-               if (gssd_get_krb5_machine_cred_list(&credlist)) {
-                       printerr(0, "WARNING: Failed to obtain machine "
-                                   "credentials for connection to "
-                                   "server %s\n", clp->servername);
-                               goto out_return_error;
-               }
-               for (ccname = credlist; ccname && *ccname; ccname++) {
-                       gssd_setup_krb5_machine_gss_ccache(*ccname);
-                       if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
-                                                   AUTHTYPE_KRB5)) == 0) {
-                               /* Success! */
-                               success++;
-                               break;
-                       }
-                       printerr(2, "WARNING: Failed to create krb5 context "
-                                   "for user with uid %d with credentials "
-                                   "cache %s for server %s\n",
-                                uid, *ccname, clp->servername);
-               }
-               gssd_free_krb5_machine_cred_list(credlist);
-               if (!success) {
-                       printerr(0, "WARNING: Failed to create krb5 context "
-                                   "for user with uid %d with any "
-                                   "credentials cache for server %s\n",
-                                uid, clp->servername);
-                       goto out_return_error;
-               }
-       }
-       else {
+       if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) {
                /* Tell krb5 gss which credentials cache to use */
                gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
 
-               if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
-                                                       AUTHTYPE_KRB5)) != 0) {
+               create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
+                                                    AUTHTYPE_KRB5);
+       }
+       if (create_resp != 0) {
+               if (uid == 0 && root_uses_machine_creds == 1) {
+                       int success = 0;
+
+                       /*
+                        * Get a list of credential cache names and try each
+                        * of them until one works or we've tried them all
+                        */
+                       if (gssd_get_krb5_machine_cred_list(&credlist)) {
+                               printerr(0, "WARNING: Failed to obtain machine "
+                                        "credentials for connection to "
+                                        "server %s\n", clp->servername);
+                                       goto out_return_error;
+                       }
+                       for (ccname = credlist; ccname && *ccname; ccname++) {
+                               gssd_setup_krb5_machine_gss_ccache(*ccname);
+                               if ((create_auth_rpc_client(clp, &rpc_clnt,
+                                                           &auth, uid,
+                                                           AUTHTYPE_KRB5)) == 0) {
+                                       /* Success! */
+                                       success++;
+                                       break;
+                               }
+                               printerr(2, "WARNING: Failed to create krb5 context "
+                                        "for user with uid %d with credentials "
+                                        "cache %s for server %s\n",
+                                        uid, *ccname, clp->servername);
+                       }
+                       gssd_free_krb5_machine_cred_list(credlist);
+                       if (!success) {
+                               printerr(0, "WARNING: Failed to create krb5 context "
+                                        "for user with uid %d with any "
+                                        "credentials cache for server %s\n",
+                                        uid, clp->servername);
+                               goto out_return_error;
+                       }
+               } else {
                        printerr(0, "WARNING: Failed to create krb5 context "
-                                   "for user with uid %d for server %s\n",
+                                "for user with uid %d for server %s\n",
                                 uid, clp->servername);
                        goto out_return_error;
                }