00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define SMBMOUNT_MALLOC 1
00024
00025 #include "includes.h"
00026
00027 #include <mntent.h>
00028 #include <sys/utsname.h>
00029
00030 #include <asm/types.h>
00031 #include <asm/posix_types.h>
00032 #include <linux/smb.h>
00033 #include <linux/smb_mount.h>
00034 #include <asm/unistd.h>
00035
00036 #ifndef MS_MGC_VAL
00037
00038
00039
00040
00041 #include <linux/fs.h>
00042 #endif
00043
00044 static uid_t mount_uid;
00045 static gid_t mount_gid;
00046 static int mount_ro;
00047 static unsigned mount_fmask;
00048 static unsigned mount_dmask;
00049 static int user_mount;
00050 static char *options;
00051
00052 static void
00053 help(void)
00054 {
00055 printf("\n");
00056 printf("Usage: smbmnt mount-point [options]\n");
00057 printf("Version %s\n\n",SAMBA_VERSION_STRING);
00058 printf("-s share share name on server\n"
00059 "-r mount read-only\n"
00060 "-u uid mount as uid\n"
00061 "-g gid mount as gid\n"
00062 "-f mask permission mask for files\n"
00063 "-d mask permission mask for directories\n"
00064 "-o options name=value, list of options\n"
00065 "-h print this help text\n");
00066 }
00067
00068 static int
00069 parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
00070 {
00071 int opt;
00072
00073 while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF)
00074 {
00075 switch (opt)
00076 {
00077 case 's':
00078 *share = optarg;
00079 break;
00080 case 'u':
00081 if (!user_mount) {
00082 mount_uid = strtol(optarg, NULL, 0);
00083 }
00084 break;
00085 case 'g':
00086 if (!user_mount) {
00087 mount_gid = strtol(optarg, NULL, 0);
00088 }
00089 break;
00090 case 'r':
00091 mount_ro = 1;
00092 break;
00093 case 'f':
00094 mount_fmask = strtol(optarg, NULL, 8);
00095 break;
00096 case 'd':
00097 mount_dmask = strtol(optarg, NULL, 8);
00098 break;
00099 case 'o':
00100 options = optarg;
00101 break;
00102 default:
00103 return -1;
00104 }
00105 }
00106 return 0;
00107
00108 }
00109
00110 static char *
00111 fullpath(const char *p)
00112 {
00113 char path[PATH_MAX+1];
00114
00115 if (strlen(p) > PATH_MAX) {
00116 return NULL;
00117 }
00118
00119 if (realpath(p, path) == NULL) {
00120 fprintf(stderr,"Failed to find real path for mount point %s: %s\n",
00121 p, strerror(errno));
00122 exit(1);
00123 }
00124 return strdup(path);
00125 }
00126
00127
00128
00129 static int mount_ok(char *mount_point)
00130 {
00131 struct stat st;
00132
00133 if (chdir(mount_point) != 0) {
00134 return -1;
00135 }
00136
00137 if (stat(".", &st) != 0) {
00138 return -1;
00139 }
00140
00141 if (!S_ISDIR(st.st_mode)) {
00142 errno = ENOTDIR;
00143 return -1;
00144 }
00145
00146 if ((getuid() != 0) &&
00147 ((getuid() != st.st_uid) ||
00148 ((st.st_mode & S_IRWXU) != S_IRWXU))) {
00149 errno = EPERM;
00150 return -1;
00151 }
00152
00153 return 0;
00154 }
00155
00156
00157
00158 static int
00159 do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
00160 {
00161 pstring opts;
00162 struct utsname uts;
00163 char *release, *major, *minor;
00164 char *data1, *data2;
00165
00166 uname(&uts);
00167 release = uts.release;
00168 major = strtok(release, ".");
00169 minor = strtok(NULL, ".");
00170 if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
00171
00172 data1 = (char *) data;
00173 data2 = opts;
00174 } else {
00175
00176 data1 = opts;
00177 data2 = (char *) data;
00178 }
00179
00180 slprintf(opts, sizeof(opts)-1,
00181 "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
00182 mount_uid, mount_gid, data->file_mode, data->dir_mode,options);
00183 if (mount(share_name, ".", "smbfs", flags, data1) == 0)
00184 return 0;
00185 return mount(share_name, ".", "smbfs", flags, data2);
00186 }
00187
00188 int main(int argc, char *argv[])
00189 {
00190 char *mount_point, *share_name = NULL;
00191 FILE *mtab;
00192 int fd;
00193 unsigned int flags;
00194 struct smb_mount_data data;
00195 struct mntent ment;
00196
00197 memset(&data, 0, sizeof(struct smb_mount_data));
00198
00199 if (argc < 2) {
00200 help();
00201 exit(1);
00202 }
00203
00204 if (argv[1][0] == '-') {
00205 help();
00206 exit(1);
00207 }
00208
00209 if (getuid() != 0) {
00210 user_mount = 1;
00211 }
00212
00213 if (geteuid() != 0) {
00214 fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid());
00215 exit(1);
00216 }
00217
00218 mount_uid = getuid();
00219 mount_gid = getgid();
00220 mount_fmask = umask(0);
00221 umask(mount_fmask);
00222 mount_fmask = ~mount_fmask;
00223
00224 mount_point = fullpath(argv[1]);
00225
00226 argv += 1;
00227 argc -= 1;
00228
00229 if (mount_ok(mount_point) != 0) {
00230 fprintf(stderr, "cannot mount on %s: %s\n",
00231 mount_point, strerror(errno));
00232 exit(1);
00233 }
00234
00235 data.version = SMB_MOUNT_VERSION;
00236
00237
00238 data.mounted_uid = getuid();
00239
00240 if (parse_args(argc, argv, &data, &share_name) != 0) {
00241 help();
00242 return -1;
00243 }
00244
00245 data.uid = mount_uid;
00246 data.gid = mount_gid;
00247 data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask;
00248 data.dir_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask;
00249
00250 if (mount_dmask == 0) {
00251 data.dir_mode = data.file_mode;
00252 if ((data.dir_mode & S_IRUSR) != 0)
00253 data.dir_mode |= S_IXUSR;
00254 if ((data.dir_mode & S_IRGRP) != 0)
00255 data.dir_mode |= S_IXGRP;
00256 if ((data.dir_mode & S_IROTH) != 0)
00257 data.dir_mode |= S_IXOTH;
00258 }
00259
00260 flags = MS_MGC_VAL | MS_NOSUID | MS_NODEV;
00261
00262 if (mount_ro) flags |= MS_RDONLY;
00263
00264 if (do_mount(share_name, flags, &data) < 0) {
00265 switch (errno) {
00266 case ENODEV:
00267 fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n");
00268 break;
00269 default:
00270 perror("mount error");
00271 }
00272 fprintf(stderr, "Please refer to the smbmnt(8) manual page\n");
00273 return -1;
00274 }
00275
00276 ment.mnt_fsname = share_name ? share_name : "none";
00277 ment.mnt_dir = mount_point;
00278 ment.mnt_type = "smbfs";
00279 ment.mnt_opts = "";
00280 ment.mnt_freq = 0;
00281 ment.mnt_passno= 0;
00282
00283 mount_point = ment.mnt_dir;
00284
00285 if (mount_point == NULL)
00286 {
00287 fprintf(stderr, "Mount point too long\n");
00288 return -1;
00289 }
00290
00291 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
00292 {
00293 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
00294 return 1;
00295 }
00296 close(fd);
00297
00298 if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
00299 {
00300 fprintf(stderr, "Can't open " MOUNTED);
00301 return 1;
00302 }
00303
00304 if (addmntent(mtab, &ment) == 1)
00305 {
00306 fprintf(stderr, "Can't write mount entry");
00307 return 1;
00308 }
00309 if (fchmod(fileno(mtab), 0644) == -1)
00310 {
00311 fprintf(stderr, "Can't set perms on "MOUNTED);
00312 return 1;
00313 }
00314 endmntent(mtab);
00315
00316 if (unlink(MOUNTED"~") == -1)
00317 {
00318 fprintf(stderr, "Can't remove "MOUNTED"~");
00319 return 1;
00320 }
00321
00322 return 0;
00323 }