1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * New implementation of pfexec(1) and all of the profile shells.
27 *
28 * The algorithm is as follows:
29 * first try to derive the shell's path from getexecname();
30 * note that this requires a *hard* link to the program, so
31 * if we find that we are actually executing pfexec, we start
32 * looking at argv[0].
33 * argv[0] is also our fallback in case getexecname doesn't find it.
34 */
35 #include <sys/param.h>
36 #include <alloca.h>
37 #include <errno.h>
38 #include <locale.h>
39 #include <priv.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #define PFEXEC "pfexec"
46 #ifndef TEXT_DOMAIN
47 #define TEXT_DOMAIN "SYS_TEST"
48 #endif
49
50 #define RES_PFEXEC 1
51 #define RES_OK 0
52 #define RES_FAILURE -1
53
54 /*
55 * Return the shellname
56 */
57 int
shellname(const char * name,char buf[MAXPATHLEN])58 shellname(const char *name, char buf[MAXPATHLEN])
59 {
60 const char *cmd = strrchr(name, '/');
61
62 if (cmd == NULL)
63 cmd = name;
64 else
65 cmd++;
66
67 if (strncmp(cmd, "pf", 2) != 0)
68 return (RES_FAILURE);
69
70 if (strcmp(cmd, PFEXEC) == 0)
71 return (RES_PFEXEC);
72
73 if (strlen(name) >= MAXPATHLEN)
74 return (RES_FAILURE);
75
76 if (cmd == name) {
77 (void) strlcpy(buf, cmd + 2, MAXPATHLEN);
78 } else {
79 (void) strncpy(buf, name, cmd - name);
80 (void) strcpy(buf + (cmd - name), cmd + 2);
81 }
82 return (RES_OK);
83
84 }
85
86 static void
usage(void)87 usage(void)
88 {
89 (void) fprintf(stderr, gettext("pfexec [-P privset] cmd [arg ..]\n"));
90 exit(EXIT_FAILURE);
91 }
92
93 int
main(int argc,char ** argv)94 main(int argc, char **argv)
95 {
96 char *cmd;
97 char *pset = NULL;
98 char pathbuf[MAXPATHLEN];
99 int c;
100 priv_set_t *wanted;
101 int oflag;
102
103 oflag = getpflags(PRIV_PFEXEC);
104 if (setpflags(PRIV_PFEXEC, 1) != 0) {
105 perror("setpflags(PRIV_PFEXEC)");
106 exit(1);
107 }
108
109 if (*argv[0] == '-')
110 cmd = argv[0] + 1;
111 else
112 cmd = argv[0];
113
114 /* Strip "pf" from argv[0], it confuses some shells. */
115 if (strncmp(cmd, "pf", 2) == 0) {
116 argv[0] += 2;
117 /* argv[0] will need to start with '-' again. */
118 if (argv[0][-2] == '-')
119 *argv[0] = '-';
120 }
121
122 /* If this fails, we just continue with plan B */
123 if (shellname(getexecname(), pathbuf) == RES_OK)
124 (void) execv(pathbuf, argv);
125
126 switch (shellname(cmd, pathbuf)) {
127 case RES_OK:
128 (void) execv(pathbuf, argv);
129 perror(pathbuf);
130 return (1);
131 case RES_PFEXEC:
132 case RES_FAILURE:
133 while ((c = getopt(argc, argv, "P:")) != EOF) {
134 switch (c) {
135 case 'P':
136 if (pset == NULL) {
137 pset = optarg;
138 break;
139 }
140 /* FALLTHROUGH */
141 default:
142 usage();
143 }
144 }
145 argc -= optind;
146 argv += optind;
147 if (argc < 1)
148 usage();
149
150 if (pset != NULL) {
151 wanted = priv_str_to_set(pset, ",", NULL);
152 if (setppriv(PRIV_ON, PRIV_INHERITABLE, wanted) != 0) {
153 (void) fprintf(stderr,
154 gettext("setppriv(): %s\n"),
155 strerror(errno));
156 exit(EXIT_FAILURE);
157 }
158 (void) setpflags(PRIV_PFEXEC, oflag);
159 }
160
161 (void) execvp(argv[0], argv);
162 perror(argv[0]);
163 return (1);
164 }
165 return (1);
166 }
167