2 * Copyright (c) 1997-2003 Red Hat, Inc. All rights reserved.
4 * This software may be freely redistributed under the terms of the GNU
7 * You should have received a copy of the GNU General Public License
8 * along with this program; if not, write to the Free Software
9 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* This will be running setuid root, so be careful! */
25 static const char * safeEnviron[] = {
26 "PATH=/bin:/sbin:/usr/bin:/usr/sbin",
31 #define FOUND_FALSE -1
36 #define SBINDIR "/sbin"
41 fprintf(stderr, "usage: usernetctl <interface-config> <up|down|report>\n");
46 testSafe(char *ifaceConfig, int fd) {
49 /* These shouldn't be symbolic links -- anal, but that's fine w/ mkj. */
51 fprintf(stderr, "failed to stat %s: %s\n", ifaceConfig,
56 /* Safety/sanity checks. */
57 if (!S_ISREG(sb.st_mode)) {
58 fprintf(stderr, "%s is not a normal file\n", ifaceConfig);
63 fprintf(stderr, "%s should be owned by root\n", ifaceConfig);
67 if (sb.st_mode & S_IWOTH) {
68 fprintf(stderr, "%s should not be world writeable\n", ifaceConfig);
79 char *contents = NULL;
82 int fd = -1, retval = NOT_FOUND;
85 /* Open the file and then test it to see if we like it. This way
86 we avoid switcheroo attacks. */
87 if ((fd = open(file, O_RDONLY)) == -1) {
88 fprintf(stderr, "failed to open %s: %s\n", file, strerror(errno));
92 size = testSafe(file, fd);
94 fprintf(stderr, "file %s is too big\n", file);
98 buf = contents = malloc(size + 2);
99 if (contents == NULL) {
100 fprintf(stderr, "failed to allocate memory\n");
104 if (read(fd, contents, size) != size) {
105 perror("error reading device configuration");
110 contents[size] = '\n';
111 contents[size + 1] = '\0';
113 /* Each pass parses a single line (until an answer is found), The contents
114 pointer itself points to the beginning of the current line. */
117 while (*chptr != '\n') chptr++;
119 while (chptr >= contents && isspace(*chptr)) chptr--;
122 if (!strncasecmp(contents, "USERCTL=", 8)) {
124 if ((contents[0] == '"' &&
125 contents[strlen(contents) - 1] == '"') ||
126 (contents[0] == '\'' &&
127 contents[strlen(contents) - 1] == '\''))
130 contents[strlen(contents) - 1] = '\0';
133 if (!strcasecmp(contents, "yes") || !strcasecmp(contents, "true"))
136 retval = FOUND_FALSE;
150 main(int argc, char ** argv) {
157 if (argc != 3) usage();
159 if (!strcmp(argv[2], "up")) {
160 cmd = SBINDIR "/ifup";
161 } else if (!strcmp(argv[2], "down")) {
162 cmd = SBINDIR "/ifdown";
163 } else if (!strcmp(argv[2], "report")) {
169 if (chdir("/etc/sysconfig/interfaces")) {
170 fprintf(stderr, "error switching to /etc/sysconfig/interfaces: "
171 "%s\n", strerror(errno));
175 /* force the interface configuration to be in the current directory */
176 chptr = ifaceConfig = argv[1];
179 ifaceConfig = chptr + 1;
183 /* automatically prepend "ifcfg-" if it is not specified */
184 if (strncmp(ifaceConfig, "ifcfg-", 6)) {
186 size_t len = strlen(ifaceConfig);
188 /* Make sure a wise guys hasn't tried an integer wrap-around or
189 stack overflow attack. There's no way it could refer to anything
190 bigger than the largest filename, so cut 'em off there. */
194 temp = (char *) alloca(len + 7);
195 strcpy(temp, "ifcfg-");
196 /* strcat is safe because we got the length from strlen */
197 strcat(temp, ifaceConfig);
202 switch (userCtl(ifaceConfig)) {
206 /* a `-' will be found at least in "ifcfg-" */
207 dash = strrchr(ifaceConfig, '-');
208 if (*(dash-1) != 'g') {
209 /* This was a clone configuration; ask the parent config */
212 if (userCtl(ifaceConfig) == FOUND_TRUE) {
213 /* exit the switch; users are allowed to control */
219 /* else fall through */
223 "Users are not allowed to control this interface.\n");
228 /* looks good to me -- let's go for it if we are changing the interface,
229 * report good status to the user otherwise */
234 /* pppd wants the real uid to be the same as the effective (god only
235 knows why when it works fine setuid out of the box) */
238 execle(cmd, cmd, ifaceConfig, NULL, safeEnviron);
239 fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno));