network-manager-vpnc r2 - in trunk: . auth-dialog common-gnome doc po properties src



Author: dcbw
Date: Thu Dec 11 19:45:12 2008
New Revision: 2
URL: http://svn.gnome.org/viewvc/network-manager-vpnc?rev=2&view=rev

Log:
2008-12-11  Dan Williams  <dcbw redhat com>

	* Split into separate repository



Added:
   trunk/AUTHORS
   trunk/ChangeLog
   trunk/MAINTAINERS
   trunk/Makefile.am
   trunk/NEWS
   trunk/README
   trunk/auth-dialog/
   trunk/auth-dialog/.cvsignore
   trunk/auth-dialog/Makefile.am
   trunk/auth-dialog/gnome-two-password-dialog.c
   trunk/auth-dialog/gnome-two-password-dialog.h
   trunk/auth-dialog/main.c
   trunk/autogen.sh   (contents, props changed)
   trunk/common-gnome/
   trunk/common-gnome/Makefile.am
   trunk/common-gnome/keyring-helpers.c
   trunk/common-gnome/keyring-helpers.h
   trunk/configure.in
   trunk/doc/
   trunk/doc/example-vpnc-system-wide-connection.sh   (contents, props changed)
   trunk/gnome-mime-application-x-cisco-vpn-settings.png   (contents, props changed)
   trunk/nm-vpnc-service.conf
   trunk/nm-vpnc-service.name.in
   trunk/nm-vpnc.desktop.in
   trunk/po/
   trunk/po/.cvsignore
   trunk/po/ChangeLog
   trunk/po/LINGUAS
   trunk/po/POTFILES.in
   trunk/po/ar.po
   trunk/po/bg.po
   trunk/po/ca.po
   trunk/po/cs.po
   trunk/po/da.po
   trunk/po/de.po
   trunk/po/dz.po
   trunk/po/el.po
   trunk/po/en_GB.po
   trunk/po/es.po
   trunk/po/et.po
   trunk/po/eu.po
   trunk/po/fi.po
   trunk/po/fr.po
   trunk/po/gl.po
   trunk/po/hu.po
   trunk/po/it.po
   trunk/po/ja.po
   trunk/po/ka.po
   trunk/po/ko.po
   trunk/po/lt.po
   trunk/po/mk.po
   trunk/po/nb.po
   trunk/po/nl.po
   trunk/po/pa.po
   trunk/po/pl.po
   trunk/po/pt.po
   trunk/po/pt_BR.po
   trunk/po/ru.po
   trunk/po/sl.po
   trunk/po/sv.po
   trunk/po/th.po
   trunk/po/uk.po
   trunk/po/vi.po
   trunk/po/zh_CN.po
   trunk/po/zh_HK.po
   trunk/po/zh_TW.po
   trunk/properties/
   trunk/properties/.cvsignore
   trunk/properties/Makefile.am
   trunk/properties/nm-vpnc-dialog.glade
   trunk/properties/nm-vpnc.c
   trunk/properties/nm-vpnc.h
   trunk/properties/pcf-file.c
   trunk/properties/pcf-file.h
   trunk/src/
   trunk/src/.cvsignore
   trunk/src/Makefile.am
   trunk/src/nm-vpnc-service-vpnc-helper.c
   trunk/src/nm-vpnc-service.c
   trunk/src/nm-vpnc-service.h

Added: trunk/AUTHORS
==============================================================================
--- (empty file)
+++ trunk/AUTHORS	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,3 @@
+Dan Williams <dcbw redhat com>
+David Zeuthen <davidz redhat com>
+

Added: trunk/MAINTAINERS
==============================================================================
--- (empty file)
+++ trunk/MAINTAINERS	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,4 @@
+Dan Williams
+E-mail: dcbw redhat com
+Userid: dcbw
+

Added: trunk/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/Makefile.am	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,37 @@
+AUTOMAKE_OPTIONS = foreign
+
+if WITH_GNOME
+SUBDIRS = src common-gnome auth-dialog properties po
+else
+SUBDIRS = src
+endif
+
+dbusservicedir = $(sysconfdir)/dbus-1/system.d
+dbusservice_DATA = nm-vpnc-service.conf
+
+nmvpnservicedir = $(sysconfdir)/NetworkManager/VPN
+nmvpnservice_DATA = nm-vpnc-service.name
+
+if WITH_GNOME
+desktopdir = $(datadir)/applications
+desktop_in_files = nm-vpnc.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+ INTLTOOL_DESKTOP_RULE@
+
+icondir = $(datadir)/icons/hicolor/48x48/apps
+icon_DATA = gnome-mime-application-x-cisco-vpn-settings.png
+endif
+
+nm-vpnc-service.name: $(srcdir)/nm-vpnc-service.name.in
+	sed -e 's|[ ]LIBEXECDIR[@]|$(libexecdir)|g' $< >$@
+
+EXTRA_DIST = nm-vpnc-service.name.in \
+             $(dbusservice_DATA)  \
+             $(desktop_in_files)  \
+             $(icon_DATA)         \
+             intltool-extract.in  \
+             intltool-merge.in    \
+             intltool-update.in
+
+CLEANFILES = $(nmvpnservice_DATA) $(desktop_DATA) *~
+DISTCLEANFILES = intltool-extract intltool-merge intltool-update

Added: trunk/NEWS
==============================================================================

Added: trunk/README
==============================================================================

Added: trunk/auth-dialog/.cvsignore
==============================================================================
--- (empty file)
+++ trunk/auth-dialog/.cvsignore	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,3 @@
+Makefile.in
+Makefile
+nm-vpnc-auth-dialog

Added: trunk/auth-dialog/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/auth-dialog/Makefile.am	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,32 @@
+INCLUDES = -I${top_srcdir}
+
+libexec_PROGRAMS = nm-vpnc-auth-dialog
+
+nm_vpnc_auth_dialog_CPPFLAGS = \
+	$(NM_UTILS_CFLAGS) \
+	$(GTHREAD_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(GCONF_CFLAGS) \
+	$(GNOMEKEYRING_CFLAGS) \
+	-DICONDIR=\""$(datadir)/pixmaps"\" \
+	-DGLADEDIR=\""$(gladedir)"\" \
+	-DBINDIR=\""$(bindir)"\" \
+	-DDBUS_API_SUBJECT_TO_CHANGE \
+	-DG_DISABLE_DEPRECATED \
+	-DGDK_DISABLE_DEPRECATED \
+	-DGNOME_DISABLE_DEPRECATED \
+	-DGNOMELOCALEDIR=\"$(datadir)/locale\" \
+	-DVERSION=\"$(VERSION)\"
+
+nm_vpnc_auth_dialog_SOURCES = \
+	main.c \
+	gnome-two-password-dialog.c \
+	gnome-two-password-dialog.h
+
+nm_vpnc_auth_dialog_LDADD = \
+	$(GTK_LIBS) \
+	$(GCONF_LIBS) \
+	$(top_builddir)/common-gnome/libnm-vpnc-common-gnome.la
+
+CLEANFILES = *~
+

Added: trunk/auth-dialog/gnome-two-password-dialog.c
==============================================================================
--- (empty file)
+++ trunk/auth-dialog/gnome-two-password-dialog.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,523 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* gnome-password-dialog.c - A use password prompting dialog widget.
+
+   Copyright (C) 1999, 2000 Eazel, Inc.
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the ree Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Authors: Ramiro Estrugo <ramiro eazel com>
+*/
+
+#include <config.h>
+#include "gnome-two-password-dialog.h"
+#include <gtk/gtkbox.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkradiobutton.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkcombobox.h>
+#include <gnome-keyring-memory.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "src/nm-vpnc-service.h"
+
+G_DEFINE_TYPE (VpnPasswordDialog, vpn_password_dialog, GTK_TYPE_DIALOG)
+
+#define VPN_PASSWORD_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                            VPN_TYPE_PASSWORD_DIALOG, \
+                                            VpnPasswordDialogPrivate))
+
+typedef struct {
+	/* Attributes */
+	gboolean show_password;
+	gboolean show_password_secondary;
+	
+	/* TODO: */
+	gboolean remember;
+	char *remember_label_text;
+
+	/* Internal widgetry and flags */
+	GtkWidget *password_entry;
+	GtkWidget *password_entry_secondary;
+	GtkWidget *show_passwords_checkbox;
+
+	GtkWidget *table_alignment;
+	GtkWidget *table;
+	GtkSizeGroup *group;
+	
+	GtkWidget *remember_session_button;
+	GtkWidget *remember_forever_button;
+
+	char *secondary_password_label;
+} VpnPasswordDialogPrivate;
+
+/* VpnPasswordDialogClass methods */
+static void vpn_password_dialog_class_init (VpnPasswordDialogClass *password_dialog_class);
+static void vpn_password_dialog_init       (VpnPasswordDialog      *password_dialog);
+
+/* GtkDialog callbacks */
+static void dialog_show_callback (GtkWidget *widget, gpointer callback_data);
+static void dialog_close_callback (GtkWidget *widget, gpointer callback_data);
+
+static void
+finalize (GObject *object)
+{
+	VpnPasswordDialogPrivate *priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (object);
+	
+	g_object_unref (priv->password_entry);
+	g_object_unref (priv->password_entry_secondary);
+	g_object_unref (priv->group);
+
+	g_free (priv->remember_label_text);
+	g_free (priv->secondary_password_label);
+
+	G_OBJECT_CLASS (vpn_password_dialog_parent_class)->finalize (object);
+}
+
+static void
+vpn_password_dialog_class_init (VpnPasswordDialogClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (VpnPasswordDialogPrivate));
+
+	object_class->finalize = finalize;
+}
+
+static void
+vpn_password_dialog_init (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	priv->show_password = TRUE;
+	priv->show_password_secondary = TRUE;
+	priv->secondary_password_label = g_strdup ( _("_Secondary Password:") );
+}
+
+/* GtkDialog callbacks */
+static void
+dialog_show_callback (GtkWidget *widget, gpointer callback_data)
+{
+	VpnPasswordDialog *dialog = VPN_PASSWORD_DIALOG (callback_data);
+	VpnPasswordDialogPrivate *priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	if (GTK_WIDGET_VISIBLE (priv->password_entry))
+		gtk_widget_grab_focus (priv->password_entry);
+	else if (GTK_WIDGET_VISIBLE (priv->password_entry_secondary))
+		gtk_widget_grab_focus (priv->password_entry_secondary);
+}
+
+static void
+dialog_close_callback (GtkWidget *widget, gpointer callback_data)
+{
+	gtk_widget_hide (widget);
+}
+
+static void
+add_row (GtkWidget *table, int row, const char *label_text, GtkWidget *entry)
+{
+	GtkWidget *label;
+
+	label = gtk_label_new_with_mnemonic (label_text);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+	gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, row, row + 1);
+	gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, row, row + 1);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+}
+
+static void
+remove_child (GtkWidget *child, GtkWidget *table)
+{
+	gtk_container_remove (GTK_CONTAINER (table), child);
+}
+
+static void
+add_table_rows (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	int row;
+	int offset = 0;
+
+	gtk_alignment_set_padding (GTK_ALIGNMENT (priv->table_alignment), 0, 0, offset, 0);
+
+	/* This will not kill the entries, since they are ref:ed */
+	gtk_container_foreach (GTK_CONTAINER (priv->table), (GtkCallback) remove_child, priv->table);
+	
+	row = 0;
+	if (priv->show_password)
+		add_row (priv->table, row++, _("_Password:"), priv->password_entry);
+	if (priv->show_password_secondary)
+		add_row (priv->table, row++, priv->secondary_password_label,  priv->password_entry_secondary);
+
+	gtk_table_attach_defaults (GTK_TABLE (priv->table), priv->show_passwords_checkbox, 1, 2, row, row + 1);
+
+	gtk_widget_show_all (priv->table);
+}
+
+static void
+show_passwords_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+	VpnPasswordDialog *dialog = VPN_PASSWORD_DIALOG (user_data);
+	VpnPasswordDialogPrivate *priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	gboolean visible;
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), visible);
+	gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry_secondary), visible);
+}
+
+/* Public VpnPasswordDialog methods */
+GtkWidget *
+vpn_password_dialog_new (const char *title,
+                         const char *message,
+                         const char *password)
+{
+	GtkWidget *dialog;
+	VpnPasswordDialogPrivate *priv;
+	GtkLabel *message_label;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	GtkWidget *main_vbox;
+	GtkWidget *dialog_icon;
+	GSList *group;
+
+	dialog = gtk_widget_new (VPN_TYPE_PASSWORD_DIALOG, NULL);
+	if (!dialog)
+		return NULL;
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), title);
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+	                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+	                        GTK_STOCK_OK, GTK_RESPONSE_OK,
+	                        NULL);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	/* Setup the dialog */
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2); /* 2 * 5 + 2 = 12 */
+	gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
+
+ 	gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+	g_signal_connect (dialog, "show",
+	                  G_CALLBACK (dialog_show_callback),
+	                  dialog);
+	g_signal_connect (dialog, "close",
+	                  G_CALLBACK (dialog_close_callback),
+	                  dialog);
+
+	/* The table that holds the captions */
+	priv->table_alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
+
+	priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	priv->table = gtk_table_new (4, 2, FALSE);
+	gtk_table_set_col_spacings (GTK_TABLE (priv->table), 12);
+	gtk_table_set_row_spacings (GTK_TABLE (priv->table), 6);
+	gtk_container_add (GTK_CONTAINER (priv->table_alignment), priv->table);
+
+	priv->password_entry = gtk_entry_new ();
+	priv->password_entry_secondary = gtk_entry_new ();
+
+	priv->show_passwords_checkbox = gtk_check_button_new_with_mnemonic (_("Sh_ow passwords"));
+
+	/* We want to hold on to these during the table rearrangement */
+#if GLIB_CHECK_VERSION (2, 10, 0)
+	g_object_ref_sink (priv->password_entry);
+	g_object_ref_sink (priv->password_entry_secondary);
+	g_object_ref_sink (priv->show_passwords_checkbox);
+#else
+	g_object_ref (priv->password_entry);
+	gtk_object_sink (GTK_OBJECT (priv->password_entry));
+
+	g_object_ref (priv->password_entry_secondary);
+	gtk_object_sink (GTK_OBJECT (priv->password_entry_secondary));
+
+	g_object_ref (priv->show_passwords_checkbox);
+	gtk_object_sink (GTK_OBJECT (priv->show_passwords_checkbox));
+#endif
+	
+	gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE);
+	gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry_secondary), FALSE);
+
+	g_signal_connect_swapped (priv->password_entry, "activate",
+	                          G_CALLBACK (gtk_window_activate_default),
+	                          dialog);
+	g_signal_connect_swapped (priv->password_entry_secondary, "activate",
+	                          G_CALLBACK (gtk_window_activate_default),
+	                          dialog);
+
+	g_signal_connect (priv->show_passwords_checkbox, "toggled",
+	                  G_CALLBACK (show_passwords_toggled_cb),
+	                  dialog);
+
+	add_table_rows (VPN_PASSWORD_DIALOG (dialog));
+
+	/* Adds some eye-candy to the dialog */
+	hbox = gtk_hbox_new (FALSE, 12);
+ 	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+	dialog_icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
+	gtk_misc_set_alignment (GTK_MISC (dialog_icon), 0.5, 0.0);
+	gtk_box_pack_start (GTK_BOX (hbox), dialog_icon, FALSE, FALSE, 0);
+
+	/* Fills the vbox */
+	main_vbox = gtk_vbox_new (FALSE, 18);
+
+	if (message) {
+		message_label = GTK_LABEL (gtk_label_new (message));
+		gtk_label_set_justify (message_label, GTK_JUSTIFY_LEFT);
+		gtk_label_set_line_wrap (message_label, TRUE);
+		gtk_size_group_add_widget (priv->group, GTK_WIDGET (message_label));
+		gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (message_label), FALSE, FALSE, 0);
+		gtk_size_group_add_widget (priv->group, priv->table_alignment);
+	}
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), priv->table_alignment, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), main_vbox, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+	gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
+
+	priv->remember_session_button = gtk_check_button_new_with_mnemonic (_("_Remember passwords for this session"));
+	priv->remember_forever_button = gtk_check_button_new_with_mnemonic (_("_Save passwords in keyring"));
+
+	gtk_box_pack_start (GTK_BOX (vbox), priv->remember_session_button, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), priv->remember_forever_button, FALSE, FALSE, 0);
+
+	vpn_password_dialog_set_password (VPN_PASSWORD_DIALOG (dialog), password);
+	
+	return GTK_WIDGET (dialog);
+}
+
+gboolean
+vpn_password_dialog_run_and_block (VpnPasswordDialog *dialog)
+{
+	gint button_clicked;
+
+	g_return_val_if_fail (dialog != NULL, FALSE);
+	g_return_val_if_fail (VPN_IS_PASSWORD_DIALOG (dialog), FALSE);
+
+	button_clicked = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_hide (GTK_WIDGET (dialog));
+
+	return button_clicked == GTK_RESPONSE_OK;
+}
+
+void
+vpn_password_dialog_set_password (VpnPasswordDialog	*dialog,
+                                  const char *password)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	gtk_entry_set_text (GTK_ENTRY (priv->password_entry), password ? password : "");
+}
+
+void
+vpn_password_dialog_set_password_secondary (VpnPasswordDialog *dialog,
+                                            const char *password_secondary)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	gtk_entry_set_text (GTK_ENTRY (priv->password_entry_secondary),
+	                    password_secondary ? password_secondary : "");
+}
+
+void
+vpn_password_dialog_set_show_password (VpnPasswordDialog *dialog, gboolean show)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (dialog != NULL);
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	show = !!show;
+	if (priv->show_password != show) {
+		priv->show_password = show;
+		add_table_rows (dialog);
+	}
+}
+
+void
+vpn_password_dialog_set_show_password_secondary (VpnPasswordDialog *dialog,
+                                                 gboolean show)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (dialog != NULL);
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	show = !!show;
+	if (priv->show_password_secondary != show) {
+		priv->show_password_secondary = show;
+		add_table_rows (dialog);
+	}
+}
+
+void
+vpn_password_dialog_focus_password (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (dialog != NULL);
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	if (priv->show_password)
+		gtk_widget_grab_focus (priv->password_entry);
+}
+
+void
+vpn_password_dialog_focus_password_secondary (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (dialog != NULL);
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	if (priv->show_password_secondary)
+		gtk_widget_grab_focus (priv->password_entry_secondary);
+}
+
+const char *
+vpn_password_dialog_get_password (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_val_if_fail (VPN_IS_PASSWORD_DIALOG (dialog), NULL);
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	return gtk_entry_get_text (GTK_ENTRY (priv->password_entry));
+}
+
+const char *
+vpn_password_dialog_get_password_secondary (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_val_if_fail (VPN_IS_PASSWORD_DIALOG (dialog), NULL);
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	return gtk_entry_get_text (GTK_ENTRY (priv->password_entry_secondary));
+}
+
+void
+vpn_password_dialog_set_show_remember (VpnPasswordDialog *dialog,
+                                       gboolean show_remember)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+	if (show_remember) {
+		gtk_widget_show (priv->remember_session_button);
+		gtk_widget_show (priv->remember_forever_button);
+	} else {
+		gtk_widget_hide (priv->remember_session_button);
+		gtk_widget_hide (priv->remember_forever_button);
+	}
+}
+
+void
+vpn_password_dialog_set_remember (VpnPasswordDialog *dialog,
+                                  VpnPasswordRemember remember)
+{
+	VpnPasswordDialogPrivate *priv;
+	gboolean session = FALSE, forever = FALSE;
+
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	if (remember == VPN_PASSWORD_REMEMBER_SESSION)
+		session = TRUE;
+	else if (remember == VPN_PASSWORD_REMEMBER_FOREVER)
+		forever = TRUE;
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->remember_session_button), session);
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->remember_forever_button), forever);
+}
+
+VpnPasswordRemember
+vpn_password_dialog_get_remember (VpnPasswordDialog *dialog)
+{
+	VpnPasswordDialogPrivate *priv;
+	gboolean session, forever;
+
+	g_return_val_if_fail (dialog != NULL, VPN_PASSWORD_REMEMBER_NOTHING);
+	g_return_val_if_fail (VPN_IS_PASSWORD_DIALOG (dialog), VPN_PASSWORD_REMEMBER_NOTHING);
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	session = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->remember_session_button));
+	forever = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->remember_forever_button));
+	if (forever)
+		return VPN_PASSWORD_REMEMBER_FOREVER;
+	else if (session)
+		return VPN_PASSWORD_REMEMBER_SESSION;
+
+	return VPN_PASSWORD_REMEMBER_NOTHING;
+}
+
+void vpn_password_dialog_set_password_secondary_label (VpnPasswordDialog *dialog,
+                                                       const char *label)
+{
+	VpnPasswordDialogPrivate *priv;
+
+	g_return_if_fail (dialog != NULL);
+	g_return_if_fail (VPN_IS_PASSWORD_DIALOG (dialog));
+
+	priv = VPN_PASSWORD_DIALOG_GET_PRIVATE (dialog);
+
+	g_free (priv->secondary_password_label);
+	priv->secondary_password_label = g_strdup (label);
+
+	if (priv->show_password_secondary)
+		add_table_rows (dialog);
+}
+

