xref: /titanic_52/usr/src/cmd/pfexec/pfexec.c (revision 511ef1d6e74f3d1db7bd854375a0926d87bdd7e6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f48205beScasper  * Common Development and Distribution License (the "License").
6f48205beScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*511ef1d6SGary Mills  * Copyright 2014 Gary Mills
23134a1f4eSCasper H.S. Dik  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
26134a1f4eSCasper H.S. Dik /*
27134a1f4eSCasper H.S. Dik  * New implementation of pfexec(1) and all of the profile shells.
28134a1f4eSCasper H.S. Dik  *
29134a1f4eSCasper H.S. Dik  * The algorithm is as follows:
30134a1f4eSCasper H.S. Dik  * 	first try to derive the shell's path from getexecname();
31134a1f4eSCasper H.S. Dik  *	note that this requires a *hard* link to the program, so
32134a1f4eSCasper H.S. Dik  *	if we find that we are actually executing pfexec, we start
33134a1f4eSCasper H.S. Dik  *	looking at argv[0].
34134a1f4eSCasper H.S. Dik  *	argv[0] is also our fallback in case getexecname doesn't find it.
35134a1f4eSCasper H.S. Dik  */
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
37134a1f4eSCasper H.S. Dik #include <alloca.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
39134a1f4eSCasper H.S. Dik #include <locale.h>
407c478bd9Sstevel@tonic-gate #include <priv.h>
41134a1f4eSCasper H.S. Dik #include <stdio.h>
42134a1f4eSCasper H.S. Dik #include <stdlib.h>
43134a1f4eSCasper H.S. Dik #include <string.h>
44134a1f4eSCasper H.S. Dik #include <unistd.h>
457c478bd9Sstevel@tonic-gate 
46134a1f4eSCasper H.S. Dik #define	PFEXEC	"pfexec"
47134a1f4eSCasper H.S. Dik #ifndef TEXT_DOMAIN
487c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
497c478bd9Sstevel@tonic-gate #endif
507c478bd9Sstevel@tonic-gate 
51134a1f4eSCasper H.S. Dik #define	RES_PFEXEC	1
52134a1f4eSCasper H.S. Dik #define	RES_OK		0
53134a1f4eSCasper H.S. Dik #define	RES_FAILURE	-1
547c478bd9Sstevel@tonic-gate 
55134a1f4eSCasper H.S. Dik /*
56134a1f4eSCasper H.S. Dik  * Return the shellname
57134a1f4eSCasper H.S. Dik  */
58134a1f4eSCasper H.S. Dik int
59134a1f4eSCasper H.S. Dik shellname(const char *name, char buf[MAXPATHLEN])
60134a1f4eSCasper H.S. Dik {
61134a1f4eSCasper H.S. Dik 	const char *cmd = strrchr(name, '/');
627c478bd9Sstevel@tonic-gate 
63134a1f4eSCasper H.S. Dik 	if (cmd == NULL)
64134a1f4eSCasper H.S. Dik 		cmd = name;
65134a1f4eSCasper H.S. Dik 	else
66134a1f4eSCasper H.S. Dik 		cmd++;
677c478bd9Sstevel@tonic-gate 
68134a1f4eSCasper H.S. Dik 	if (strncmp(cmd, "pf", 2) != 0)
69134a1f4eSCasper H.S. Dik 		return (RES_FAILURE);
707c478bd9Sstevel@tonic-gate 
71134a1f4eSCasper H.S. Dik 	if (strcmp(cmd, PFEXEC) == 0)
72134a1f4eSCasper H.S. Dik 		return (RES_PFEXEC);
73134a1f4eSCasper H.S. Dik 
74134a1f4eSCasper H.S. Dik 	if (strlen(name) >= MAXPATHLEN)
75134a1f4eSCasper H.S. Dik 		return (RES_FAILURE);
76134a1f4eSCasper H.S. Dik 
77134a1f4eSCasper H.S. Dik 	if (cmd == name) {
78134a1f4eSCasper H.S. Dik 		(void) strlcpy(buf, cmd + 2, MAXPATHLEN);
79134a1f4eSCasper H.S. Dik 	} else {
80134a1f4eSCasper H.S. Dik 		(void) strncpy(buf, name, cmd - name);
81134a1f4eSCasper H.S. Dik 		(void) strcpy(buf + (cmd - name), cmd + 2);
82134a1f4eSCasper H.S. Dik 	}
83134a1f4eSCasper H.S. Dik 	return (RES_OK);
84134a1f4eSCasper H.S. Dik 
85134a1f4eSCasper H.S. Dik }
86134a1f4eSCasper H.S. Dik 
87134a1f4eSCasper H.S. Dik static void
88134a1f4eSCasper H.S. Dik usage(void)
89134a1f4eSCasper H.S. Dik {
90134a1f4eSCasper H.S. Dik 	(void) fprintf(stderr, gettext("pfexec [-P privset] cmd [arg ..]\n"));
91134a1f4eSCasper H.S. Dik 	exit(EXIT_FAILURE);
92134a1f4eSCasper H.S. Dik }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate int
95134a1f4eSCasper H.S. Dik main(int argc, char **argv)
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	char *cmd;
987c478bd9Sstevel@tonic-gate 	char *pset = NULL;
99134a1f4eSCasper H.S. Dik 	char pathbuf[MAXPATHLEN];
100134a1f4eSCasper H.S. Dik 	int c;
101134a1f4eSCasper H.S. Dik 	priv_set_t *wanted;
102134a1f4eSCasper H.S. Dik 	int oflag;
1037c478bd9Sstevel@tonic-gate 
104134a1f4eSCasper H.S. Dik 	oflag = getpflags(PRIV_PFEXEC);
105134a1f4eSCasper H.S. Dik 	if (setpflags(PRIV_PFEXEC, 1) != 0) {
106*511ef1d6SGary Mills 		(void) fprintf(stderr,
107*511ef1d6SGary Mills 		    gettext("pfexec: unable to set PFEXEC flag: %s\n"),
108*511ef1d6SGary Mills 		    strerror(errno));
109134a1f4eSCasper H.S. Dik 		exit(1);
110134a1f4eSCasper H.S. Dik 	}
1117c478bd9Sstevel@tonic-gate 
112134a1f4eSCasper H.S. Dik 	if (*argv[0] == '-')
113134a1f4eSCasper H.S. Dik 		cmd = argv[0] + 1;
114134a1f4eSCasper H.S. Dik 	else
115134a1f4eSCasper H.S. Dik 		cmd = argv[0];
116134a1f4eSCasper H.S. Dik 
117134a1f4eSCasper H.S. Dik 	/* Strip "pf" from argv[0], it confuses some shells. */
118134a1f4eSCasper H.S. Dik 	if (strncmp(cmd, "pf", 2) == 0) {
119134a1f4eSCasper H.S. Dik 		argv[0] += 2;
120134a1f4eSCasper H.S. Dik 		/* argv[0] will need to start with '-' again. */
121134a1f4eSCasper H.S. Dik 		if (argv[0][-2] == '-')
122134a1f4eSCasper H.S. Dik 			*argv[0] = '-';
123134a1f4eSCasper H.S. Dik 	}
124134a1f4eSCasper H.S. Dik 
125134a1f4eSCasper H.S. Dik 	/* If this fails, we just continue with plan B */
126134a1f4eSCasper H.S. Dik 	if (shellname(getexecname(), pathbuf) == RES_OK)
127134a1f4eSCasper H.S. Dik 		(void) execv(pathbuf, argv);
128134a1f4eSCasper H.S. Dik 
129134a1f4eSCasper H.S. Dik 	switch (shellname(cmd, pathbuf)) {
130134a1f4eSCasper H.S. Dik 	case RES_OK:
131134a1f4eSCasper H.S. Dik 		(void) execv(pathbuf, argv);
132*511ef1d6SGary Mills 		(void) fprintf(stderr,
133*511ef1d6SGary Mills 		    gettext("pfexec: unable to execute %s: %s\n"),
134*511ef1d6SGary Mills 		    pathbuf, strerror(errno));
135134a1f4eSCasper H.S. Dik 		return (1);
136134a1f4eSCasper H.S. Dik 	case RES_PFEXEC:
137134a1f4eSCasper H.S. Dik 	case RES_FAILURE:
1387c478bd9Sstevel@tonic-gate 		while ((c = getopt(argc, argv, "P:")) != EOF) {
1397c478bd9Sstevel@tonic-gate 			switch (c) {
1407c478bd9Sstevel@tonic-gate 			case 'P':
1417c478bd9Sstevel@tonic-gate 				if (pset == NULL) {
1427c478bd9Sstevel@tonic-gate 					pset = optarg;
1437c478bd9Sstevel@tonic-gate 					break;
1447c478bd9Sstevel@tonic-gate 				}
1457c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
1467c478bd9Sstevel@tonic-gate 			default:
1477c478bd9Sstevel@tonic-gate 				usage();
1487c478bd9Sstevel@tonic-gate 			}
1497c478bd9Sstevel@tonic-gate 		}
1507c478bd9Sstevel@tonic-gate 		argc -= optind;
1517c478bd9Sstevel@tonic-gate 		argv += optind;
1527c478bd9Sstevel@tonic-gate 		if (argc < 1)
1537c478bd9Sstevel@tonic-gate 			usage();
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 		if (pset != NULL) {
156*511ef1d6SGary Mills 			if ((wanted = priv_str_to_set(pset, ",", NULL)) ==
157*511ef1d6SGary Mills 			    NULL) {
158*511ef1d6SGary Mills 				(void) fprintf(stderr,
159*511ef1d6SGary Mills 				    gettext("pfexec: error parsing "
160*511ef1d6SGary Mills 				    "privileges: %s\n"), strerror(errno));
161*511ef1d6SGary Mills 				exit(EXIT_FAILURE);
162*511ef1d6SGary Mills 			}
1637c478bd9Sstevel@tonic-gate 			if (setppriv(PRIV_ON, PRIV_INHERITABLE, wanted) != 0) {
1647c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
165*511ef1d6SGary Mills 				    gettext("pfexec: error setting "
166*511ef1d6SGary Mills 				    "privileges: %s\n"), strerror(errno));
1677c478bd9Sstevel@tonic-gate 				exit(EXIT_FAILURE);
1687c478bd9Sstevel@tonic-gate 			}
169134a1f4eSCasper H.S. Dik 			(void) setpflags(PRIV_PFEXEC, oflag);
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 
172134a1f4eSCasper H.S. Dik 		(void) execvp(argv[0], argv);
173*511ef1d6SGary Mills 		(void) fprintf(stderr,
174*511ef1d6SGary Mills 		    gettext("pfexec: unable to execute %s: %s\n"),
175*511ef1d6SGary Mills 		    argv[0], strerror(errno));
1767c478bd9Sstevel@tonic-gate 		return (1);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	return (1);
1797c478bd9Sstevel@tonic-gate }
180