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  */
254bff34e3Sthurlow 
26*6a1a5bb9SJohn Levon /*
27*6a1a5bb9SJohn Levon  * Copyright (c) 2018, Joyent, Inc.
28*6a1a5bb9SJohn Levon  */
29*6a1a5bb9SJohn Levon 
304bff34e3Sthurlow /*
314bff34e3Sthurlow  * smbfs umount
324bff34e3Sthurlow  */
334bff34e3Sthurlow 
344bff34e3Sthurlow #include <stdio.h>
354bff34e3Sthurlow #include <stdlib.h>
364bff34e3Sthurlow #include <string.h>
374bff34e3Sthurlow #include <stdarg.h>
384bff34e3Sthurlow #include <signal.h>
394bff34e3Sthurlow #include <unistd.h>
404bff34e3Sthurlow #include <kstat.h>
414bff34e3Sthurlow #include <rpc/rpc.h>
424bff34e3Sthurlow #include <sys/mnttab.h>
434bff34e3Sthurlow #include <sys/mount.h>
444bff34e3Sthurlow #include <sys/mntent.h>
454bff34e3Sthurlow #include <errno.h>
464bff34e3Sthurlow #include <locale.h>
474bff34e3Sthurlow #include <fslib.h>
4842d15982SGordon Ross #include <priv_utils.h>
494bff34e3Sthurlow 
504bff34e3Sthurlow #define	RET_OK	0
514bff34e3Sthurlow #define	RET_ERR	32
524bff34e3Sthurlow 
534bff34e3Sthurlow static void pr_err(const char *fmt, ...);
544bff34e3Sthurlow static void usage();
554bff34e3Sthurlow static int smbfs_unmount(char *, int);
564bff34e3Sthurlow static struct extmnttab *mnttab_find();
574bff34e3Sthurlow 
584bff34e3Sthurlow static char *myname;
594bff34e3Sthurlow static char typename[64];
604bff34e3Sthurlow 
614bff34e3Sthurlow int
624bff34e3Sthurlow main(int argc, char *argv[])
634bff34e3Sthurlow {
644bff34e3Sthurlow 	extern int optind;
654bff34e3Sthurlow 	int c;
664bff34e3Sthurlow 	int umnt_flag = 0;
674bff34e3Sthurlow 
684bff34e3Sthurlow 	(void) setlocale(LC_ALL, "");
694bff34e3Sthurlow 
704bff34e3Sthurlow #if !defined(TEXT_DOMAIN)
714bff34e3Sthurlow #define	TEXT_DOMAIN "SYS_TEST"
724bff34e3Sthurlow #endif
734bff34e3Sthurlow 	(void) textdomain(TEXT_DOMAIN);
744bff34e3Sthurlow 
7542d15982SGordon Ross 	/*
7642d15982SGordon Ross 	 * Normal users are allowed to umount smbfs mounts they own.
7742d15982SGordon Ross 	 * To allow that, this program is installed setuid root, and
7842d15982SGordon Ross 	 * it adds SYS_MOUNT privilege here (if needed), and then
7942d15982SGordon Ross 	 * restores the user's normal privileges.
8042d15982SGordon Ross 	 */
8142d15982SGordon Ross 	if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
8242d15982SGordon Ross 		(void) fprintf(stderr,
8342d15982SGordon Ross 		    gettext("Insufficient privileges, "
8442d15982SGordon Ross 		    "%s must be set-uid root\n"), argv[0]);
8542d15982SGordon Ross 		exit(RET_ERR);
8642d15982SGordon Ross 	}
8742d15982SGordon Ross 
884bff34e3Sthurlow 	myname = strrchr(argv[0], '/');
894bff34e3Sthurlow 	myname = myname ? myname+1 : argv[0];
904bff34e3Sthurlow 	(void) sprintf(typename, "smbfs %s", myname);
914bff34e3Sthurlow 	argv[0] = typename;
924bff34e3Sthurlow 
934bff34e3Sthurlow 	/*
944bff34e3Sthurlow 	 * Set options
954bff34e3Sthurlow 	 */
964bff34e3Sthurlow 	while ((c = getopt(argc, argv, "f")) != EOF) {
974bff34e3Sthurlow 		switch (c) {
984bff34e3Sthurlow 		case 'f':
994bff34e3Sthurlow 			umnt_flag |= MS_FORCE; /* forced unmount is desired */
1004bff34e3Sthurlow 			break;
1014bff34e3Sthurlow 		default:
1024bff34e3Sthurlow 			usage();
1034bff34e3Sthurlow 			exit(RET_ERR);
1044bff34e3Sthurlow 		}
1054bff34e3Sthurlow 	}
1064bff34e3Sthurlow 	if (argc - optind != 1) {
1074bff34e3Sthurlow 		usage();
1084bff34e3Sthurlow 		exit(RET_ERR);
1094bff34e3Sthurlow 	}
1104bff34e3Sthurlow 
1114bff34e3Sthurlow 	return (smbfs_unmount(argv[optind], umnt_flag));
1124bff34e3Sthurlow }
1134bff34e3Sthurlow 
1144bff34e3Sthurlow static void
1154bff34e3Sthurlow pr_err(const char *fmt, ...)
1164bff34e3Sthurlow {
1174bff34e3Sthurlow 	va_list ap;
1184bff34e3Sthurlow 
1194bff34e3Sthurlow 	va_start(ap, fmt);
1204bff34e3Sthurlow 	(void) fprintf(stderr, "%s: ", typename);
1214bff34e3Sthurlow 	(void) vfprintf(stderr, fmt, ap);
1224bff34e3Sthurlow 	(void) fflush(stderr);
1234bff34e3Sthurlow 	va_end(ap);
1244bff34e3Sthurlow }
1254bff34e3Sthurlow 
1264bff34e3Sthurlow static void
1274bff34e3Sthurlow usage()
1284bff34e3Sthurlow {
1294bff34e3Sthurlow 	(void) fprintf(stderr,
1304bff34e3Sthurlow 	    gettext("Usage: smbfs umount [-o opts] {//server/share | dir}\n"));
1314bff34e3Sthurlow 	exit(RET_ERR);
1324bff34e3Sthurlow }
1334bff34e3Sthurlow 
1344bff34e3Sthurlow static int
1354bff34e3Sthurlow smbfs_unmount(char *pathname, int umnt_flag)
1364bff34e3Sthurlow {
1374bff34e3Sthurlow 	struct extmnttab *mntp;
13842d15982SGordon Ross 	int rc;
1394bff34e3Sthurlow 
1404bff34e3Sthurlow 	mntp = mnttab_find(pathname);
1414bff34e3Sthurlow 	if (mntp) {
1424bff34e3Sthurlow 		pathname = mntp->mnt_mountp;
1434bff34e3Sthurlow 	}
1444bff34e3Sthurlow 
14542d15982SGordon Ross 	/* Need sys_mount privilege for the umount call. */
14642d15982SGordon Ross 	(void) __priv_bracket(PRIV_ON);
14742d15982SGordon Ross 	rc = umount2(pathname, umnt_flag);
14842d15982SGordon Ross 	(void) __priv_bracket(PRIV_OFF);
14942d15982SGordon Ross 
15042d15982SGordon Ross 	if (rc < 0) {
1514bff34e3Sthurlow 		pr_err(gettext("%s: %s\n"), pathname, strerror(errno));
1524bff34e3Sthurlow 		return (RET_ERR);
1534bff34e3Sthurlow 	}
1544bff34e3Sthurlow 
1554bff34e3Sthurlow 	return (RET_OK);
1564bff34e3Sthurlow }
1574bff34e3Sthurlow 
1584bff34e3Sthurlow /*
1594bff34e3Sthurlow  *  Find the mnttab entry that corresponds to "name".
1604bff34e3Sthurlow  *  We're not sure what the name represents: either
1614bff34e3Sthurlow  *  a mountpoint name, or a special name (server:/path).
1624bff34e3Sthurlow  *  Return the last entry in the file that matches.
1634bff34e3Sthurlow  */
1644bff34e3Sthurlow static struct extmnttab *
1654bff34e3Sthurlow mnttab_find(dirname)
1664bff34e3Sthurlow 	char *dirname;
1674bff34e3Sthurlow {
1684bff34e3Sthurlow 	FILE *fp;
1694bff34e3Sthurlow 	struct extmnttab mnt;
1704bff34e3Sthurlow 	struct extmnttab *res = NULL;
1714bff34e3Sthurlow 
1724bff34e3Sthurlow 	fp = fopen(MNTTAB, "r");
1734bff34e3Sthurlow 	if (fp == NULL) {
1744bff34e3Sthurlow 		pr_err("%s: %s\n", MNTTAB, strerror(errno));
1754bff34e3Sthurlow 		return (NULL);
1764bff34e3Sthurlow 	}
1774bff34e3Sthurlow 	while (getextmntent(fp, &mnt, sizeof (struct extmnttab)) == 0) {
1784bff34e3Sthurlow 		if (strcmp(mnt.mnt_mountp, dirname) == 0 ||
1794bff34e3Sthurlow 		    strcmp(mnt.mnt_special, dirname) == 0) {
1804bff34e3Sthurlow 			if (res)
1814bff34e3Sthurlow 				fsfreemnttab(res);
1824bff34e3Sthurlow 			res = fsdupmnttab(&mnt);
1834bff34e3Sthurlow 		}
1844bff34e3Sthurlow 	}
1854bff34e3Sthurlow 
186*6a1a5bb9SJohn Levon 	(void) fclose(fp);
1874bff34e3Sthurlow 	return (res);
1884bff34e3Sthurlow }
189