Added: trunk/auth-dialog/gnome-two-password-dialog.h
==============================================================================
--- (empty file)
+++ trunk/auth-dialog/gnome-two-password-dialog.h	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* gnome-two-password-dialog.h - A use password prompting dialog widget
+                                 asking for two passwords. Based of
+                                 gnome-password-dialog.[ch] from libgnomeui
+
+   Copyright (C) 1999, 2000 Eazel, Inc.
+   Copyright (C) 2005, Red Hat, Inc.
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Authors: Ramiro Estrugo <ramiro eazel com>
+*/
+
+#ifndef VPN_PASSWORD_DIALOG_H
+#define VPN_PASSWORD_DIALOG_H
+
+#include <gtk/gtkdialog.h>
+
+G_BEGIN_DECLS
+
+#define VPN_TYPE_PASSWORD_DIALOG            (vpn_password_dialog_get_type ())
+#define VPN_PASSWORD_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VPN_TYPE_PASSWORD_DIALOG, VpnPasswordDialog))
+#define VPN_PASSWORD_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), VPN_TYPE_PASSWORD_DIALOG, VpnPasswordDialogClass))
+#define VPN_IS_PASSWORD_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VPN_TYPE_PASSWORD_DIALOG))
+#define VPN_IS_PASSWORD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VPN_TYPE_PASSWORD_DIALOG))
+
+typedef struct VpnPasswordDialog        VpnPasswordDialog;
+typedef struct VpnPasswordDialogClass   VpnPasswordDialogClass;
+
+struct VpnPasswordDialog {
+	GtkDialog parent;
+};
+
+struct VpnPasswordDialogClass {
+	GtkDialogClass parent_class;
+};
+
+typedef enum {
+	VPN_PASSWORD_REMEMBER_NOTHING,
+	VPN_PASSWORD_REMEMBER_SESSION,
+	VPN_PASSWORD_REMEMBER_FOREVER
+} VpnPasswordRemember;
+
+
+GType      vpn_password_dialog_get_type              (void);
+GtkWidget* vpn_password_dialog_new                   (const char *title,
+                                                      const char *message,
+                                                      const char *password);
+
+gboolean   vpn_password_dialog_run_and_block         (VpnPasswordDialog *dialog);
+
+/* Attribute mutators */
+void vpn_password_dialog_set_show_password            (VpnPasswordDialog *dialog,
+                                                       gboolean show);
+void vpn_password_dialog_focus_password               (VpnPasswordDialog *dialog);
+void vpn_password_dialog_set_password                 (VpnPasswordDialog *dialog,
+                                                       const char *password);
+
+void vpn_password_dialog_set_show_password_secondary  (VpnPasswordDialog *dialog,
+                                                       gboolean show);
+void vpn_password_dialog_focus_password_secondary     (VpnPasswordDialog *dialog);
+void vpn_password_dialog_set_password_secondary       (VpnPasswordDialog *dialog,
+                                                       const char *password_secondary);
+void vpn_password_dialog_set_password_secondary_label (VpnPasswordDialog *dialog,
+                                                       const char *label);
+
+void vpn_password_dialog_set_show_remember            (VpnPasswordDialog *dialog,
+                                                       gboolean show_remember);
+void vpn_password_dialog_set_remember                 (VpnPasswordDialog *dialog,
+                                                       VpnPasswordRemember remember);
+VpnPasswordRemember vpn_password_dialog_get_remember  (VpnPasswordDialog *dialog);
+
+/* Attribute accessors */
+const char *vpn_password_dialog_get_password                (VpnPasswordDialog *dialog);
+
+const char *vpn_password_dialog_get_password_secondary      (VpnPasswordDialog *dialog);
+
+G_END_DECLS
+
+#endif /* VPN_PASSWORD_DIALOG_H */

