Files
bpfire/src/misc-progs/ipsecctrl.c

333 lines
8.5 KiB
C

/*
*
* File originally from the Smoothwall project
* (c) 2001 Smoothwall Team
*
* $Id: ipsecctrl.c,v 1.5.2.14 2005/05/15 12:58:28 rkerr Exp $
*
*/
#include "libsmooth.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "setuid.h"
void usage() {
fprintf (stderr, "Usage:\n");
fprintf (stderr, "\tipsecctrl S [connectionkey]\n");
fprintf (stderr, "\tipsecctrl D [connectionkey]\n");
fprintf (stderr, "\tipsecctrl R\n");
fprintf (stderr, "\t\tS : Start/Restart Connection\n");
fprintf (stderr, "\t\tD : Stop Connection\n");
fprintf (stderr, "\t\tR : Reload Certificates and Secrets\n");
}
void loadalgmodules() {
safe_system("/sbin/modprobe ipsec_3des");
safe_system("/sbin/modprobe ipsec_aes");
safe_system("/sbin/modprobe ipsec_blowfish");
safe_system("/sbin/modprobe ipsec_md5");
safe_system("/sbin/modprobe ipsec_serpent");
safe_system("/sbin/modprobe ipsec_sha1");
safe_system("/sbin/modprobe ipsec_sha2");
safe_system("/sbin/modprobe ipsec_twofish");
}
void ipsecrules(char *chain, char *interface)
{
char str[STRING_SIZE];
sprintf(str, "/sbin/iptables -A %s -p 47 -i %s -j ACCEPT", chain, interface);
safe_system(str);
sprintf(str, "/sbin/iptables -A %s -p 50 -i %s -j ACCEPT", chain, interface);
safe_system(str);
sprintf(str, "/sbin/iptables -A %s -p 51 -i %s -j ACCEPT", chain, interface);
safe_system(str);
sprintf(str, "/sbin/iptables -A %s -p udp -i %s --sport 500 --dport 500 -j ACCEPT", chain, interface);
safe_system(str);
sprintf(str, "/sbin/iptables -A %s -p udp -i %s --dport 4500 -j ACCEPT", chain, interface);
safe_system(str);
}
void addaliasinterfaces(char *configtype, char *redtype, char *redif, char *enablered, char*enableblue)
{
FILE *file = NULL;
char s[STRING_SIZE];
char *sptr;
char *aliasip=NULL;
char *enabled=NULL;
char *comment=NULL;
int count=0;
int alias=0;
int add=0;
if ( strcmp(enablered, "on") == 0 )
add += 1;
if ( strcmp(enableblue, "on") == 0 )
add += 1;
/* Check for CONFIG_TYPE=2 or 3 i.e. RED ethernet present. If not,
* exit gracefully. This is not an error... */
if (!((strcmp(configtype, "2")==0) || (strcmp(configtype, "3")==0) || (strcmp(configtype, "6")==0) || (strcmp(configtype, "7")==0)))
return;
/* Now check the RED_TYPE - aliases only work with STATIC. */
if (!(strcmp(redtype, "STATIC")==0))
return;
/* Now set up the new aliases from the config file */
if (!(file = fopen(CONFIG_ROOT "/ethernet/aliases", "r")))
{
fprintf(stderr, "Unable to open aliases configuration file\n");
return;
}
while (fgets(s, STRING_SIZE, file) != NULL && (add+alias) < 16)
{
if (s[strlen(s) - 1] == '\n')
s[strlen(s) - 1] = '\0';
sptr = strtok(s, ",");
count = 0;
aliasip = NULL;
enabled = NULL;
comment = NULL;
while (sptr)
{
if (count == 0)
aliasip = sptr;
if (count == 1)
enabled = sptr;
else
comment = sptr;
count++;
sptr = strtok(NULL, ",");
}
if (!(aliasip && enabled))
continue;
if (!VALID_IP(aliasip))
{
fprintf(stderr, "Bad alias : %s\n", aliasip);
return;
}
if (strcmp(enabled, "on") == 0)
{
memset(s, 0, STRING_SIZE);
snprintf(s, STRING_SIZE-1, "/usr/sbin/ipsec tncfg --attach --virtual ipsec%d --physical %s:%d >/dev/null", alias+add, redif, alias);
safe_system(s);
alias++;
}
}
}
int main(int argc, char *argv[]) {
int count;
char s[STRING_SIZE];
char configtype[STRING_SIZE];
char redtype[STRING_SIZE] = "";
char command[STRING_SIZE];
char *result;
char *key;
char *enabled;
char *name;
char *type;
char *running;
FILE *file = NULL;
struct keyvalue *kv = NULL;
char enablered[STRING_SIZE] = "off";
char enableblue[STRING_SIZE] = "off";
char redif[STRING_SIZE] = "";;
char blueif[STRING_SIZE] = "";
FILE *ifacefile = NULL;
if (!(initsetuid()))
exit(1);
if (argc < 2) {
usage();
exit(1);
}
/* FIXME: workaround for pclose() issue - still no real idea why
* this is happening */
signal(SIGCHLD, SIG_DFL);
/* Init the keyvalue structure */
kv=initkeyvalues();
/* Read in the current values */
if (!readkeyvalues(kv, CONFIG_ROOT "/vpn/settings"))
{
fprintf(stderr, "Cannot read vpn settings\n");
exit(1);
}
findkey(kv, "ENABLED", enablered);
findkey(kv, "ENABLED_BLUE", enableblue);
freekeyvalues(kv);
kv=initkeyvalues();
if (!readkeyvalues(kv, CONFIG_ROOT "/ethernet/settings"))
{
fprintf(stderr, "Cannot read ethernet settings\n");
exit(1);
}
if (!findkey(kv, "CONFIG_TYPE", configtype))
{
fprintf(stderr, "Cannot read CONFIG_TYPE\n");
exit(1);
}
findkey(kv, "RED_TYPE", redtype);
findkey(kv, "BLUE_DEV", blueif);
freekeyvalues(kv);
memset(redif, 0, STRING_SIZE);
if ((ifacefile = fopen(CONFIG_ROOT "/red/iface", "r")))
{
if (fgets(redif, STRING_SIZE, ifacefile))
{
if (redif[strlen(redif) - 1] == '\n')
redif[strlen(redif) - 1] = '\0';
}
fclose (ifacefile);
ifacefile = NULL;
if (!VALID_DEVICE(redif))
{
memset(redif, 0, STRING_SIZE);
}
}
safe_system("/sbin/iptables -F IPSECRED");
if (!strcmp(enablered, "on") && strlen(redif)) {
ipsecrules("IPSECRED", redif);
}
safe_system("/sbin/iptables -F IPSECBLUE");
if (!strcmp(enableblue, "on")) {
if (VALID_DEVICE(blueif))
ipsecrules("IPSECBLUE", blueif);
else
{
fprintf(stderr, "IPSec enabled on blue but blue interface is invalid or not found\n");
exit(1);
}
}
/* Only shutdown pluto if it really is running */
if (argc == 2) {
if (strcmp(argv[1], "D") == 0) {
int fd;
/* Get pluto pid */
if ((fd = open("/var/run/pluto.pid", O_RDONLY)) != -1) {
safe_system("/etc/rc.d/ipsec stop 2> /dev/null >/dev/null");
close(fd);
}
}
}
if ((strcmp(enablered, "on") || !strlen(redif)) && strcmp(enableblue, "on"))
exit(0);
if (argc == 2) {
if (strcmp(argv[1], "S") == 0) {
loadalgmodules();
safe_system("/usr/sbin/ipsec tncfg --clear >/dev/null");
safe_system("/etc/rc.d/ipsec restart >/dev/null");
addaliasinterfaces(configtype, redtype, redif, enablered, enableblue);
} else if (strcmp(argv[1], "R") == 0) {
safe_system("/usr/sbin/ipsec auto --rereadall");
} else {
fprintf(stderr, "Bad arg\n");
usage();
exit(1);
}
} else if (strspn(argv[2], NUMBERS) == strlen(argv[2])) {
if (!(file = fopen(CONFIG_ROOT "/vpn/config", "r"))) {
fprintf(stderr, "Couldn't open vpn settings file");
exit(1);
}
while (fgets(s, STRING_SIZE, file) != NULL) {
if (s[strlen(s) - 1] == '\n')
s[strlen(s) - 1] = '\0';
running = strdup (s);
result = strsep(&running, ",");
count = 0;
key = NULL;
name = NULL;
enabled = NULL;
type = NULL;
while (result) {
if (count == 0)
key = result;
if (count == 1)
enabled = result;
if (count == 2)
name = result;
if (count == 4)
type = result;
count++;
result = strsep(&running, ",");
}
if (strcmp(key, argv[2]) != 0)
continue;
if (!(name && enabled))
continue;
if (strspn(name, LETTERS_NUMBERS) != strlen(name)) {
fprintf(stderr, "Bad connection name: %s\n", name);
goto EXIT;
}
if (! (strcmp(type, "host") == 0 || strcmp(type, "net") == 0)) {
fprintf(stderr, "Bad connection type: %s\n", type);
goto EXIT;
}
if (strcmp(argv[1], "S") == 0 && strcmp(enabled, "on") == 0) {
safe_system("/usr/sbin/ipsec auto --rereadsecrets >/dev/null");
memset(command, 0, STRING_SIZE);
snprintf(command, STRING_SIZE - 1,
"/usr/sbin/ipsec auto --replace %s >/dev/null", name);
safe_system(command);
if (strcmp(type, "net") == 0) {
memset(command, 0, STRING_SIZE);
snprintf(command, STRING_SIZE - 1,
"/usr/sbin/ipsec auto --asynchronous --up %s >/dev/null", name);
safe_system(command);
}
} else if (strcmp(argv[1], "D") == 0) {
safe_system("/usr/sbin/ipsec auto --rereadsecrets >/dev/null");
memset(command, 0, STRING_SIZE);
snprintf(command, STRING_SIZE - 1,
"/usr/sbin/ipsec auto --down %s >/dev/null", name);
safe_system(command);
memset(command, 0, STRING_SIZE);
snprintf(command, STRING_SIZE - 1,
"/usr/sbin/ipsec auto --delete %s >/dev/null", name);
safe_system(command);
}
}
} else {
fprintf(stderr, "Bad arg\n");
usage();
exit(1);
}
EXIT:
if (file)
fclose(file);
return 0;
}