]> git.pld-linux.org Git - projects/rc-scripts.git/blame - src/usernetctl.c
Synced with latest from old repo
[projects/rc-scripts.git] / src / usernetctl.c
CommitLineData
7742e157
AF
1#include <alloca.h>
2#include <ctype.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/stat.h>
9#include <unistd.h>
10
11/* this will be running setuid root, so be careful! */
12
13void usage(void) {
14 fprintf(stderr, "usage: usernetctl <interface-config> <up|down|report>\n");
15 exit(1);
16}
17
18static char * safeEnviron[] = {
19 "PATH=/bin:/sbin:/usr/bin:/usr/sbin",
20 "HOME=/root",
21 NULL
22};
23
24#define FOUND_FALSE -1
25#define NOT_FOUND 0
26#define FOUND_TRUE 1
27
28
29int testSafe(char * ifaceConfig) {
30 struct stat sb;
31
32 /* these shouldn't be symbolic links -- anal, but that's fine w/ me */
33 if (lstat(ifaceConfig, &sb)) {
34 fprintf(stderr, "failed to stat %s: %s\n", ifaceConfig,
35 strerror(errno));
36 exit(1);
37 }
38
39 /* safety checks */
40 if (!S_ISREG(sb.st_mode)) {
41 fprintf(stderr, "%s is not a normal file\n", ifaceConfig);
42 exit(1);
43 }
44
45 if (sb.st_uid) {
46 fprintf(stderr, "%s should be owned by root\n", ifaceConfig);
47 exit(1);
48 }
49
50 if (sb.st_mode & S_IWOTH) {
51 fprintf(stderr, "%s should not be world writeable\n", ifaceConfig);
52 exit(1);
53 }
54
55 return sb.st_size;
56}
57
58
59int userCtl(char * file) {
60 char * contents;
61 char * chptr;
62 char * end;
63 int fd;
64 int size;
65
66 size = testSafe(file);
67
68 contents = alloca(size + 2);
69
70 if ((fd = open(file, O_RDONLY)) < 0) {
71 fprintf(stderr, "failed to open %s: %s\n", file, strerror(errno));
72 exit(1);
73 }
74
75 if (read(fd, contents, size) != size) {
76 perror("error reading device configuration");
77 exit(1);
78 }
79 close(fd);
80
81 contents[size] = '\n';
82 contents[size + 1] = '\0';
83
84 /* each pass parses a single line (until an answer is found), contents
85 itself points to the beginning of the current line */
86 while (*contents) {
87 chptr = contents;
88 while (*chptr != '\n') chptr++;
89 end = chptr + 1;
12de71be 90 while (chptr >= contents && isspace(*chptr)) chptr--;
7742e157
AF
91 *(++chptr) = '\0';
92
93 if (!strncmp(contents, "USERCTL=", 8)) {
12de71be 94 contents += 8;
95 if (contents[0] == '"' &&
96 contents[strlen(contents) - 1] == '"') {
97 contents++;
98 contents[strlen(contents) - 1] = '\0';
99 }
100
101 if (!strcmp(contents, "yes") || !strcmp(contents, "true"))
102 return FOUND_TRUE;
103 else
104 return FOUND_FALSE;
7742e157
AF
105 }
106
107 contents = end;
108 }
109
110 return NOT_FOUND;
111}
112
113
114int main(int argc, char ** argv) {
115 char * ifaceConfig;
116 char * chptr;
117 char * cmd;
118 int report = 0;
119 char tmp;
120
121 if (argc != 3) usage();
122
123 if (!strcmp(argv[2], "up")) {
124 cmd = "./ifup";
125 } else if (!strcmp(argv[2], "down")) {
126 cmd = "./ifdown";
127 } else if (!strcmp(argv[2], "report")) {
128 report = 1;
129 } else {
130 usage();
131 }
132
133 if (chdir("/etc/sysconfig/network-scripts")) {
134 fprintf(stderr, "error switching to /etc/sysconfig/network-scripts: "
135 "%s\n", strerror(errno));
136 exit(1);
137 }
138
139 /* force the interface configuration to be in the current directory */
140 chptr = ifaceConfig = argv[1];
141 while (*chptr) {
142 if (*chptr == '/')
143 ifaceConfig = chptr + 1;
144 chptr++;
145 }
146
147 /* automatically prepend "ifcfg-" if it is not specified */
148 if (strncmp(ifaceConfig, "ifcfg-", 6)) {
149 char *temp;
150
151 temp = (char *) alloca(strlen(ifaceConfig) + 7);
152 strcpy(temp, "ifcfg-");
153 /* strcat is safe because we got the length from strlen */
154 strcat(temp, ifaceConfig);
155 ifaceConfig = temp;
156 }
157
158
159 switch (userCtl(ifaceConfig)) {
160 char *dash;
161
162 case NOT_FOUND:
163 /* a `-' will be found at least in "ifcfg-" */
164 dash = strrchr(ifaceConfig, '-');
165 if (*(dash-1) != 'g') {
166 /* This was a clone configuration; ask the parent config */
167 tmp = *dash;
168 *dash = '\0';
169 if (userCtl(ifaceConfig) == FOUND_TRUE) {
170 /* exit the switch; users are allowed to control */
171 *dash = tmp;
172 break;
173 }
174 *dash = tmp;
175 }
176 /* else fall through */
177 case FOUND_FALSE:
178 if (! report)
179 fprintf(stderr,
180 "Users are not allowed to control this interface.\n");
181 exit(1);
182 break;
183 }
184
185 /* looks good to me -- let's go for it if we are changing the interface,
186 * report good status to the user otherwise */
187
188 if (report)
189 exit(0);
190
191 /* pppd wants the real uid to be the same as the effective (god only
192 knows why when it works fine setuid out of the box) */
193 setuid(geteuid());
194
195 execle(cmd, cmd, ifaceConfig, NULL, safeEnviron);
196 fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno));
197
198 exit(1);
199}
This page took 0.046151 seconds and 4 git commands to generate.