Added: trunk/auth-dialog/main.c
==============================================================================
--- (empty file)
+++ trunk/auth-dialog/main.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,362 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2004 - 2008 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gnome-keyring.h>
+#include <gnome-keyring-memory.h>
+#include <gconf/gconf-client.h>
+
+#include <nm-setting-vpn.h>
+#include <nm-setting-connection.h>
+
+#include "common-gnome/keyring-helpers.h"
+#include "src/nm-vpnc-service.h"
+#include "gnome-two-password-dialog.h"
+
+#define KEYRING_UUID_TAG "connection-uuid"
+#define KEYRING_SN_TAG "setting-name"
+#define KEYRING_SK_TAG "setting-key"
+
+static char *
+find_connection_path (const char *vpn_uuid)
+{
+	char *key, *str, *connection_path = NULL;
+	GConfClient *gconf_client = NULL;
+	GSList *conf_list;
+	GSList *iter;
+
+	/* FIXME: This whole thing sucks: we should not go around poking gconf
+	   directly, but there's nothing that does it for us right now */
+
+	gconf_client = gconf_client_get_default ();
+
+	conf_list = gconf_client_all_dirs (gconf_client, "/system/networking/connections", NULL);
+	if (!conf_list)
+		return NULL;
+
+	for (iter = conf_list; iter; iter = iter->next) {
+		const char *path = (const char *) iter->data;
+
+		key = g_strdup_printf ("%s/%s/%s", 
+		                       path,
+		                       NM_SETTING_CONNECTION_SETTING_NAME,
+		                       NM_SETTING_CONNECTION_TYPE);
+		str = gconf_client_get_string (gconf_client, key, NULL);
+		g_free (key);
+
+		if (!str || strcmp (str, "vpn")) {
+			g_free (str);
+			continue;
+		}
+		g_free (str);
+
+		key = g_strdup_printf ("%s/%s/%s", 
+		                       path,
+		                       NM_SETTING_CONNECTION_SETTING_NAME,
+		                       NM_SETTING_CONNECTION_UUID);
+		str = gconf_client_get_string (gconf_client, key, NULL);
+		g_free (key);
+
+		if (!str || strcmp (str, vpn_uuid)) {
+			g_free (str);
+			continue;
+		}
+		g_free (str);
+
+		/* Woo, found the connection */
+		connection_path = g_strdup (path);
+		break;
+	}
+
+	g_slist_foreach (conf_list, (GFunc) g_free, NULL);
+	g_slist_free (conf_list);
+
+	g_object_unref (gconf_client);
+	return connection_path;
+}
+
+static gboolean
+get_secrets (const char *vpn_uuid,
+             const char *vpn_name,
+             gboolean retry,
+             char **upw,
+             const char *upw_type,
+             char **gpw,
+             const char *gpw_type)
+{
+	VpnPasswordDialog *dialog;
+	gboolean is_session = TRUE;
+	gboolean found_upw = FALSE;
+	gboolean found_gpw = FALSE;
+	char *prompt;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (vpn_uuid != NULL, FALSE);
+	g_return_val_if_fail (vpn_name != NULL, FALSE);
+	g_return_val_if_fail (upw != NULL, FALSE);
+	g_return_val_if_fail (*upw == NULL, FALSE);
+	g_return_val_if_fail (gpw != NULL, FALSE);
+	g_return_val_if_fail (*gpw == NULL, FALSE);
+
+	/* If a password type wasn't present in the VPN connection details, then
+	 * default to saving the password if it was found in the keyring.  But if
+	 * it wasn't found in the keyring, default to always asking for the password.
+	 */
+
+	found_upw = keyring_helpers_get_one_secret (vpn_uuid, VPNC_USER_PASSWORD, upw, &is_session);
+	if (!upw_type)
+		upw_type = found_upw ? NM_VPNC_PW_TYPE_SAVE : NM_VPNC_PW_TYPE_ASK;
+	else if (!strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		gnome_keyring_memory_free (*upw);
+		*upw = NULL;
+	}
+
+	found_gpw = keyring_helpers_get_one_secret (vpn_uuid, VPNC_GROUP_PASSWORD, gpw, &is_session);
+	if (!gpw_type)
+		gpw_type = found_gpw ? NM_VPNC_PW_TYPE_SAVE : NM_VPNC_PW_TYPE_ASK;
+	else if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		gnome_keyring_memory_free (*gpw);
+		*gpw = NULL;
+	}
+
+	if (!retry) {
+		gboolean need_upw = TRUE, need_gpw = TRUE;
+
+		/* Don't ask if both passwords are either saved and present, or unused */
+		if (   (!strcmp (upw_type, NM_VPNC_PW_TYPE_SAVE) && found_upw && *upw)
+		    || (!upw_type && found_upw && *upw)  /* treat unknown type as "save" */
+		    || !strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED))
+			need_upw = FALSE;
+
+		if (   (!strcmp (gpw_type, NM_VPNC_PW_TYPE_SAVE) && found_gpw && *gpw)
+		    || (!gpw_type && found_gpw && *gpw)  /* treat unknown type as "save" */
+		    || !strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+			need_gpw = FALSE;
+
+		if (!need_upw && !need_gpw)
+			return TRUE;
+	} else {
+		/* Don't ask if both passwords are unused */
+		if (   !strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED)
+		    && !strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+			return TRUE;
+	}
+
+	prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), vpn_name);
+	dialog = VPN_PASSWORD_DIALOG (vpn_password_dialog_new (_("Authenticate VPN"), prompt, NULL));
+	g_free (prompt);
+
+	vpn_password_dialog_set_show_remember (dialog, FALSE);
+	vpn_password_dialog_set_password_secondary_label (dialog, _("_Group Password:"));
+
+	if (!strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED))
+		vpn_password_dialog_set_show_password (dialog, FALSE);
+	else if (!retry && found_upw && strcmp (upw_type, NM_VPNC_PW_TYPE_ASK))
+		vpn_password_dialog_set_show_password (dialog, FALSE);
+
+	if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+		vpn_password_dialog_set_show_password_secondary (dialog, FALSE);
+	else if (!retry && found_gpw && strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK))
+		vpn_password_dialog_set_show_password_secondary (dialog, FALSE);
+
+	/* On reprompt the first entry of type 'ask' gets the focus */
+	if (retry) {
+		if (!strcmp (upw_type, NM_VPNC_PW_TYPE_ASK))
+			vpn_password_dialog_focus_password (dialog);
+		else if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK))
+			vpn_password_dialog_focus_password_secondary (dialog);
+	}
+
+	/* if retrying, pre-fill dialog with the password */
+	if (*upw) {
+		vpn_password_dialog_set_password (dialog, *upw);
+		gnome_keyring_memory_free (*upw);
+		*upw = NULL;
+	}
+	if (*gpw) {
+		vpn_password_dialog_set_password_secondary (dialog, *gpw);
+		gnome_keyring_memory_free (*gpw);
+		*gpw = NULL;
+	}
+
+	gtk_widget_show (GTK_WIDGET (dialog));
+
+	success = vpn_password_dialog_run_and_block (dialog);
+	if (success) {
+		*upw = gnome_keyring_memory_strdup (vpn_password_dialog_get_password (dialog));
+		*gpw = gnome_keyring_memory_strdup (vpn_password_dialog_get_password_secondary (dialog));
+
+		if (!strcmp (upw_type, NM_VPNC_PW_TYPE_SAVE)) {
+			if (*upw)
+				keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_USER_PASSWORD, *upw);
+		} else if (   !strcmp (upw_type, NM_VPNC_PW_TYPE_ASK)
+		         || !strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+			/* Clear the password from the keyring */
+			keyring_helpers_delete_secret (vpn_uuid, VPNC_USER_PASSWORD);
+		}
+
+		if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_SAVE)) {
+			if (*gpw)
+				keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_GROUP_PASSWORD, *gpw);
+		} else if (   !strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK)
+		         || !strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+			/* Clear the password from the keyring */
+			keyring_helpers_delete_secret (vpn_uuid, VPNC_GROUP_PASSWORD);
+		}
+	}
+
+	gtk_widget_hide (GTK_WIDGET (dialog));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+
+	return success;
+}
+
+static gboolean
+get_connection_info (const char *vpn_uuid,
+                     char **out_name,
+                     char **out_upw_type,
+                     char **out_gpw_type)
+{
+	char *key, *str;
+	char *connection_path = NULL;
+	char *upw_type = NULL, *gpw_type = NULL;
+	GConfClient *gconf_client;
+
+	connection_path = find_connection_path (vpn_uuid);
+	if (!connection_path)
+		return FALSE;
+
+	gconf_client = gconf_client_get_default ();
+	key = g_strdup_printf ("%s/%s/%s", connection_path,
+	                       NM_SETTING_CONNECTION_SETTING_NAME,
+	                       NM_SETTING_CONNECTION_ID);
+	*out_name = gconf_client_get_string (gconf_client, key, NULL);
+	g_free (key);
+
+	key = g_strdup_printf ("%s/%s/%s", connection_path,
+	                       NM_SETTING_VPN_SETTING_NAME,
+	                       NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	*out_upw_type = gconf_client_get_string (gconf_client, key, NULL);
+	g_free (key);
+
+	key = g_strdup_printf ("%s/%s/%s", connection_path,
+	                       NM_SETTING_VPN_SETTING_NAME,
+	                       NM_VPNC_KEY_SECRET_TYPE);
+	*out_gpw_type = gconf_client_get_string (gconf_client, key, NULL);
+	g_free (key);
+	
+	g_free (connection_path);
+	g_object_unref (gconf_client);
+	return TRUE;
+}
+
+int 
+main (int argc, char *argv[])
+{
+	gboolean retry = FALSE;
+	char *vpn_name = NULL, *vpn_uuid = NULL, *vpn_service = NULL;
+	char *ignored;
+	char *password = NULL, *group_password = NULL;
+	char *upw_type = NULL, *gpw_type = NULL;
+	char buf[1];
+	int ret;
+	GError *error = NULL;
+	GOptionContext *context;
+	GOptionEntry entries[] = {
+			{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
+			{ "uuid", 'u', 0, G_OPTION_ARG_STRING, &vpn_uuid, "UUID of VPN connection", NULL},
+			{ "name", 'n', 0, G_OPTION_ARG_STRING, &ignored, "Name of VPN connection", NULL},
+			{ "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL},
+			{ NULL }
+		};
+
+	bindtextdomain (GETTEXT_PACKAGE, NULL);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	gtk_init (&argc, &argv);
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new ("- vpnc auth dialog");
+	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+
+	if (!g_option_context_parse (context, &argc, &argv, &error)) {
+		g_warning ("Error parsing options: %s\n", error->message);
+		g_error_free (error);
+		return 1;
+	}
+
+	g_option_context_free (context);
+
+	if (vpn_uuid == NULL || vpn_service == NULL) {
+		fprintf (stderr, "A connection UUID and VPN plugin service name are required.\n");
+		return 1;
+	}
+
+	if (strcmp (vpn_service, NM_DBUS_SERVICE_VPNC) != 0) {
+		fprintf (stderr, "This dialog only works with the '%s' service\n", NM_DBUS_SERVICE_VPNC);
+		return 1;
+	}
+
+	if (!get_connection_info (vpn_uuid, &vpn_name, &upw_type, &gpw_type)) {
+		g_free (upw_type);
+		g_free (gpw_type);
+		fprintf (stderr, "This VPN connection '%s' (%s) could not be found in GConf.",
+		         vpn_name ? vpn_name : "(unknown)", vpn_uuid);
+		return 1;
+	}
+
+	if (!get_secrets (vpn_uuid, vpn_name, retry, &password, upw_type, &group_password, gpw_type)) {
+		g_free (upw_type);
+		g_free (gpw_type);
+		return 1;
+	}
+	g_free (upw_type);
+	g_free (gpw_type);
+
+	/* dump the passwords to stdout */
+	if (password)
+		printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, password);
+	if (group_password)
+		printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, group_password);
+	printf ("\n\n");
+
+	if (password) {
+		memset (password, 0, strlen (password));
+		gnome_keyring_memory_free (password);
+	}
+	if (group_password) {
+		memset (group_password, 0, strlen (group_password));
+		gnome_keyring_memory_free (group_password);
+	}
+
+	/* for good measure, flush stdout since Kansas is going Bye-Bye */
+	fflush (stdout);
+
+	/* wait for data on stdin  */
+	ret = fread (buf, sizeof (char), sizeof (buf), stdin);
+	return 0;
+}

Added: trunk/autogen.sh
==============================================================================
--- (empty file)
+++ trunk/autogen.sh	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+REQUIRED_AUTOMAKE_VERSION=1.7
+PKG_NAME=NetworkManager-vpnc
+
+(test -f $srcdir/configure.in \
+  && test -f $srcdir/auth-dialog/main.c) || {
+    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+    echo " top-level $PKG_NAME directory"
+    exit 1
+}
+
+
+which gnome-autogen.sh || {
+    echo "You need to install gnome-common from the GNOME CVS"
+    exit 1
+}
+USE_GNOME2_MACROS=1 . gnome-autogen.sh
+
+

Added: trunk/common-gnome/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/common-gnome/Makefile.am	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES=libnm-vpnc-common-gnome.la
+
+libnm_vpnc_common_gnome_la_CPPFLAGS = \
+	$(NM_UTILS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GNOMEKEYRING_CFLAGS) \
+	-DG_DISABLE_DEPRECATED
+
+libnm_vpnc_common_gnome_la_SOURCES= \
+	keyring-helpers.c \
+	keyring-helpers.h
+
+libnm_vpnc_common_gnome_la_LIBADD = \
+	$(NM_UTILS_LIBS) \
+	$(GLIB_LIBS) \
+	$(GNOMEKEYRING_LIBS)
+

Added: trunk/common-gnome/keyring-helpers.c
==============================================================================
--- (empty file)
+++ trunk/common-gnome/keyring-helpers.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,200 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2004 - 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <gnome-keyring-memory.h>
+
+#include <nm-setting-vpn.h>
+
+#include "keyring-helpers.h"
+#include "../src/nm-vpnc-service.h"
+
+#define KEYRING_UUID_TAG "connection-uuid"
+#define KEYRING_SN_TAG "setting-name"
+#define KEYRING_SK_TAG "setting-key"
+
+static char *
+find_one_password (const char *vpn_uuid,
+                   const char *secret_name,
+                   gboolean *is_session)
+{
+	GList *found_list = NULL;
+	GnomeKeyringResult ret;
+	GnomeKeyringFound *found;
+	char *secret;
+
+	ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      &found_list,
+	                                      KEYRING_UUID_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      vpn_uuid,
+	                                      KEYRING_SN_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      NM_SETTING_VPN_SETTING_NAME,
+	                                      KEYRING_SK_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      secret_name,
+	                                      NULL);
+	if ((ret != GNOME_KEYRING_RESULT_OK) || (g_list_length (found_list) == 0))
+		return NULL;
+
+	found = (GnomeKeyringFound *) found_list->data;
+
+	if (is_session) {
+		if (strcmp (found->keyring, "session") == 0)
+			*is_session = TRUE;
+		else
+			*is_session = FALSE;
+	}
+
+	secret = found->secret ? gnome_keyring_memory_strdup (found->secret) : NULL;
+	gnome_keyring_found_list_free (found_list);
+
+	return secret;
+}
+
+gboolean
+keyring_helpers_lookup_secrets (const char *vpn_uuid,
+                                char **password,
+                                char **group_password,
+                                gboolean *is_session)
+{
+	g_return_val_if_fail (password != NULL, FALSE);
+	g_return_val_if_fail (*password == NULL, FALSE);
+	g_return_val_if_fail (group_password != NULL, FALSE);
+	g_return_val_if_fail (*group_password == NULL, FALSE);
+
+	*password = find_one_password (vpn_uuid, VPNC_USER_PASSWORD, is_session);
+	if (!*password)
+		return FALSE;
+
+	*group_password = find_one_password (vpn_uuid, VPNC_GROUP_PASSWORD, is_session);
+	if (!*group_password) {
+		memset (*password, 0, strlen (*password));
+		gnome_keyring_memory_free (*password);
+		*password = NULL;
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+gboolean
+keyring_helpers_get_one_secret (const char *vpn_uuid,
+                                const char *which_secret,
+                                char **password,
+                                gboolean *is_session)
+{
+	g_return_val_if_fail (password != NULL, FALSE);
+	g_return_val_if_fail (*password == NULL, FALSE);
+
+	*password = find_one_password (vpn_uuid, which_secret, is_session);
+	if (!*password)
+		return FALSE;
+
+	return TRUE;
+}
+
+GnomeKeyringResult
+keyring_helpers_save_secret (const char *vpn_uuid,
+                             const char *vpn_name,
+                             const char *keyring,
+                             const char *secret_name,
+                             const char *secret)
+{
+	char *display_name;
+	GnomeKeyringResult ret;
+	GnomeKeyringAttributeList *attrs = NULL;
+	guint32 id = 0;
+
+	display_name = g_strdup_printf ("VPN %s secret for %s/%s/" NM_SETTING_VPN_SETTING_NAME,
+	                                secret_name,
+	                                vpn_name,
+	                                NM_DBUS_SERVICE_VPNC);
+
+	attrs = gnome_keyring_attribute_list_new ();
+	gnome_keyring_attribute_list_append_string (attrs,
+	                                            KEYRING_UUID_TAG,
+	                                            vpn_uuid);
+	gnome_keyring_attribute_list_append_string (attrs,
+	                                            KEYRING_SN_TAG,
+	                                            NM_SETTING_VPN_SETTING_NAME);
+	gnome_keyring_attribute_list_append_string (attrs,
+	                                            KEYRING_SK_TAG,
+	                                            secret_name);
+
+	ret = gnome_keyring_item_create_sync (keyring,
+	                                      GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      display_name,
+	                                      attrs,
+	                                      secret,
+	                                      TRUE,
+	                                      &id);
+	gnome_keyring_attribute_list_free (attrs);
+	g_free (display_name);
+	return ret;
+}
+
+static void
+ignore_callback (GnomeKeyringResult result, gpointer data)
+{
+}
+
+gboolean
+keyring_helpers_delete_secret (const char *vpn_uuid,
+                               const char *secret_name)
+{
+	GList *found = NULL, *iter;
+	GnomeKeyringResult ret;
+
+	g_return_val_if_fail (vpn_uuid != NULL, FALSE);
+	g_return_val_if_fail (secret_name != NULL, FALSE);
+
+	ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      &found,
+	                                      KEYRING_UUID_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      vpn_uuid,
+	                                      KEYRING_SN_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      NM_SETTING_VPN_SETTING_NAME,
+	                                      KEYRING_SK_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      secret_name,
+	                                      NULL);
+	if (ret != GNOME_KEYRING_RESULT_OK && ret != GNOME_KEYRING_RESULT_NO_MATCH)
+		return FALSE;
+	if (g_list_length (found) == 0)
+		return TRUE;
+
+	/* delete them all */
+	for (iter = found; iter; iter = g_list_next (iter)) {
+		GnomeKeyringFound *item = (GnomeKeyringFound *) iter->data;
+
+		gnome_keyring_item_delete (item->keyring, item->item_id,
+		                           ignore_callback, NULL, NULL);
+	}
+
+	gnome_keyring_found_list_free (found);
+	return TRUE;
+}
+

Added: trunk/common-gnome/keyring-helpers.h
==============================================================================
--- (empty file)
+++ trunk/common-gnome/keyring-helpers.h	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2004 - 2008 Red Hat, Inc.
+ */
+
+#ifndef KEYRING_HELPERS_H
+#define KEYRING_HELPERS_H
+
+#include <glib.h>
+#include <gnome-keyring.h>
+
+#define VPNC_USER_PASSWORD "password"
+#define VPNC_GROUP_PASSWORD "group-password"
+
+gboolean keyring_helpers_lookup_secrets (const char *vpn_uuid,
+                                         char **password,
+                                         char **group_password,
+                                         gboolean *is_session);
+
+gboolean keyring_helpers_get_one_secret (const char *vpn_uuid,
+                                         const char *which_secret,
+                                         char **password,
+                                         gboolean *is_session);
+
+GnomeKeyringResult keyring_helpers_save_secret (const char *vpn_uuid,
+                                                const char *vpn_name,
+                                                const char *keyring,
+                                                const char *secret_name,
+                                                const char *secret);
+
+gboolean keyring_helpers_delete_secret (const char *vpn_uuid,
+                                        const char *secret_name);
+
+#endif  /* KEYRING_HELPERS_H */
+

Added: trunk/configure.in
==============================================================================
--- (empty file)
+++ trunk/configure.in	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,125 @@
+AC_PREREQ(2.52)
+
+AC_INIT(NetworkManager-vpnc, 0.7.0, dcbw redhat com, NetworkManager-vpnc)
+AC_CONFIG_AUX_DIR(.)
+AM_INIT_AUTOMAKE([subdir-objects])
+AM_MAINTAINER_MODE
+
+AM_CONFIG_HEADER(config.h)
+
+dnl
+dnl Require programs
+dnl
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+dnl
+dnl Required headers
+dnl
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h paths.h sys/ioctl.h sys/time.h syslog.h unistd.h)
+
+dnl
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl
+AC_TYPE_MODE_T
+AC_TYPE_PID_T
+AC_HEADER_TIME
+
+dnl
+dnl Checks for library functions.
+dnl
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_CHECK_FUNCS(select socket uname)
+
+dnl
+dnl GNOME support
+dnl
+AC_ARG_WITH(gnome, AC_HELP_STRING([--without-gnome], [Build NetworkManager-vpnc without GNOME support, e.g. vpn service only]))
+AM_CONDITIONAL(WITH_GNOME, test x"$with_gnome" != xno)
+
+GETTEXT_PACKAGE=NetworkManager-vpnc
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package])
+
+IT_PROG_INTLTOOL([0.35])
+AM_GLIB_GNU_GETTEXT
+
+PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
+AC_SUBST(GTHREAD_CFLAGS)
+AC_SUBST(GTHREAD_LIBS)
+
+PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= 0.30)
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
+if test x"$with_gnome" != xno; then
+	PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6)
+	AC_SUBST(GTK_CFLAGS)
+	AC_SUBST(GTK_LIBS)
+
+	PKG_CHECK_MODULES(GDK_PIXBUF, gdk-pixbuf-2.0)
+	AC_SUBST(GDK_PIXBUF_CFLAGS)
+	AC_SUBST(GDK_PIXBUF_LIBS)
+
+	PKG_CHECK_MODULES(GLADE, libglade-2.0)
+	AC_SUBST(GLADE_CFLAGS)
+	AC_SUBST(GLADE_LIBS)
+
+	PKG_CHECK_MODULES(GCONF, gconf-2.0)
+	AC_SUBST(GCONF_CFLAGS)
+	AC_SUBST(GCONF_LIBS)
+
+	PKG_CHECK_MODULES(GNOMEKEYRING, gnome-keyring-1)
+	AC_SUBST(GNOMEKEYRING_CFLAGS)
+	AC_SUBST(GNOMEKEYRING_LIBS)
+fi
+
+PKG_CHECK_MODULES(NM_UTILS, NetworkManager >= 0.7.0 libnm-util libnm_glib libnm_glib_vpn)
+AC_SUBST(NM_UTILS_CFLAGS)
+AC_SUBST(NM_UTILS_LIBS)
+
+AC_ARG_ENABLE(more-warnings,
+AC_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings]),
+set_more_warnings="$enableval",[
+if test -d "$srcdir/{arch}" || test -d "$srcdir/CVS"; then
+	set_more_warnings=yes
+else
+	set_more_warnings=no
+fi
+])
+AC_MSG_CHECKING(for more warnings, including -Werror)
+if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+	AC_MSG_RESULT(yes)
+	CFLAGS="-Wall -Werror -std=gnu89 $CFLAGS"
+
+	for option in -Wno-unused -Wno-strict-aliasing -Wno-sign-compare -Wdeclaration-after-statement -Wno-pointer-sign ; do
+		SAVE_CFLAGS="$CFLAGS"
+		CFLAGS="$CFLAGS $option"
+		AC_MSG_CHECKING([whether gcc understands $option])
+		AC_TRY_COMPILE([], [],
+			has_option=yes,
+			has_option=no,)
+		if test $has_option = no; then
+			CFLAGS="$SAVE_CFLAGS"
+		fi
+		AC_MSG_RESULT($has_option)
+		unset has_option
+		unset SAVE_CFLAGS
+	done
+	unset option
+else
+	AC_MSG_RESULT(no)
+fi
+
+AC_OUTPUT([
+Makefile
+src/Makefile
+common-gnome/Makefile
+auth-dialog/Makefile
+properties/Makefile
+po/Makefile.in
+])

Added: trunk/doc/example-vpnc-system-wide-connection.sh
==============================================================================
--- (empty file)
+++ trunk/doc/example-vpnc-system-wide-connection.sh	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# This is an example of how to install a system-wide connection that
+# cannot be edited by unprivileged users using nm-vpn-properties. This
+# script needs to be run as root and you may need to restart any
+# gconfd daemons after the script has run (logging in and out will
+# suffice)
+
+NAME="vpnc-system-wide"
+ESCAPED_NAME="vpnc-system-wide"
+IPSEC_GATEWAY="1.2.3.4"
+IPSEC_ID="myGroupName"
+IPSEC_ROUTES="[172.16.0.0/16,192.168.4.0/24]"
+
+GCONF_PATH="/system/networking/vpn_connections/$ESCAPED_NAME"
+
+GCONFTOOL2_OPTS="--direct --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory"
+
+gconftool-2 $GCONFTOOL2_OPTS --type string --set $GCONF_PATH/name "$NAME"
+gconftool-2 $GCONFTOOL2_OPTS --type string --set $GCONF_PATH/service_name "org.freedesktop.NetworkManager.vpnc"
+gconftool-2 $GCONFTOOL2_OPTS --type list --list-type=string --set $GCONF_PATH/vpn_data ["IPSec gateway","$IPSEC_GATEWAY","IPSec ID","$IPSEC_ID"]
+gconftool-2 $GCONFTOOL2_OPTS --type list --list-type=string --set $GCONF_PATH/routes $IPSEC_ROUTES
+

Added: trunk/gnome-mime-application-x-cisco-vpn-settings.png
==============================================================================
Binary file. No diff available.

Added: trunk/nm-vpnc-service.conf
==============================================================================
--- (empty file)
+++ trunk/nm-vpnc-service.conf	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,16 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+	<policy user="root">
+		<allow own="org.freedesktop.NetworkManager.vpnc"/>
+		<allow send_destination="org.freedesktop.NetworkManager.vpnc"/>
+		<allow send_interface="org.freedesktop.NetworkManager.vpnc"/>
+	</policy>
+	<policy context="default">
+		<deny own="org.freedesktop.NetworkManager.vpnc"/>
+		<deny send_destination="org.freedesktop.NetworkManager.vpnc"/>
+		<deny send_interface="org.freedesktop.NetworkManager.vpnc"/>
+	</policy>
+</busconfig>
+

