Cisco VPN config files converter



Heya,

As I didn't fancy entering all this data by hand in GConf, and that I
realised I couldn't write Perl to save my life, I wrote this little C
program to parse .PCF files from the Cisco VPN Client, and feed the data
into GConf.

As I haven't done quite enough work on making sure the keynames, and
data that gets in GConf is sane, I didn't make it write to GConf
directly. If David fancies, I'll integrate this into his VPN properties
thingo as an import utility.

I couldn't quite get the VPN stuff to work yet (I didn't remember
setting a password for the keyring, especially as this install is 3 days
old).

$ gcc -Wall -o convert `pkg-config --libs --cflags glib-2.0
gnome-vfs-2.0` convert.c
$ ./convert -u my_vpn_user_name *.pcf > apply.sh
$ <check apply.sh for errors>
$ sh apply.sh

Gaze at your full VPN connections menu. Or send me your VPN config files
privately if something is broken.

Cheers

-- 
Bastien Nocera <hadess hadess net>
// gcc -Wall -o convert `pkg-config --libs --cflags glib-2.0 gnome-vfs-2.0` convert.c

#include <glib.h>
#include <libgnomevfs/gnome-vfs.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define GROUP_NAME "main"

GHashTable *table = NULL;

static void
help (const char *argv0)
{
	fprintf (stderr, "Usage: %s [-u <username>] <PCF files>\n", argv0);
	exit (1);
}

static char *get_without_suffix (const char *file)
{
	char *dot;

	dot = strstr (file, ".");
	if (dot == NULL)
		return NULL;
	if (strcmp (dot, ".pcf") != 0)
		return NULL;
	return g_strndup (file, dot - file);
}

/* Get the secret from http://www.unix-ag.uni-kl.de/~massar/bin/cisco-decode */
static char *
get_ipsec_secret (GKeyFile *keyfile)
{
	char *key, *url, *contents;
	int size;
	char *secret = NULL;

	secret = g_key_file_get_string (keyfile, GROUP_NAME, "GroupPwd", NULL);
	if (secret != NULL && *secret != '\0')
		return secret;
	g_free (secret);

	key = g_key_file_get_string (keyfile, GROUP_NAME, "enc_GroupPwd", NULL);
	if (key == NULL)
		return NULL;

	secret = g_strdup (g_hash_table_lookup (table, (gconstpointer) key));
	if (secret != NULL)
		return secret;

	//url = g_strdup ("file:///home/hadess/Desktop/cisco-config/test.html");
	url = g_strdup_printf ("http://www.unix-ag.uni-kl.de/~massar/bin/cisco-decode?enc=%s&.submit=decode%%21";, key);

	if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK)
		goto out;

	{
		char *beginning, *end;

		beginning = strstr (contents, "clear: ") + strlen ("clear: ");
		if (beginning == NULL)
			goto out;
		end = beginning;
		while (*end != '\n')
			end++;
		secret = g_strndup (beginning, end - beginning);
	}

	g_hash_table_insert (table, key, g_strdup (secret));

out:
	g_free (contents);
	g_free (url);

	return secret;
}

static void
convert (const char *file, const char *orig_user)
{
	GKeyFile *keyfile;
	GError *err = NULL;
	char *name, *username, *gateway_ip, *group_pass, *ipsec_secret, *desc;

	name = get_without_suffix (file);
	if (name == NULL) {
		fprintf (stderr, "Can't open file '%s' as a Cisco definition file: not ending in .pcf\n", file); 
		return;
	}

	keyfile = g_key_file_new ();
	if (g_key_file_load_from_file (keyfile, file, G_KEY_FILE_NONE, &err) == FALSE) {
		fprintf (stderr, "Can't open file '%s' as a Cisco definition file: %s\n", file, err->message);
		return;
	}

	if (orig_user == NULL) {
		username = g_key_file_get_string (keyfile, GROUP_NAME, "Username", NULL);
		if (username == NULL)
			username = g_strdup (g_get_user_name ());
	} else {
		username = g_strdup (orig_user);
	}

	desc = g_key_file_get_string (keyfile, GROUP_NAME, "Description", NULL);
	if (desc == NULL)
		desc = g_strdup (name);
	gateway_ip = g_key_file_get_string (keyfile, GROUP_NAME, "Host", NULL);
	group_pass = g_key_file_get_string (keyfile, GROUP_NAME, "GroupName", NULL);
	ipsec_secret = get_ipsec_secret (keyfile);

	g_key_file_free (keyfile);

	if (!gateway_ip || !group_pass || !ipsec_secret) {
		fprintf (stderr, "Can't use file '%s': some configuration items are missing\n", file);
	} else {
		g_print ("# Items for connection to %s\n", desc);
		g_print ("gconftool-2 --type string --set /system/networking/vpn_connections/%s/name \"%s\"\n", name, desc);
		g_print ("gconftool-2 --type string --set /system/networking/vpn_connections/%s/service_name %s\n", name, "org.freedesktop.vpnc");
		g_print ("gconftool-2 --type string --set /system/networking/vpn_connections/%s/user_name %s\n", name, username);
		g_print ("gconftool-2 --type string --set /system/networking/vpn_connections/%s/vpn_data \"IPSec gateway, %s, IPSec ID, %s, IPSec Secret, %s\"\n", name, gateway_ip, group_pass, ipsec_secret);
		g_print ("\n");
	}

	g_free (name);
	g_free (username);
	g_free (desc);
	g_free (gateway_ip);
	g_free (group_pass);
	g_free (ipsec_secret);
}

int main (int argc, char **argv)
{
	GList *list = NULL, *l;
	const char *username = NULL;
	int i;

	gnome_vfs_init ();

	table = g_hash_table_new (g_str_hash, g_str_equal);

	if (argc == 1) {
		help (argv[0]);
	}

	/* Argument parsing */
	for (i = 1; i < argc; i++) {
		if (strcmp (argv[i], "-u") == 0) {
			i++;
			if (i >= argc)
				help(argv[0]);
			username = argv[i];
			continue;
		}
		list = g_list_append (list, argv[i]);
	}

	if (list == NULL)
		help (argv[0]);

	for (l = list; l; l = l->next) {
		char *file = l->data;
		if (g_file_test (file, G_FILE_TEST_IS_REGULAR) == FALSE) {
			fprintf (stderr, "'%s' doesn't exist, ignoring\n", file);
			list = g_list_remove (list, l->data);
		}
		convert (file, username);
	}

	return 0;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]