[Nix-dev] [PATCH] autofs: Allow mounting ssufs-fuse filesystem using ssh-agents of the users only. There is afuse as well which might do a better job but that doesn't unmount automatically AFAIK. Using the example should prevent other users which are logged into your machinge using your mounts.

Marc Weber marco-oweber at gmx.de
Fri Dec 18 19:44:18 CET 2009


I'd call it a useful hack
---
 modules/services/misc/autofs.nix |   74 +++++++++++++++++++++++++++-----------
 1 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/modules/services/misc/autofs.nix b/modules/services/misc/autofs.nix
index ec92212..ed0d0bd 100644
--- a/modules/services/misc/autofs.nix
+++ b/modules/services/misc/autofs.nix
@@ -6,28 +6,54 @@ let
 
   cfg = config.services.autofs;
 
-  # Try all running ssh-agents. They may know how to connect to the target.
-  # This is more secure than using keys without passphrases!
+
+  # ugly but helpful script: if the sshfs mount arguments contain uid= setting
+  # it will try connecting to the remote location using all ssh-agents run by that user.
+  # As the mount is done using sudo only that user can access it unless you use
+  # mount options such as allow_other
+  # See example autoMaster below.
   sshfsWrapped = pkgs.writeScriptBin "sshfs-wrapped" ''
     #!/bin/sh -e
-    export PATH=${pkgs.sshfsFuse}/bin:${pkgs.openssh}/bin:${pkgs.procps}/bin:${pkgs.lsof}/bin:${pkgs.gnused}/bin/
+
+    # This is to be run by automount when mounting sshfs-fuse filesystems
+    # for each running ssh-agent it will try connecting using its pid
+    # and auth socket only if the ssh-agent is running as uid = uid of mount
+    # target
+    # This should be much more secure than using empty passwords
+
+    # setuid-wrappers for fusermount
+    export PATH=/var/setuid-wrappers:${pkgs.coreutils}/bin:${pkgs.sshfsFuse}/bin:${pkgs.openssh}/bin:${pkgs.procps}/bin:${pkgs.lsof}/bin:${pkgs.gnused}/bin/:${pkgs.sudo}/bin
     pids=`pgrep ssh-agent`
+    # get uid=nr from arguments
+    uid=$(echo "$@"| sed -n 's at .*uid=\([0123456789]\+\).*@\1 at p')
     connect(){
-      sshfs -o ssh_command="ssh -o NumberOfPasswordPrompts=0" "$@" \
+      sudo=$1; shift
+      $sudo sshfs -o ssh_command="ssh -o NumberOfPasswordPrompts=0" "$@" \
        && exit 0 || true
     }
-    if [ -z "$pids" ]; then
-        # no ssh-agent found. Maybe there is a key without password ? You should not be using this!
-        connect "$@"
-    else
-      for p in $pids; do
+    # Change ownership of mountpoint. Ownership will be overridden when mount suceeds.
+    # Otherwise fusermount can't access it (?!)
+    chown $uid "$2"
+    chmod u+w "$2"
+    for p in $pids; do
+      res="$(lsof -p $p -a -U  -Fnu)"
+      user_id=$(echo "$res"| sed -n 's/^u//p')
+      if [ "$user_id" == "$uid" ]; then
+        export SSH_AUTH_SOCK=$(echo "$res"| sed -n 's/^n//p')
         export SSH_AGENT_PID=$p
-        export SSH_AUTH_SOCK=$(lsof -p $p -a -U  -Fn | sed -n 's/^n//p')
         echo "trying to connect using ssh-agent $p $SSH_AUTH_SOCK" 1>&2
-        connect "$@"
-      done
-      exit 1
-    fi
+        # by using sudo -u allow accessing mount by target user - Is there a better way to achieve this??
+        connect "sudo -E -u#$user_id" "$@"
+        echo -n " .. failed" 1>&2
+      fi
+    done
+    unset SSH_AGENT_PID; unset SSH_AUTH_SOCK
+
+    # no ssh-agent found or they all belong to different users..
+    # Try again. Maybe there is a key without password ?
+    # You should not be using this!
+    connect "" "$@"
+    exit 1
     '';
 in
 
@@ -42,7 +68,9 @@ in
       enable = mkOption {
         default = false;
         description = "
-          automatically mount and unmount filesystems
+          automatically mount and unmount filesystems.
+          Note: You should also know about afuse. But afuse doesn't unmount automatically.
+          Known BUGS: If you  cd /auto; pkill -TERM automount then /auto/* won't be unmounted (Try umount -l /auto)
         ";
       };
 
@@ -59,7 +87,8 @@ in
              server    -rw,hard,intr       / -ro myserver.me.org:/ \
                                            /usr myserver.me.org:/usr \
                                            /home myserver.me.org:/home
-             sshfstarget -fstype=fuse,rw,nodev,nonempty,noatime,allow_other,max_read=65536,uid=YOUR_LOCAL_UID,gid=YOUR_LOCAL_GID ''${sshfs}:/home/marc/bin/sshfs\#USER at HOST\:
+             # replace constants:
+             sshfstarget -fstype=fuse,rw,nodev,nonempty,noatime,max_read=65536,uid=LOCAL_UID,gid=LOCAL_GID ''${sshfs}\#USER at HOST\:
             ''';
           in '''
             /auto file:''${mapConf}
@@ -67,8 +96,7 @@ in
         '';
         description = "
           file contents of /etc/auto.master. See man auto.master
-          see 
-          man auto.master and man 5 autofs
+          See man 5 auto.master and man 5 autofs.
         ";
 
         apply = textOrFunc: if builtins.isFunction textOrFunc then
@@ -80,6 +108,11 @@ in
         else textOrFunc;
       };
 
+      kernelModules = mkOption {
+        default = ["fuse"];
+        description="kernel modules to load";
+      };
+
       timeout = mkOption {
         default = 600;
         description = "Set the global minimum timeout, in seconds, until directories are unmounted";
@@ -115,9 +148,8 @@ in
           };
 
         preStart =
-          ''
-            modprobe autofs4 || true
-          '';
+          pkgs.lib.concatMapStrings (module : "modprobe ${module} || true\n")
+                                    (["autofs4"] ++ cfg.kernelModules);
 
         preStop = 
           ''
-- 
1.6.5.6




More information about the nix-dev mailing list