Added: trunk/nm-vpnc-service.name.in
==============================================================================
--- (empty file)
+++ trunk/nm-vpnc-service.name.in	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,8 @@
+[VPN Connection]
+name=vpnc
+service=org.freedesktop.NetworkManager.vpnc
+program= LIBEXECDIR@/nm-vpnc-service
+
+[GNOME]
+auth-dialog=nm-vpnc-auth-dialog
+properties=libnm-vpnc-properties

Added: trunk/nm-vpnc.desktop.in
==============================================================================
--- (empty file)
+++ trunk/nm-vpnc.desktop.in	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=VPN Connection Manager (vpnc)
+_GenericName=VPN Connection Manager (vpnc)
+_Comment=Add, Remove, and Edit VPN Connections
+Exec=nm-vpn-properties --import-service org.freedesktop.NetworkManager.vpnc --import-file %f
+Icon=gnome-mime-application-x-cisco-vpn-settings
+Terminal=false
+Type=Application
+DocPath=
+Categories=GNOME;Application;Network;
+MimeType=application/x-cisco-vpn-settings
+NoDisplay=true

Added: trunk/po/.cvsignore
==============================================================================
--- (empty file)
+++ trunk/po/.cvsignore	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,7 @@
+Makefile.in.in
+Makefile
+Makefile.in
+POTFILES
+*.pot
+stamp-it
+*.gmo

Added: trunk/po/LINGUAS
==============================================================================
--- (empty file)
+++ trunk/po/LINGUAS	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,38 @@
+# please keep this list sorted alphabetically
+ar
+bg
+ca
+cs
+da
+de
+dz
+el
+en_GB
+es
+et
+eu
+fi
+fr
+gl
+hu
+it
+ja
+ka
+ko
+lt
+mk
+nb
+nl
+pa
+pl
+pt
+pt_BR
+ru
+sl
+sv
+th
+uk
+vi
+zh_CN
+zh_HK
+zh_TW

Added: trunk/po/POTFILES.in
==============================================================================
--- (empty file)
+++ trunk/po/POTFILES.in	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,10 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+auth-dialog/gnome-two-password-dialog.c
+auth-dialog/main.c
+nm-vpnc.desktop.in
+properties/nm-vpnc.c
+properties/nm-vpnc-dialog.glade
+src/nm-vpnc-service.c
+
+

Added: trunk/properties/.cvsignore
==============================================================================
--- (empty file)
+++ trunk/properties/.cvsignore	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile

