root/source4/client/smbmnt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. help
  2. parse_args
  3. fullpath
  4. mount_ok
  5. do_mount
  6. main

   1 /*
   2  *  smbmnt.c
   3  *
   4  *  Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke
   5  *  extensively modified by Tridge
   6  *
   7  */
   8 
   9 #include "includes.h"
  10 
  11 #include <mntent.h>
  12 #include <sys/utsname.h>
  13 
  14 #include <asm/types.h>
  15 #include <asm/posix_types.h>
  16 #include <linux/smb.h>
  17 #include <linux/smb_mount.h>
  18 #include <asm/unistd.h>
  19 
  20 #ifndef MS_MGC_VAL
  21 /* This may look strange but MS_MGC_VAL is what we are looking for and
  22         is what we need from <linux/fs.h> under libc systems and is
  23         provided in standard includes on glibc systems.  So...  We
  24         switch on what we need...  */
  25 #include <linux/fs.h>
  26 #endif
  27 
  28 static uid_t mount_uid;
  29 static gid_t mount_gid;
  30 static int mount_ro;
  31 static uint_t mount_fmask;
  32 static uint_t mount_dmask;
  33 static int user_mount;
  34 static char *options;
  35 
  36 static void
  37 help(void)
     /* [<][>][^][v][top][bottom][index][help] */
  38 {
  39         printf("\n");
  40         printf("Usage: smbmnt mount-point [options]\n");
  41         printf("Version %s\n\n",VERSION);
  42         printf("-s share       share name on server\n"
  43                "-r             mount read-only\n"
  44                "-u uid         mount as uid\n"
  45                "-g gid         mount as gid\n"
  46                "-f mask        permission mask for files\n"
  47                "-d mask        permission mask for directories\n"
  48                "-o options     name=value, list of options\n"
  49                "-h             print this help text\n");
  50 }
  51 
  52 static int
  53 parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
     /* [<][>][^][v][top][bottom][index][help] */
  54 {
  55         int opt;
  56 
  57         while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF)
  58         {
  59                 switch (opt)
  60                 {
  61                 case 's':
  62                         *share = optarg;
  63                         break;
  64                 case 'u':
  65                         if (!user_mount) {
  66                                 mount_uid = strtol(optarg, NULL, 0);
  67                         }
  68                         break;
  69                 case 'g':
  70                         if (!user_mount) {
  71                                 mount_gid = strtol(optarg, NULL, 0);
  72                         }
  73                         break;
  74                 case 'r':
  75                         mount_ro = 1;
  76                         break;
  77                 case 'f':
  78                         mount_fmask = strtol(optarg, NULL, 8);
  79                         break;
  80                 case 'd':
  81                         mount_dmask = strtol(optarg, NULL, 8);
  82                         break;
  83                 case 'o':
  84                         options = optarg;
  85                         break;
  86                 default:
  87                         return -1;
  88                 }
  89         }
  90         return 0;
  91         
  92 }
  93 
  94 static char *
  95 fullpath(const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
  96 {
  97         char path[MAXPATHLEN];
  98 
  99         if (strlen(p) > MAXPATHLEN-1) {
 100                 return NULL;
 101         }
 102 
 103         if (realpath(p, path) == NULL) {
 104                 fprintf(stderr,"Failed to find real path for mount point\n");
 105                 exit(1);
 106         }
 107         return strdup(path);
 108 }
 109 
 110 /* Check whether user is allowed to mount on the specified mount point. If it's
 111    OK then we change into that directory - this prevents race conditions */
 112 static int mount_ok(char *mount_point)
     /* [<][>][^][v][top][bottom][index][help] */
 113 {
 114         struct stat st;
 115 
 116         if (chdir(mount_point) != 0) {
 117                 return -1;
 118         }
 119 
 120         if (stat(".", &st) != 0) {
 121                 return -1;
 122         }
 123 
 124         if (!S_ISDIR(st.st_mode)) {
 125                 errno = ENOTDIR;
 126                 return -1;
 127         }
 128 
 129         if ((getuid() != 0) && 
 130             ((getuid() != st.st_uid) || 
 131              ((st.st_mode & S_IRWXU) != S_IRWXU))) {
 132                 errno = EPERM;
 133                 return -1;
 134         }
 135 
 136         return 0;
 137 }
 138 
 139 /* Tries to mount using the appropriate format. For 2.2 the struct,
 140    for 2.4 the ascii version. */
 141 static int
 142 do_mount(char *share_name, uint_t flags, struct smb_mount_data *data)
     /* [<][>][^][v][top][bottom][index][help] */
 143 {
 144         pstring opts;
 145         struct utsname uts;
 146         char *release, *major, *minor;
 147         char *data1, *data2;
 148 
 149         uname(&uts);
 150         release = uts.release;
 151         major = strtok(release, ".");
 152         minor = strtok(NULL, ".");
 153         if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
 154                 /* < 2.4, assume struct */
 155                 data1 = (char *) data;
 156                 data2 = opts;
 157         } else {
 158                 /* >= 2.4, assume ascii but fall back on struct */
 159                 data1 = opts;
 160                 data2 = (char *) data;
 161         }
 162 
 163         slprintf(opts, sizeof(opts)-1,
 164                  "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
 165                  data->uid, data->gid, data->file_mode, data->dir_mode,options);
 166         if (mount(share_name, ".", "smbfs", flags, data1) == 0)
 167                 return 0;
 168         return mount(share_name, ".", "smbfs", flags, data2);
 169 }
 170 
 171  int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 172 {
 173         char *mount_point, *share_name = NULL;
 174         FILE *mtab;
 175         int fd;
 176         uint_t flags;
 177         struct smb_mount_data data;
 178         struct mntent ment;
 179 
 180         memset(&data, 0, sizeof(struct smb_mount_data));
 181 
 182         if (argc < 2) {
 183                 help();
 184                 exit(1);
 185         }
 186 
 187         if (argv[1][0] == '-') {
 188                 help();
 189                 exit(1);
 190         }
 191 
 192         if (getuid() != 0) {
 193                 user_mount = 1;
 194         }
 195 
 196         if (geteuid() != 0) {
 197                 fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid());
 198                 exit(1);
 199         }
 200 
 201         mount_uid = getuid();
 202         mount_gid = getgid();
 203         mount_fmask = umask(0);
 204         umask(mount_fmask);
 205         mount_fmask = ~mount_fmask;
 206 
 207         mount_point = fullpath(argv[1]);
 208 
 209         argv += 1;
 210         argc -= 1;
 211 
 212         if (mount_ok(mount_point) != 0) {
 213                 fprintf(stderr, "cannot mount on %s: %s\n",
 214                         mount_point, strerror(errno));
 215                 exit(1);
 216         }
 217 
 218         data.version = SMB_MOUNT_VERSION;
 219 
 220         /* getuid() gives us the real uid, who may umount the fs */
 221         data.mounted_uid = getuid();
 222 
 223         if (parse_args(argc, argv, &data, &share_name) != 0) {
 224                 help();
 225                 return -1;
 226         }
 227 
 228         data.uid = mount_uid;
 229         data.gid = mount_gid;
 230         data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask;
 231         data.dir_mode  = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask;
 232 
 233         if (mount_dmask == 0) {
 234                 data.dir_mode = data.file_mode;
 235                 if ((data.dir_mode & S_IRUSR) != 0)
 236                         data.dir_mode |= S_IXUSR;
 237                 if ((data.dir_mode & S_IRGRP) != 0)
 238                         data.dir_mode |= S_IXGRP;
 239                 if ((data.dir_mode & S_IROTH) != 0)
 240                         data.dir_mode |= S_IXOTH;
 241         }
 242 
 243         flags = MS_MGC_VAL;
 244 
 245         if (mount_ro) flags |= MS_RDONLY;
 246 
 247         if (do_mount(share_name, flags, &data) < 0) {
 248                 switch (errno) {
 249                 case ENODEV:
 250                         fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n");
 251                         break;
 252                 default:
 253                         perror("mount error");
 254                 }
 255                 fprintf(stderr, "Please refer to the smbmnt(8) manual page\n");
 256                 return -1;
 257         }
 258 
 259         ment.mnt_fsname = share_name ? share_name : "none";
 260         ment.mnt_dir = mount_point;
 261         ment.mnt_type = "smbfs";
 262         ment.mnt_opts = "";
 263         ment.mnt_freq = 0;
 264         ment.mnt_passno= 0;
 265 
 266         mount_point = ment.mnt_dir;
 267 
 268         if (mount_point == NULL)
 269         {
 270                 fprintf(stderr, "Mount point too long\n");
 271                 return -1;
 272         }
 273         
 274         if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
 275         {
 276                 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
 277                 return 1;
 278         }
 279         close(fd);
 280         
 281         if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
 282         {
 283                 fprintf(stderr, "Can't open " MOUNTED);
 284                 return 1;
 285         }
 286 
 287         if (addmntent(mtab, &ment) == 1)
 288         {
 289                 fprintf(stderr, "Can't write mount entry");
 290                 return 1;
 291         }
 292         if (fchmod(fileno(mtab), 0644) == -1)
 293         {
 294                 fprintf(stderr, "Can't set perms on "MOUNTED);
 295                 return 1;
 296         }
 297         endmntent(mtab);
 298 
 299         if (unlink(MOUNTED"~") == -1)
 300         {
 301                 fprintf(stderr, "Can't remove "MOUNTED"~");
 302                 return 1;
 303         }
 304 
 305         return 0;
 306 }       

/* [<][>][^][v][top][bottom][index][help] */