/* * smbmount.c * * Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke * */ #include "includes.h" #include <mntent.h> #include <asm/types.h> #include <asm/posix_types.h> #include <linux/smb.h> #include <linux/smb_mount.h> #include <asm/unistd.h> #ifndef MS_MGC_VAL /* This may look strange but MS_MGC_VAL is what we are looking for and is what we need from <linux/fs.h> under libc systems and is provided in standard includes on glibc systems. So... We switch on what we need... */ #include <linux/fs.h> #endif static char *progname; static void usage(void) { printf("usage: %s mount-point [options]\n", progname); printf("Try `%s -h' for more information\n", progname); } static void help(void) { printf("\n"); printf("usage: %s mount-point [options]\n", progname); printf("-u uid uid the mounted files get\n" "-g gid gid the mounted files get\n" "-f mode permission the files get (octal notation)\n" "-d mode permission the dirs get (octal notation)\n" "-P pid connection handler's pid\n\n" "-s share share name on server\n\n" "-h print this help text\n"); } static int parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share) { int opt; struct passwd *pwd; struct group *grp; while ((opt = getopt (argc, argv, "u:g:f:d:s:")) != EOF) { switch (opt) { case 'u': if (isdigit(optarg[0])) { data->uid = atoi(optarg); } else { pwd = getpwnam(optarg); if (pwd == NULL) { fprintf(stderr, "Unknown user: %s\n", optarg); return 1; } data->uid = pwd->pw_uid; } break; case 'g': if (isdigit(optarg[0])) { data->gid = atoi(optarg); } else { grp = getgrnam(optarg); if (grp == NULL) { fprintf(stderr, "Unknown group: %s\n", optarg); return 1; } data->gid = grp->gr_gid; } break; case 'f': data->file_mode = strtol(optarg, NULL, 8); break; case 'd': data->dir_mode = strtol(optarg, NULL, 8); break; case 's': *share = optarg; break; default: return -1; } } return 0; } static char * fullpath(const char *p) { char path[MAXPATHLEN]; if (strlen(p) > MAXPATHLEN-1) { return NULL; } if (realpath(p, path) == NULL) { return strdup(p); } return strdup(path); } /* Check whether user is allowed to mount on the specified mount point */ static int mount_ok(SMB_STRUCT_STAT *st) { if (!S_ISDIR(st->st_mode)) { errno = ENOTDIR; return -1; } if ( (getuid() != 0) && ( (getuid() != st->st_uid) || ((st->st_mode & S_IRWXU) != S_IRWXU))) { errno = EPERM; return -1; } return 0; } int main(int argc, char *argv[]) { char *mount_point, *share_name = NULL; FILE *mtab; int fd, um; unsigned int flags; struct smb_mount_data data; SMB_STRUCT_STAT st; struct mntent ment; progname = argv[0]; memset(&data, 0, sizeof(struct smb_mount_data)); if ( (argc == 2) && (argv[1][0] == '-') && (argv[1][1] == 'h') && (argv[1][2] == '\0')) { help(); return 0; } if (geteuid() != 0) { fprintf(stderr, "%s must be installed suid root\n", progname); exit(1); } if (argc < 2) { usage(); return 1; } mount_point = argv[1]; argv += 1; argc -= 1; if (sys_stat(mount_point, &st) == -1) { fprintf(stderr, "could not find mount point %s: %s\n", mount_point, strerror(errno)); exit(1); } if (mount_ok(&st) != 0) { fprintf(stderr, "cannot mount on %s: %s\n", mount_point, strerror(errno)); exit(1); } data.version = SMB_MOUNT_VERSION; /* getuid() gives us the real uid, who may umount the fs */ data.mounted_uid = getuid(); data.uid = getuid(); data.gid = getgid(); um = umask(0); umask(um); data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um; data.dir_mode = 0; if (parse_args(argc, argv, &data, &share_name) != 0) { usage(); return -1; } if (data.dir_mode == 0) { data.dir_mode = data.file_mode; if ((data.dir_mode & S_IRUSR) != 0) data.dir_mode |= S_IXUSR; if ((data.dir_mode & S_IRGRP) != 0) data.dir_mode |= S_IXGRP; if ((data.dir_mode & S_IROTH) != 0) data.dir_mode |= S_IXOTH; } flags = MS_MGC_VAL; if (mount(share_name, mount_point, "smbfs", flags, (char *)&data) < 0) { perror("mount error"); printf("Please refer to the smbmnt(8) manual page\n"); return -1; } ment.mnt_fsname = share_name ? share_name : "none"; ment.mnt_dir = fullpath(mount_point); ment.mnt_type = "smbfs"; ment.mnt_opts = ""; ment.mnt_freq = 0; ment.mnt_passno= 0; mount_point = ment.mnt_dir; if (mount_point == NULL) { fprintf(stderr, "Mount point too long\n"); return -1; } if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { fprintf(stderr, "Can't get "MOUNTED"~ lock file"); return 1; } close(fd); if ((mtab = setmntent(MOUNTED, "a+")) == NULL) { fprintf(stderr, "Can't open " MOUNTED); return 1; } if (addmntent(mtab, &ment) == 1) { fprintf(stderr, "Can't write mount entry"); return 1; } if (fchmod(fileno(mtab), 0644) == -1) { fprintf(stderr, "Can't set perms on "MOUNTED); return 1; } endmntent(mtab); if (unlink(MOUNTED"~") == -1) { fprintf(stderr, "Can't remove "MOUNTED"~"); return 1; } return 0; }