Added: trunk/properties/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/properties/Makefile.am	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,41 @@
+INCLUDES = -I${top_srcdir}
+
+plugindir = $(libdir)/NetworkManager
+plugin_LTLIBRARIES = libnm-vpnc-properties.la
+
+libnm_vpnc_properties_la_SOURCES = \
+	pcf-file.c \
+	pcf-file.h \
+	nm-vpnc.c \
+	nm-vpnc.h
+
+gladedir = $(datadir)/gnome-vpn-properties/vpnc
+glade_DATA = nm-vpnc-dialog.glade
+
+libnm_vpnc_properties_la_CPPFLAGS = \
+	$(GLADE_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(GCONF_CFLAGS) \
+	$(GNOMEKEYRING_CFLAGS) \
+	$(NM_UTILS_CFLAGS) \
+	-DICONDIR=\""$(datadir)/pixmaps"\" \
+	-DGLADEDIR=\""$(gladedir)"\" \
+	-DG_DISABLE_DEPRECATED \
+	-DGDK_DISABLE_DEPRECATED \
+	-DGNOME_DISABLE_DEPRECATED \
+	-DGNOMELOCALEDIR=\"$(datadir)/locale\" \
+	-DVERSION=\"$(VERSION)\"
+
+libnm_vpnc_properties_la_LIBADD = \
+	$(GLADE_LIBS) \
+	$(GTK_LIBS) \
+	$(GCONF_LIBS) \
+	$(NM_UTILS_LIBS) \
+	$(top_builddir)/common-gnome/libnm-vpnc-common-gnome.la
+
+libnm_vpnc_properties_la_LDFLAGS = \
+        -avoid-version
+
+CLEANFILES = *.bak *.gladep *~
+
+EXTRA_DIST = $(glade_DATA)

Added: trunk/properties/nm-vpnc-dialog.glade
==============================================================================
--- (empty file)
+++ trunk/properties/nm-vpnc-dialog.glade	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkWindow" id="vpnc-widget">
+    <property name="title" translatable="yes">window1</property>
+    <child>
+      <widget class="GtkVBox" id="vpnc-vbox">
+        <property name="visible">True</property>
+        <property name="border_width">12</property>
+        <property name="spacing">16</property>
+        <child>
+          <widget class="GtkVBox" id="vbox8">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label22">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkAlignment" id="alignment8">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkTable" id="table2">
+                    <property name="visible">True</property>
+                    <property name="n_rows">5</property>
+                    <property name="n_columns">3</property>
+                    <property name="column_spacing">6</property>
+                    <property name="row_spacing">6</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="group_pass_type_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="user_pass_type_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkCheckButton" id="show_passwords_checkbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="label" translatable="yes">Show passwords</property>
+                        <property name="response_id">0</property>
+                        <property name="draw_indicator">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">4</property>
+                        <property name="bottom_attach">5</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="group_password_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="visibility">False</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Gro_up password:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">group_entry</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label23">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">_Gateway:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">gateway_entry</property>
+                      </widget>
+                      <packing>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label24">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">G_roup name:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">group_entry</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="gateway_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="group_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">_User password:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">group_entry</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="user_password_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="visibility">False</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkVBox" id="vbox11">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label25">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">&lt;b&gt;Optional&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkAlignment" id="alignment9">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkTable" id="table3">
+                    <property name="visible">True</property>
+                    <property name="n_rows">5</property>
+                    <property name="n_columns">2</property>
+                    <property name="column_spacing">6</property>
+                    <property name="row_spacing">6</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <widget class="GtkCheckButton" id="disable_dpd_checkbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="label" translatable="yes">Disable Dead Peer Detection</property>
+                        <property name="response_id">0</property>
+                        <property name="draw_indicator">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">4</property>
+                        <property name="bottom_attach">5</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="encryption_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Encryption method:</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label26">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">User name:</property>
+                      </widget>
+                      <packing>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="user_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label27">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Domain:</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="domain_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">NAT traversal:</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="natt_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>

Added: trunk/properties/nm-vpnc.c
==============================================================================
--- (empty file)
+++ trunk/properties/nm-vpnc.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,1387 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/***************************************************************************
+ * CVSID: $Id: nm-vpnc.c 4366 2008-12-06 00:19:59Z dcbw $
+ *
+ * nm-vpnc.c : GNOME UI dialogs for configuring vpnc VPN connections
+ *
+ * Copyright (C) 2005 David Zeuthen, <davidz redhat com>
+ * Copyright (C) 2005 - 2008 Dan Williams, <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gnome-keyring.h>
+#include <gnome-keyring-memory.h>
+
+#define NM_VPN_API_SUBJECT_TO_CHANGE
+
+#include <nm-vpn-plugin-ui-interface.h>
+#include <nm-setting-vpn.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-ip4-config.h>
+
+#include "src/nm-vpnc-service.h"
+#include "common-gnome/keyring-helpers.h"
+#include "pcf-file.h"
+#include "nm-vpnc.h"
+
+#define VPNC_PLUGIN_NAME    _("Cisco Compatible VPN (vpnc)")
+#define VPNC_PLUGIN_DESC    _("Compatible with various Cisco, Juniper, Netscreen, and Sonicwall IPSec-based VPN gateways.")
+#define VPNC_PLUGIN_SERVICE NM_DBUS_SERVICE_VPNC 
+
+#define ENC_TYPE_SECURE 0
+#define ENC_TYPE_WEAK   1
+#define ENC_TYPE_NONE   2
+
+#define PW_TYPE_SAVE   0
+#define PW_TYPE_ASK	   1
+#define PW_TYPE_UNUSED 2
+
+/************** plugin class **************/
+
+static void vpnc_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class);
+
+G_DEFINE_TYPE_EXTENDED (VpncPluginUi, vpnc_plugin_ui, G_TYPE_OBJECT, 0,
+						G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_INTERFACE,
+											   vpnc_plugin_ui_interface_init))
+
+/************** UI widget class **************/
+
+static void vpnc_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class);
+
+G_DEFINE_TYPE_EXTENDED (VpncPluginUiWidget, vpnc_plugin_ui_widget, G_TYPE_OBJECT, 0,
+						G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE,
+											   vpnc_plugin_ui_widget_interface_init))
+
+#define VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VPNC_TYPE_PLUGIN_UI_WIDGET, VpncPluginUiWidgetPrivate))
+
+typedef struct {
+	GladeXML *xml;
+	GtkWidget *widget;
+	GtkSizeGroup *group;
+	gint orig_dpd_timeout;
+} VpncPluginUiWidgetPrivate;
+
+
+#define VPNC_PLUGIN_UI_ERROR vpnc_plugin_ui_error_quark ()
+
+static GQuark
+vpnc_plugin_ui_error_quark (void)
+{
+	static GQuark error_quark = 0;
+
+	if (G_UNLIKELY (error_quark == 0))
+		error_quark = g_quark_from_static_string ("vpnc-plugin-ui-error-quark");
+
+	return error_quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+vpnc_plugin_ui_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			/* Unknown error. */
+			ENUM_ENTRY (VPNC_PLUGIN_UI_ERROR_UNKNOWN, "UnknownError"),
+			/* The specified property was invalid. */
+			ENUM_ENTRY (VPNC_PLUGIN_UI_ERROR_INVALID_PROPERTY, "InvalidProperty"),
+			/* The specified property was missing and is required. */
+			ENUM_ENTRY (VPNC_PLUGIN_UI_ERROR_MISSING_PROPERTY, "MissingProperty"),
+			/* The connection was missing invalid. */
+			ENUM_ENTRY (VPNC_PLUGIN_UI_ERROR_INVALID_CONNECTION, "InvalidConnection"),
+			{ 0, 0, 0 }
+		};
+		etype = g_enum_register_static ("VpncPluginUiError", values);
+	}
+	return etype;
+}
+
+
+static gboolean
+check_validity (VpncPluginUiWidget *self, GError **error)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	GtkWidget *widget;
+	char *str;
+
+	widget = glade_xml_get_widget (priv->xml, "gateway_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!str || !strlen (str) || strstr (str, " ") || strstr (str, "\t")) {
+		g_set_error (error,
+		             VPNC_PLUGIN_UI_ERROR,
+		             VPNC_PLUGIN_UI_ERROR_INVALID_PROPERTY,
+		             NM_VPNC_KEY_GATEWAY);
+		return FALSE;
+	}
+
+	widget = glade_xml_get_widget (priv->xml, "group_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!str || !strlen (str)) {
+		g_set_error (error,
+		             VPNC_PLUGIN_UI_ERROR,
+		             VPNC_PLUGIN_UI_ERROR_INVALID_PROPERTY,
+		             NM_VPNC_KEY_ID);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+stuff_changed_cb (GtkWidget *widget, gpointer user_data)
+{
+	g_signal_emit_by_name (VPNC_PLUGIN_UI_WIDGET (user_data), "changed");
+}
+
+static gboolean
+fill_vpn_passwords (VpncPluginUiWidget *self, NMConnection *connection)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	GtkWidget *widget;
+	gboolean success = FALSE;
+	char *password = NULL;
+	char *group_password = NULL;
+
+	/* Grab secrets from the keyring */
+	if (connection) {
+		NMSettingConnection *s_con;
+		NMSettingVPN *s_vpn;
+		const char *tmp;
+
+		s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+
+		if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
+			if (s_vpn) {
+				tmp = nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD);
+				if (tmp)
+					password = gnome_keyring_memory_strdup (tmp);
+
+				tmp = nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET);
+				if (tmp)
+					group_password = gnome_keyring_memory_strdup (tmp);
+			}
+		} else {
+			s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+
+			/* Lookup passwords in the keyring, and if they weren't there, try
+			 * the connection itself, which is where they'd be right after import.
+			 */
+			keyring_helpers_get_one_secret (nm_setting_connection_get_uuid (s_con),
+			                                VPNC_USER_PASSWORD,
+			                                &password,
+			                                NULL);
+			if (!password)
+				password = gnome_keyring_memory_strdup (nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD));
+
+			keyring_helpers_get_one_secret (nm_setting_connection_get_uuid (s_con),
+			                                VPNC_GROUP_PASSWORD,
+			                                &group_password,
+			                                NULL);
+			if (!group_password)
+				group_password = gnome_keyring_memory_strdup (nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET));
+		}
+	}
+
+	/* User password */
+	widget = glade_xml_get_widget (priv->xml, "user_password_entry");
+	if (!widget)
+		goto out;
+	if (password)
+		gtk_entry_set_text (GTK_ENTRY (widget), password);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	/* Group password */
+	widget = glade_xml_get_widget (priv->xml, "group_password_entry");
+	if (!widget)
+		goto out;
+	if (group_password)
+		gtk_entry_set_text (GTK_ENTRY (widget), group_password);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	success = TRUE;
+
+out:
+	gnome_keyring_memory_free (password);
+	gnome_keyring_memory_free (group_password);
+
+	return success;
+}
+
+static void
+show_toggled_cb (GtkCheckButton *button, VpncPluginUiWidget *self)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	GtkWidget *widget;
+	gboolean visible;
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+	widget = glade_xml_get_widget (priv->xml, "user_password_entry");
+	g_assert (widget);
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+
+	widget = glade_xml_get_widget (priv->xml, "group_password_entry");
+	g_assert (widget);
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static void
+pw_type_changed_helper (VpncPluginUiWidget *self, GtkWidget *combo)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	const char *entry = NULL;
+	GtkWidget *widget;
+	GtkTreeModel *model;
+
+	/* If the user chose "Not required", desensitize and clear the correct
+	 * password entry.
+	 */
+	widget = glade_xml_get_widget (priv->xml, "user_pass_type_combo");
+	if (combo == widget)
+		entry = "user_password_entry";
+	else {
+		widget = glade_xml_get_widget (priv->xml, "group_pass_type_combo");
+		if (combo == widget)
+			entry = "group_password_entry";
+	}
+	if (!entry)
+		return;
+
+	widget = glade_xml_get_widget (priv->xml, entry);
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
+	case PW_TYPE_ASK:
+	case PW_TYPE_UNUSED:
+		gtk_entry_set_text (GTK_ENTRY (widget), "");
+		gtk_widget_set_sensitive (widget, FALSE);
+		break;
+	default:
+		gtk_widget_set_sensitive (widget, TRUE);
+		break;
+	}
+}
+
+static void
+pw_type_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (user_data);
+
+	pw_type_changed_helper (self, combo);
+	stuff_changed_cb (combo, self);
+}
+
+static void
+init_one_pw_combo (VpncPluginUiWidget *self,
+                   NMSettingVPN *s_vpn,
+                   const char *combo_name,
+                   const char *key,
+                   const char *entry_name)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	int active = -1;
+	GtkWidget *widget;
+	GtkListStore *store;
+	GtkTreeIter iter;
+	const char *value = NULL;
+	guint32 default_idx = 1;
+
+	/* If there's already a password and the password type can't be found in
+	 * the VPN settings, default to saving it.  Otherwise, always ask for it.
+	 */
+	widget = glade_xml_get_widget (priv->xml, entry_name);
+	if (widget) {
+		const char *tmp;
+
+		tmp = gtk_entry_get_text (GTK_ENTRY (widget));
+		if (tmp && strlen (tmp))
+			default_idx = 0;
+	}
+
+	store = gtk_list_store_new (1, G_TYPE_STRING);
+	if (s_vpn)
+		value = nm_setting_vpn_get_data_item (s_vpn, key);
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Saved"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_SAVE))
+			active = 0;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Always Ask"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_ASK))
+			active = 1;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Not Required"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_UNUSED))
+			active = 2;
+	}
+
+	widget = glade_xml_get_widget (priv->xml, combo_name);
+	g_assert (widget);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+	g_object_unref (store);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? default_idx : active);
+	pw_type_changed_helper (self, widget);
+
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (pw_type_combo_changed_cb), self);
+}
+
+static gboolean
+init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **error)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	NMSettingVPN *s_vpn;
+	GtkWidget *widget;
+	GtkListStore *store;
+	GtkTreeIter iter;
+	const char *value = NULL;
+	int active = -1;
+	const char *natt_mode = NULL;
+
+	s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+
+	priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	widget = glade_xml_get_widget (priv->xml, "gateway_entry");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_GATEWAY);
+		if (value && strlen (value))
+			gtk_entry_set_text (GTK_ENTRY (widget), value);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = glade_xml_get_widget (priv->xml, "group_entry");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_ID);
+		if (value && strlen (value))
+			gtk_entry_set_text (GTK_ENTRY (widget), value);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = glade_xml_get_widget (priv->xml, "encryption_combo");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+
+	store = gtk_list_store_new (1, G_TYPE_STRING);
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Secure (default)"), -1);
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Weak (use with caution)"), -1);
+	if (s_vpn && (active < 0)) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SINGLE_DES);
+		if (value && !strcmp (value, "yes"))
+			active = 1;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("None (completely insecure)"), -1);
+	if (s_vpn && (active < 0)) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_NO_ENCRYPTION);
+		if (value && !strcmp (value, "yes"))
+			active = 2;
+	}
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+	g_object_unref (store);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active);
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	/* Fill the VPN passwords *before* initializing the PW type combos, since
+	 * knowing if there are passwords when initializing the combos is helpful.
+	 */
+	fill_vpn_passwords (self, connection);
+
+	init_one_pw_combo (self, s_vpn, "user_pass_type_combo",
+	                   NM_VPNC_KEY_XAUTH_PASSWORD_TYPE, "user_password_entry");
+	init_one_pw_combo (self, s_vpn, "group_pass_type_combo",
+	                   NM_VPNC_KEY_SECRET_TYPE, "group_password_entry");
+
+	widget = glade_xml_get_widget (priv->xml, "user_entry");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_USER);
+		if (value && strlen (value))
+			gtk_entry_set_text (GTK_ENTRY (widget), value);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = glade_xml_get_widget (priv->xml, "domain_entry");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_DOMAIN);
+		if (value && strlen (value))
+			gtk_entry_set_text (GTK_ENTRY (widget), value);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	active = -1;
+	store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+	if (s_vpn)
+		natt_mode = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE);
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Cisco UDP (default)"), 1, NM_VPNC_NATT_MODE_CISCO, -1);
+	if ((active < 0) && natt_mode) {
+		if (!strcmp (natt_mode, NM_VPNC_NATT_MODE_CISCO))
+			active = 0;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("NAT-T"), 1, NM_VPNC_NATT_MODE_NATT, -1);
+	if ((active < 0) && natt_mode) {
+		if (!strcmp (natt_mode, NM_VPNC_NATT_MODE_NATT))
+			active = 1;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Disabled"), 1, NM_VPNC_NATT_MODE_NONE, -1);
+	if ((active < 0) && natt_mode) {
+		if (!strcmp (natt_mode, NM_VPNC_NATT_MODE_NONE))
+			active = 2;
+	}
+
+	widget = glade_xml_get_widget (priv->xml, "natt_combo");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
+	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+	g_object_unref (store);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active);
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = glade_xml_get_widget (priv->xml, "disable_dpd_checkbutton");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT);
+		if (value) {
+			long int tmp;
+
+			errno = 0;
+			tmp = strtol (value, NULL, 10);
+			if (tmp >= 0 && tmp <= G_MAXUINT32 && errno == 0)
+				priv->orig_dpd_timeout = (guint32) tmp;
+
+			if (priv->orig_dpd_timeout == 0)
+				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+		}
+	}
+	g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = glade_xml_get_widget (priv->xml, "show_passwords_checkbutton");
+	g_return_val_if_fail (widget != NULL, FALSE);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  self);
+
+	return TRUE;
+}
+
+static GObject *
+get_widget (NMVpnPluginUiWidgetInterface *iface)
+{
+	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (iface);
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+
+	return G_OBJECT (priv->widget);
+}
+
+static guint32
+handle_one_pw_type (NMSettingVPN *s_vpn, GladeXML *xml, const char *name, const char *key)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	guint32 pw_type;
+
+	widget = glade_xml_get_widget (xml, name);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+
+	pw_type = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+	switch (pw_type) {
+	case PW_TYPE_SAVE:
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_SAVE);
+		break;
+	case PW_TYPE_UNUSED:
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_UNUSED);
+		break;
+	case PW_TYPE_ASK:
+	default:
+		pw_type = PW_TYPE_ASK;
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_ASK);
+		break;
+	}
+
+	return pw_type;
+}
+
+static gboolean
+update_connection (NMVpnPluginUiWidgetInterface *iface,
+                   NMConnection *connection,
+                   GError **error)
+{
+	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (iface);
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	NMSettingVPN *s_vpn;
+	GtkWidget *widget;
+	char *str;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	guint32 upw_type, gpw_type;
+
+	if (!check_validity (self, error))
+		return FALSE;
+
+	s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ());
+	g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, NM_DBUS_SERVICE_VPNC, NULL);
+
+	/* Gateway */
+	widget = glade_xml_get_widget (priv->xml, "gateway_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (str && strlen (str))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_GATEWAY, str);
+
+	/* Group name */
+	widget = glade_xml_get_widget (priv->xml, "group_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (str && strlen (str))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_ID, str);
+
+	widget = glade_xml_get_widget (priv->xml, "user_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (str && strlen (str))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_XAUTH_USER, str);
+
+	widget = glade_xml_get_widget (priv->xml, "domain_entry");
+	str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+	if (str && strlen (str))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DOMAIN, str);
+
+	widget = glade_xml_get_widget (priv->xml, "encryption_combo");
+	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget))) {
+	case ENC_TYPE_WEAK:
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_SINGLE_DES, "yes");
+		break;
+	case ENC_TYPE_NONE:
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NO_ENCRYPTION, "yes");
+		break;
+	case ENC_TYPE_SECURE:
+	default:
+		break;
+	}
+
+	widget = glade_xml_get_widget (priv->xml, "natt_combo");
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+		const char *mode = NULL;
+
+		gtk_tree_model_get (model, &iter, 1, &mode, -1);
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, mode);
+	} else
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, NM_VPNC_NATT_MODE_NATT);
+
+	widget = glade_xml_get_widget (priv->xml, "disable_dpd_checkbutton");
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT, "0");
+	} else {
+		/* If DPD was disabled and now the user wishes to enable it, just
+		 * don't pass the DPD_IDLE_TIMEOUT option to vpnc and thus use the
+		 * default DPD idle time.  Otherwise keep the original DPD idle timeout.
+		 */
+		if (priv->orig_dpd_timeout >= 10) {
+			char *tmp = g_strdup_printf ("%d", priv->orig_dpd_timeout);
+			nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT, tmp);
+			g_free (tmp);
+		}
+	}
+
+	upw_type = handle_one_pw_type (s_vpn, priv->xml, "user_pass_type_combo", NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	gpw_type = handle_one_pw_type (s_vpn, priv->xml, "group_pass_type_combo", NM_VPNC_KEY_SECRET_TYPE);
+
+	/* System secrets get stored in the connection, user secrets are saved
+	 * via the save_secrets() hook.
+	 */
+	if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
+		/* User password */
+		widget = glade_xml_get_widget (priv->xml, "user_password_entry");
+		str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+		if (str && strlen (str) && (upw_type != PW_TYPE_UNUSED))
+			nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD, str);
+
+		/* Group password */
+		widget = glade_xml_get_widget (priv->xml, "group_password_entry");
+		str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+		if (str && strlen (str) && (gpw_type != PW_TYPE_UNUSED))
+			nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_SECRET, str);
+	}
+
+	nm_connection_add_setting (connection, NM_SETTING (s_vpn));
+	return TRUE;
+}
+
+static void
+save_one_password (GladeXML *xml,
+                   const char *keyring_tag,
+                   const char *uuid,
+                   const char *id,
+                   const char *entry,
+                   const char *combo,
+                   const char *desc)
+{
+	GnomeKeyringResult ret;
+	GtkWidget *widget;
+	const char *password;
+	GtkTreeModel *model;
+	gboolean saved = FALSE;
+
+	widget = glade_xml_get_widget (xml, combo);
+	g_assert (widget);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == PW_TYPE_SAVE) {
+		widget = glade_xml_get_widget (xml, entry);
+		g_assert (widget);
+		password = gtk_entry_get_text (GTK_ENTRY (widget));
+		if (password && strlen (password)) {
+			ret = keyring_helpers_save_secret (uuid, id, NULL, keyring_tag, password);
+			if (ret == GNOME_KEYRING_RESULT_OK)
+				saved = TRUE;
+			else
+				g_warning ("%s: failed to save %s to keyring.", __func__, desc);
+		}
+	}
+
+	if (!saved)
+		keyring_helpers_delete_secret (uuid, keyring_tag);
+}
+
+static gboolean
+save_secrets (NMVpnPluginUiWidgetInterface *iface,
+              NMConnection *connection,
+              GError **error)
+{
+	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (iface);
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	NMSettingConnection *s_con;
+	const char *str, *id, *uuid;
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	if (!s_con) {
+		g_set_error (error,
+		             VPNC_PLUGIN_UI_ERROR,
+		             VPNC_PLUGIN_UI_ERROR_INVALID_CONNECTION,
+		             "missing 'connection' setting");
+		return FALSE;
+	}
+
+	id = nm_setting_connection_get_id (s_con);
+	uuid = nm_setting_connection_get_uuid (s_con);
+
+	save_one_password (priv->xml, VPNC_USER_PASSWORD, uuid, id,
+	                   "user_password_entry", "user_pass_type_combo", "user password");
+	save_one_password (priv->xml, VPNC_GROUP_PASSWORD, uuid, id,
+	                   "group_password_entry", "group_pass_type_combo", "group password");
+
+	return TRUE;
+}
+
+static NMVpnPluginUiWidgetInterface *
+nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error)
+{
+	NMVpnPluginUiWidgetInterface *object;
+	VpncPluginUiWidgetPrivate *priv;
+	char *glade_file;
+
+	if (error)
+		g_return_val_if_fail (*error == NULL, NULL);
+
+	object = NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (VPNC_TYPE_PLUGIN_UI_WIDGET, NULL));
+	if (!object) {
+		g_set_error (error, VPNC_PLUGIN_UI_ERROR, 0, "could not create vpnc object");
+		return NULL;
+	}
+
+	priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (object);
+
+	glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-vpnc-dialog.glade");
+	priv->xml = glade_xml_new (glade_file, "vpnc-vbox", GETTEXT_PACKAGE);
+	if (priv->xml == NULL) {
+		g_set_error (error, VPNC_PLUGIN_UI_ERROR, 0,
+		             "could not load required resources at %s", glade_file);
+		g_free (glade_file);
+		g_object_unref (object);
+		return NULL;
+	}
+	g_free (glade_file);
+
+	priv->widget = glade_xml_get_widget (priv->xml, "vpnc-vbox");
+	if (!priv->widget) {
+		g_set_error (error, VPNC_PLUGIN_UI_ERROR, 0, "could not load UI widget");
+		g_object_unref (object);
+		return NULL;
+	}
+	g_object_ref_sink (priv->widget);
+
+	if (!init_plugin_ui (VPNC_PLUGIN_UI_WIDGET (object), connection, error)) {
+		g_object_unref (object);
+		return NULL;
+	}
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	VpncPluginUiWidget *plugin = VPNC_PLUGIN_UI_WIDGET (object);
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin);
+
+	if (priv->group)
+		g_object_unref (priv->group);
+
+	if (priv->widget)
+		g_object_unref (priv->widget);
+
+	if (priv->xml)
+		g_object_unref (priv->xml);
+
+	G_OBJECT_CLASS (vpnc_plugin_ui_widget_parent_class)->dispose (object);
+}
+
+static void
+vpnc_plugin_ui_widget_class_init (VpncPluginUiWidgetClass *req_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+	g_type_class_add_private (req_class, sizeof (VpncPluginUiWidgetPrivate));
+
+	object_class->dispose = dispose;
+}
+
+static void
+vpnc_plugin_ui_widget_init (VpncPluginUiWidget *plugin)
+{
+}
+
+static void
+vpnc_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class)
+{
+	/* interface implementation */
+	iface_class->get_widget = get_widget;
+	iface_class->update_connection = update_connection;
+	iface_class->save_secrets = save_secrets;
+}
+
+static void
+add_routes (NMSettingIP4Config *s_ip4, const char *routelist)
+{
+	char **substrs;
+	unsigned int i;
+
+	substrs = g_strsplit (routelist, " ", 0);
+	for (i = 0; substrs[i] != NULL; i++) {
+		struct in_addr tmp;
+		char *p, *str_route;
+		long int prefix = 32;
+
+		str_route = g_strdup (substrs[i]);
+		p = strchr (str_route, '/');
+		if (!p || !(*(p + 1))) {
+			g_warning ("Ignoring invalid route '%s'", str_route);
+			goto next;
+		}
+
+		errno = 0;
+		prefix = strtol (p + 1, NULL, 10);
+		if (errno || prefix <= 0 || prefix > 32) {
+			g_warning ("Ignoring invalid route '%s'", str_route);
+			goto next;
+		}
+
+		/* don't pass the prefix to inet_pton() */
+		*p = '\0';
+		if (inet_pton (AF_INET, str_route, &tmp) > 0) {
+			NMIP4Route *route = nm_ip4_route_new ();
+
+			nm_ip4_route_set_dest (route, tmp.s_addr);
+			nm_ip4_route_set_prefix (route, (guint32) prefix);
+
+			nm_setting_ip4_config_add_route (s_ip4, route);
+		} else
+			g_warning ("Ignoring invalid route '%s'", str_route);
+
+next:
+		g_free (str_route);
+	}
+
+	g_strfreev (substrs);
+}
+
+static void
+decrypt_child_finished_cb (GPid pid, gint status, gpointer userdata)
+{
+	int *child_status = (gint *) userdata;
+
+	*child_status = status;
+}
+
+static gboolean
+child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer userdata)
+{
+	char *str;
+	char **output = (char **) userdata;
+
+	if (*output || !(condition & (G_IO_IN | G_IO_ERR)))
+		return TRUE;
+
+	if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
+		int len;
+
+		len = strlen (str);
+		if (len > 0) {
+			/* remove terminating newline */
+			*output = g_strchomp (str);
+		} else
+			g_free (str);
+	}
+	return TRUE;
+}
+
+static char *
+decrypt_cisco_key (const char* enc_key)
+{
+	int child_stdout, child_status;
+	GPid child_pid;
+	guint32 ioid;
+	char *key = NULL;
+	GIOChannel *channel;
+	const char **decrypt_path;
+	GError *error = NULL;
+
+	const char *decrypt_possible_paths[] = {
+		"/usr/lib/vpnc/cisco-decrypt",
+		"/usr/bin/cisco-decrypt",
+		NULL
+	};
+
+	const char *argv[] = {
+		NULL, /* The path we figure out later. */
+		enc_key, /* The key in encrypted form */
+		NULL
+	};
+
+	/* Find the binary. */
+	decrypt_path = decrypt_possible_paths;
+	while (*decrypt_path != NULL){
+		if (g_file_test (*decrypt_path, G_FILE_TEST_EXISTS))
+			break;
+		++decrypt_path;
+	}
+
+	if (*decrypt_path == NULL){
+		g_warning ("Couldn't find cisco-decrypt.\n");
+		return NULL;
+	}
+
+	/* Now that we know where it is, we call the decrypter. */
+	argv[0] = *decrypt_path;
+	child_status = -1;
+
+	if (!g_spawn_async_with_pipes ("/", /* working directory */
+	                               (gchar **) argv, /* argv */
+	                               NULL , /* envp */
+	                               G_SPAWN_DO_NOT_REAP_CHILD, /* flags */
+	                               NULL, /* child setup */
+	                               NULL, /* user data */
+	                               &child_pid, /* child pid */
+	                               NULL, /* child stdin */
+	                               &child_stdout, /* child stdout */
+	                               NULL, /* child stderr */
+	                               &error)) { /* error */
+		/* The child did not spawn */
+		g_warning ("Error processing password: %s", error ? error->message : "(none)");
+		if (error)
+			g_error_free (error);
+		return NULL;
+	}
+
+	g_child_watch_add (child_pid, decrypt_child_finished_cb, (gpointer) &child_status);
+
+	/* Grab child output and wait for it to exit */
+	channel = g_io_channel_unix_new (child_stdout);
+	g_io_channel_set_encoding (channel, NULL, NULL);
+	ioid = g_io_add_watch (channel, G_IO_IN | G_IO_ERR, child_stdout_data_cb, &key);
+
+	while (child_status == -1) /* Wait until the child has finished. */
+		g_main_context_iteration (NULL, TRUE);
+
+	g_source_remove (ioid);
+	g_io_channel_shutdown (channel, TRUE, NULL);
+	g_io_channel_unref (channel);
+
+	return key;
+}
+
+static NMConnection *
+import (NMVpnPluginUiInterface *iface, const char *path, GError **error)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingVPN *s_vpn;
+	GHashTable *pcf;
+	const char *buf;
+	gboolean have_value;
+
+	pcf = pcf_file_load (path);
+	if (!pcf) {
+		g_set_error (error, 0, 0, "does not look like a %s VPN connection",
+		             VPNC_PLUGIN_NAME);
+		return NULL;
+	}
+
+	connection = nm_connection_new ();
+	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ());
+	g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, NM_DBUS_SERVICE_VPNC, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_vpn));
+
+	/* Connection name */
+	if ((buf = pcf_file_lookup_value (pcf, "main", "Description")))
+		g_object_set (s_con, NM_SETTING_CONNECTION_ID, buf, NULL);
+	else {
+		g_set_error (error, 0, 0, "does not look like a %s VPN connection (parse failed)",
+		             VPNC_PLUGIN_NAME);
+		g_object_unref (connection);
+		return NULL;
+	}
+
+	/* Gateway */
+	if ((buf = pcf_file_lookup_value (pcf, "main", "Host")))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_GATEWAY, buf);
+	else {
+		g_set_error (error, 0, 0, "does not look like a %s VPN connection (no Host)",
+		             VPNC_PLUGIN_NAME);
+		g_object_unref (connection);
+		return NULL;
+	}
+
+	/* Group name */
+	if ((buf = pcf_file_lookup_value (pcf, "main", "GroupName")))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_ID, buf);
+	else {
+		g_set_error (error, 0, 0, "does not look like a %s VPN connection (no GroupName)",
+		             VPNC_PLUGIN_NAME);
+		g_object_unref (connection);
+		return NULL;
+	}
+
+	/* Optional settings */
+
+	buf = pcf_file_lookup_value (pcf, "main", "UserName");
+	have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+	if (have_value)
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_XAUTH_USER, buf);
+
+	buf = pcf_file_lookup_value (pcf, "main", "UserPassword");
+	have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+	if (have_value)
+		nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD, buf);
+
+	buf = pcf_file_lookup_value (pcf, "main", "GroupPwd");
+	have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+	if (have_value)
+		nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_SECRET, buf);
+	else {
+		/* Handle encrypted passwords */
+		buf = pcf_file_lookup_value (pcf, "main", "enc_GroupPwd");
+		have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+		if (have_value) {
+			char *decrypted;
+
+			decrypted = decrypt_cisco_key (buf);
+			if (decrypted) {
+				nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_SECRET, decrypted);
+				memset (decrypted, 0, strlen (decrypted));
+				g_free (decrypted);
+			}
+		}
+	}
+
+	buf = pcf_file_lookup_value (pcf, "main", "NTDomain");
+	have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+	if (have_value)
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DOMAIN, buf);
+
+	buf = pcf_file_lookup_value (pcf, "main", "SingleDES");
+	have_value = (buf == NULL ? FALSE : strcmp (buf, "0") != 0);
+	if (have_value)
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_SINGLE_DES, "yes");
+
+	/* Default is enabled, only disabled if explicit EnableNat=0 exists */
+	buf = pcf_file_lookup_value (pcf, "main", "EnableNat");
+	have_value = (buf ? strncmp (buf, "0", 1) == 0 : FALSE);
+	if (have_value)
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, NM_VPNC_NATT_MODE_NATT);
+
+	if ((buf = pcf_file_lookup_value (pcf, "main", "PeerTimeout"))) {
+		long int val;
+
+		errno = 0;
+		val = strtol (buf, NULL, 10);
+		if ((errno == 0) && ((val == 0) || ((val >= 10) && (val <= 86400)))) {
+			char *tmp = g_strdup_printf ("%d", (gint) val);
+			nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT, tmp);
+			g_free (tmp);
+		}
+	}
+
+	buf = pcf_file_lookup_value (pcf, "main", "X-NM-Routes");
+	have_value = buf == NULL ? FALSE : strlen (buf) > 0;
+	if (have_value) {
+		NMSettingIP4Config *s_ip4;
+
+		s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+		nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+		add_routes (s_ip4, buf);
+	}
+
+	if ((buf = pcf_file_lookup_value (pcf, "main", "TunnelingMode"))) {
+		/* If applicable, put up warning that TCP tunneling will be disabled */
+
+		if (strncmp (buf, "1", 1) == 0) {
+			GtkWidget *dialog;
+			char *basename;
+
+			basename = g_path_get_basename (path);
+			dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+											 GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
+											 _("TCP tunneling not supported"));
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+													  _("The VPN settings file '%s' specifies that VPN traffic should be tunneled through TCP which is currently not supported in the vpnc software.\n\nThe connection can still be created, with TCP tunneling disabled, however it may not work as expected."), basename);
+			g_free (basename);
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+	}
+
+	g_hash_table_destroy (pcf);
+
+	return connection;
+}
+
+static gboolean
+export (NMVpnPluginUiInterface *iface,
+        const char *path,
+        NMConnection *connection,
+        GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingIP4Config *s_ip4;
+	NMSettingVPN *s_vpn;
+	FILE *f;
+	const char *value;
+	const char *gateway = NULL;
+	gboolean enablenat = TRUE;
+	gboolean singledes = FALSE;
+	const char *groupname = NULL;
+	const char *username = NULL;
+	const char *domain = NULL;
+	const char *peertimeout = NULL;
+	GString *routes = NULL;
+	gboolean success = FALSE;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+
+	s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+
+	f = fopen (path, "w");
+	if (!f) {
+		g_set_error (error, 0, 0, "could not open file for writing");
+		return FALSE;
+	}
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_GATEWAY);
+	if (value && strlen (value))
+		gateway = value;
+	else {
+		g_set_error (error, 0, 0, "connection was incomplete (missing gateway)");
+		goto done;
+	}
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_ID);
+	if (value && strlen (value))
+		groupname = value;
+	else {
+		g_set_error (error, 0, 0, "connection was incomplete (missing group)");
+		goto done;
+	}
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_USER);
+	if (value && strlen (value))
+		username = value;
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_DOMAIN);
+	if (value && strlen (value))
+		domain =  value;
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SINGLE_DES);
+	if (value && !strcmp (value, "yes"))
+		singledes = TRUE;
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE);
+	if (value && strlen (value) && strcmp (value, NM_VPNC_NATT_MODE_NONE))
+		enablenat = TRUE;
+
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT);
+	if (value && strlen (value))
+		peertimeout = value;
+
+	routes = g_string_new ("");
+	if (s_ip4 && nm_setting_ip4_config_get_num_routes (s_ip4)) {
+		int i;
+
+		for (i = 0; i < nm_setting_ip4_config_get_num_routes (s_ip4); i++) {
+			NMIP4Route *route = nm_setting_ip4_config_get_route (s_ip4, i);
+			char str_addr[INET_ADDRSTRLEN + 1];
+			struct in_addr num_addr;
+
+			if (routes->len)
+				g_string_append_c (routes, ' ');
+
+			num_addr.s_addr = nm_ip4_route_get_dest (route);
+			if (inet_ntop (AF_INET, &num_addr, &str_addr[0], INET_ADDRSTRLEN + 1))
+				g_string_append_printf (routes, "%s/%d", str_addr, nm_ip4_route_get_prefix (route));
+		}
+	}
+
+	fprintf (f, 
+		 "[main]\n"
+		 "Description=%s\n"
+		 "Host=%s\n"
+		 "AuthType=1\n"
+		 "GroupName=%s\n"
+		 "GroupPwd=\n"
+		 "EnableISPConnect=0\n"
+		 "ISPConnectType=0\n"
+		 "ISPConnect=\n"
+		 "ISPCommand=\n"
+		 "Username=%s\n"
+		 "SaveUserPassword=0\n"
+		 "EnableBackup=0\n"
+		 "BackupServer=\n"
+		 "EnableNat=%s\n"
+		 "CertStore=0\n"
+		 "CertName=\n"
+		 "CertPath=\n"
+		 "CertSubjectName=\n"
+		 "CertSerialHash=\n"
+		 "DHGroup=2\n"
+		 "ForceKeepAlives=0\n"
+		 "enc_GroupPwd=\n"
+		 "UserPassword=\n"
+		 "enc_UserPassword=\n"
+		 "NTDomain=%s\n"
+		 "EnableMSLogon=0\n"
+		 "MSLogonType=0\n"
+		 "TunnelingMode=0\n"
+		 "TcpTunnelingPort=10000\n"
+		 "PeerTimeout=%s\n"
+		 "EnableLocalLAN=1\n"
+		 "SendCertChain=0\n"
+		 "VerifyCertDN=\n"
+		 "EnableSplitDNS=1\n"
+		 "SingleDES=%s\n"
+		 "SPPhonebook=\n"
+		 "%s",
+		 /* Description */ nm_setting_connection_get_id (s_con),
+		 /* Host */        gateway,
+		 /* GroupName */   groupname,
+		 /* Username */    username != NULL ? username : "",
+		 /* EnableNat */   enablenat ? "1" : "0",
+		 /* NTDomain */    domain != NULL ? domain : "",
+		 /* PeerTimeout */ peertimeout != NULL ? peertimeout : "0",
+		 /* SingleDES */   singledes ? "1" : "0",
+		 /* X-NM-Routes */ routes->str ? routes->str : "");
+
+	success = TRUE;
+
+done:
+	if (routes)
+		g_string_free (routes, TRUE);
+	fclose (f);
+	return success;
+}
+
+static char *
+get_suggested_name (NMVpnPluginUiInterface *iface, NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+	const char *id;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_return_val_if_fail (s_con != NULL, NULL);
+
+	id = nm_setting_connection_get_id (s_con);
+	g_return_val_if_fail (id != NULL, NULL);
+
+	return g_strdup_printf ("%s.pcf", id);
+}
+
+static guint32
+get_capabilities (NMVpnPluginUiInterface *iface)
+{
+	return (NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT | NM_VPN_PLUGIN_UI_CAPABILITY_EXPORT);
+}
+
+static gboolean
+delete_connection (NMVpnPluginUiInterface *iface,
+                   NMConnection *connection,
+                   GError **error)
+{
+	NMSettingConnection *s_con;
+	const char *id, *uuid;
+
+	/* Remove any secrets in the keyring associated with this connection's UUID */
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	if (!s_con) {
+		g_set_error (error,
+		             VPNC_PLUGIN_UI_ERROR,
+		             VPNC_PLUGIN_UI_ERROR_INVALID_CONNECTION,
+		             "missing 'connection' setting");
+		return FALSE;
+	}
+
+	id = nm_setting_connection_get_id (s_con);
+	uuid = nm_setting_connection_get_uuid (s_con);
+
+	if (!keyring_helpers_delete_secret (uuid, VPNC_USER_PASSWORD))
+		g_message ("%s: couldn't delete user password for '%s'", __func__, id);
+
+	if (!keyring_helpers_delete_secret (uuid, VPNC_GROUP_PASSWORD))
+		g_message ("%s: couldn't delete group password for '%s'", __func__, id);
+
+	return TRUE;
+}
+
+static NMVpnPluginUiWidgetInterface *
+ui_factory (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error)
+{
+	return nm_vpn_plugin_ui_widget_interface_new (connection, error);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME:
+		g_value_set_string (value, VPNC_PLUGIN_NAME);
+		break;
+	case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC:
+		g_value_set_string (value, VPNC_PLUGIN_DESC);
+		break;
+	case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE:
+		g_value_set_string (value, VPNC_PLUGIN_SERVICE);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+vpnc_plugin_ui_class_init (VpncPluginUiClass *req_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+	object_class->get_property = get_property;
+
+	g_object_class_override_property (object_class,
+									  NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME,
+									  NM_VPN_PLUGIN_UI_INTERFACE_NAME);
+
+	g_object_class_override_property (object_class,
+									  NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC,
+									  NM_VPN_PLUGIN_UI_INTERFACE_DESC);
+
+	g_object_class_override_property (object_class,
+									  NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE,
+									  NM_VPN_PLUGIN_UI_INTERFACE_SERVICE);
+}
+
+static void
+vpnc_plugin_ui_init (VpncPluginUi *plugin)
+{
+}
+
+static void
+vpnc_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class)
+{
+	/* interface implementation */
+	iface_class->ui_factory = ui_factory;
+	iface_class->get_capabilities = get_capabilities;
+	iface_class->import = import;
+	iface_class->export = export;
+	iface_class->get_suggested_name = get_suggested_name;
+	iface_class->delete_connection = delete_connection;
+}
+
+
+G_MODULE_EXPORT NMVpnPluginUiInterface *
+nm_vpn_plugin_ui_factory (GError **error)
+{
+	if (error)
+		g_return_val_if_fail (*error == NULL, NULL);
+
+	return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (VPNC_TYPE_PLUGIN_UI, NULL));
+}
+

