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