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