Added: trunk/properties/nm-vpnc.h
==============================================================================
--- (empty file)
+++ trunk/properties/nm-vpnc.h	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/***************************************************************************
+ * nm-vpnc.h : GNOME UI dialogs for configuring vpnc VPN connections
+ *
+ * Copyright (C) 2008 Dan Williams, <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _NM_VPNC_H_
+#define _NM_VPNC_H_
+
+#include <glib-object.h>
+
+typedef enum
+{
+	VPNC_PLUGIN_UI_ERROR_UNKNOWN = 0,
+	VPNC_PLUGIN_UI_ERROR_INVALID_PROPERTY,
+	VPNC_PLUGIN_UI_ERROR_MISSING_PROPERTY,
+	VPNC_PLUGIN_UI_ERROR_INVALID_CONNECTION
+} VpncPluginUiError;
+
+#define VPNC_TYPE_PLUGIN_UI_ERROR (vpnc_plugin_ui_error_get_type ()) 
+GType vpnc_plugin_ui_error_get_type (void);
+
+#define VPNC_TYPE_PLUGIN_UI            (vpnc_plugin_ui_get_type ())
+#define VPNC_PLUGIN_UI(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VPNC_TYPE_PLUGIN_UI, VpncPluginUi))
+#define VPNC_PLUGIN_UI_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), VPNC_TYPE_PLUGIN_UI, VpncPluginUiClass))
+#define VPNC_IS_PLUGIN_UI(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VPNC_TYPE_PLUGIN_UI))
+#define VPNC_IS_PLUGIN_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), VPNC_TYPE_PLUGIN_UI))
+#define VPNC_PLUGIN_UI_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), VPNC_TYPE_PLUGIN_UI, VpncPluginUiClass))
+
+typedef struct _VpncPluginUi VpncPluginUi;
+typedef struct _VpncPluginUiClass VpncPluginUiClass;
+
+struct _VpncPluginUi {
+	GObject parent;
+};
+
+struct _VpncPluginUiClass {
+	GObjectClass parent;
+};
+
+GType vpnc_plugin_ui_get_type (void);
+
+
+#define VPNC_TYPE_PLUGIN_UI_WIDGET            (vpnc_plugin_ui_widget_get_type ())
+#define VPNC_PLUGIN_UI_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VPNC_TYPE_PLUGIN_UI_WIDGET, VpncPluginUiWidget))
+#define VPNC_PLUGIN_UI_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), VPNC_TYPE_PLUGIN_UI_WIDGET, VpncPluginUiWidgetClass))
+#define VPNC_IS_PLUGIN_UI_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VPNC_TYPE_PLUGIN_UI_WIDGET))
+#define VPNC_IS_PLUGIN_UI_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), VPNC_TYPE_PLUGIN_UI_WIDGET))
+#define VPNC_PLUGIN_UI_WIDGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), VPNC_TYPE_PLUGIN_UI_WIDGET, VpncPluginUiWidgetClass))
+
+typedef struct _VpncPluginUiWidget VpncPluginUiWidget;
+typedef struct _VpncPluginUiWidgetClass VpncPluginUiWidgetClass;
+
+struct _VpncPluginUiWidget {
+	GObject parent;
+};
+
+struct _VpncPluginUiWidgetClass {
+	GObjectClass parent;
+};
+
+GType vpnc_plugin_ui_widget_get_type (void);
+
+#endif	/* _NM_VPNC_H_ */
+

Added: trunk/properties/pcf-file.c
==============================================================================
--- (empty file)
+++ trunk/properties/pcf-file.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "pcf-file.h"
+
+static void
+pcf_entry_free (PcfEntry *entry)
+{
+	if (entry) {
+		g_free (entry->key);
+		g_free (entry->value);
+		g_free (entry);
+	}
+}
+
+/*
+  The main reader loop here is based on the simple .ini file
+  parser from avahi/avahi-daemon/ini-file-parser.c
+*/
+
+GHashTable *
+pcf_file_load (const char *fname)
+{
+	FILE *fo;
+	unsigned line;
+    GHashTable *pcf;
+	GHashTable *group = NULL;
+    
+    g_return_val_if_fail (fname != NULL, NULL);
+
+    if (!(fo = fopen (fname, "r"))) {
+        g_warning ("Failed to open file '%s': %s", fname, strerror (errno));
+        return NULL;
+    }
+
+	pcf = g_hash_table_new_full (g_str_hash, g_str_equal,
+								 g_free,
+								 (GDestroyNotify) g_hash_table_destroy);
+
+    line = 0;
+    while (!feof (fo)) {
+        char ln[256], *s, *e;
+        
+        if (!(fgets (ln, sizeof (ln), fo)))
+            break;
+
+        line++;
+
+        s = ln + strspn (ln, " \t");
+        s[strcspn (s, "\r\n")] = 0;
+
+        /* Skip comments and empty lines */
+        if (*s == ';' || *s == 0)
+            continue;
+
+        if (*s == '[') {
+            /* new group */
+            
+            if (!(e = strchr (s, ']'))) {
+                g_warning ("Unclosed group header in %s:%u: <%s>", fname, line, s);
+                goto fail;
+            }
+
+            *e = 0;
+
+			group = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+										   (GDestroyNotify) pcf_entry_free);
+
+			g_hash_table_insert (pcf, g_utf8_strdown (s+1, -1), group);
+        } else {
+			PcfEntry *entry;
+
+            /* Normal assignment */
+            if (!(e = strchr (s, '='))) {
+                g_warning ("Missing assignment in %s:%u: <%s>", fname, line, s);
+                goto fail;
+            }
+            
+            if (!group) {
+                g_warning ("Assignment outside group in %s:%u <%s>", fname, line, s);
+                goto fail;
+            }
+            
+            /* Split the key and the value */
+            *(e++) = 0;
+
+			entry = g_new (PcfEntry, 1);
+			entry->value = g_strdup (e);
+
+			if (*s == '!') {
+				entry->key = g_utf8_strdown (s+1, -1);
+				entry->read_only = TRUE;
+			} else {
+				entry->key = g_utf8_strdown (s, -1);
+				entry->read_only = FALSE;
+			}
+
+			g_hash_table_insert (group, entry->key, entry);
+        }
+    }
+    
+    fclose (fo);
+        
+    return pcf;
+
+fail:
+
+    if (fo)
+        fclose (fo);
+
+    if (pcf)
+        g_hash_table_destroy (pcf);
+
+    return NULL;
+}
+
+PcfEntry *
+pcf_file_lookup (GHashTable *pcf_file,
+				 const char *group,
+				 const char *key)
+{
+	gpointer section;
+	PcfEntry *entry = NULL;
+	char *group_lower = NULL;
+	char *key_lower = NULL;
+
+	g_return_val_if_fail (pcf_file != NULL, NULL);
+	g_return_val_if_fail (group != NULL, NULL);
+	g_return_val_if_fail (key != NULL, NULL);
+
+	group_lower = g_utf8_strdown (group, -1);
+	section = g_hash_table_lookup (pcf_file, group_lower);
+	if (section) {
+		key_lower = g_utf8_strdown (key, -1);
+		entry = (PcfEntry *) g_hash_table_lookup ((GHashTable *) section, key_lower);
+	}
+
+	g_free (group_lower);
+	g_free (key_lower);
+
+	return entry;
+}
+
+const char *
+pcf_file_lookup_value (GHashTable *pcf_file,
+					   const char *group,
+					   const char *key)
+{
+	PcfEntry *entry;
+
+	entry = pcf_file_lookup (pcf_file, group, key);
+	if (entry)
+		return entry->value;
+
+	return NULL;
+}

