static void
test_items (const char *detail, NMSettingVPN *s_vpn, const Item *items, gboolean secrets)
{
	const Item *iter;
	guint32 expected_count = 0, actual_count = 0;
	const char *value;

	for (iter = items; iter->name; iter++) {
		if (secrets)
			value = nm_setting_vpn_get_secret (s_vpn, iter->name);
		else
			value = nm_setting_vpn_get_data_item (s_vpn, iter->name);

		if (!iter->value) {
			ASSERT (value == NULL, detail, "unexpected item '%s'", iter->name);
		} else {
			ASSERT (value != NULL, detail, "unexpected missing value for item %s", iter->name);
			ASSERT (strcmp (value, iter->value) == 0, detail, "unexpected value for item %s (%s != %s",
			        iter->name, value, iter->value);
			expected_count++;
		}
	}

	if (secrets)
		nm_setting_vpn_foreach_secret (s_vpn, item_count_func, &actual_count);
	else
		nm_setting_vpn_foreach_data_item (s_vpn, item_count_func, &actual_count);

	ASSERT (actual_count == expected_count,
	        detail, "unexpected number of items (got %d, expected %d)", actual_count, expected_count);
}
static gboolean
real_need_secrets (NMVPNPlugin *plugin,
                   NMConnection *connection,
                   char **setting_name,
                   GError **error)
{
	NMSettingVPN *s_vpn;
	gboolean need_secrets = FALSE;

	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;
	}

	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENSSH_KEY_PASSWORD))
		need_secrets = TRUE;

	if (need_secrets)
		*setting_name = NM_SETTING_VPN_SETTING_NAME;

	return need_secrets;
}
static gboolean
real_need_secrets (NMVpnServicePlugin *plugin,
                   NMConnection *connection,
                   const char **setting_name,
                   GError **error)
{
	NMSettingVpn *s_vpn;
	NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;

	g_return_val_if_fail (NM_IS_VPN_SERVICE_PLUGIN (plugin), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);

	s_vpn = nm_connection_get_setting_vpn (connection);

	nm_setting_get_secret_flags (NM_SETTING (s_vpn), NM_SSTP_KEY_PASSWORD, &flags, NULL);

	/* Don't need the password if it's not required */
	if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
		return FALSE;

	/* Don't need the password if we already have one */
	if (nm_setting_vpn_get_secret (NM_SETTING_VPN (s_vpn), NM_SSTP_KEY_PASSWORD))
		return FALSE;

	/* Otherwise we need a password */
	*setting_name = NM_SETTING_VPN_SETTING_NAME;
	return TRUE;
}
static gboolean
_service_cache_credentials (NML2tpPppService *self,
							NMConnection *connection,
							GError **error)
{
	NML2tpPppServicePrivate *priv = NM_L2TP_PPP_SERVICE_GET_PRIVATE (self);
	NMSettingVPN *s_vpn;
	const char *username, *password, *domain;

	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (connection != NULL, FALSE);

	s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
	if (!s_vpn) {
		g_set_error_literal (error,
							 NM_VPN_PLUGIN_ERROR,
							 NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
		                     _("Could not find secrets (connection invalid, no vpn setting)."));
		return FALSE;
	}

	/* Username; try L2TP specific username first, then generic username */
	username = nm_setting_vpn_get_data_item (s_vpn, NM_L2TP_KEY_USER);
	if (username && strlen (username)) {
		/* FIXME: This check makes about 0 sense. */
		if (!username || !strlen (username)) {
			g_set_error_literal (error,
								 NM_VPN_PLUGIN_ERROR,
								 NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
			                     _("Invalid VPN username."));
			return FALSE;
		}
	} else {
		username = nm_setting_vpn_get_user_name (s_vpn);
		if (!username || !strlen (username)) {
			g_set_error_literal (error,
								 NM_VPN_PLUGIN_ERROR,
								 NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
								 _("Missing VPN username."));
			return FALSE;
		}
	}

	password = nm_setting_vpn_get_secret (s_vpn, NM_L2TP_KEY_PASSWORD);
	if (!password || !strlen (password)) {
		g_set_error_literal (error,
							 NM_VPN_PLUGIN_ERROR,
							 NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
							 _("Missing or invalid VPN password."));
		return FALSE;
	}

	domain = nm_setting_vpn_get_data_item (s_vpn, NM_L2TP_KEY_DOMAIN);
	if (domain && strlen (domain))
		priv->domain = g_strdup(domain);

	priv->username = g_strdup(username);
	priv->password = g_strdup(password);
	return TRUE;
}
static void
setup_password_widget (OpenswanPluginUiWidget *self,
                       const char *entry_name,
                       NMSettingVPN *s_vpn,
                       const char *secret_name,
                       gboolean new_connection)
{
	OpenswanPluginUiWidgetPrivate *priv = OPENSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
	NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
	GtkWidget *widget;
	const char *value;

	if (new_connection)
		secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;

	widget = (GtkWidget *) gtk_builder_get_object (priv->builder, entry_name);
	g_assert (widget);
	gtk_size_group_add_widget (priv->group, widget);

	if (s_vpn) {
		value = nm_setting_vpn_get_secret (s_vpn, secret_name);
		gtk_entry_set_text (GTK_ENTRY (widget), value ? value : "");
		nm_setting_get_secret_flags (NM_SETTING (s_vpn), secret_name, &secret_flags, NULL);
	}
	secret_flags &= ~(NM_SETTING_SECRET_FLAG_NOT_SAVED | NM_SETTING_SECRET_FLAG_NOT_REQUIRED);
	g_object_set_data (G_OBJECT (widget), "flags", GUINT_TO_POINTER (secret_flags));

	g_signal_connect (widget, "changed", G_CALLBACK (stuff_changed_cb), self);
}
static void
remove_user_password (NMConnection *connection)
{
	NMSettingVPN *s_vpn;

	s_vpn = nm_connection_get_setting_vpn (connection);
	if (!s_vpn)
		return;

	if (nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD))
		nm_setting_vpn_remove_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD);
}
static gboolean
handle_need_secrets (NMDBusSstpPpp *object,
                     GDBusMethodInvocation *invocation,
                     gpointer user_data)
{
	NMSstpPlugin *self = NM_SSTP_PLUGIN (user_data);
	NMSstpPluginPrivate *priv = NM_SSTP_PLUGIN_GET_PRIVATE (self);
	NMSettingVpn *s_vpn;
	const char *user, *password, *domain;
	gchar *username;

	remove_timeout_handler (NM_SSTP_PLUGIN (user_data));

	s_vpn = nm_connection_get_setting_vpn (priv->connection);
	g_assert (s_vpn);

	/* Username; try SSTP specific username first, then generic username */
	user = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_USER);
	if (!user || !strlen (user))
		user = nm_setting_vpn_get_user_name (s_vpn);
	if (!user || !strlen (user)) {
		g_dbus_method_invocation_return_error_literal (invocation,
		                                               NM_VPN_PLUGIN_ERROR,
		                                               NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
		                                               _("Missing VPN username."));
		return FALSE;
	}

	password = nm_setting_vpn_get_secret (s_vpn, NM_SSTP_KEY_PASSWORD);
	if (!password || !strlen (password)) {
		g_dbus_method_invocation_return_error_literal (invocation,
		                                               NM_VPN_PLUGIN_ERROR,
		                                               NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
		                                               _("Missing or invalid VPN password."));
		return FALSE;;
	}

	/* Domain is optional */
	domain = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_DOMAIN);

	/* Success */
	if (domain && strlen (domain))
		username = g_strdup_printf ("%s\\%s", domain, user);
	else
		username = g_strdup (user);

	nmdbus_sstp_ppp_complete_need_secrets (object, invocation, username, password);
	g_free (username);

	return TRUE;
}
static gboolean
real_need_secrets (NMVPNPlugin *plugin,
                   NMConnection *connection,
                   char **setting_name,
                   GError **error)
{
	NMSettingVPN *s_vpn;

	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;
	}

	/* We just need the WebVPN cookie, and the final IP address of the gateway
	   (after HTTP redirects, which do happen). All the certificate/SecurID 
	   nonsense can be handled for us, in the user's context, by auth-dialog */
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT)) {
		*setting_name = NM_SETTING_VPN_SETTING_NAME;
		return TRUE;
	}
	return FALSE;
}
Esempio n. 9
0
static GtkWidget *
fill_password (GladeXML *xml,
               const char *widget_name,
               NMConnection *connection,
               const char *password_type)
{
    GtkWidget *widget = NULL;
    gchar *password = NULL;

    widget = glade_xml_get_widget (xml, widget_name);
    g_assert (widget);

    if (!connection)
        return widget;

    password = NULL;

    if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
        NMSettingVPN *s_vpn;

        s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
        if (s_vpn) {
            const gchar *tmp = NULL;

            tmp = nm_setting_vpn_get_secret (s_vpn, password_type);
            if (tmp)
                password = gnome_keyring_memory_strdup (tmp);
        }
    } else {
        NMSettingConnection *s_con = NULL;
        gboolean unused;
        const char *uuid;

        s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
        uuid = nm_setting_connection_get_uuid (s_con);
        password = keyring_helpers_lookup_secret (uuid,
                   password_type,
                   &unused);
    }

    if (password) {
        gtk_entry_set_text (GTK_ENTRY (widget), password);
        gnome_keyring_memory_free (password);
    }

    return widget;
}
Esempio n. 10
0
static gboolean
compare_one_secret (NMSettingVPN *a,
                    NMSettingVPN *b,
                    NMSettingCompareFlags flags)
{
	GHashTable *a_secrets, *b_secrets;
	GHashTableIter iter;
	const char *key, *val;

	a_secrets = NM_SETTING_VPN_GET_PRIVATE (a)->secrets;
	b_secrets = NM_SETTING_VPN_GET_PRIVATE (b)->secrets;

	g_hash_table_iter_init (&iter, a_secrets);
	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
		NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
		NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;

		nm_setting_get_secret_flags (NM_SETTING (a), key, &a_secret_flags, NULL);
		nm_setting_get_secret_flags (NM_SETTING (b), key, &b_secret_flags, NULL);

		/* If the secret flags aren't the same, the settings aren't the same */
		if (a_secret_flags != b_secret_flags)
			return FALSE;

		if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
		    && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
			continue;

		if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
		    && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
			continue;

		/* Now compare the values themselves */
		if (g_strcmp0 (val, nm_setting_vpn_get_secret (b, key)) != 0)
			return FALSE;
	}

	return TRUE;
}
Esempio n. 11
0
static void
setup_password_widget (VpncEditor *self,
                       const char *entry_name,
                       NMSettingVpn *s_vpn,
                       const char *secret_name,
                       gboolean new_connection)
{
	VpncEditorPrivate *priv = VPNC_EDITOR_GET_PRIVATE (self);
	GtkWidget *widget;
	const char *value;

	widget = (GtkWidget *) gtk_builder_get_object (priv->builder, entry_name);
	g_assert (widget);
	gtk_size_group_add_widget (priv->group, widget);

	if (s_vpn) {
		value = nm_setting_vpn_get_secret (s_vpn, secret_name);
		gtk_entry_set_text (GTK_ENTRY (widget), value ? value : "");
	}

	g_signal_connect (widget, "changed", G_CALLBACK (stuff_changed_cb), self);
}
static GPtrArray *
construct_pppd_args (NMSstpPlugin *plugin,
                     NMSettingVpn *s_vpn,
                     const char *pppd,
                     const char *gwaddr,
                     GError **error)
{
	GPtrArray *args = NULL;
	const char *value, *sstp_binary;
	char *ipparam, *tmp, *ca_cert = NULL, *proxy = NULL, *uuid = NULL;
	const char *proxy_server, *proxy_port;
	gboolean ign_cert;


	/* Get the proxy settings */
	proxy_server = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_PROXY_SERVER);
	proxy_port = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_PROXY_PORT);
	if (proxy_server && proxy_port && strlen(proxy_server) && strlen(proxy_port)) {
		const char *proxy_user, *proxy_password;
		long int tmp_int;

		if (!str_to_int (proxy_port, &tmp_int))
			tmp_int = 0;

		proxy_user = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_PROXY_USER);
		proxy_password = nm_setting_vpn_get_secret (s_vpn, NM_SSTP_KEY_PROXY_PASSWORD);

		proxy = g_strdup_printf("--proxy http://%s%s%s@%s:%ld",
		                        proxy_user,
		                        proxy_password ? ":" : "",
		                        proxy_password ?     : "",
		                        proxy_server,
		                        tmp_int);
	}

	sstp_binary = nm_find_sstpc ();
	if (!sstp_binary) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("Could not find sstp client binary."));
		return FALSE;
	}

	/* Validate the Gateway option */
	if (!gwaddr || !strlen (gwaddr)) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
		             "%s",
		             _("Missing VPN gateway."));
		goto error;
	}

	/* Create the argument vector for pppd */
	args = g_ptr_array_new ();
	g_ptr_array_add (args, (gpointer) g_strdup (pppd));
	g_ptr_array_add (args, (gpointer) g_strdup ("pty"));

	/* Get the CA Certificate (if any) */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_CA_CERT);
	if (value && strlen (value))
		ca_cert = g_strdup_printf ("--ca-cert %s", value);

    /*  Set the UUID of the connection */
    value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_UUID);
    if (value && strlen(value))
        uuid = g_strdup_printf ("--uuid %s", value);

	/* Ignore any certificate warnings */
	value = nm_setting_vpn_get_data_item(s_vpn, NM_SSTP_KEY_IGN_CERT_WARN);
	if (value && !strcmp(value, "yes")) {
		ign_cert = TRUE;
	}

	/* Prepare the PTY option */
	ipparam = g_strdup_printf ("nm-sstp-service-%d", getpid ());
	tmp = g_strdup_printf ("%s %s %s --nolaunchpppd %s %s --ipparam %s %s %s",
						   sstp_binary, gwaddr,
						   ign_cert == TRUE ? "--cert-warn" : "",
						   debug ? "--log-level 4" : "",
						   proxy ? proxy : "",
						   ipparam,
                           uuid ? uuid : "",
						   ca_cert ? ca_cert : ""
						   );

	g_ptr_array_add (args, (gpointer) tmp);
    if (ca_cert)
    	g_free(ca_cert);
    if (uuid)
        g_free(uuid);

	/* Enable debug */
	if (debug)
		g_ptr_array_add (args, (gpointer) g_strdup ("debug"));

	/* PPP options */
	g_ptr_array_add (args, (gpointer) g_strdup ("noipv6"));
	g_ptr_array_add (args, (gpointer) g_strdup ("ipparam"));
	g_ptr_array_add (args, (gpointer) ipparam);

	g_ptr_array_add (args, (gpointer) g_strdup ("nodetach"));
	g_ptr_array_add (args, (gpointer) g_strdup ("lock"));
	g_ptr_array_add (args, (gpointer) g_strdup ("usepeerdns"));
	g_ptr_array_add (args, (gpointer) g_strdup ("noipdefault"));
	g_ptr_array_add (args, (gpointer) g_strdup ("nodefaultroute"));

	/* Don't need to auth the SSTP server */
	g_ptr_array_add (args, (gpointer) g_strdup ("noauth"));

	/* Username; try SSTP specific username first, then generic username */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_USER);
	if (!value || !strlen (value))
		value = nm_setting_vpn_get_user_name (s_vpn);
	if (!value || !strlen (value)) {
		g_set_error_literal (error,
		                     NM_VPN_PLUGIN_ERROR,
		                     NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
		                     _("Missing VPN username."));
		return FALSE;
	}
	g_ptr_array_add (args, (gpointer) g_strdup ("user"));
	g_ptr_array_add (args, (gpointer) g_strdup (value));

	/* Allow EAP (currently not supported */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REFUSE_EAP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("refuse-eap"));

	/* Allow plain text passwords */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REFUSE_PAP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("refuse-pap"));

	/* Allow CHAP-MD5 */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REFUSE_CHAP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("refuse-chap"));

	/* Allow MSCHAP */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REFUSE_MSCHAP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("refuse-mschap"));

	/* Allow MSCHAP-v2 */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REFUSE_MSCHAPV2);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("refuse-mschap-v2"));

	/* Require MPPE */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REQUIRE_MPPE);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("require-mppe"));

	/* Use MPPE-40 bit */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REQUIRE_MPPE_40);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("require-mppe-40"));

	/* Use MPPE-128 bit */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_REQUIRE_MPPE_128);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("require-mppe-128"));

	/* Use stateful MPPE */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_MPPE_STATEFUL);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("mppe-stateful"));

	/* No BSD Compression */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_NOBSDCOMP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("nobsdcomp"));

	/* No Deflate */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_NODEFLATE);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("nodeflate"));

	/* No Compression */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_NO_VJ_COMP);
	if (value && !strcmp (value, "yes"))
		g_ptr_array_add (args, (gpointer) g_strdup ("novj"));

	/* LCP Echo Failure */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_LCP_ECHO_FAILURE);
	if (value && strlen (value)) {
		long int tmp_int;

		/* Convert to integer and then back to string for security's sake
		 * because strtol ignores some leading and trailing characters.
		 */
		if (str_to_int (value, &tmp_int)) {
			g_ptr_array_add (args, (gpointer) g_strdup ("lcp-echo-failure"));
			g_ptr_array_add (args, (gpointer) g_strdup_printf ("%ld", tmp_int));
		} else {
			g_warning ("failed to convert lcp-echo-failure value '%s'", value);
		}
	} else {
		g_ptr_array_add (args, (gpointer) g_strdup ("lcp-echo-failure"));
		g_ptr_array_add (args, (gpointer) g_strdup ("0"));
	}

	/* LCP Echo Interval */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_LCP_ECHO_INTERVAL);
	if (value && strlen (value)) {
		long int tmp_int;

		/* Convert to integer and then back to string for security's sake
		 * because strtol ignores some leading and trailing characters.
		 */
		if (str_to_int (value, &tmp_int)) {
			g_ptr_array_add (args, (gpointer) g_strdup ("lcp-echo-interval"));
			g_ptr_array_add (args, (gpointer) g_strdup_printf ("%ld", tmp_int));
		} else {
			g_warning ("failed to convert lcp-echo-interval value '%s'", value);
		}
	} else {
		g_ptr_array_add (args, (gpointer) g_strdup ("lcp-echo-interval"));
		g_ptr_array_add (args, (gpointer) g_strdup ("0"));
	}

	/* Unit Number */
	value = nm_setting_vpn_get_data_item (s_vpn, NM_SSTP_KEY_UNIT_NUM);
	if (value && *value) {
		long int tmp_int;
		if (str_to_int (value, &tmp_int)) {
			g_ptr_array_add (args, (gpointer) g_strdup ("unit"));
			g_ptr_array_add (args, (gpointer) g_strdup_printf ("%ld", tmp_int));
		} else
			g_warning ("failed to convert unit value '%s'", value);
	}

	/* Add the SSTP PPP Plugin */
	g_ptr_array_add (args, (gpointer) g_strdup ("plugin"));
	g_ptr_array_add (args, (gpointer) g_strdup (NM_SSTP_PPPD_PLUGIN));

	/* Terminate pointer array with NULL */
	g_ptr_array_add (args, NULL);

	return args;

