]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/misc-progs/openvpnctrl.c
Import new version of ovpnmain.cgi.
[people/teissler/ipfire-2.x.git] / src / misc-progs / openvpnctrl.c
CommitLineData
39877197 1#include <signal.h>
6e13d0a5
MT
2#include <stdio.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdlib.h>
6#include <sys/types.h>
7#include <fcntl.h>
8#include "setuid.h"
9#include "libsmooth.h"
10
c894a342 11#define noovpndebug
6e13d0a5
MT
12
13// global vars
14 struct keyvalue *kv = NULL;
15 FILE *ifacefile = NULL;
16
17char redif[STRING_SIZE];
18char blueif[STRING_SIZE];
19char orangeif[STRING_SIZE];
20char enablered[STRING_SIZE] = "off";
21char enableblue[STRING_SIZE] = "off";
22char enableorange[STRING_SIZE] = "off";
23
24// consts
25char OVPNRED[STRING_SIZE] = "OVPN";
26char OVPNBLUE[STRING_SIZE] = "OVPN_BLUE_";
27char OVPNORANGE[STRING_SIZE] = "OVPN_ORANGE_";
39877197 28char WRAPPERVERSION[STRING_SIZE] = "ipfire-2.1.2";
6925b8ef
AF
29
30struct connection_struct {
31 char name[STRING_SIZE];
91a0a221 32 char type[STRING_SIZE];
6925b8ef
AF
33 char proto[STRING_SIZE];
34 int port;
35 struct connection_struct *next;
36};
37
38typedef struct connection_struct connection;
6e13d0a5
MT
39
40void exithandler(void)
41{
42 if(kv)
43 freekeyvalues(kv);
44 if (ifacefile)
45 fclose(ifacefile);
46}
47
48void usage(void)
49{
50#ifdef ovpndebug
07081137 51 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION);
6e13d0a5 52#else
07081137 53 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION);
6e13d0a5
MT
54#endif
55 printf("openvpnctrl <option>\n");
56 printf(" Valid options are:\n");
57 printf(" -s --start\n");
58 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
59 printf(" -k --kill\n");
60 printf(" kills/stops OpenVPN\n");
61 printf(" -r --restart\n");
62 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
63 printf(" -d --display\n");
64 printf(" displays OpenVPN status to syslog\n");
65 printf(" -fwr --firewall-rules\n");
66 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
67 printf(" -sdo --start-daemon-only\n");
afabe9f7 68 printf(" starts OpenVPN daemon only\n");
6e13d0a5
MT
69 printf(" -ccr --create-chains-and-rules\n");
70 printf(" creates chains and rules for OpenVPN\n");
71 printf(" -dcr --delete-chains-and-rules\n");
72 printf(" removes all chains for OpenVPN\n");
73 exit(1);
74}
75
6925b8ef
AF
76connection *getConnections() {
77 FILE *fp = NULL;
78
79 if (!(fp = fopen(CONFIG_ROOT "/ovpn/ovpnconfig", "r"))) {
80 fprintf(stderr, "Could not open openvpn n2n configuration file.\n");
81 exit(1);
82 }
83
84 char line[STRING_SIZE] = "";
85 char *result;
86 int count;
87 connection *conn_first = NULL;
88 connection *conn_last = NULL;
89 connection *conn_curr;
90
91 while ((fgets(line, STRING_SIZE, fp) != NULL)) {
92 if (line[strlen(line) - 1] == '\n')
93 line[strlen(line) - 1] = '\0';
94
95 conn_curr = (connection *)malloc(sizeof(connection));
96 memset(conn_curr, 0, sizeof(connection));
97
98 if (conn_first == NULL) {
99 conn_first = conn_curr;
100 } else {
101 conn_last->next = conn_curr;
102 }
103 conn_last = conn_curr;
104
105 count = 0;
106 result = strtok(line, ",");
107 while (result) {
108 if (count == 2) {
109 strcpy(conn_curr->name, result);
91a0a221
MT
110 } else if (count == 4) {
111 strcpy(conn_curr->type, result);
6925b8ef
AF
112 } else if (count == 12) {
113 strcpy(conn_curr->proto, result);
114 } else if (count == 13) {
115 conn_curr->port = atoi(result);
116 }
117
118 result = strtok(NULL, ",");
119 count++;
120 }
121 }
122
123 fclose(fp);
124
125 return conn_first;
126}
127
80ca8bd0
MT
128int readPidFile(const char *pidfile) {
129 FILE *fp = fopen(pidfile, "r");
130 if (fp == NULL) {
131 fprintf(stderr, "PID file not found: '%s'\n", pidfile);
132 exit(1);
133 }
134
135 int pid = 0;
136 fscanf(fp, "%d", &pid);
137 fclose(fp);
138
139 return pid;
140}
141
6e13d0a5
MT
142void ovpnInit(void) {
143
144 // Read OpenVPN configuration
145 kv = initkeyvalues();
146 if (!readkeyvalues(kv, CONFIG_ROOT "/ovpn/settings")) {
147 fprintf(stderr, "Cannot read ovpn settings\n");
148 exit(1);
149 }
150
151 if (!findkey(kv, "ENABLED", enablered)) {
152 fprintf(stderr, "Cannot read ENABLED\n");
153 exit(1);
154 }
155
156 if (!findkey(kv, "ENABLED_BLUE", enableblue)){
157 fprintf(stderr, "Cannot read ENABLED_BLUE\n");
158 exit(1);
159 }
160
161 if (!findkey(kv, "ENABLED_ORANGE", enableorange)){
162 fprintf(stderr, "Cannot read ENABLED_ORANGE\n");
163 exit(1);
164 }
165 freekeyvalues(kv);
166
167 // read interface settings
168
169 // details for the red int
170 memset(redif, 0, STRING_SIZE);
171 if ((ifacefile = fopen(CONFIG_ROOT "/red/iface", "r")))
172 {
173 if (fgets(redif, STRING_SIZE, ifacefile))
174 {
175 if (redif[strlen(redif) - 1] == '\n')
176 redif[strlen(redif) - 1] = '\0';
177 }
178 fclose (ifacefile);
179 ifacefile = NULL;
180
181 if (!VALID_DEVICE(redif))
182 {
183 memset(redif, 0, STRING_SIZE);
184 }
185 }
186
187 kv=initkeyvalues();
188 if (!readkeyvalues(kv, CONFIG_ROOT "/ethernet/settings"))
189 {
190 fprintf(stderr, "Cannot read ethernet settings\n");
191 exit(1);
192 }
193
194 if (strcmp(enableblue, "on")==0){
195 if (!findkey(kv, "BLUE_DEV", blueif)){
196 fprintf(stderr, "Cannot read BLUE_DEV\n");
197 exit(1);
198 }
199 }
200 if (strcmp(enableorange, "on")==0){
201 if (!findkey(kv, "ORANGE_DEV", orangeif)){
202 fprintf(stderr, "Cannot read ORNAGE_DEV\n");
203 exit(1);
204 }
205 }
206 freekeyvalues(kv);
207}
208
209void executeCommand(char *command) {
210#ifdef ovpndebug
211 printf(strncat(command, "\n", 2));
212#endif
213 safe_system(strncat(command, " >/dev/null 2>&1", 17));
214}
215
216void setChainRules(char *chain, char *interface, char *protocol, char *port)
217{
218 char str[STRING_SIZE];
07081137 219
6e13d0a5
MT
220 sprintf(str, "/sbin/iptables -A %sINPUT -i %s -p %s --dport %s -j ACCEPT", chain, interface, protocol, port);
221 executeCommand(str);
222 sprintf(str, "/sbin/iptables -A %sINPUT -i tun+ -j ACCEPT", chain);
223 executeCommand(str);
224 sprintf(str, "/sbin/iptables -A %sFORWARD -i tun+ -j ACCEPT", chain);
225 executeCommand(str);
226}
227
228void flushChain(char *chain) {
229 char str[STRING_SIZE];
230
231 sprintf(str, "/sbin/iptables -F %sINPUT", chain);
232 executeCommand(str);
233 sprintf(str, "/sbin/iptables -F %sFORWARD", chain);
234 executeCommand(str);
235 safe_system(str);
236}
237
238void deleteChainReference(char *chain) {
239 char str[STRING_SIZE];
240
241 sprintf(str, "/sbin/iptables -D INPUT -j %sINPUT", chain);
242 executeCommand(str);
243 safe_system(str);
244 sprintf(str, "/sbin/iptables -D FORWARD -j %sFORWARD", chain);
245 executeCommand(str);
246 safe_system(str);
247}
248
249void deleteChain(char *chain) {
250 char str[STRING_SIZE];
251
252 sprintf(str, "/sbin/iptables -X %sINPUT", chain);
253 executeCommand(str);
254 sprintf(str, "/sbin/iptables -X %sFORWARD", chain);
255 executeCommand(str);
256}
257
258void deleteAllChains(void) {
259 // not an elegant solution, but to avoid timing problems with undeleted chain references
260 deleteChainReference(OVPNRED);
261 deleteChainReference(OVPNBLUE);
262 deleteChainReference(OVPNORANGE);
263 flushChain(OVPNRED);
264 flushChain(OVPNBLUE);
265 flushChain(OVPNORANGE);
266 deleteChain(OVPNRED);
267 deleteChain(OVPNBLUE);
268 deleteChain(OVPNORANGE);
269}
270
271void createChainReference(char *chain) {
272 char str[STRING_SIZE];
273 sprintf(str, "/sbin/iptables -I INPUT %s -j %sINPUT", "14", chain);
274 executeCommand(str);
275 sprintf(str, "/sbin/iptables -I FORWARD %s -j %sFORWARD", "12", chain);
276 executeCommand(str);
277}
278
279void createChain(char *chain) {
280 char str[STRING_SIZE];
281 sprintf(str, "/sbin/iptables -N %sINPUT", chain);
282 executeCommand(str);
283 sprintf(str, "/sbin/iptables -N %sFORWARD", chain);
284 executeCommand(str);
285}
286
287void createAllChains(void) {
858d8d90
MT
288 // create chain and chain references
289 if (!strcmp(enableorange, "on")) {
290 if (strlen(orangeif)) {
291 createChain(OVPNORANGE);
292 createChainReference(OVPNORANGE);
293 } else {
294 fprintf(stderr, "OpenVPN enabled on orange but no orange interface found\n");
295 //exit(1);
6e13d0a5 296 }
858d8d90
MT
297 }
298
299 if (!strcmp(enableblue, "on")) {
300 if (strlen(blueif)) {
301 createChain(OVPNBLUE);
302 createChainReference(OVPNBLUE);
303 } else {
304 fprintf(stderr, "OpenVPN enabled on blue but no blue interface found\n");
305 //exit(1);
6e13d0a5 306 }
858d8d90
MT
307 }
308
309 if (!strcmp(enablered, "on")) {
310 if (strlen(redif)) {
311 createChain(OVPNRED);
312 createChainReference(OVPNRED);
313 } else {
314 fprintf(stderr, "OpenVPN enabled on red but no red interface found\n");
315 //exit(1);
6e13d0a5
MT
316 }
317 }
318}
319
320void setFirewallRules(void) {
321 char protocol[STRING_SIZE] = "";
322 char dport[STRING_SIZE] = "";
323 char dovpnip[STRING_SIZE] = "";
324
6e13d0a5
MT
325 kv = initkeyvalues();
326 if (!readkeyvalues(kv, CONFIG_ROOT "/ovpn/settings"))
327 {
328 fprintf(stderr, "Cannot read ovpn settings\n");
329 exit(1);
330 }
331
332 /* we got one device, so lets proceed further */
333 if (!findkey(kv, "DDEST_PORT", dport)){
334 fprintf(stderr, "Cannot read DDEST_PORT\n");
335 exit(1);
336 }
337
338 if (!findkey(kv, "DPROTOCOL", protocol)){
339 fprintf(stderr, "Cannot read DPROTOCOL\n");
340 exit(1);
341 }
342
343 if (!findkey(kv, "VPN_IP", dovpnip)){
344 fprintf(stderr, "Cannot read VPN_IP\n");
345// exit(1); step further as we don't need an ip
346 }
347 freekeyvalues(kv);
348
07081137
MT
349 // Flush all chains.
350 flushChain(OVPNRED);
351 flushChain(OVPNBLUE);
352 flushChain(OVPNORANGE);
353
6e13d0a5
MT
354 // set firewall rules
355 if (!strcmp(enablered, "on") && strlen(redif))
356 setChainRules(OVPNRED, redif, protocol, dport);
357 if (!strcmp(enableblue, "on") && strlen(blueif))
358 setChainRules(OVPNBLUE, blueif, protocol, dport);
359 if (!strcmp(enableorange, "on") && strlen(orangeif))
360 setChainRules(OVPNORANGE, orangeif, protocol, dport);
6925b8ef 361
91a0a221
MT
362 // read connection configuration
363 connection *conn = getConnections();
364
6925b8ef 365 // set firewall rules for n2n connections
91a0a221 366 char command[STRING_SIZE];
7d653d51 367 while (conn != NULL) {
91a0a221
MT
368 if (strcmp(conn->type, "net") == 0) {
369 sprintf(command, "/sbin/iptables -A %sINPUT -i %s -p %s --dport %d -j ACCEPT",
370 OVPNRED, redif, conn->proto, conn->port);
371 executeCommand(command);
372 }
373
6925b8ef
AF
374 conn = conn->next;
375 }
6e13d0a5
MT
376}
377
378void stopDaemon(void) {
379 char command[STRING_SIZE];
380
2bcff894 381 int pid = readPidFile("/var/run/openvpn.pid");
80ca8bd0 382 if (!pid > 0) {
2bcff894
MT
383 exit(1);
384 }
385
386 fprintf(stderr, "Killing PID %d.\n", pid);
387 kill(pid, SIGTERM);
388
6e13d0a5
MT
389 snprintf(command, STRING_SIZE - 1, "/bin/rm -f /var/run/openvpn.pid");
390 executeCommand(command);
391}
392
393void startDaemon(void) {
394 char command[STRING_SIZE];
395
396 if (!((strcmp(enablered, "on")==0) || (strcmp(enableblue, "on")==0) || (strcmp(enableorange, "on")==0))){
397 fprintf(stderr, "OpenVPN is not enabled on any interface\n");
398 exit(1);
399 } else {
7d3af7f7
MT
400 snprintf(command, STRING_SIZE-1, "/sbin/modprobe tun");
401 executeCommand(command);
072cd997 402 snprintf(command, STRING_SIZE-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
6e13d0a5
MT
403 executeCommand(command);
404 }
405}
406
6925b8ef
AF
407void startNet2Net(char *name) {
408 connection *conn = NULL;
409 connection *conn_iter;
410
411 conn_iter = getConnections();
412
413 while (conn_iter) {
91a0a221 414 if ((strcmp(conn_iter->type, "net") == 0) && (strcmp(conn_iter->name, name) == 0)) {
6925b8ef
AF
415 conn = conn_iter;
416 break;
417 }
418 conn_iter = conn_iter->next;
419 }
420
421 if (conn == NULL) {
422 fprintf(stderr, "Connection not found.\n");
423 exit(1);
424 }
425
39877197
MT
426 char configfile[STRING_SIZE];
427 snprintf(configfile, STRING_SIZE - 1, CONFIG_ROOT "/ovpn/n2nconf/%s/%s.conf",
428 conn->name, conn->name);
429
430 FILE *fp = fopen(configfile, "r");
431 if (fp == NULL) {
432 fprintf(stderr, "Could not find configuration file for connection '%s' at '%s'.\n",
433 conn->name, configfile);
434 exit(2);
435 }
436 fclose(fp);
437
07081137
MT
438 // Make sure all firewall rules are up to date.
439 setFirewallRules();
440
6925b8ef 441 char command[STRING_SIZE];
81a789d9
MT
442 snprintf(command, STRING_SIZE-1, "/sbin/modprobe tun");
443 executeCommand(command);
444 snprintf(command, STRING_SIZE-1, "/usr/sbin/openvpn --config %s", configfile);
6925b8ef
AF
445 executeCommand(command);
446}
447
39877197
MT
448void killNet2Net(char *name) {
449 connection *conn = NULL;
450 connection *conn_iter;
451
452 conn_iter = getConnections();
453
454 while (conn_iter) {
455 if (strcmp(conn_iter->name, name) == 0) {
456 conn = conn_iter;
457 break;
458 }
459 conn_iter = conn_iter->next;
460 }
461
462 if (conn == NULL) {
463 fprintf(stderr, "Connection not found.\n");
464 exit(1);
465 }
466
467 char pidfile[STRING_SIZE];
80ca8bd0 468 snprintf(pidfile, STRING_SIZE - 1, "/var/run/%sn2n.pid", conn->name);
39877197 469
2bcff894 470 int pid = readPidFile(pidfile);
80ca8bd0 471 if (!pid > 0) {
39877197
MT
472 exit(1);
473 }
474
39877197
MT
475 fprintf(stderr, "Killing PID %d.\n", pid);
476 kill(pid, SIGTERM);
477
d4c8b6be
MT
478 char command[STRING_SIZE];
479 snprintf(command, STRING_SIZE - 1, "/bin/rm -f %s", pidfile);
480 executeCommand(command);
481
39877197 482 exit(0);
6925b8ef
AF
483}
484
6e13d0a5
MT
485void displayopenvpn(void) {
486 char command[STRING_SIZE];
487
488 snprintf(command, STRING_SIZE - 1, "/bin/killall -sSIGUSR2 openvpn");
489 executeCommand(command);
490}
491
492int main(int argc, char *argv[]) {
493 if (!(initsetuid()))
494 exit(1);
495 if(argc < 2)
496 usage();
6925b8ef
AF
497
498 if(argc == 3) {
91a0a221
MT
499 ovpnInit();
500
6925b8ef
AF
501 if( (strcmp(argv[1], "-sn2n") == 0) || (strcmp(argv[1], "--start-net-2-net") == 0) ) {
502 startNet2Net(argv[2]);
503 return 0;
504 }
505 else if( (strcmp(argv[1], "-kn2n") == 0) || (strcmp(argv[1], "--kill-net-2-net") == 0) ) {
506 killNet2Net(argv[2]);
507 return 0;
508 } else {
509 usage();
510 return 1;
511 }
512 }
513 else if(argc == 2) {
6e13d0a5
MT
514 if( (strcmp(argv[1], "-k") == 0) || (strcmp(argv[1], "--kill") == 0) ) {
515 stopDaemon();
516 return 0;
517 }
518 else if( (strcmp(argv[1], "-d") == 0) || (strcmp(argv[1], "--display") == 0) ) {
519 displayopenvpn();
520 return 0;
521 }
522 else if( (strcmp(argv[1], "-dcr") == 0) || (strcmp(argv[1], "--delete-chains-and-rules") == 0) ) {
523 deleteAllChains();
524 return 0;
525 }
526 else {
527 ovpnInit();
528
529 if( (strcmp(argv[1], "-s") == 0) || (strcmp(argv[1], "--start") == 0) ) {
530 deleteAllChains();
531 createAllChains();
532 setFirewallRules();
533 startDaemon();
534 return 0;
535 }
536 else if( (strcmp(argv[1], "-sdo") == 0) || (strcmp(argv[1], "--start-daemon-only") == 0) ) {
537 startDaemon();
538 return 0;
539 }
540 else if( (strcmp(argv[1], "-r") == 0) || (strcmp(argv[1], "--restart") == 0) ) {
541 stopDaemon();
542 deleteAllChains();
543 createAllChains();
544 setFirewallRules();
545 startDaemon();
546 return 0;
547 }
548 else if( (strcmp(argv[1], "-fwr") == 0) || (strcmp(argv[1], "--firewall-rules") == 0) ) {
549 deleteAllChains();
550 createAllChains();
551 setFirewallRules();
552 return 0;
553 }
554 else if( (strcmp(argv[1], "-ccr") == 0) || (strcmp(argv[1], "--create-chains-and-rules") == 0) ) {
555 createAllChains();
556 setFirewallRules();
557 return 0;
558 }
559 else {
560 usage();
561 return 0;
562 }
563 }
564 }
565 else {
566 usage();
567 return 0;
568 }
569return 0;
570}
571