about summary refs log tree commit diff
path: root/src/ppp-manager/nm-ppp-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ppp-manager/nm-ppp-manager.c')
-rw-r--r--src/ppp-manager/nm-ppp-manager.c226
1 files changed, 124 insertions, 102 deletions
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 1258b8f6..767b9315 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -82,6 +82,7 @@ typedef struct {
 
 	NMActRequest *act_req;
 	DBusGMethodInvocation *pending_secrets_context;
+	guint32 secrets_id;
 
 	guint32 ppp_watch_id;
 	guint32 ppp_timeout_handler;
@@ -203,8 +204,7 @@ set_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_PARENT_IFACE:
-		if (priv->parent_iface)
-			g_free (priv->parent_iface);
+		g_free (priv->parent_iface);
 		priv->parent_iface = g_value_dup_string (value);
 		break;
 	default:
@@ -350,19 +350,29 @@ remove_timeout_handler (NMPPPManager *manager)
 }
 
 static void
-impl_ppp_manager_need_secrets (NMPPPManager *manager,
-                               DBusGMethodInvocation *context)
+cancel_get_secrets (NMPPPManager *self)
+{
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+
+	if (priv->secrets_id) {
+		nm_act_request_cancel_secrets (priv->act_req, priv->secrets_id);
+		priv->secrets_id = 0;
+	}
+}
+
+static gboolean
+extract_details_from_connection (NMConnection *connection,
+                                 const char **username,
+                                 const char **password,
+                                 GError **error)
 {
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
-	NMConnection *connection;
 	NMSettingConnection *s_con;
+	NMSetting *setting;
 	const char *connection_type;
-	const char *setting_name;
-	guint32 tries;
-	GPtrArray *hints = NULL;
-	const char *hint1 = NULL, *hint2 = NULL;
 
-	connection = nm_act_request_get_connection (priv->act_req);
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (username != NULL, FALSE);
+	g_return_val_if_fail (password != NULL, FALSE);
 
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
@@ -370,67 +380,117 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager,
 	connection_type = nm_setting_connection_get_connection_type (s_con);
 	g_assert (connection_type);
 
+	setting = nm_connection_get_setting_by_name (connection, connection_type);
+	if (!setting) {
+		g_set_error_literal (error, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN,
+		                     "Missing type-specific setting; no secrets could be found.");
+		return FALSE;
+	}
+
+	/* FIXME: push this down to the settings and keep PPP manager generic */
+	if (NM_IS_SETTING_PPPOE (setting)) {
+		*username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting));
+		*password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting));
+	} else if (NM_IS_SETTING_GSM (setting)) {
+		*username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting));
+		*password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting));
+	} else if (NM_IS_SETTING_CDMA (setting)) {
+		*username = nm_setting_cdma_get_username (NM_SETTING_CDMA (setting));
+		*password = nm_setting_cdma_get_password (NM_SETTING_CDMA (setting));
+	}
+
+	return TRUE;
+}
+
+static void
+ppp_secrets_cb (NMActRequest *req,
+                guint32 call_id,
+                NMConnection *connection,
+                GError *error,
+                gpointer user_data)
+{
+	NMPPPManager *self = NM_PPP_MANAGER (user_data);
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+	const char *username = NULL;
+	const char *password = NULL;
+	GError *local = NULL;
+
+	g_return_if_fail (priv->pending_secrets_context != NULL);
+	g_return_if_fail (req == priv->act_req);
+	g_return_if_fail (call_id == priv->secrets_id);
+
+	if (error) {
+		nm_log_warn (LOGD_PPP, "%s", error->message);
+		dbus_g_method_return_error (priv->pending_secrets_context, error);
+		goto out;
+	}
+
+	if (!extract_details_from_connection (connection, &username, &password, &local)) {
+		nm_log_warn (LOGD_PPP, "%s", local->message);
+		dbus_g_method_return_error (priv->pending_secrets_context, local);
+		g_clear_error (&local);
+		goto out;
+	}
+
+	/* This is sort of a hack but...
+	 * pppd plugin only ever needs username and password. Passing the full
+	 * connection there would mean some bloat: the plugin would need to link
+	 * against libnm-util just to parse this. So instead, let's just send what
+	 * it needs.
+	 */
+	dbus_g_method_return (priv->pending_secrets_context, username, password);
+
+out:
+	priv->pending_secrets_context = NULL;
+	priv->secrets_id = 0;
+}
+
+static void
+impl_ppp_manager_need_secrets (NMPPPManager *manager,
+                               DBusGMethodInvocation *context)
+{
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+	NMConnection *connection;
+	const char *setting_name;
+	const char *username = NULL;
+	const char *password = NULL;
+	guint32 tries;
+	GPtrArray *hints = NULL;
+	GError *error = NULL;
+	NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION;
+
+	connection = nm_act_request_get_connection (priv->act_req);
+
 	nm_connection_clear_secrets (connection);
 	setting_name = nm_connection_need_secrets (connection, &hints);
 	if (!setting_name) {
-		NMSetting *setting;
-
-		setting = nm_connection_get_setting_by_name (connection, connection_type);
-		if (setting) {
-			const char *username = NULL;
-			const char *password = NULL;
-
-			/* FIXME: push this down to the settings and keep PPP manager generic */
-			if (NM_IS_SETTING_PPPOE (setting)) {
-				username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting));
-				password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting));
-			} else if (NM_IS_SETTING_GSM (setting)) {
-				username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting));
-				password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting));
-			} else if (NM_IS_SETTING_CDMA (setting)) {
-				username = nm_setting_cdma_get_username (NM_SETTING_CDMA (setting));
-				password = nm_setting_cdma_get_password (NM_SETTING_CDMA (setting));
-			}
-
-			/* If secrets are not required, send the existing username and password
-			 * back to the PPP plugin immediately.
-			 */
+		/* Use existing secrets from the connection */
+		if (extract_details_from_connection (connection, &username, &password, &error)) {
+			/* Send existing secrets to the PPP plugin */
 			priv->pending_secrets_context = context;
-			nm_ppp_manager_update_secrets (manager,
-			                               priv->parent_iface,
-			                               username ? username : "",
-			                               password ? password : "",
-			                               NULL);
+			ppp_secrets_cb (priv->act_req, priv->secrets_id, connection, NULL, manager);
 		} else {
-			GError *err = NULL;
-
-			g_set_error (&err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN,
-			             "Missing type-specific setting; no secrets could be found.");
-			nm_log_warn (LOGD_PPP, "%s", err->message);
-			dbus_g_method_return_error (context, err);
+			nm_log_warn (LOGD_PPP, "%s", error->message);
+			dbus_g_method_return_error (priv->pending_secrets_context, error);
+			g_clear_error (&error);
 		}
 		return;
 	}
 
