]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/nfsumount.c
Support unmount by not privileged users
[nfs-utils.git] / utils / mount / nfsumount.c
index 077219d6ae87e223669492c642e55bfc9d481b5e..381ca6e344e0bdf13d21a1760a651597f8777325 100644 (file)
  *
  */
 
+#include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
 #include <getopt.h>
 #include <mntent.h>
 #include <sys/mount.h>
 #include <ctype.h>
+#include <pwd.h>
 
 #include "xcommon.h"
 #include "fstab.h"
@@ -147,7 +149,7 @@ int del_mtab(const char *spec, const char *node)
                 res = mount(spec, node, NULL,
                             MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
                 if (res == 0) {
-                        nfs_mntent_t remnt;
+                        struct mntent remnt;
                         fprintf(stderr,
                                 _("umount: %s busy - remounted read-only\n"),
                                 spec);
@@ -324,16 +326,46 @@ int nfsumount(int argc, char *argv[])
        if (!mc && verbose)
                printf(_("Could not find %s in mtab\n"), spec);
 
+       if (getuid() != 0) {
+               /* only permitted if "user=" or "users" is in mount options */
+               if (!mc) {
+               only_root:
+                       fprintf(stderr,"%s: You are not permitted to unmount %s\n",
+                               progname, spec);
+                       return 0;
+               }
+               if (hasmntopt(&mc->m, "users") == NULL) {
+                       char *opt = hasmntopt(&mc->m, "user");
+                       struct passwd *pw;
+                       char *comma;
+                       int len;
+                       if (!opt)
+                               goto only_root;
+                       if (opt[5] != '=')
+                               goto only_root;
+                       comma = strchr(opt, ',');
+                       if (comma)
+                               len = comma - (opt + 5);
+                       else
+                               len = strlen(opt+5);
+                       pw = getpwuid(getuid());
+                       if (pw == NULL || strlen(pw->pw_name) != len
+                           || strncmp(pw->pw_name, opt+5, len) != 0)
+                               goto only_root;
+               }
+       }
+
+       ret = 0;
        if (mc) {
-               ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
+               if (!lazy)
+                       ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
                if(ret)
                        ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
-       } else {
-               if (*spec != '/')
+       } else if (*spec != '/') {
+               if (!lazy)
                        ret = _nfsumount(spec, "tcp,v3");
-               else
-                       ret = del_mtab(NULL, spec);
-       }
+       } else
+               ret = del_mtab(NULL, spec);
 
        return(ret);
 }