Hinzugefügt:
[ipfire-2.x.git] / src / misc-progs / openvpnctrl.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <fcntl.h>
7 #include "setuid.h"
8 #include "libsmooth.h"
9
10 /*
11 Version History
12
13 1.0.0.0 many things happend before ...
14
15 2.0.0.1 2005/06/09 tarralan
16 add. Version History
17 add. deleteChainReference(char*)
18 add. createChainReference(char*)
19 mod. deleteChain(char*)
20 mod. flushChain(char*)
21 add. flushAllChains()
22 del. deletechains()
23 add. consts for chain names
24 del. createchains()
25 add. createAllChains()
26 add. ovpnInit()
27 add. global vars for chain and interface status
28 add. usage of consts for chain names
29 mod. reworked createAllChains()
30
31 2.0.0.2 2005/06/09 horizont
32 change the input + forward chain position index based on active interfaces
33
34 2.0.0.3 2005/06/09 tarralan
35 mod. removed const attribute
36
37 2.0.0.4 2005/06/12 tarralan
38 add. debug condition für output
39 mod. changed definition auf consts
40
41 2.0.0.5-7 2005/06/12 tarralan
42 debugging
43
44 2.0.0.8 2005/06/12 tarralan
45 add. executeCommand()
46
47 2.0.0.9-16 2005/06/12 tarralan
48 debugging
49
50 2.0.0.17 2005/06/12 tarralan
51 mod. createAllChains
52
53 2.0.1.1 2005/06/12 tarralan
54 non-debug build
55
56 2.0.1.2 2005/06/13 tarralan
57 mod. some options renamed
58
59 2.0.1.3 2005/06/13 tarralan
60 mod. startDaemon() to verify if OpenVPN is enabled
61 mod. createAllChains() to verify if OpenVPN is enabled
62 mod. command help
63
64 2.0.1.4 2005/06/13 tarralan
65 mod. bug fixed with the -sdo option
66 2.0.1.5 2005/11/06 Ufuk Altinkaynak
67 mod. bug fixed no need to read blue and orange dev, when they are not enabled
68 2.0.1.6 2005/01/03 Ufuk Altinkaynak
69 mod. bug fixed reported by weizen_42 see http://www.vpnforum.de/viewtopic.php?p=7113#7113
70
71 # ZERNINA-VERSION:0.9.0b
72 # (c) 2005 tarralan + Ufuk Altinkaynak
73 #
74 # Ipcop and OpenVPN eas as one two three..
75 #
76 */
77 #define noovpndebug
78
79 // global vars
80 struct keyvalue *kv = NULL;
81 FILE *ifacefile = NULL;
82
83 char redif[STRING_SIZE];
84 char blueif[STRING_SIZE];
85 char orangeif[STRING_SIZE];
86 char enablered[STRING_SIZE] = "off";
87 char enableblue[STRING_SIZE] = "off";
88 char enableorange[STRING_SIZE] = "off";
89
90 // consts
91 char OVPNRED[STRING_SIZE] = "OVPN";
92 char OVPNBLUE[STRING_SIZE] = "OVPN_BLUE_";
93 char OVPNORANGE[STRING_SIZE] = "OVPN_ORANGE_";
94 char WRAPPERVERSION[STRING_SIZE] = "2.0.1.6";
95
96 void exithandler(void)
97 {
98 if(kv)
99 freekeyvalues(kv);
100 if (ifacefile)
101 fclose(ifacefile);
102 }
103
104 void usage(void)
105 {
106 #ifdef ovpndebug
107 printf("Wrapper for OpenVPN v%s-debug\n", WRAPPERVERSION);
108 #else
109 printf("Wrapper for OpenVPN v%s\n", WRAPPERVERSION);
110 #endif
111 printf("openvpnctrl <option>\n");
112 printf(" Valid options are:\n");
113 printf(" -s --start\n");
114 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
115 printf(" -k --kill\n");
116 printf(" kills/stops OpenVPN\n");
117 printf(" -r --restart\n");
118 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
119 printf(" -d --display\n");
120 printf(" displays OpenVPN status to syslog\n");
121 printf(" -fwr --firewall-rules\n");
122 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
123 printf(" -sdo --start-daemon-only\n");
124 printf(" starts OpenVPN daemon only (useful for rc.local)\n");
125 printf(" -ccr --create-chains-and-rules\n");
126 printf(" creates chains and rules for OpenVPN\n");
127 printf(" -dcr --delete-chains-and-rules\n");
128 printf(" removes all chains for OpenVPN\n");
129 exit(1);
130 }
131
132 void ovpnInit(void) {
133
134 // Read OpenVPN configuration
135 kv = initkeyvalues();
136 if (!readkeyvalues(kv, CONFIG_ROOT "/ovpn/settings")) {
137 fprintf(stderr, "Cannot read ovpn settings\n");
138 exit(1);
139 }
140
141 if (!findkey(kv, "ENABLED", enablered)) {
142 fprintf(stderr, "Cannot read ENABLED\n");
143 exit(1);
144 }
145
146 if (!findkey(kv, "ENABLED_BLUE", enableblue)){
147 fprintf(stderr, "Cannot read ENABLED_BLUE\n");
148 exit(1);
149 }
150
151 if (!findkey(kv, "ENABLED_ORANGE", enableorange)){
152 fprintf(stderr, "Cannot read ENABLED_ORANGE\n");
153 exit(1);
154 }
155 freekeyvalues(kv);
156
157 // read interface settings
158
159 // details for the red int
160 memset(redif, 0, STRING_SIZE);
161 if ((ifacefile = fopen(CONFIG_ROOT "/red/iface", "r")))
162 {
163 if (fgets(redif, STRING_SIZE, ifacefile))
164 {
165 if (redif[strlen(redif) - 1] == '\n')
166 redif[strlen(redif) - 1] = '\0';
167 }
168 fclose (ifacefile);
169 ifacefile = NULL;
170
171 if (!VALID_DEVICE(redif))
172 {
173 memset(redif, 0, STRING_SIZE);
174 }
175 }
176
177 kv=initkeyvalues();
178 if (!readkeyvalues(kv, CONFIG_ROOT "/ethernet/settings"))
179 {
180 fprintf(stderr, "Cannot read ethernet settings\n");
181 exit(1);
182 }
183
184 if (strcmp(enableblue, "on")==0){
185 if (!findkey(kv, "BLUE_DEV", blueif)){
186 fprintf(stderr, "Cannot read BLUE_DEV\n");
187 exit(1);
188 }
189 }
190 if (strcmp(enableorange, "on")==0){
191 if (!findkey(kv, "ORANGE_DEV", orangeif)){
192 fprintf(stderr, "Cannot read ORNAGE_DEV\n");
193 exit(1);
194 }
195 }
196 freekeyvalues(kv);
197 }
198
199 void executeCommand(char *command) {
200 #ifdef ovpndebug
201 printf(strncat(command, "\n", 2));
202 #endif
203 safe_system(strncat(command, " >/dev/null 2>&1", 17));
204 }
205
206 void setChainRules(char *chain, char *interface, char *protocol, char *port)
207 {
208 char str[STRING_SIZE];
209
210 sprintf(str, "/sbin/iptables -A %sINPUT -i %s -p %s --dport %s -j ACCEPT", chain, interface, protocol, port);
211 executeCommand(str);
212 sprintf(str, "/sbin/iptables -A %sINPUT -i tun+ -j ACCEPT", chain);
213 executeCommand(str);
214 sprintf(str, "/sbin/iptables -A %sFORWARD -i tun+ -j ACCEPT", chain);
215 executeCommand(str);
216 }
217
218 void flushChain(char *chain) {
219 char str[STRING_SIZE];
220
221 sprintf(str, "/sbin/iptables -F %sINPUT", chain);
222 executeCommand(str);
223 sprintf(str, "/sbin/iptables -F %sFORWARD", chain);
224 executeCommand(str);
225 safe_system(str);
226 }
227
228 void deleteChainReference(char *chain) {
229 char str[STRING_SIZE];
230
231 sprintf(str, "/sbin/iptables -D INPUT -j %sINPUT", chain);
232 executeCommand(str);
233 safe_system(str);
234 sprintf(str, "/sbin/iptables -D FORWARD -j %sFORWARD", chain);
235 executeCommand(str);
236 safe_system(str);
237 }
238
239 void deleteChain(char *chain) {
240 char str[STRING_SIZE];
241
242 sprintf(str, "/sbin/iptables -X %sINPUT", chain);
243 executeCommand(str);
244 sprintf(str, "/sbin/iptables -X %sFORWARD", chain);
245 executeCommand(str);
246 }
247
248 void deleteAllChains(void) {
249 // not an elegant solution, but to avoid timing problems with undeleted chain references
250 deleteChainReference(OVPNRED);
251 deleteChainReference(OVPNBLUE);
252 deleteChainReference(OVPNORANGE);
253 flushChain(OVPNRED);
254 flushChain(OVPNBLUE);
255 flushChain(OVPNORANGE);
256 deleteChain(OVPNRED);
257 deleteChain(OVPNBLUE);
258 deleteChain(OVPNORANGE);
259 }
260
261 void createChainReference(char *chain) {
262 char str[STRING_SIZE];
263 sprintf(str, "/sbin/iptables -I INPUT %s -j %sINPUT", "14", chain);
264 executeCommand(str);
265 sprintf(str, "/sbin/iptables -I FORWARD %s -j %sFORWARD", "12", chain);
266 executeCommand(str);
267 }
268
269 void createChain(char *chain) {
270 char str[STRING_SIZE];
271 sprintf(str, "/sbin/iptables -N %sINPUT", chain);
272 executeCommand(str);
273 sprintf(str, "/sbin/iptables -N %sFORWARD", chain);
274 executeCommand(str);
275 }
276
277 void createAllChains(void) {
278 if (!((strcmp(enablered, "on")==0) || (strcmp(enableblue, "on")==0) || (strcmp(enableorange, "on")==0))){
279 fprintf(stderr, "OpenVPN is not enabled on any interface\n");
280 exit(1);
281 } else {
282 // create chain and chain references
283 if (!strcmp(enableorange, "on")) {
284 if (strlen(orangeif)) {
285 createChain(OVPNORANGE);
286 createChainReference(OVPNORANGE);
287 } else {
288 fprintf(stderr, "OpenVPN enabled on orange but no orange interface found\n");
289 //exit(1);
290 }
291 }
292
293 if (!strcmp(enableblue, "on")) {
294 if (strlen(blueif)) {
295 createChain(OVPNBLUE);
296 createChainReference(OVPNBLUE);
297 } else {
298 fprintf(stderr, "OpenVPN enabled on blue but no blue interface found\n");
299 //exit(1);
300 }
301 }
302
303 if (!strcmp(enablered, "on")) {
304 if (strlen(redif)) {
305 createChain(OVPNRED);
306 createChainReference(OVPNRED);
307 } else {
308 fprintf(stderr, "OpenVPN enabled on red but no red interface found\n");
309 //exit(1);
310 }
311 }
312 }
313 }
314
315 void setFirewallRules(void) {
316 char protocol[STRING_SIZE] = "";
317 char dport[STRING_SIZE] = "";
318 char dovpnip[STRING_SIZE] = "";
319
320 /* check if it makes sence to proceed further */
321 if (!((strcmp(enablered, "on")==0) || (strcmp(enableblue, "on")==0) || (strcmp(enableorange, "on")==0))){
322 fprintf(stderr, "Config error, at least one device must be enabled\n");
323 exit(1);
324 }
325
326 kv = initkeyvalues();
327 if (!readkeyvalues(kv, CONFIG_ROOT "/ovpn/settings"))
328 {
329 fprintf(stderr, "Cannot read ovpn settings\n");
330 exit(1);
331 }
332
333 /* we got one device, so lets proceed further */
334 if (!findkey(kv, "DDEST_PORT", dport)){
335 fprintf(stderr, "Cannot read DDEST_PORT\n");
336 exit(1);
337 }
338
339 if (!findkey(kv, "DPROTOCOL", protocol)){
340 fprintf(stderr, "Cannot read DPROTOCOL\n");
341 exit(1);
342 }
343
344 if (!findkey(kv, "VPN_IP", dovpnip)){
345 fprintf(stderr, "Cannot read VPN_IP\n");
346 // exit(1); step further as we don't need an ip
347 }
348 freekeyvalues(kv);
349
350 // set firewall rules
351 if (!strcmp(enablered, "on") && strlen(redif))
352 setChainRules(OVPNRED, redif, protocol, dport);
353 if (!strcmp(enableblue, "on") && strlen(blueif))
354 setChainRules(OVPNBLUE, blueif, protocol, dport);
355 if (!strcmp(enableorange, "on") && strlen(orangeif))
356 setChainRules(OVPNORANGE, orangeif, protocol, dport);
357 }
358
359 void stopDaemon(void) {
360 char command[STRING_SIZE];
361
362 snprintf(command, STRING_SIZE - 1, "/bin/killall openvpn");
363 executeCommand(command);
364 snprintf(command, STRING_SIZE - 1, "/bin/rm -f /var/run/openvpn.pid");
365 executeCommand(command);
366 }
367
368 void startDaemon(void) {
369 char command[STRING_SIZE];
370
371 if (!((strcmp(enablered, "on")==0) || (strcmp(enableblue, "on")==0) || (strcmp(enableorange, "on")==0))){
372 fprintf(stderr, "OpenVPN is not enabled on any interface\n");
373 exit(1);
374 } else {
375 snprintf(command, STRING_SIZE-1, "/usr/bin/openvpn --config /var/ipfire/ovpn/server.conf");
376 executeCommand(command);
377 }
378 }
379
380 void displayopenvpn(void) {
381 char command[STRING_SIZE];
382
383 snprintf(command, STRING_SIZE - 1, "/bin/killall -sSIGUSR2 openvpn");
384 executeCommand(command);
385 }
386
387 int main(int argc, char *argv[]) {
388 if (!(initsetuid()))
389 exit(1);
390 if(argc < 2)
391 usage();
392
393 if(argc == 2) {
394 if( (strcmp(argv[1], "-k") == 0) || (strcmp(argv[1], "--kill") == 0) ) {
395 stopDaemon();
396 return 0;
397 }
398 else if( (strcmp(argv[1], "-d") == 0) || (strcmp(argv[1], "--display") == 0) ) {
399 displayopenvpn();
400 return 0;
401 }
402 else if( (strcmp(argv[1], "-dcr") == 0) || (strcmp(argv[1], "--delete-chains-and-rules") == 0) ) {
403 deleteAllChains();
404 return 0;
405 }
406 else {
407 ovpnInit();
408
409 if( (strcmp(argv[1], "-s") == 0) || (strcmp(argv[1], "--start") == 0) ) {
410 deleteAllChains();
411 createAllChains();
412 setFirewallRules();
413 startDaemon();
414 return 0;
415 }
416 else if( (strcmp(argv[1], "-sdo") == 0) || (strcmp(argv[1], "--start-daemon-only") == 0) ) {
417 startDaemon();
418 return 0;
419 }
420 else if( (strcmp(argv[1], "-r") == 0) || (strcmp(argv[1], "--restart") == 0) ) {
421 stopDaemon();
422 deleteAllChains();
423 createAllChains();
424 setFirewallRules();
425 startDaemon();
426 return 0;
427 }
428 else if( (strcmp(argv[1], "-fwr") == 0) || (strcmp(argv[1], "--firewall-rules") == 0) ) {
429 deleteAllChains();
430 createAllChains();
431 setFirewallRules();
432 return 0;
433 }
434 else if( (strcmp(argv[1], "-ccr") == 0) || (strcmp(argv[1], "--create-chains-and-rules") == 0) ) {
435 createAllChains();
436 setFirewallRules();
437 return 0;
438 }
439 else {
440 usage();
441 return 0;
442 }
443 }
444 }
445 else {
446 usage();
447 return 0;
448 }
449 return 0;
450 }
451