-	/* Extract hints */
-	if (hints) {
-		if (hints->len > 0)
-			hint1 = g_ptr_array_index (hints, 0);
-		if (hints->len > 1)
-			hint2 = g_ptr_array_index (hints, 1);
-	}
-
-	tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), PPP_MANAGER_SECRET_TRIES));
-	/* Only ask for completely new secrets after retrying them once; some PPP
-	 * servers (T-Mobile USA) appear to ask a few times when they actually don't
-	 * even care what you pass back.
+	/* Only ask for completely new secrets after retrying them once; some devices
+	 * appear to ask a few times when they actually don't even care what you
+	 * pass back.
 	 */
-	nm_act_request_get_secrets (priv->act_req,
-	                            setting_name,
-	                            tries > 1 ? TRUE : FALSE,
-	                            SECRETS_CALLER_PPP,
-	                            hint1,
-	                            hint2);
+	tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), PPP_MANAGER_SECRET_TRIES));
+	if (tries > 1)
+		flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW;
+
+	priv->secrets_id = nm_act_request_get_secrets (priv->act_req,
+	                                               setting_name,
+	                                               flags,
+	                                               hints ? g_ptr_array_index (hints, 0) : NULL,
+	                                               ppp_secrets_cb,
+	                                               manager);
 	g_object_set_data (G_OBJECT (connection), PPP_MANAGER_SECRET_TRIES, GUINT_TO_POINTER (++tries));
 	priv->pending_secrets_context = context;
 
@@ -982,46 +1042,6 @@ nm_ppp_manager_start (NMPPPManager *manager,
 	return priv->pid > 0;
 }
 
-void
-nm_ppp_manager_update_secrets (NMPPPManager *manager,
-                               const char *device,
-                               const char *username,
-                               const char *password,
-                               const char *error_message)
-{
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
-
-	g_return_if_fail (NM_IS_PPP_MANAGER (manager));
-	g_return_if_fail (device != NULL);
-	g_return_if_fail (priv->pending_secrets_context != NULL);
-
-	if (error_message) {
-		g_return_if_fail (username == NULL);
-		g_return_if_fail (password == NULL);
-	} else {
-		g_return_if_fail (username != NULL);
-		g_return_if_fail (password != NULL);
-	}
-
-	if (error_message) {
-		GError *err = NULL;
-
-		g_set_error (&err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN, "%s", error_message);
-		nm_log_warn (LOGD_PPP, "%s", error_message);
-		dbus_g_method_return_error (priv->pending_secrets_context, err);
-		g_error_free (err);
-	} else {
-		/* This is sort of a hack but...
-		   pppd plugin only ever needs username and password.
-		   Passing the full connection there would mean some bloat:
-		   the plugin would need to link against libnm-util just to parse this.
-		   So instead, let's just send what it needs */
-
-		dbus_g_method_return (priv->pending_secrets_context, username, password);
-	}
-	priv->pending_secrets_context = NULL;
-}
-
 static gboolean
 ensure_killed (gpointer data)
 {
@@ -1047,6 +1067,8 @@ _ppp_cleanup (NMPPPManager *manager)
 
 	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
 
+	cancel_get_secrets (manager);
+
 	if (priv->monitor_id) {
 		g_source_remove (priv->monitor_id);
 		priv->monitor_id = 0;