autofs-5.0.7 - samples/auto.smb: add logic to obtain credentials

From: Martin Wilck <martin.wilck@ts.fujitsu.com>

In some environments, hosts will require credentials for a share
listing.

This patch introduces 2 methods to obtain credentials:
 1) if a credentials file is present
    under /etc/creds/$key, use it.
 2) Otherwise, try to find a usable kerberos credentials cache
    for the calling user (using the UID the script is running as)
    and use that.
If both methods fail, the script will try to obtain the list
of shares anonymously, falling back to the previous behavior.

edit: imk
There is a kernel bug (which I don't know how to resolve) where,
if there's more than one concurrent mount request for a mount
the one that corresponds to the call back to the daemon is the
one that is recorded as the ownser of the mount. So the above
script might break in rare cases.

Also, rather than change autofs to use setuid(2) (which is in
fact a good idea but changes existing behavior), and assume that
program maps are scripts run within a shell, the standard
variables UID, GID, etc. are set in the environment and used
within this script instead of the id(1) command.

In the updated script point 2) above has been changed to:
 2) Otherwise, try to find a usable kerberos credentials cache
    for the uid of the user that was first to trigger the mount
    and use that.
end edit: imk
---
 CHANGELOG        |    1 +
 samples/auto.smb |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index c920c9d..1895116 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -81,6 +81,7 @@
 - fix get_nfs_info() probe.
 - fix portmap lookup.
 - add std vars to program map invocation.
+- samples/auto.smb: add logic to obtain credentials.
 
 25/07/2012 autofs-5.0.7
 =======================
diff --git a/samples/auto.smb b/samples/auto.smb
index 2dfb8f8..6af5d85 100755
--- a/samples/auto.smb
+++ b/samples/auto.smb
@@ -2,6 +2,41 @@
 
 # This file must be executable to work! chmod 755!
 
+# Automagically mount CIFS shares in the network, similar to
+# what autofs -hosts does for NFS.
+
+# Put a line like the following in /etc/auto.master:
+# /cifs  /etc/auto.smb --timeout=300
+# You'll be able to access Windows and Samba shares in your network
+# under /cifs/host.domain/share
+
+# "smbclient -L" is used to obtain a list of shares from the given host.
+# In some environments, this requires valid credentials.
+
+# This script knows 2 methods to obtain credentials:
+# 1) if a credentials file (see mount.cifs(8)) is present
+#    under /etc/creds/$key, use it.
+# 2) Otherwise, try to find a usable kerberos credentials cache
+#    for the uid of the user that was first to trigger the mount
+#    and use that.
+# If both methods fail, the script will try to obtain the list
+# of shares anonymously.
+
+get_krb5_cache() {
+    cache=
+    uid=${UID}
+    for x in $(ls -d /run/user/$uid/krb5cc_* 2>/dev/null); do
+        if [ -d "$x" ] && klist -s DIR:"$x"; then
+	    cache=DIR:$x
+            return
+        fi
+    done
+    if [ -f /tmp/krb5cc_$uid ] && klist -s /tmp/krb5cc_$uid; then
+	    cache=/tmp/krb5cc_$uid
+	    return
+    fi
+}
+
 key="$1"
 opts="-fstype=cifs"
 
@@ -16,7 +51,23 @@ done
 
 [ -x $SMBCLIENT ] || exit 1
 
-$SMBCLIENT -gNL $key 2>/dev/null| awk -v key="$key" -v opts="$opts" -F'|' -- '
+creds=/etc/creds/$key
+if [ -f "$creds" ]; then
+    opts="$opts"',uid=$UID,gid=$GID,credentials='"$creds"
+    smbopts="-A $creds"
+else
+    get_krb5_cache
+    if [ -n "$cache" ]; then
+        opts="$opts"',multiuser,cruid=$UID,sec=krb5i'
+        smbopts="-k"
+        export KRB5CCNAME=$cache
+    else
+        opts="$opts"',guest'
+        smbopts="-N"
+    fi
+fi
+
+$SMBCLIENT $smbopts -gL "$key" 2>/dev/null| awk -v "key=$key" -v "opts=$opts" -F '|' -- '
 	BEGIN	{ ORS=""; first=1 }
 	/Disk/	{
 		  if (first)