error:
	free_pppd_args (args);
	return FALSE;
}
static gboolean
nm_openssh_start (NMVPNPlugin *plugin, NMSettingVPN *s_vpn, GError **error)
{
	NMOpensshPluginPrivate *priv = NM_OPENSSH_PLUGIN_GET_PRIVATE(plugin);
	sshtun_handle_t handle;
	const char *tun_mode;
	char *tun_owner = NULL, *host = NULL, *user = NULL,
		*public_key = NULL, *private_key = NULL, *config_script = NULL;
	const char *val;
	int ret;
	gboolean retval = TRUE;
	GIOChannel *event_channel;
	GSource *child_watch, *event_watch;

	val = nm_setting_vpn_get_user_name (s_vpn);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "Can't get username.");
		retval = FALSE;
		goto out;
	}
	tun_owner = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_TUN_USE_TAP);
	tun_mode = val && !strcmp (val, "yes") ? "ethernet" : "pointopoint";

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_USER);
	user = val ? g_strdup (val) : g_strdup (tun_owner);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_HOST);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "Host is missing.");
		retval = FALSE;
		goto out;
	}
	host = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PUBLIC_KEY);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "SSH public key is missing.");
		retval = FALSE;
		goto out;
	}
	public_key = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PRIVATE_KEY);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "SSH private key is missing.");
		retval = FALSE;
		goto out;
	}
	private_key = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_CONFIG_SCRIPT);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "IP config script is missing.");
		retval = FALSE;
		goto out;
	}
	config_script = g_strdup (val);

	ret = sshtun_new (&handle);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_GENERAL,
		             "%s",
		             "Could not allocate memory for an sshtun process.");
		retval = FALSE;
		goto out;
	}

	ret = sshtun_set_params (handle,
							 SSHTUN_PARAM_TUN_MODE, tun_mode,
							 SSHTUN_PARAM_TUN_OWNER, tun_owner,
							 SSHTUN_PARAM_USER, user,
							 SSHTUN_PARAM_HOST, host,
							 SSHTUN_PARAM_SERVICE, "ssh",
							 SSHTUN_PARAM_PUBLIC_KEY, public_key,
							 SSHTUN_PARAM_PRIVATE_KEY, private_key,
							 SSHTUN_PARAM_CONFIG_SCRIPT, config_script,
							 0);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
		             "%s",
		             "Could not set parameters for an sshtun process.");
		retval = FALSE;
		goto out;
	}

	ret = sshtun_start (handle);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             "Could not start an sshtun process.");
		retval = FALSE;
		goto out;
	}

	priv->handle = handle;

	val = nm_setting_vpn_get_secret (s_vpn, NM_OPENSSH_KEY_PASSWORD);
	priv->password = val ? g_strdup (val) : NULL;

	/* Watch the status change of the sshtun child process. */
	child_watch = g_child_watch_source_new (sshtun_pid (priv->handle));
	g_source_set_callback (child_watch,
						   (GSourceFunc) child_watch_cb, plugin,
						   NULL);
	g_source_attach (child_watch, NULL);
	g_source_unref (child_watch);

	/* Watch the normal event from the sshtun child process. */
	event_channel =	g_io_channel_unix_new (sshtun_event_fd (priv->handle));
	event_watch = g_io_create_watch (event_channel, G_IO_IN);
	g_source_set_callback (event_watch,
						   (GSourceFunc) event_watch_cb, plugin,
						   NULL);
	g_source_attach (event_watch, NULL);
	g_source_unref (event_watch);
	g_io_channel_unref (event_channel);

 out:
	g_free (tun_owner);
	g_free (host);
	g_free (user);
	g_free (public_key);
	g_free (private_key);
	g_free (config_script);

	return retval;
}
static gint
nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
                                         NMSettingVPN *s_vpn,
                                         GError **error)
{
	NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin);
	GPid	pid;
	const char **openconnect_binary = NULL;
	GPtrArray *openconnect_argv;
	GSource *openconnect_watch;
	gint	stdin_fd;
	const char *props_vpn_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy;
	
	/* Find openconnect */
	openconnect_binary = openconnect_binary_paths;
	while (*openconnect_binary != NULL) {
		if (g_file_test (*openconnect_binary, G_FILE_TEST_EXISTS))
			break;
		openconnect_binary++;
	}

	if (!*openconnect_binary) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("Could not find openconnect binary."));
		return -1;
	}

	/* The actual gateway to use (after redirection) comes from the auth
	   dialog, so it's in the secrets hash not the properties */
	props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY);
	if (!props_vpn_gw || !strlen (props_vpn_gw) ) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No VPN gateway specified."));
		return -1;
	}

	props_cookie = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE);
	if (!props_cookie || !strlen (props_cookie)) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No WebVPN cookie provided."));
		return -1;
	}
	props_gwcert = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT);

	props_cacert = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_CACERT);
	props_mtu = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_MTU);

	props_proxy = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_PROXY);

	openconnect_argv = g_ptr_array_new ();
	g_ptr_array_add (openconnect_argv, (gpointer) (*openconnect_binary));

	if (props_gwcert && strlen(props_gwcert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--servercert");
		g_ptr_array_add (openconnect_argv, (gpointer) props_gwcert);
	} else if (props_cacert && strlen(props_cacert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--cafile");
		g_ptr_array_add (openconnect_argv, (gpointer) props_cacert);
	}

	if (props_mtu && strlen(props_mtu)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--mtu");
		g_ptr_array_add (openconnect_argv, (gpointer) props_mtu);
	}

	if (props_proxy && strlen(props_proxy)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--proxy");
		g_ptr_array_add (openconnect_argv, (gpointer) props_proxy);
	}
		
	g_ptr_array_add (openconnect_argv, (gpointer) "--syslog");
	g_ptr_array_add (openconnect_argv, (gpointer) "--cookie-on-stdin");

	g_ptr_array_add (openconnect_argv, (gpointer) "--script");
	g_ptr_array_add (openconnect_argv, (gpointer) NM_OPENCONNECT_HELPER_PATH);

	priv->tun_name = create_persistent_tundev ();
	if (priv->tun_name) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--interface");
		g_ptr_array_add (openconnect_argv, (gpointer) priv->tun_name);
	}

	g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw);

	if (debug)
		g_ptr_array_add (openconnect_argv, (gpointer) "--verbose");

	g_ptr_array_add (openconnect_argv, NULL);

	if (!g_spawn_async_with_pipes (NULL, (char **) openconnect_argv->pdata, NULL,
	                               G_SPAWN_DO_NOT_REAP_CHILD,
	                               openconnect_drop_child_privs, priv->tun_name,
	                               &pid, &stdin_fd, NULL, NULL, error)) {
		g_ptr_array_free (openconnect_argv, TRUE);
		g_warning ("openconnect failed to start.  error: '%s'", (*error)->message);
		return -1;
	}
	g_ptr_array_free (openconnect_argv, TRUE);

	g_message ("openconnect started with pid %d", pid);

	if (write(stdin_fd, props_cookie, strlen(props_cookie)) != strlen(props_cookie) ||
	    write(stdin_fd, "\n", 1) != 1) {
		g_warning ("openconnect didn't eat the cookie we fed it");
		return -1;
	}

	close(stdin_fd);

	NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin)->pid = pid;
	openconnect_watch = g_child_watch_source_new (pid);
	g_source_set_callback (openconnect_watch, (GSourceFunc) openconnect_watch_cb, plugin, NULL);
	g_source_attach (openconnect_watch, NULL);
	g_source_unref (openconnect_watch);

	return 0;
}