Added: trunk/properties/pcf-file.h
==============================================================================
--- (empty file)
+++ trunk/properties/pcf-file.h	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,23 @@
+#ifndef PCF_FILE_H
+#define PCF_FILE_H
+
+#include <glib.h>
+
+typedef struct PcfEntry PcfEntry;
+
+struct PcfEntry {
+	char *key;
+	char *value;
+	gboolean read_only;
+};
+
+GHashTable  *pcf_file_load        (const char *fname);
+PcfEntry    *pcf_file_lookup      (GHashTable *pcf_file,
+								   const char *group,
+								   const char *key);
+
+const char *pcf_file_lookup_value (GHashTable *pcf_file,
+								   const char *group,
+								   const char *key);
+
+#endif /* PCF_FILE_H */

Added: trunk/src/.cvsignore
==============================================================================
--- (empty file)
+++ trunk/src/.cvsignore	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,4 @@
+Makefile.in
+Makefile
+nm-vpnc-service
+nm-vpnc-service-vpnc-helper

Added: trunk/src/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/Makefile.am	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,40 @@
+INCLUDES = -I${top_srcdir} 
+
+AM_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GTHREAD_CFLAGS) \
+	$(NM_UTILS_CFLAGS) \
+	-DDBUS_API_SUBJECT_TO_CHANGE \
+	-DG_DISABLE_DEPRECATED \
+	-DBINDIR=\"$(bindir)\" \
+	-DPREFIX=\""$(prefix)"\" \
+	-DSYSCONFDIR=\""$(sysconfdir)"\" \
+	-DVERSION="\"$(VERSION)\"" \
+	-DLIBDIR=\""$(libdir)"\" \
+	-DLIBEXECDIR=\""$(libexecdir)"\" \
+	-DLOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DDATADIR=\"$(datadir)\"
+
+libexec_PROGRAMS = nm-vpnc-service nm-vpnc-service-vpnc-helper
+
+nm_vpnc_service_SOURCES = \
+				nm-vpnc-service.c \
+				nm-vpnc-service.h
+
+
+nm_vpnc_service_LDADD = \
+				$(DBUS_LIBS) \
+				$(GTHREAD_LIBS) \
+				$(NM_UTILS_LIBS) \
+				-lnm_glib_vpn
+
+
+nm_vpnc_service_vpnc_helper_SOURCES = \
+				nm-vpnc-service-vpnc-helper.c
+
+nm_vpnc_service_vpnc_helper_LDADD = \
+				$(DBUS_LIBS) \
+				$(GTHREAD_LIBS) \
+				$(NM_UTILS_LIBS)
+
+CLEANFILES = *~

Added: trunk/src/nm-vpnc-service-vpnc-helper.c
==============================================================================
--- (empty file)
+++ trunk/src/nm-vpnc-service-vpnc-helper.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,380 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* nm-vpnc-service - vpnc integration with NetworkManager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+#include <NetworkManager.h>
+
+#include "nm-vpnc-service.h"
+#include "nm-utils.h"
+
+/* These are here because nm-dbus-glib-types.h isn't exported */
+#define DBUS_TYPE_G_ARRAY_OF_UINT          (dbus_g_type_get_collection ("GArray", G_TYPE_UINT))
+#define DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_ARRAY_OF_UINT))
+
+static void
+helper_failed (DBusGConnection *connection, const char *reason)
+{
+	DBusGProxy *proxy;
+	GError *err = NULL;
+
+	nm_warning ("nm-nvpnc-service-vpnc-helper did not receive a valid %s from vpnc", reason);
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+								NM_DBUS_SERVICE_VPNC,
+								NM_VPN_DBUS_PLUGIN_PATH,
+								NM_VPN_DBUS_PLUGIN_INTERFACE);
+
+	dbus_g_proxy_call (proxy, "SetFailure", &err,
+				    G_TYPE_STRING, reason,
+				    G_TYPE_INVALID,
+				    G_TYPE_INVALID);
+
+	if (err) {
+		nm_warning ("Could not send failure information: %s", err->message);
+		g_error_free (err);
+	}
+
+	g_object_unref (proxy);
+
+	exit (1);
+}
+
+static void
+send_ip4_config (DBusGConnection *connection, GHashTable *config)
+{
+	DBusGProxy *proxy;
+	GError *err = NULL;
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+								NM_DBUS_SERVICE_VPNC,
+								NM_VPN_DBUS_PLUGIN_PATH,
+								NM_VPN_DBUS_PLUGIN_INTERFACE);
+
+	dbus_g_proxy_call (proxy, "SetIp4Config", &err,
+				    dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+				    config,
+				    G_TYPE_INVALID,
+				    G_TYPE_INVALID);
+
+	if (err) {
+		nm_warning ("Could not send failure information: %s", err->message);
+		g_error_free (err);
+	}
+
+	g_object_unref (proxy);
+}
+
+static GValue *
+str_to_gvalue (const char *str, gboolean try_convert)
+{
+	GValue *val;
+
+	/* Empty */
+	if (!str || strlen (str) < 1)
+		return NULL;
+
+	if (!g_utf8_validate (str, -1, NULL)) {
+		if (try_convert && !(str = g_convert (str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL)))
+			str = g_convert (str, -1, "C", "UTF-8", NULL, NULL, NULL);
+
+		if (!str)
+			/* Invalid */
+			return NULL;
+	}
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, G_TYPE_STRING);
+	g_value_set_string (val, str);
+
+	return val;
+}
+
+static GValue *
+uint_to_gvalue (guint32 num)
+{
+	GValue *val;
+
+	if (num == 0)
+		return NULL;
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, G_TYPE_UINT);
+	g_value_set_uint (val, num);
+
+	return val;
+}
+
+static GValue *
+addr_to_gvalue (const char *str)
+{
+	struct in_addr	temp_addr;
+
+	/* Empty */
+	if (!str || strlen (str) < 1)
+		return NULL;
+
+	if (inet_pton (AF_INET, str, &temp_addr) <= 0)
+		return NULL;
+
+	return uint_to_gvalue (temp_addr.s_addr);
+}
+
+static GValue *
+addr_list_to_gvalue (const char *str)
+{
+	GValue *val;
+	char **split;
+	int i;
+	GArray *array;
+
+	/* Empty */
+	if (!str || strlen (str) < 1)
+		return NULL;
+
+	split = g_strsplit (str, " ", -1);
+	if (g_strv_length (split) == 0)
+		return NULL;
+
+	array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), g_strv_length (split));
+	for (i = 0; split[i]; i++) {
+		struct in_addr addr;
+
+		if (inet_pton (AF_INET, split[i], &addr) > 0) {
+			g_array_append_val (array, addr.s_addr);
+		} else {
+			g_strfreev (split);
+			g_array_free (array, TRUE);
+			return NULL;
+		}
+	}
+
+	g_strfreev (split);
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
+	g_value_set_boxed (val, array);
+
+	return val;
+}
+
+static GValue *
+get_routes (void)
+{
+	GValue *value = NULL;
+	GPtrArray *routes;
+	char *tmp;
+	int num;
+	int i;
+
+#define BUFLEN 256
+
+	tmp = getenv ("CISCO_SPLIT_INC");
+	if (!tmp || strlen (tmp) < 1)
+		return NULL;
+
+	num = atoi (tmp);
+	if (!num)
+		return NULL;
+
+	routes = g_ptr_array_new ();
+
+	for (i = 0; i < num; i++) {
+		GArray *array;
+		char buf[BUFLEN];
+		struct in_addr network;
+		guint32 next_hop = 0; /* no next hop */
+		guint32 prefix, metric = 0;
+
+		snprintf (buf, BUFLEN, "CISCO_SPLIT_INC_%d_ADDR", i);
+		tmp = getenv (buf);
+		if (!tmp || inet_pton (AF_INET, tmp, &network) <= 0) {
+			nm_warning ("Ignoring invalid static route address '%s'", tmp ? tmp : "NULL");
+			continue;
+		}
+
+		snprintf (buf, BUFLEN, "CISCO_SPLIT_INC_%d_MASKLEN", i);
+		tmp = getenv (buf);
+		if (tmp) {
+			long int tmp_prefix;
+
+			errno = 0;
+			tmp_prefix = strtol (tmp, NULL, 10);
+			if (errno || tmp_prefix <= 0 || tmp_prefix > 32) {
+				nm_warning ("Ignoring invalid static route prefix '%s'", tmp ? tmp : "NULL");
+				continue;
+			}
+			prefix = (guint32) tmp_prefix;
+		} else {
+			struct in_addr netmask;
+
+			snprintf (buf, BUFLEN, "CISCO_SPLIT_INC_%d_MASK", i);
+			tmp = getenv (buf);
+			if (!tmp || inet_pton (AF_INET, tmp, &netmask) <= 0) {
+				nm_warning ("Ignoring invalid static route netmask '%s'", tmp ? tmp : "NULL");
+				continue;
+			}
+			prefix = nm_utils_ip4_netmask_to_prefix (netmask.s_addr);
+		}
+
+		array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4);
+		g_array_append_val (array, network.s_addr);
+		g_array_append_val (array, prefix);
+		g_array_append_val (array, next_hop);
+		g_array_append_val (array, metric);
+		g_ptr_array_add (routes, array);
+	}
+
+	if (routes->len > 0) {
+		value = g_new0 (GValue, 1);
+		g_value_init (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT);
+		g_value_take_boxed (value, routes);
+	} else
+		g_ptr_array_free (routes, TRUE);
+
+	return value;
+}
+
+/*
+ * Environment variables passed back from 'vpnc':
+ *
+ * VPNGATEWAY             -- vpn gateway address (always present)
+ * TUNDEV                 -- tunnel device (always present)
+ * INTERNAL_IP4_ADDRESS   -- address (always present)
+ * INTERNAL_IP4_NETMASK   -- netmask (often unset)
+ * INTERNAL_IP4_DNS       -- list of dns serverss
+ * INTERNAL_IP4_NBNS      -- list of wins servers
+ * CISCO_DEF_DOMAIN       -- default domain name
+ * CISCO_BANNER           -- banner from server
+ *
+ */
+int 
+main (int argc, char *argv[])
+{
+	DBusGConnection *connection;
+	char *tmp;
+	GHashTable *config;
+	GValue *val;
+	GError *err = NULL;
+	struct in_addr temp_addr;
+
+	g_type_init ();
+
+	/* vpnc 0.3.3 gives us a "reason" code.  If we are given one,
+	 * don't proceed unless its "connect".
+	 */
+	tmp = getenv ("reason");
+	if (tmp && strcmp (tmp, "connect") != 0)
+		exit (0);
+
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+	if (!connection) {
+		nm_warning ("Could not get the system bus: %s", err->message);
+		exit (1);
+	}
+
+	config = g_hash_table_new (g_str_hash, g_str_equal);
+
+	/* Gateway */
+	val = addr_to_gvalue (getenv ("VPNGATEWAY"));
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val);
+	else
+		helper_failed (connection, "VPN Gateway");
+
+	/* Tunnel device */
+	val = str_to_gvalue (getenv ("TUNDEV"), FALSE);
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
+	else
+		helper_failed (connection, "Tunnel Device");
+
+	/* IP address */
+	val = addr_to_gvalue (getenv ("INTERNAL_IP4_ADDRESS"));
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
+	else
+		helper_failed (connection, "IP4 Address");
+
+	/* PTP address; for vpnc PTP address == internal IP4 address */
+	val = addr_to_gvalue (getenv ("INTERNAL_IP4_ADDRESS"));
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_PTP, val);
+	else
+		helper_failed (connection, "IP4 PTP Address");
+
+	/* Netmask */
+	tmp = getenv ("INTERNAL_IP4_NETMASK");
+	if (tmp && inet_pton (AF_INET, tmp, &temp_addr) > 0) {
+		GValue *val;
+
+		val = g_slice_new0 (GValue);
+		g_value_init (val, G_TYPE_UINT);
+		g_value_set_uint (val, nm_utils_ip4_netmask_to_prefix (temp_addr.s_addr));
+
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+	}
+
+	/* DNS */
+	val = addr_list_to_gvalue (getenv ("INTERNAL_IP4_DNS"));
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
+
+	/* WINS servers */
+	val = addr_list_to_gvalue (getenv ("INTERNAL_IP4_NBNS"));
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
+
+	/* Default domain */
+	val = str_to_gvalue (getenv ("CISCO_DEF_DOMAIN"), TRUE);
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN, val);
+
+	/* Routes */
+	val = get_routes ();
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, val);
+
+	/* Banner */
+	val = str_to_gvalue (getenv ("CISCO_BANNER"), TRUE);
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, val);
+
+	/* Set MTU to 1412 */
+	val = uint_to_gvalue (1412);
+	if (val)
+		g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, val);
+
+	/* Send the config info to nm-vpnc-service */
+	send_ip4_config (connection, config);
+
+	exit (0);
+}

