diff options
Diffstat (limited to 'source3/client/smbmnt.c')
-rw-r--r-- | source3/client/smbmnt.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/source3/client/smbmnt.c b/source3/client/smbmnt.c new file mode 100644 index 00000000000..9bb7f566721 --- /dev/null +++ b/source3/client/smbmnt.c @@ -0,0 +1,297 @@ +/* + * smbmount.c + * + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * + */ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <grp.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/stat.h> +#include <sys/types.h> +/* #include <sys/wait.h> */ /* generates a warning here */ +extern pid_t waitpid(pid_t, int *, int); +#include <sys/errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <sys/mount.h> +#include <mntent.h> + +#include <linux/fs.h> +#include <linux/smb.h> +#include <linux/smb_mount.h> + +#include <asm/unistd.h> + +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" + "-h print this help text\n"); +} + +static int +parse_args(int argc, char *argv[], struct smb_mount_data *data) +{ + int opt; + struct passwd *pwd; + struct group *grp; + + while ((opt = getopt (argc, argv, "u:g:f:d:")) + != 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; + 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(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[]) +{ + struct smb_mount_data data; + struct stat st; + + int fd; + int um; + unsigned int flags; + + char *mount_point; + + struct mntent ment; + FILE *mtab; + + 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 (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) != 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(NULL, mount_point, "smbfs", + flags, (char *)&data) < 0) { + perror("mount error"); + printf("Please look at smbmount's manual page for " + "possible reasons\n"); + return -1; + } + + ment.mnt_fsname = "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; +} |