187866Ssheldonh/* 295267Ssheldonh * Copyright (c) 2000-2002, Boris Popov 387866Ssheldonh * All rights reserved. 487866Ssheldonh * 587866Ssheldonh * Redistribution and use in source and binary forms, with or without 687866Ssheldonh * modification, are permitted provided that the following conditions 787866Ssheldonh * are met: 887866Ssheldonh * 1. Redistributions of source code must retain the above copyright 987866Ssheldonh * notice, this list of conditions and the following disclaimer. 1087866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright 1187866Ssheldonh * notice, this list of conditions and the following disclaimer in the 1287866Ssheldonh * documentation and/or other materials provided with the distribution. 1387866Ssheldonh * 3. All advertising materials mentioning features or use of this software 1487866Ssheldonh * must display the following acknowledgement: 1587866Ssheldonh * This product includes software developed by Boris Popov. 1687866Ssheldonh * 4. Neither the name of the author nor the names of any co-contributors 1787866Ssheldonh * may be used to endorse or promote products derived from this software 1887866Ssheldonh * without specific prior written permission. 1987866Ssheldonh * 2087866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2187866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2287866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2387866Ssheldonh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2487866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2587866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2687866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2787866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2887866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2987866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3087866Ssheldonh * SUCH DAMAGE. 3187866Ssheldonh * 3295267Ssheldonh * $Id: mount_smbfs.c,v 1.17 2002/04/10 04:17:51 bp Exp $ 33117804Stjr * $FreeBSD: releng/10.3/contrib/smbfs/mount_smbfs/mount_smbfs.c 272118 2014-09-25 17:47:26Z trasz $ 3487866Ssheldonh */ 3587866Ssheldonh#include <sys/param.h> 3687866Ssheldonh#include <sys/stat.h> 3787866Ssheldonh#include <sys/errno.h> 38130789Smux#include <sys/linker.h> 3987866Ssheldonh#include <sys/mount.h> 4087866Ssheldonh 4187866Ssheldonh#include <stdio.h> 4287866Ssheldonh#include <string.h> 4387866Ssheldonh#include <pwd.h> 4487866Ssheldonh#include <grp.h> 4587866Ssheldonh#include <unistd.h> 4687866Ssheldonh#include <ctype.h> 4787866Ssheldonh#include <stdlib.h> 4887866Ssheldonh#include <err.h> 4987866Ssheldonh#include <sysexits.h> 5087866Ssheldonh 5187866Ssheldonh#include <cflib.h> 5287866Ssheldonh 5387866Ssheldonh#include <netsmb/smb.h> 5487866Ssheldonh#include <netsmb/smb_conn.h> 5587866Ssheldonh#include <netsmb/smb_lib.h> 5687866Ssheldonh 5787866Ssheldonh#include <fs/smbfs/smbfs.h> 5887866Ssheldonh 5987866Ssheldonh#include "mntopts.h" 6087866Ssheldonh 6187866Ssheldonhstatic char mount_point[MAXPATHLEN + 1]; 6287866Ssheldonhstatic void usage(void); 6387866Ssheldonh 6487866Ssheldonhstatic struct mntopt mopts[] = { 6587866Ssheldonh MOPT_STDOPTS, 66152467Srodrigc MOPT_END 6787866Ssheldonh}; 6887866Ssheldonh 69152467Srodrigcstatic char smbfs_vfsname[] = "smbfs"; 7087866Ssheldonh 7187866Ssheldonhint 7287866Ssheldonhmain(int argc, char *argv[]) 7387866Ssheldonh{ 74152467Srodrigc struct iovec *iov; 75152467Srodrigc unsigned int iovlen; 7687866Ssheldonh struct smb_ctx sctx, *ctx = &sctx; 7787866Ssheldonh struct stat st; 7888282Ssheldonh#ifdef APPLE 7988282Ssheldonh extern void dropsuid(); 8088282Ssheldonh extern int loadsmbvfs(); 81130789Smux#else 82130789Smux struct xvfsconf vfc; 83128140Smux#endif 84272118Strasz char *next, *p, *val; 85250236Sdavide int opt, error, mntflags, caseopt, fd; 86152467Srodrigc uid_t uid; 87152467Srodrigc gid_t gid; 88152467Srodrigc mode_t dir_mode, file_mode; 89152467Srodrigc char errmsg[255] = { 0 }; 9087866Ssheldonh 91152467Srodrigc iov = NULL; 92152467Srodrigc iovlen = 0; 93250236Sdavide fd = 0; 94152523Sru uid = (uid_t)-1; 95152523Sru gid = (gid_t)-1; 96152467Srodrigc caseopt = 0; 97152467Srodrigc file_mode = 0; 98152467Srodrigc dir_mode = 0; 9988282Ssheldonh 10088282Ssheldonh#ifdef APPLE 10188282Ssheldonh dropsuid(); 102128140Smux#endif 10387866Ssheldonh if (argc == 2) { 10487866Ssheldonh if (strcmp(argv[1], "-h") == 0) { 10587866Ssheldonh usage(); 10687866Ssheldonh } 10787866Ssheldonh } 10887866Ssheldonh if (argc < 3) 10987866Ssheldonh usage(); 11087866Ssheldonh 11188282Ssheldonh#ifdef APPLE 11288282Ssheldonh error = loadsmbvfs(); 113130789Smux#else 114152467Srodrigc error = getvfsbyname(smbfs_vfsname, &vfc); 115130789Smux if (error) { 116152467Srodrigc if (kldload(smbfs_vfsname) < 0) 117152467Srodrigc err(EX_OSERR, "kldload(%s)", smbfs_vfsname); 118152467Srodrigc error = getvfsbyname(smbfs_vfsname, &vfc); 119130789Smux } 120130789Smux#endif 12187866Ssheldonh if (error) 12287866Ssheldonh errx(EX_OSERR, "SMB filesystem is not available"); 12387866Ssheldonh 12487866Ssheldonh if (smb_lib_init() != 0) 12587866Ssheldonh exit(1); 12687866Ssheldonh 12787866Ssheldonh mntflags = error = 0; 128152467Srodrigc 12987866Ssheldonh caseopt = SMB_CS_NONE; 13087866Ssheldonh 13187866Ssheldonh if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0) 13287866Ssheldonh exit(1); 13387866Ssheldonh if (smb_ctx_readrc(ctx) != 0) 13487866Ssheldonh exit(1); 13587866Ssheldonh if (smb_rc) 13687866Ssheldonh rc_close(smb_rc); 13787866Ssheldonh 13887866Ssheldonh while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) { 13987866Ssheldonh switch (opt) { 14087866Ssheldonh case STDPARAM_ARGS: 14187866Ssheldonh error = smb_ctx_opt(ctx, opt, optarg); 14287866Ssheldonh if (error) 14387866Ssheldonh exit(1); 14487866Ssheldonh break; 14587866Ssheldonh case 'u': { 14687866Ssheldonh struct passwd *pwd; 14787866Ssheldonh 14887866Ssheldonh pwd = isdigit(optarg[0]) ? 14987866Ssheldonh getpwuid(atoi(optarg)) : getpwnam(optarg); 15087866Ssheldonh if (pwd == NULL) 15187866Ssheldonh errx(EX_NOUSER, "unknown user '%s'", optarg); 152152467Srodrigc uid = pwd->pw_uid; 15387866Ssheldonh break; 15487866Ssheldonh } 15587866Ssheldonh case 'g': { 15687866Ssheldonh struct group *grp; 15787866Ssheldonh 15887866Ssheldonh grp = isdigit(optarg[0]) ? 15987866Ssheldonh getgrgid(atoi(optarg)) : getgrnam(optarg); 16087866Ssheldonh if (grp == NULL) 16187866Ssheldonh errx(EX_NOUSER, "unknown group '%s'", optarg); 162152467Srodrigc gid = grp->gr_gid; 16387866Ssheldonh break; 16487866Ssheldonh } 16587866Ssheldonh case 'd': 16687866Ssheldonh errno = 0; 167152467Srodrigc dir_mode = strtol(optarg, &next, 8); 16887866Ssheldonh if (errno || *next != 0) 16987866Ssheldonh errx(EX_DATAERR, "invalid value for directory mode"); 17087866Ssheldonh break; 17187866Ssheldonh case 'f': 17287866Ssheldonh errno = 0; 173152467Srodrigc file_mode = strtol(optarg, &next, 8); 17487866Ssheldonh if (errno || *next != 0) 17587866Ssheldonh errx(EX_DATAERR, "invalid value for file mode"); 17687866Ssheldonh break; 17787866Ssheldonh case '?': 17887866Ssheldonh usage(); 17987866Ssheldonh /*NOTREACHED*/ 18087866Ssheldonh case 'n': { 18187866Ssheldonh char *inp, *nsp; 18287866Ssheldonh 18387866Ssheldonh nsp = inp = optarg; 18487866Ssheldonh while ((nsp = strsep(&inp, ",;:")) != NULL) { 185152467Srodrigc if (strcasecmp(nsp, "LONG") == 0) { 186152467Srodrigc build_iovec(&iov, &iovlen, 187152467Srodrigc "nolong", NULL, 0); 188152467Srodrigc } else { 189152467Srodrigc errx(EX_DATAERR, 190152467Srodrigc "unknown suboption '%s'", nsp); 191152467Srodrigc } 19287866Ssheldonh } 19387866Ssheldonh break; 19487866Ssheldonh }; 19587866Ssheldonh case 'o': 19687866Ssheldonh getmntopts(optarg, mopts, &mntflags, 0); 197272118Strasz p = strchr(optarg, '='); 198272118Strasz val = NULL; 199272118Strasz if (p != NULL) { 200272118Strasz *p = '\0'; 201272118Strasz val = p + 1; 202272118Strasz } 203272118Strasz build_iovec(&iov, &iovlen, optarg, val, (size_t)-1); 20487866Ssheldonh break; 20587866Ssheldonh case 'c': 20687866Ssheldonh switch (optarg[0]) { 20787866Ssheldonh case 'l': 20887866Ssheldonh caseopt |= SMB_CS_LOWER; 20987866Ssheldonh break; 21087866Ssheldonh case 'u': 21187866Ssheldonh caseopt |= SMB_CS_UPPER; 21287866Ssheldonh break; 21387866Ssheldonh default: 21487866Ssheldonh errx(EX_DATAERR, "invalid suboption '%c' for -c", 21587866Ssheldonh optarg[0]); 21687866Ssheldonh } 21787866Ssheldonh break; 21887866Ssheldonh default: 21987866Ssheldonh usage(); 22087866Ssheldonh } 22187866Ssheldonh } 22287866Ssheldonh 22387866Ssheldonh if (optind == argc - 2) 22487866Ssheldonh optind++; 22587866Ssheldonh 22687866Ssheldonh if (optind != argc - 1) 22787866Ssheldonh usage(); 22887866Ssheldonh realpath(argv[optind], mount_point); 22987866Ssheldonh 23087866Ssheldonh if (stat(mount_point, &st) == -1) 23187866Ssheldonh err(EX_OSERR, "could not find mount point %s", mount_point); 23287866Ssheldonh if (!S_ISDIR(st.st_mode)) { 23387866Ssheldonh errno = ENOTDIR; 23487866Ssheldonh err(EX_OSERR, "can't mount on %s", mount_point); 23587866Ssheldonh } 23687866Ssheldonh/* 23787866Ssheldonh if (smb_getextattr(mount_point, &einfo) == 0) 23887866Ssheldonh errx(EX_OSERR, "can't mount on %s twice", mount_point); 23987866Ssheldonh*/ 240152523Sru if (uid == (uid_t)-1) 241152467Srodrigc uid = st.st_uid; 242152523Sru if (gid == (gid_t)-1) 243152467Srodrigc gid = st.st_gid; 244152467Srodrigc if (file_mode == 0 ) 245152467Srodrigc file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 246152467Srodrigc if (dir_mode == 0) { 247152467Srodrigc dir_mode = file_mode; 248152467Srodrigc if (dir_mode & S_IRUSR) 249152467Srodrigc dir_mode |= S_IXUSR; 250152467Srodrigc if (dir_mode & S_IRGRP) 251152467Srodrigc dir_mode |= S_IXGRP; 252152467Srodrigc if (dir_mode & S_IROTH) 253152467Srodrigc dir_mode |= S_IXOTH; 25487866Ssheldonh } 25587866Ssheldonh /* 25687866Ssheldonh * For now, let connection be private for this mount 25787866Ssheldonh */ 25887866Ssheldonh ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE; 25987866Ssheldonh ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */ 260152467Srodrigc ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = gid; 26187866Ssheldonh opt = 0; 262152467Srodrigc if (dir_mode & S_IXGRP) 26387866Ssheldonh opt |= SMBM_EXECGRP; 264152467Srodrigc if (dir_mode & S_IXOTH) 26587866Ssheldonh opt |= SMBM_EXECOTH; 26687866Ssheldonh ctx->ct_ssn.ioc_rights |= opt; 26787866Ssheldonh ctx->ct_sh.ioc_rights |= opt; 26887866Ssheldonh error = smb_ctx_resolve(ctx); 26987866Ssheldonh if (error) 27087866Ssheldonh exit(1); 27187866Ssheldonh error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE); 27287866Ssheldonh if (error) { 27387866Ssheldonh exit(1); 27487866Ssheldonh } 275152467Srodrigc 276250236Sdavide fd = ctx->ct_fd; 277152467Srodrigc 278152467Srodrigc build_iovec(&iov, &iovlen, "fstype", strdup("smbfs"), -1); 279152467Srodrigc build_iovec(&iov, &iovlen, "fspath", mount_point, -1); 280250236Sdavide build_iovec_argf(&iov, &iovlen, "fd", "%d", fd); 281152467Srodrigc build_iovec(&iov, &iovlen, "mountpoint", mount_point, -1); 282152467Srodrigc build_iovec_argf(&iov, &iovlen, "uid", "%d", uid); 283152467Srodrigc build_iovec_argf(&iov, &iovlen, "gid", "%d", gid); 284152467Srodrigc build_iovec_argf(&iov, &iovlen, "file_mode", "%d", file_mode); 285152467Srodrigc build_iovec_argf(&iov, &iovlen, "dir_mode", "%d", dir_mode); 286152467Srodrigc build_iovec_argf(&iov, &iovlen, "caseopt", "%d", caseopt); 287152467Srodrigc build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof errmsg); 288152467Srodrigc 289152467Srodrigc error = nmount(iov, iovlen, mntflags); 29087866Ssheldonh smb_ctx_done(ctx); 29187866Ssheldonh if (error) { 292152467Srodrigc smb_error("mount error: %s %s", error, mount_point, errmsg); 29387866Ssheldonh exit(1); 29487866Ssheldonh } 29587866Ssheldonh return 0; 29687866Ssheldonh} 29787866Ssheldonh 29887866Ssheldonhstatic void 29987866Ssheldonhusage(void) 30087866Ssheldonh{ 30187866Ssheldonh fprintf(stderr, "%s\n%s\n%s\n%s\n", 30288492Ssheldonh "usage: mount_smbfs [-E cs1:cs2] [-I host] [-L locale] [-M crights:srights]", 30388492Ssheldonh " [-N] [-O cowner:cgroup/sowner:sgroup] [-R retrycount]", 30488492Ssheldonh " [-T timeout] [-W workgroup] [-c case] [-d mode] [-f mode]", 305187583Strhodes " [-g gid] [-n opt] [-u uid] [-U username] //user@server/share node"); 30687866Ssheldonh 30787866Ssheldonh exit (1); 30887866Ssheldonh} 309