Added: trunk/src/nm-vpnc-service.c
==============================================================================
--- (empty file)
+++ trunk/src/nm-vpnc-service.c	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,598 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include <nm-setting-vpn.h>
+#include "nm-vpnc-service.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMVPNCPlugin, nm_vpnc_plugin, NM_TYPE_VPN_PLUGIN)
+
+typedef struct {
+	GPid pid;
+} NMVPNCPluginPrivate;
+
+#define NM_VPNC_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginPrivate))
+
+static const char *vpnc_binary_paths[] =
+{
+	"/usr/sbin/vpnc",
+	"/sbin/vpnc",
+	"/usr/local/sbin/vpnc",
+	NULL
+};
+
+#define NM_VPNC_HELPER_PATH		LIBEXECDIR"/nm-vpnc-service-vpnc-helper"
+#define NM_VPNC_UDP_ENCAPSULATION_PORT	0 /* random port */
+
+typedef struct {
+	const char *name;
+	GType type;
+	gint int_min;
+	gint int_max;
+} ValidProperty;
+
+#define LEGACY_NAT_KEEPALIVE "NAT-Keepalive packet interval"
+
+static ValidProperty valid_properties[] = {
+	{ NM_VPNC_KEY_GATEWAY,               G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_ID,                    G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_USER,            G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_DOMAIN,                G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_DHGROUP,               G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_PERFECT_FORWARD,       G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_APP_VERSION,           G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_SINGLE_DES,            G_TYPE_BOOLEAN, 0, 0 },
+	{ NM_VPNC_KEY_NO_ENCRYPTION,         G_TYPE_BOOLEAN, 0, 0 },
+	{ NM_VPNC_KEY_DPD_IDLE_TIMEOUT,      G_TYPE_INT, 0, 86400 },
+	{ NM_VPNC_KEY_NAT_TRAVERSAL_MODE,    G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT, G_TYPE_INT, 0, 65535 },
+	/* Ignored option for internal use */
+	{ NM_VPNC_KEY_SECRET_TYPE,           G_TYPE_NONE, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_PASSWORD_TYPE,   G_TYPE_NONE, 0, 0 },
+	/* Legacy options that are ignored */
+	{ LEGACY_NAT_KEEPALIVE,              G_TYPE_STRING, 0, 0 },
+	{ NULL,                              G_TYPE_NONE, 0, 0 }
+};
+
+static ValidProperty valid_secrets[] = {
+	{ NM_VPNC_KEY_SECRET,                G_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_PASSWORD,        G_TYPE_STRING, 0, 0 },
+	{ NULL,                              G_TYPE_NONE, 0, 0 }
+};
+
+typedef struct ValidateInfo {
+	ValidProperty *table;
+	GError **error;
+	gboolean have_items;
+} ValidateInfo;
+
+static void
+validate_one_property (const char *key, const char *value, gpointer user_data)
+{
+	ValidateInfo *info = (ValidateInfo *) user_data;
+	int i;
+
+	if (*(info->error))
+		return;
+
+	info->have_items = TRUE;
+
+	/* 'name' is the setting name; always allowed but unused */
+	if (!strcmp (key, NM_SETTING_NAME))
+		return;
+
+	for (i = 0; info->table[i].name; i++) {
+		ValidProperty prop = info->table[i];
+		long int tmp;
+
+		if (strcmp (prop.name, key))
+			continue;
+
+		switch (prop.type) {
+		case G_TYPE_NONE:
+			return; /* technically valid, but unused */
+		case G_TYPE_STRING:
+			return; /* valid */
+		case G_TYPE_INT:
+			errno = 0;
+			tmp = strtol (value, NULL, 10);
+			if (errno == 0 && tmp >= prop.int_min && tmp <= prop.int_max)
+				return; /* valid */
+
+			g_set_error (info->error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+			             "invalid integer property '%s' or out of range [%d -> %d]",
+			             key, prop.int_min, prop.int_max);
+			break;
+		case G_TYPE_BOOLEAN:
+			if (!strcmp (value, "yes") || !strcmp (value, "no"))
+				return; /* valid */
+
+			g_set_error (info->error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+			             "invalid boolean property '%s' (not yes or no)",
+			             key);
+			break;
+		default:
+			g_set_error (info->error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+			             "unhandled property '%s' type %s",
+			             key, g_type_name (prop.type));
+			break;
+		}
+	}
+
+	/* Did not find the property from valid_properties or the type did not match */
+	if (!info->table[i].name) {
+		g_set_error (info->error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "property '%s' invalid or not supported",
+		             key);
+	}
+}
+
+static gboolean
+nm_vpnc_properties_validate (NMSettingVPN *s_vpn, GError **error)
+{
+	ValidateInfo info = { &valid_properties[0], error, FALSE };
+
+	nm_setting_vpn_foreach_data_item (s_vpn, validate_one_property, &info);
+	if (!info.have_items) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "%s",
+		             "No VPN configuration options.");
+		return FALSE;
+	}
+
+	return *error ? FALSE : TRUE;
+}
+
+static gboolean
+nm_vpnc_secrets_validate (NMSettingVPN *s_vpn, GError **error)
+{
+	ValidateInfo info = { &valid_secrets[0], error, FALSE };
+
+	nm_setting_vpn_foreach_secret (s_vpn, validate_one_property, &info);
+	if (!info.have_items) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "%s",
+		             "No VPN secrets!");
+		return FALSE;
+	}
+
+	return *error ? FALSE : TRUE;
+}
+
+static void
+vpnc_watch_cb (GPid pid, gint status, gpointer user_data)
+{
+	NMVPNCPlugin *plugin = NM_VPNC_PLUGIN (user_data);
+	NMVPNCPluginPrivate *priv = NM_VPNC_PLUGIN_GET_PRIVATE (plugin);
+	guint error = 0;
+
+	if (WIFEXITED (status)) {
+		error = WEXITSTATUS (status);
+		if (error != 0)
+			nm_warning ("vpnc exited with error code %d", error);
+	}
+	else if (WIFSTOPPED (status))
+		nm_warning ("vpnc stopped unexpectedly with signal %d", WSTOPSIG (status));
+	else if (WIFSIGNALED (status))
+		nm_warning ("vpnc died with signal %d", WTERMSIG (status));
+	else
+		nm_warning ("vpnc died from an unknown cause");
+
+	/* Reap child if needed. */
+	waitpid (priv->pid, NULL, WNOHANG);
+	priv->pid = 0;
+
+	/* Must be after data->state is set since signals use data->state */
+	switch (error) {
+	case 2:
+		/* Couldn't log in due to bad user/pass */
+		nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
+		break;
+	case 1:
+		/* Other error (couldn't bind to address, etc) */
+		nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
+		break;
+	default:
+		break;
+	}
+
+	nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED);
+}
+
+static gint
+nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin, GError **error)
+{
+	GPid	pid;
+	const char **vpnc_binary = NULL;
+	GPtrArray *vpnc_argv;
+	GSource *vpnc_watch;
+	gint	stdin_fd;
+
+	/* Find vpnc */
+	vpnc_binary = vpnc_binary_paths;
+	while (*vpnc_binary != NULL) {
+		if (g_file_test (*vpnc_binary, G_FILE_TEST_EXISTS))
+			break;
+		vpnc_binary++;
+	}
+
+	if (!*vpnc_binary) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+		             "%s",
+		             "Could not find vpnc binary.");
+		return -1;
+	}
+
+	vpnc_argv = g_ptr_array_new ();
+	g_ptr_array_add (vpnc_argv, (gpointer) (*vpnc_binary));
+	g_ptr_array_add (vpnc_argv, (gpointer) "--non-inter");
+	g_ptr_array_add (vpnc_argv, (gpointer) "--no-detach");
+	g_ptr_array_add (vpnc_argv, (gpointer) "-");
+	g_ptr_array_add (vpnc_argv, NULL);
+
+	if (!g_spawn_async_with_pipes (NULL, (char **) vpnc_argv->pdata, NULL,
+							 G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd,
+							 NULL, NULL, error)) {
+		g_ptr_array_free (vpnc_argv, TRUE);
+		nm_warning ("vpnc failed to start.  error: '%s'", (*error)->message);
+		return -1;
+	}
+	g_ptr_array_free (vpnc_argv, TRUE);
+
+	nm_info ("vpnc started with pid %d", pid);
+
+	NM_VPNC_PLUGIN_GET_PRIVATE (plugin)->pid = pid;
+	vpnc_watch = g_child_watch_source_new (pid);
+	g_source_set_callback (vpnc_watch, (GSourceFunc) vpnc_watch_cb, plugin, NULL);
+	g_source_attach (vpnc_watch, NULL);
+	g_source_unref (vpnc_watch);
+
+	return stdin_fd;
+}
+
+static inline void
+write_config_option (int fd, const char *format, ...)
+{
+	char * 	string;
+	va_list	args;
+	int		x;
+
+	va_start (args, format);
+	string = g_strdup_vprintf (format, args);
+	x = write (fd, string, strlen (string));
+	g_free (string);
+	va_end (args);
+}
+
+typedef struct {
+	int fd;
+	GError *error;
+	gboolean upw_ignored;
+	gboolean gpw_ignored;
+} WriteConfigInfo;
+
+static void
+write_one_property (const char *key, const char *value, gpointer user_data)
+{
+	WriteConfigInfo *info = (WriteConfigInfo *) user_data;
+	GType type = G_TYPE_INVALID;
+	int i;
+
+	if (info->error)
+		return;
+
+	/* Find the value in the table to get its type */
+	for (i = 0; valid_properties[i].name; i++) {
+		ValidProperty prop = valid_properties[i];
+
+		if (!strcmp (prop.name, (char *) key)) {
+  			/* Property is ok */
+  			type = prop.type;
+			break;
+		}
+	}
+
+	/* Try the valid secrets table */
+	for (i = 0; type == G_TYPE_INVALID && valid_secrets[i].name; i++) {
+		ValidProperty prop = valid_secrets[i];
+
+		if (!strcmp (prop.name, (char *) key)) {
+  			/* Property is ok */
+  			type = prop.type;
+			break;
+		}
+	}
+
+	if (type == G_TYPE_INVALID) {
+		g_set_error (&info->error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "Config option '%s' invalid or unknown.",
+		             (const char *) key);
+	}	
+
+	/* Don't write ignored secrets */
+	if (!strcmp (key, NM_VPNC_KEY_XAUTH_PASSWORD) && info->upw_ignored)
+		return;
+	if (!strcmp (key, NM_VPNC_KEY_SECRET) && info->gpw_ignored)
+		return;
+
+	if (type == G_TYPE_STRING)
+		write_config_option (info->fd, "%s %s\n", (char *) key, (char *) value);
+	else if (type == G_TYPE_BOOLEAN) {
+		if (!strcmp (value, "yes"))
+			write_config_option (info->fd, "%s\n", (char *) key);
+	} else if (type == G_TYPE_INT) {
+		long int tmp_int;
+		char *tmp_str;
+
+		/* Convert -> int and back to string for security's sake since
+		 * strtol() ignores leading and trailing characters.
+		 */
+		errno = 0;
+		tmp_int = strtol (value, NULL, 10);
+		if (errno == 0) {
+			tmp_str = g_strdup_printf ("%ld", tmp_int);
+			write_config_option (info->fd, "%s %s\n", (char *) key, tmp_str);
+			g_free (tmp_str);
+		} else {
+			g_set_error (&info->error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+			             "Config option '%s' not an integer.",
+			             (const char *) key);
+		}
+	} else if (type == G_TYPE_NONE) {
+		/* ignored */
+	} else {
+		/* Just ignore unknown properties */
+		nm_warning ("Don't know how to write property '%s' with type %s",
+				  (char *) key, g_type_name (type));
+	}
+}
+
+static gboolean
+nm_vpnc_config_write (gint vpnc_fd,
+                      NMSettingVPN *s_vpn,
+                      GError **error)
+{
+	WriteConfigInfo *info;
+	const char *props_username;
+	const char *props_natt_mode;
+	const char *default_username;
+	const char *pw_type;
+
+	default_username = nm_setting_vpn_get_user_name (s_vpn);
+
+	write_config_option (vpnc_fd, "Script " NM_VPNC_HELPER_PATH "\n");
+
+	write_config_option (vpnc_fd,
+	                     NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT " %d\n",
+	                     NM_VPNC_UDP_ENCAPSULATION_PORT);
+
+	/* Fill username if it's not present */
+	props_username = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_USER);
+	if (   default_username
+	    && strlen (default_username)
+	    && (!props_username || !strlen (props_username))) {
+		write_config_option (vpnc_fd,
+		                     NM_VPNC_KEY_XAUTH_USER " %s\n",
+		                     default_username);
+	}
+	
+	/* Use Cisco UDP by default */
+	props_natt_mode = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE);
+	if (!props_natt_mode || !strlen (props_natt_mode)) {
+		write_config_option (vpnc_fd,
+		                     NM_VPNC_KEY_NAT_TRAVERSAL_MODE " %s\n",
+		                     NM_VPNC_NATT_MODE_CISCO);
+	}
+
+	info = g_malloc0 (sizeof (WriteConfigInfo));
+	info->fd = vpnc_fd;
+
+	/* Check for ignored user password */
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	if (pw_type && !strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED))
+		info->upw_ignored = TRUE;
+
+	/* Check for ignored group password */
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SECRET_TYPE);
+	if (pw_type && !strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED))
+		info->gpw_ignored = TRUE;
+
+	nm_setting_vpn_foreach_data_item (s_vpn, write_one_property, info);
+	nm_setting_vpn_foreach_secret (s_vpn, write_one_property, info);
+	*error = info->error;
+	g_free (info);
+
+	return *error ? FALSE : TRUE;
+}
+
+static gboolean
+real_connect (NMVPNPlugin   *plugin,
+              NMConnection  *connection,
+              GError       **error)
+{
+	NMSettingVPN *s_vpn;
+	gint vpnc_fd = -1;
+	gboolean success = FALSE;
+
+	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
+	g_assert (s_vpn);
+
+	if (!nm_vpnc_properties_validate (s_vpn, error))
+		goto out;
+	if (!nm_vpnc_secrets_validate (s_vpn, error))
+		goto out;
+
+	vpnc_fd = nm_vpnc_start_vpnc_binary (NM_VPNC_PLUGIN (plugin), error);
+	if (vpnc_fd < 0)
+		goto out;
+
+	if (!nm_vpnc_config_write (vpnc_fd, s_vpn, error))
+		goto out;
+
+	success = TRUE;
+
+out:
+	if (vpnc_fd >= 0)
+		close (vpnc_fd);
+	return success;
+}
+
+static gboolean
+real_need_secrets (NMVPNPlugin *plugin,
+                   NMConnection *connection,
+                   char **setting_name,
+                   GError **error)
+{
+	NMSettingVPN *s_vpn;
+	const char *pw_type;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
+	if (!s_vpn) {
+        g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
+		             "%s",
+		             "Could not process the request because the VPN connection settings were invalid.");
+		return FALSE;
+	}
+
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SECRET_TYPE);
+	if (!pw_type || strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET)) {
+			*setting_name = NM_SETTING_VPN_SETTING_NAME;
+			return TRUE;
+		}
+	}
+
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	if (!pw_type || strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD)) {
+			*setting_name = NM_SETTING_VPN_SETTING_NAME;
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static gboolean
+ensure_killed (gpointer data)
+{
+	int pid = GPOINTER_TO_INT (data);
+
+	if (kill (pid, 0) == 0)
+		kill (pid, SIGKILL);
+
+	return FALSE;
+}
+
+static gboolean
+real_disconnect (NMVPNPlugin   *plugin,
+			  GError       **err)
+{
+	NMVPNCPluginPrivate *priv = NM_VPNC_PLUGIN_GET_PRIVATE (plugin);
+
+	if (priv->pid) {
+		if (kill (priv->pid, SIGTERM) == 0)
+			g_timeout_add (2000, ensure_killed, GINT_TO_POINTER (priv->pid));
+		else
+			kill (priv->pid, SIGKILL);
+
+		nm_info ("Terminated vpnc daemon with PID %d.", priv->pid);
+		priv->pid = 0;
+	}
+
+	return TRUE;
+}
+
+static void
+nm_vpnc_plugin_init (NMVPNCPlugin *plugin)
+{
+}
+
+static void
+nm_vpnc_plugin_class_init (NMVPNCPluginClass *vpnc_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (vpnc_class);
+	NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS (vpnc_class);
+
+	g_type_class_add_private (object_class, sizeof (NMVPNCPluginPrivate));
+
+	/* virtual methods */
+	parent_class->connect    = real_connect;
+	parent_class->need_secrets = real_need_secrets;
+	parent_class->disconnect = real_disconnect;
+}
+
+NMVPNCPlugin *
+nm_vpnc_plugin_new (void)
+{
+	return (NMVPNCPlugin *) g_object_new (NM_TYPE_VPNC_PLUGIN,
+								   NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_VPNC,
+								   NULL);
+}
+
+static void
+quit_mainloop (NMVPNCPlugin *plugin, gpointer user_data)
+{
+	g_main_loop_quit ((GMainLoop *) user_data);
+}
+
+int
+main (int argc, char *argv[])
+{
+	NMVPNCPlugin *plugin;
+	GMainLoop *main_loop;
+
+	g_type_init ();
+
+	if (system ("/sbin/modprobe tun") == -1)
+		exit (EXIT_FAILURE);
+
+	plugin = nm_vpnc_plugin_new ();
+	if (!plugin)
+		exit (EXIT_FAILURE);
+
+	main_loop = g_main_loop_new (NULL, FALSE);
+
+	g_signal_connect (plugin, "quit",
+				   G_CALLBACK (quit_mainloop),
+				   main_loop);
+
+	g_main_loop_run (main_loop);
+
+	g_main_loop_unref (main_loop);
+	g_object_unref (plugin);
+
+	exit (EXIT_SUCCESS);
+}

Added: trunk/src/nm-vpnc-service.h
==============================================================================
--- (empty file)
+++ trunk/src/nm-vpnc-service.h	Thu Dec 11 19:45:12 2008
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_VPNC_PLUGIN_H
+#define NM_VPNC_PLUGIN_H
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include <nm-vpn-plugin.h>
+
+#define NM_TYPE_VPNC_PLUGIN            (nm_vpnc_plugin_get_type ())
+#define NM_VPNC_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPNC_PLUGIN, NMVPNCPlugin))
+#define NM_VPNC_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginClass))
+#define NM_IS_VPNC_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPNC_PLUGIN))
+#define NM_IS_VPNC_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPNC_PLUGIN))
+#define NM_VPNC_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginClass))
+
+#define NM_DBUS_SERVICE_VPNC    "org.freedesktop.NetworkManager.vpnc"
+#define NM_DBUS_INTERFACE_VPNC  "org.freedesktop.NetworkManager.vpnc"
+#define NM_DBUS_PATH_VPNC       "/org/freedesktop/NetworkManager/vpnc"
+
+#define NM_VPNC_KEY_GATEWAY "IPSec gateway"
+#define NM_VPNC_KEY_ID "IPSec ID"
+#define NM_VPNC_KEY_SECRET "IPSec secret"
+#define NM_VPNC_KEY_SECRET_TYPE "ipsec-secret-type"
+#define NM_VPNC_KEY_XAUTH_USER "Xauth username"
+#define NM_VPNC_KEY_XAUTH_PASSWORD "Xauth password"
+#define NM_VPNC_KEY_XAUTH_PASSWORD_TYPE "xauth-password-type"
+#define NM_VPNC_KEY_DOMAIN "Domain"
+#define NM_VPNC_KEY_DHGROUP "IKE DH Group"
+#define NM_VPNC_KEY_PERFECT_FORWARD "Perfect Forward Secrecy"
+#define NM_VPNC_KEY_APP_VERSION "Application Version"
+#define NM_VPNC_KEY_SINGLE_DES "Enable Single DES"
+#define NM_VPNC_KEY_NO_ENCRYPTION "Enable no encryption"
+#define NM_VPNC_KEY_NAT_TRAVERSAL_MODE "NAT Traversal Mode"
+#define NM_VPNC_KEY_DPD_IDLE_TIMEOUT "DPD idle timeout (our side)"
+#define NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT "Cisco UDP Encapsulation Port"
+
+#define NM_VPNC_NATT_MODE_NATT "natt"
+#define NM_VPNC_NATT_MODE_NONE "none"
+#define NM_VPNC_NATT_MODE_CISCO "cisco-udp"
+
+#define NM_VPNC_PW_TYPE_SAVE   "save"
+#define NM_VPNC_PW_TYPE_ASK    "ask"
+#define NM_VPNC_PW_TYPE_UNUSED "unused"
+
+typedef struct {
+	NMVPNPlugin parent;
+} NMVPNCPlugin;
+
+typedef struct {
+	NMVPNPluginClass parent;
+} NMVPNCPluginClass;
+
+GType nm_vpnc_plugin_get_type (void);
+
+NMVPNCPlugin *nm_vpnc_plugin_new (void);
+
+#endif /* NM_VPNC_PLUGIN_H */



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