14bff34e3Sthurlow /*
24bff34e3Sthurlow  * CDDL HEADER START
34bff34e3Sthurlow  *
44bff34e3Sthurlow  * The contents of this file are subject to the terms of the
54bff34e3Sthurlow  * Common Development and Distribution License (the "License").
64bff34e3Sthurlow  * You may not use this file except in compliance with the License.
74bff34e3Sthurlow  *
84bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
104bff34e3Sthurlow  * See the License for the specific language governing permissions
114bff34e3Sthurlow  * and limitations under the License.
124bff34e3Sthurlow  *
134bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
144bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
164bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
174bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
184bff34e3Sthurlow  *
194bff34e3Sthurlow  * CDDL HEADER END
204bff34e3Sthurlow  */
214bff34e3Sthurlow /*
2242d15982SGordon Ross  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
234bff34e3Sthurlow  * Use is subject to license terms.
244bff34e3Sthurlow  */
266a1a5bb9SJohn Levon /*
276a1a5bb9SJohn Levon  * Copyright (c) 2018, Joyent, Inc.
28*0463c800SGordon Ross  * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
296a1a5bb9SJohn Levon  */
306a1a5bb9SJohn Levon 
314bff34e3Sthurlow /*
324bff34e3Sthurlow  * smbfs umount
334bff34e3Sthurlow  */
354bff34e3Sthurlow #include <stdio.h>
364bff34e3Sthurlow #include <stdlib.h>
374bff34e3Sthurlow #include <string.h>
384bff34e3Sthurlow #include <stdarg.h>
394bff34e3Sthurlow #include <signal.h>
404bff34e3Sthurlow #include <unistd.h>
414bff34e3Sthurlow #include <kstat.h>
424bff34e3Sthurlow #include <rpc/rpc.h>
434bff34e3Sthurlow #include <sys/mnttab.h>
444bff34e3Sthurlow #include <sys/mount.h>
454bff34e3Sthurlow #include <sys/mntent.h>
464bff34e3Sthurlow #include <errno.h>
474bff34e3Sthurlow #include <locale.h>
484bff34e3Sthurlow #include <fslib.h>
4942d15982SGordon Ross #include <priv_utils.h>
514bff34e3Sthurlow #define	RET_OK	0
524bff34e3Sthurlow #define	RET_ERR	32
544bff34e3Sthurlow static void pr_err(const char *fmt, ...);
554bff34e3Sthurlow static void usage();
564bff34e3Sthurlow static int smbfs_unmount(char *, int);
574bff34e3Sthurlow static struct extmnttab *mnttab_find();
594bff34e3Sthurlow int
main(int argc,char * argv[])604bff34e3Sthurlow main(int argc, char *argv[])
614bff34e3Sthurlow {
624bff34e3Sthurlow 	extern int optind;
634bff34e3Sthurlow 	int c;
644bff34e3Sthurlow 	int umnt_flag = 0;
664bff34e3Sthurlow 	(void) setlocale(LC_ALL, "");
684bff34e3Sthurlow #if !defined(TEXT_DOMAIN)
694bff34e3Sthurlow #define	TEXT_DOMAIN "SYS_TEST"
704bff34e3Sthurlow #endif
714bff34e3Sthurlow 	(void) textdomain(TEXT_DOMAIN);
7342d15982SGordon Ross 	/*
7442d15982SGordon Ross 	 * Normal users are allowed to umount smbfs mounts they own.
75*0463c800SGordon Ross 	 * To allow that, this program has an exec_attr that adds
76*0463c800SGordon Ross 	 * SYS_MOUNT privilege.
77*0463c800SGordon Ross 	 *
78*0463c800SGordon Ross 	 * The __init_suid_priv call was designed for SUID programs,
79*0463c800SGordon Ross 	 * but also works for privileges granted via exec_attr with
80*0463c800SGordon Ross 	 * one difference: the added privileges are already effective
81*0463c800SGordon Ross 	 * when the program starts, and remain effective after the call.
82*0463c800SGordon Ross 	 * To make this work more like the SUID case we'll turn off the
83*0463c800SGordon Ross 	 * additional privileges with a __priv_bracket() call here.
84*0463c800SGordon Ross 	 * Later calls to __priv_bracket() make the extra privileges
85*0463c800SGordon Ross 	 * effective only when we need them.
8642d15982SGordon Ross 	 */
8742d15982SGordon Ross 	if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
8842d15982SGordon Ross 		(void) fprintf(stderr,
8942d15982SGordon Ross 		    gettext("Insufficient privileges, "
90*0463c800SGordon Ross 		    "%s should have sys_mount privilege via exec_attr\n"),
91*0463c800SGordon Ross 		    argv[0]);
9242d15982SGordon Ross 		exit(RET_ERR);
9342d15982SGordon Ross 	}
94*0463c800SGordon Ross 	(void) __priv_bracket(PRIV_OFF);
964bff34e3Sthurlow 	/*
974bff34e3Sthurlow 	 * Set options
984bff34e3Sthurlow 	 */
994bff34e3Sthurlow 	while ((c = getopt(argc, argv, "f")) != EOF) {
1004bff34e3Sthurlow 		switch (c) {
1014bff34e3Sthurlow 		case 'f':
1024bff34e3Sthurlow 			umnt_flag |= MS_FORCE; /* forced unmount is desired */
1034bff34e3Sthurlow 			break;
1044bff34e3Sthurlow 		default:
1054bff34e3Sthurlow 			usage();
1064bff34e3Sthurlow 			exit(RET_ERR);
1074bff34e3Sthurlow 		}
1084bff34e3Sthurlow 	}
1094bff34e3Sthurlow 	if (argc - optind != 1) {
1104bff34e3Sthurlow 		usage();
1114bff34e3Sthurlow 		exit(RET_ERR);
1124bff34e3Sthurlow 	}
1144bff34e3Sthurlow 	return (smbfs_unmount(argv[optind], umnt_flag));
1154bff34e3Sthurlow }
1174bff34e3Sthurlow static void
pr_err(const char * fmt,...)1184bff34e3Sthurlow pr_err(const char *fmt, ...)
1194bff34e3Sthurlow {
1204bff34e3Sthurlow 	va_list ap;
1224bff34e3Sthurlow 	va_start(ap, fmt);
123*0463c800SGordon Ross 	(void) fprintf(stderr, "smbfs/umount: ");
1244bff34e3Sthurlow 	(void) vfprintf(stderr, fmt, ap);
1254bff34e3Sthurlow 	(void) fflush(stderr);
1264bff34e3Sthurlow 	va_end(ap);
1274bff34e3Sthurlow }
1294bff34e3Sthurlow static void
usage()1304bff34e3Sthurlow usage()
1314bff34e3Sthurlow {
1324bff34e3Sthurlow 	(void) fprintf(stderr,
1334bff34e3Sthurlow 	    gettext("Usage: smbfs umount [-o opts] {//server/share | dir}\n"));
1344bff34e3Sthurlow 	exit(RET_ERR);
1354bff34e3Sthurlow }
1374bff34e3Sthurlow static int
smbfs_unmount(char * pathname,int umnt_flag)1384bff34e3Sthurlow smbfs_unmount(char *pathname, int umnt_flag)
1394bff34e3Sthurlow {
1404bff34e3Sthurlow 	struct extmnttab *mntp;
14142d15982SGordon Ross 	int rc;
1434bff34e3Sthurlow 	mntp = mnttab_find(pathname);
1444bff34e3Sthurlow 	if (mntp) {
1454bff34e3Sthurlow 		pathname = mntp->mnt_mountp;
1464bff34e3Sthurlow 	}
14842d15982SGordon Ross 	/* Need sys_mount privilege for the umount call. */
14942d15982SGordon Ross 	(void) __priv_bracket(PRIV_ON);
15042d15982SGordon Ross 	rc = umount2(pathname, umnt_flag);
15142d15982SGordon Ross 	(void) __priv_bracket(PRIV_OFF);
15242d15982SGordon Ross 
15342d15982SGordon Ross 	if (rc < 0) {
1544bff34e3Sthurlow 		pr_err(gettext("%s: %s\n"), pathname, strerror(errno));
1554bff34e3Sthurlow 		return (RET_ERR);
1564bff34e3Sthurlow 	}
1584bff34e3Sthurlow 	return (RET_OK);
1594bff34e3Sthurlow }
1614bff34e3Sthurlow /*
1624bff34e3Sthurlow  *  Find the mnttab entry that corresponds to "name".
1634bff34e3Sthurlow  *  We're not sure what the name represents: either
1644bff34e3Sthurlow  *  a mountpoint name, or a special name (server:/path).
1654bff34e3Sthurlow  *  Return the last entry in the file that matches.
1664bff34e3Sthurlow  */
1674bff34e3Sthurlow static struct extmnttab *
mnttab_find(char * dirname)168*0463c800SGordon Ross mnttab_find(char *dirname)
1694bff34e3Sthurlow {
1704bff34e3Sthurlow 	FILE *fp;
1714bff34e3Sthurlow 	struct extmnttab mnt;
1724bff34e3Sthurlow 	struct extmnttab *res = NULL;
1744bff34e3Sthurlow 	fp = fopen(MNTTAB, "r");
1754bff34e3Sthurlow 	if (fp == NULL) {
1764bff34e3Sthurlow 		pr_err("%s: %s\n", MNTTAB, strerror(errno));
1774bff34e3Sthurlow 		return (NULL);
1784bff34e3Sthurlow 	}
1794bff34e3Sthurlow 	while (getextmntent(fp, &mnt, sizeof (struct extmnttab)) == 0) {
1804bff34e3Sthurlow 		if (strcmp(mnt.mnt_mountp, dirname) == 0 ||
1814bff34e3Sthurlow 		    strcmp(mnt.mnt_special, dirname) == 0) {
1824bff34e3Sthurlow 			if (res)
1834bff34e3Sthurlow 				fsfreemnttab(res);
1844bff34e3Sthurlow 			res = fsdupmnttab(&mnt);
1854bff34e3Sthurlow 		}
1864bff34e3Sthurlow 	}
1886a1a5bb9SJohn Levon 	(void) fclose(fp);
1894bff34e3Sthurlow 	return (res);
1904bff34e3Sthurlow }