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