/* * smbmount.c * * Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke * */ #include "includes.h" #include #include #include #include #include #include #ifndef MS_MGC_VAL /* This may look strange but MS_MGC_VAL is what we are looking for and is what we need from under libc systems and is provided in standard includes on glibc systems. So... We switch on what we need... */ #include #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; }