/* * Mount helper utility for Linux CIFS VFS (virtual filesystem) client * Copyright (C) 2003,2010 Steve French (sfrench@us.ibm.com) * Copyright (C) 2008 Jeremy Allison (jra@samba.org) * Copyright (C) 2010 Jeff Layton (jlayton@samba.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_FSUID_H #include #endif /* HAVE_SYS_FSUID_H */ #ifdef HAVE_LIBCAP_NG #include #else /* HAVE_LIBCAP_NG */ #ifdef HAVE_PRCTL #include #endif /* HAVE_PRCTL */ #ifdef HAVE_LIBCAP #include #endif /* HAVE_LIBCAP */ #endif /* HAVE_LIBCAP_NG */ #include "mount.h" #include "util.h" #include "resolve_host.h" #ifndef MS_MOVE #define MS_MOVE 8192 #endif #ifndef MS_BIND #define MS_BIND 4096 #endif /* private flags - clear these before passing to kernel */ #define MS_USERS 0x40000000 #define MS_USER 0x80000000 #define MAX_UNC_LEN 1024 /* I believe that the kernel limits options data to a page */ #define MAX_OPTIONS_LEN 4096 /* max length of mtab options */ #define MTAB_OPTIONS_LEN 220 /* * Max share name, username, password and domain sizes match the kernel's * allowances for these string sizes which in turn match Microsoft's * documentation. */ /* Max length of the share name portion of a UNC. Share names over 80 * characters cannot be accessed via commandline in Windows 2000/XP. */ #define MAX_SHARE_LEN 256 /* Max user name length. */ #define MAX_USERNAME_SIZE 256 /* Max domain size. */ #define MAX_DOMAIN_SIZE 256 /* Max password size. */ #define MOUNT_PASSWD_SIZE 512 /* * mount.cifs has been the subject of many "security" bugs that have arisen * because of users and distributions installing it as a setuid root program * before it had been audited for security holes. The default behavior is * now to allow mount.cifs to be run as a setuid root program. Some admins * may want to disable this fully, so this switch remains in place. */ #define CIFS_DISABLE_SETUID_CAPABILITY 0 /* * When an unprivileged user runs a setuid mount.cifs, we set certain mount * flags by default. These defaults can be changed here. */ #define CIFS_SETUID_FLAGS (MS_NOSUID|MS_NODEV) /* * Values for parsing a credentials file. */ #define CRED_UNPARSEABLE 0 #define CRED_USER 1 #define CRED_PASS 2 #define CRED_DOM 4 /* * Values for parsing command line options. */ #define OPT_ERROR -1 #define OPT_IGNORE 0 #define OPT_USERS 1 #define OPT_USER 2 #define OPT_USER_XATTR 3 #define OPT_PASS 4 #define OPT_SEC 5 #define OPT_IP 6 #define OPT_UNC 7 #define OPT_CRED 8 #define OPT_UID 9 #define OPT_GID 10 #define OPT_FMASK 11 #define OPT_FILE_MODE 12 #define OPT_DMASK 13 #define OPT_DIR_MODE 14 #define OPT_DOM 15 #define OPT_NO_SUID 16 #define OPT_SUID 17 #define OPT_NO_DEV 18 #define OPT_DEV 19 #define OPT_NO_LOCK 20 #define OPT_NO_EXEC 21 #define OPT_EXEC 22 #define OPT_GUEST 23 #define OPT_RO 24 #define OPT_RW 25 #define OPT_REMOUNT 26 #define OPT_MAND 27 #define OPT_NOMAND 28 #define OPT_CRUID 29 #define OPT_BKUPUID 30 #define OPT_BKUPGID 31 #define OPT_NOFAIL 32 #define MNT_TMP_FILE "/.mtab.cifs.XXXXXX" /* struct for holding parsed mount info for use by privleged process */ struct parsed_mount_info { unsigned long flags; char host[NI_MAXHOST + 1]; char share[MAX_SHARE_LEN + 1]; char prefix[PATH_MAX + 1]; char options[MAX_OPTIONS_LEN]; char domain[MAX_DOMAIN_SIZE + 1]; char username[MAX_USERNAME_SIZE + 1]; char password[MOUNT_PASSWD_SIZE + 1]; char addrlist[MAX_ADDR_LIST_LEN]; unsigned int got_user:1; unsigned int got_password:1; unsigned int fakemnt:1; unsigned int nomtab:1; unsigned int verboseflag:1; unsigned int nofail:1; unsigned int got_domain:1; }; static const char *thisprogram; static const char *cifs_fstype = "cifs"; static int parse_unc(const char *unc_name, struct parsed_mount_info *parsed_info); static int check_setuid(void) { if (geteuid()) { fprintf(stderr, "This program is not installed setuid root - " " \"user\" CIFS mounts not supported.\n"); return EX_USAGE; } #if CIFS_DISABLE_SETUID_CAPABILITY if (getuid() && !geteuid()) { printf("This mount.cifs program has been built with the " "ability to run as a setuid root program disabled.\n"); return EX_USAGE; } #endif /* CIFS_DISABLE_SETUID_CAPABILITY */ return 0; } static int check_fstab(const char *progname, const char *mountpoint, const char *devname, char **options) { FILE *fstab; struct mntent *mnt; /* make sure this mount is listed in /etc/fstab */ fstab = setmntent(_PATH_MNTTAB, "r"); if (!fstab) { fprintf(stderr, "Couldn't open %s for reading!\n", _PATH_MNTTAB); return EX_FILEIO; } while ((mnt = getmntent(fstab))) { if (!strcmp(mountpoint, mnt->mnt_dir)) break; } endmntent(fstab); if (mnt == NULL || strcmp(mnt->mnt_fsname, devname)) { fprintf(stderr, "%s: permission denied: no match for " "%s found in %s\n", progname, mountpoint, _PATH_MNTTAB); return EX_USAGE; } /* * 'mount' munges the options from fstab before passing them * to us. It is non-trivial to test that we have the correct * set of options. We don't want to trust what the user * gave us, so just take whatever is in /etc/fstab. */ free(*options); *options = strdup(mnt->mnt_opts); return 0; } /* BB finish BB cifs_umount open nofollow - avoid symlink exposure? get owner of dir see if matches self or if root call system(umount argv) etc. BB end finish BB */ static int mount_usage(FILE * stream) { fprintf(stream, "\nUsage: %s -o \n", thisprogram); fprintf(stream, "\nMount the remote target, specified as a UNC name,"); fprintf(stream, " to a local directory.\n\nOptions:\n"); fprintf(stream, "\tuser=\n\tpass=\n\tdom=\n"); fprintf(stream, "\nLess commonly used options:"); fprintf(stream, "\n\tcredentials=,guest,perm,noperm,setuids,nosetuids,rw,ro,"); fprintf(stream, "\n\tsep=,iocharset=,suid,nosuid,exec,noexec,serverino,"); fprintf(stream, "\n\tnoserverino,mapchars,nomapchars,nolock,servernetbiosname="); fprintf(stream, "\n\tcache=,nounix,cifsacl,sec=,"); fprintf(stream, "\n\tsign,seal,fsc,snapshot=