commit ded2a9fa00f4c3b3e4334ad9e2277f7b502d8111
Author: Danny Kukawka <danny.kukawka@web.de>
Date:   Wed Jun 16 13:54:52 2010 +0200

    ported nm-finer-policy-fate#305657.patch

diff --git a/src/Makefile.am b/src/Makefile.am
index 42fa39b..b038e7e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,7 +94,9 @@ NetworkManager_SOURCES =				\
 		nm-netlink.c			\
 		nm-netlink.h \
 		nm-dhcp4-config.c \
-		nm-dhcp4-config.h
+		nm-dhcp4-config.h \
+		nm-polkit.c \
+		nm-polkit.h
 
 nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml
 	dbus-binding-tool --prefix=nm_access_point --mode=glib-server --output=$@ $<
@@ -136,6 +138,7 @@ NetworkManager_CPPFLAGS = \
 	$(HAL_CFLAGS) \
 	$(OPENSSL_CFLAGS) \
 	$(LIBNL_CFLAGS) \
+	$(POLKIT_CFLAGS) \
 	-DG_DISABLE_DEPRECATED \
 	-DBINDIR=\"$(bindir)\" \
 	-DSBINDIR=\"$(sbindir)\" \
@@ -152,6 +155,7 @@ NetworkManager_LDADD = \
 	$(GLIB_LIBS) \
 	$(HAL_LIBS) \
 	$(LIBNL_LIBS) \
+	$(POLKIT_LIBS) \
 	$(top_builddir)/marshallers/libmarshallers.la \
 	./named-manager/libnamed-manager.la \
 	./vpn-manager/libvpn-manager.la \
diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c
index e77adce..7ef39c2 100644
--- a/src/NetworkManagerPolicy.c
+++ b/src/NetworkManagerPolicy.c
@@ -632,6 +632,7 @@ auto_activate_device (gpointer user_data)
 		                                     specific_object,
 		                                     device_path,
 		                                     FALSE,
+						     NULL, 
 		                                     &error)) {
 			NMSettingConnection *s_con;
 
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 5d84d6b..59e9733 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <dbus/dbus-glib-lowlevel.h>
 #include <dbus/dbus-glib.h>
+#include <polkit-dbus/polkit-dbus.h>
 
 #include "nm-glib-compat.h"
 #include "nm-manager.h"
@@ -37,11 +38,17 @@
 #include "NetworkManagerSystem.h"
 #include "nm-properties-changed-signal.h"
 #include "nm-setting-connection.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-vpn.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-vpn.h"
 #include "nm-marshal.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-hal-manager.h"
+#include "nm-polkit.h"
 
 #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
 #define NM_AUTOIP_DBUS_IFACE   "org.freedesktop.nm_avahi_autoipd"
@@ -128,6 +135,8 @@ typedef struct {
 	GSList *unmanaged_udis;
 	char *hostname;
 
+	NMPolKit * nm_polkit;
+
 	PendingConnectionInfo *pending_connection_info;
 	gboolean wireless_enabled;
 	gboolean wireless_hw_enabled;
@@ -338,6 +347,8 @@ nm_manager_init (NMManager *manager)
 	                                                g_free,
 	                                                g_object_unref);
 
+	priv->nm_polkit = nm_polkit_get();
+
 	priv->system_connections = g_hash_table_new_full (g_str_hash,
 	                                                g_str_equal,
 	                                                g_free,
@@ -530,6 +541,11 @@ dispose (GObject *object)
 
 	g_free (priv->hostname);
 
+	if (priv->nm_polkit) {
+	        g_object_unref(priv->nm_polkit);
+        	priv->nm_polkit = NULL;
+	}
+
 	if (priv->system_props_proxy) {
 		g_object_unref (priv->system_props_proxy);
 		priv->system_props_proxy = NULL;
@@ -1925,12 +1941,83 @@ wait_for_connection_expired (gpointer data)
 	return FALSE;
 }
 
+static gboolean
+is_user_request_connection_type_authorized(NMManager *manager, const char *dbus_sender, NMConnection *connection, GError **error)
+{
+    const char *action_id = NULL;
+    DBusGConnection *dbus_connection;
+    NMSettingConnection *s_con;
+    const char *connection_type;
+    NMManagerPrivate *priv;
+    NMSettingIP4Config * s_ip4;
+    const char * ip4_method;
+    gboolean is_shared = FALSE;
+
+    priv = NM_MANAGER_GET_PRIVATE(manager);
+
+    s_con = NM_SETTING_CONNECTION(nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION));
+    connection_type = s_con ? nm_setting_connection_get_connection_type(s_con) : NULL;
+
+    s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
+
+    if (s_ip4) {
+        ip4_method = nm_setting_ip4_config_get_method (s_ip4);
+        if (!strcmp (ip4_method, "shared")) {
+            is_shared = TRUE;
+        }
+    }
+
+    if (!strcmp(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
+        if (is_shared) {
+            action_id = NM_POLICY_ACTION_USER_WIRED_APPLY_WITH_SHARE;
+        } else {
+            action_id = NM_POLICY_ACTION_USER_WIRED_APPLY;
+        }
+    } else if (!strcmp(connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+        if (is_shared) {
+            action_id = NM_POLICY_ACTION_USER_WIRELESS_APPLY_WITH_SHARE;
+        } else {
+            action_id = NM_POLICY_ACTION_USER_WIRELESS_APPLY;
+        }
+    } else if (!strcmp(connection_type, NM_SETTING_VPN_SETTING_NAME)) {
+        if (is_shared) {
+            action_id = NM_POLICY_ACTION_USER_VPN_APPLY_WITH_SHARE;
+        } else {
+            action_id = NM_POLICY_ACTION_USER_VPN_APPLY;
+        }
+    } else if (!strcmp(connection_type, NM_SETTING_PPP_SETTING_NAME)) {
+        if (is_shared) {
+            action_id = NM_POLICY_ACTION_USER_DSL_APPLY_WITH_SHARE;
+        } else {
+            action_id = NM_POLICY_ACTION_USER_DSL_APPLY;
+        }
+    } else if (!strcmp(connection_type, NM_SETTING_CDMA_SETTING_NAME)
+            || !strcmp(connection_type, NM_SETTING_GSM_SETTING_NAME)) {
+        if (is_shared) {
+            action_id = NM_POLICY_ACTION_USER_MOBILE_APPLY_WITH_SHARE;
+        } else {
+            action_id = NM_POLICY_ACTION_USER_MOBILE_APPLY;
+        }
+    } else {
+        g_set_error(error,
+                NM_MANAGER_ERROR,
+                NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
+                "%s", "Could not distinguish the type of connection to be actived.");
+        return FALSE;
+    }
+
+    dbus_connection = nm_dbus_manager_get_connection(priv->dbus_mgr);
+
+    return nm_polkit_check_privileges(priv->nm_polkit, dbus_connection, dbus_sender, action_id, error);
+}
+
 const char *
 nm_manager_activate_connection (NMManager *manager,
                                 NMConnection *connection,
                                 const char *specific_object,
                                 const char *device_path,
                                 gboolean user_requested,
+				const char *dbus_sender,
                                 GError **error)
 {
 	NMDevice *device = NULL;
@@ -1942,6 +2029,36 @@ nm_manager_activate_connection (NMManager *manager,
 	g_return_val_if_fail (error != NULL, NULL);
 	g_return_val_if_fail (*error == NULL, NULL);
 
+    /* polkit check */
+    if (nm_connection_get_scope(connection) == NM_CONNECTION_SCOPE_USER) {
+        const char * service_name;
+        const char * service_owner;
+        NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+
+        if (dbus_sender == NULL) {
+            service_name = dbus_g_proxy_get_bus_name (priv->user_proxy);
+            if (!service_name) {
+                g_set_error (error, NM_MANAGER_ERROR,
+                        NM_MANAGER_ERROR_PERMISSION_DENIED,
+                        "%s", "Could not determine user settings service name");
+                return NULL;
+            }
+            service_owner = nm_dbus_manager_get_name_owner (priv->dbus_mgr, service_name, NULL);
+            if (!service_owner) {
+                g_set_error (error, NM_MANAGER_ERROR,
+                        NM_MANAGER_ERROR_PERMISSION_DENIED,
+                        "%s", "Could not determine D-Bus owner of the user settings service");
+                return NULL;
+            }
+
+        } else {
+            service_owner = dbus_sender;
+        }
+        if (!is_user_request_connection_type_authorized(manager, service_owner, connection, error)) {
+            return NULL;
+        }
+    }
+
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 	g_assert (s_con);
 
@@ -2030,6 +2147,7 @@ connection_added_default_handler (NMManager *manager,
 	                                       info->specific_object_path,
 	                                       info->device_path,
 	                                       TRUE,
+					       NULL,
 	                                       &error);
 	if (path) {
 		dbus_g_method_return (info->context, path);
@@ -2161,11 +2279,13 @@ impl_manager_activate_connection (NMManager *manager,
 	GError *error = NULL;
 	char *real_sop = NULL;
 	char *path = NULL;
+	const char * dbus_sender = NULL;
 
 	if (!strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS)) {
 		if (!is_user_request_authorized (manager, context, &error))
 			goto err;
 
+	dbus_sender = dbus_g_method_get_sender (context);
 		scope = NM_CONNECTION_SCOPE_USER;
 	} else if (!strcmp (service_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS))
 		scope = NM_CONNECTION_SCOPE_SYSTEM;
@@ -2187,6 +2307,7 @@ impl_manager_activate_connection (NMManager *manager,
 		                                                real_sop,
 		                                                device_path,
 		                                                TRUE,
+								dbus_sender,
 		                                                &error);
 		if (path) {
 			dbus_g_method_return (context, path);
diff --git a/src/nm-manager.h b/src/nm-manager.h
index 486dd15..3d5949f 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -87,6 +87,7 @@ const char * nm_manager_activate_connection (NMManager *manager,
                                              const char *specific_object,
                                              const char *device_path,
                                              gboolean user_requested,
+					     const char *dbus_sender,
                                              GError **error);
 
 gboolean nm_manager_deactivate_connection (NMManager *manager,
diff --git a/src/nm-polkit.c b/src/nm-polkit.c
new file mode 100644
index 0000000..cb68a22
--- /dev/null
+++ b/src/nm-polkit.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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 2008 Novell, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+
+#include <polkit-dbus/polkit-dbus.h>
+#include "nm-polkit.h"
+
+G_DEFINE_TYPE(NMPolKit, nm_polkit, G_TYPE_OBJECT);
+
+struct NMPolKitPrivate {
+    PolKitContext *context;
+};
+
+GQuark
+nm_polkit_error_quark(void)
+{
+    static GQuark error_quark = 0;
+    if (error_quark == 0) {
+        error_quark = g_quark_from_static_string("nm-polkit-error");
+    }
+    return error_quark;
+}
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+       int fd;
+       PolKitContext *pk_context = (PolKitContext *) user_data;
+
+       fd = g_io_channel_unix_get_fd (channel);
+       polkit_context_io_func (pk_context, fd);
+
+       return TRUE;
+}
+
+static int
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+       guint id = 0;
+       GIOChannel *channel;
+
+       channel = g_io_channel_unix_new (fd);
+       if (channel == NULL)
+               goto out;
+       id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+       if (id == 0) {
+               g_io_channel_unref (channel);
+               goto out;
+       }
+       g_io_channel_unref (channel);
+
+ out:
+       return id;
+}
+
+static void
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+       g_source_remove (watch_id);
+}
+
+static PolKitContext *
+create_polkit_context (void)
+{
+       PolKitContext *pk_context = NULL;
+       PolKitError *err;
+
+       pk_context = polkit_context_new ();
+       polkit_context_set_io_watch_functions (pk_context, pk_io_add_watch, pk_io_remove_watch);
+       err = NULL;
+       if (!polkit_context_init (pk_context, &err)) {
+               g_warning ("Cannot initialize libpolkit: %s",
+                          err ? polkit_error_get_error_message (err) : "unknown error");
+               if (err)
+                       polkit_error_free (err);
+
+               /* PK 0.6's polkit_context_init() unrefs the global_context on failure */
+#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR >= 7)
+               polkit_context_unref (pk_context);
+#endif
+               pk_context = NULL;
+       }
+
+       return pk_context;
+}
+
+gboolean
+nm_polkit_check_privileges (NMPolKit *polkit,
+                    DBusGConnection *dbus_connection,
+                    const char * dbus_sender,
+                    const char * action_id,
+                                       GError **err)
+{
+       DBusError dbus_error;
+       PolKitCaller *pk_caller;
+       PolKitAction *pk_action;
+       PolKitResult pk_result;
+    PolKitContext *pol_ctx;
+
+    g_return_val_if_fail (NM_IS_POLKIT(polkit), FALSE);
+    g_return_val_if_fail (dbus_connection != NULL, FALSE);
+    g_return_val_if_fail (dbus_sender != NULL, FALSE);
+
+    pol_ctx = polkit->priv->context;
+
+       dbus_error_init (&dbus_error);
+       pk_caller = polkit_caller_new_from_dbus_name (dbus_g_connection_get_connection (dbus_connection),
+                                                                                dbus_sender,
+                                                                                &dbus_error);
+
+       if (dbus_error_is_set (&dbus_error)) {
+               *err = g_error_new (NM_POLKIT_ERROR,
+                                               NM_POLKIT_ERROR_NOT_PRIVILEGED,
+                                               "Error getting information about caller: %s: %s",
+                                               dbus_error.name, dbus_error.message);
+               dbus_error_free (&dbus_error);
+
+               if (pk_caller)
+                       polkit_caller_unref (pk_caller);
+
+               return FALSE;
+       }
+
+       pk_action = polkit_action_new ();
+       polkit_action_set_action_id (pk_action, action_id);
+
+#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR < 7)
+       pk_result = polkit_context_can_caller_do_action (pol_ctx, pk_action, pk_caller);
+#else
+       pk_result = polkit_context_is_caller_authorized (pol_ctx, pk_action, pk_caller, TRUE, NULL);
+#endif
+       polkit_caller_unref (pk_caller);
+       polkit_action_unref (pk_action);
+
+       if (pk_result != POLKIT_RESULT_YES) {
+               *err = g_error_new (NM_POLKIT_ERROR,
+                                               NM_POLKIT_ERROR_NOT_PRIVILEGED,
+                                               "%s %s",
+                                               action_id,
+                                               polkit_result_to_string_representation (pk_result));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+static void
+nm_polkit_init(NMPolKit *nm_polkit)
+{
+    nm_polkit->priv = G_TYPE_INSTANCE_GET_PRIVATE(nm_polkit, NM_TYPE_POLKIT, NMPolKitPrivate);
+    nm_polkit->priv->context = create_polkit_context();
+}
+
+static void
+finalize(GObject *polkit_obj)
+{
+    NMPolKit *nm_polkit = (NMPolKit *)polkit_obj;
+    if (nm_polkit->priv->context) {
+        polkit_context_unref(nm_polkit->priv->context);
+    }
+    G_OBJECT_CLASS(nm_polkit_parent_class)->finalize(polkit_obj);
+}
+
+static void
+nm_polkit_class_init(NMPolKitClass * nm_polkit_class)
+{
+    GObjectClass *object_class = (GObjectClass *)nm_polkit_class;
+    object_class->finalize = finalize;
+    g_type_class_add_private (nm_polkit_class, sizeof(NMPolKitPrivate));
+}
+
+NMPolKit *
+nm_polkit_get(void)
+{
+    static NMPolKit *singleton = NULL;
+    if (!singleton) {
+        singleton = NM_POLKIT(g_object_new(NM_TYPE_POLKIT, NULL));
+    } else {
+        g_object_ref (singleton);
+    }
+    return singleton;
+}
+
diff --git a/src/nm-polkit.h b/src/nm-polkit.h
new file mode 100644
index 0000000..cb6c36f
--- /dev/null
+++ b/src/nm-polkit.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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 2008 Novell, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_POLKIT_H
+#define NM_POLKIT_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#define NM_TYPE_POLKIT (nm_polkit_get_type())
+#define NM_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_POLKIT, NMPolKit))
+#define NM_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_POLKIT, NMPolKitClass))
+#define NM_IS_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_POLKIT))
+#define NM_IS_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_POLKIT))
+#define NM_POLKIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_POLKIT, NMPolKitClass))
+#define NM_POLKIT_ERROR (nm_polkit_error_quark())
+
+#define NM_POLICY_ACTION_USER_WIRED_APPLY "org.freedesktop.network-manager-settings.user.wired.apply"
+#define NM_POLICY_ACTION_USER_WIRELESS_APPLY "org.freedesktop.network-manager-settings.user.wireless.apply"
+#define NM_POLICY_ACTION_USER_MOBILE_APPLY "org.freedesktop.network-manager-settings.user.mobile.apply"
+#define NM_POLICY_ACTION_USER_VPN_APPLY "org.freedesktop.network-manager-settings.user.vpn.apply"
+#define NM_POLICY_ACTION_USER_DSL_APPLY "org.freedesktop.network-manager-settings.user.dsl.apply"
+
+#define NM_POLICY_ACTION_USER_WIRED_APPLY_WITH_SHARE "org.freedesktop.network-manager-settings.user.wired.apply-with-share"
+#define NM_POLICY_ACTION_USER_WIRELESS_APPLY_WITH_SHARE "org.freedesktop.network-manager-settings.user.wireless.apply-with-share"
+#define NM_POLICY_ACTION_USER_MOBILE_APPLY_WITH_SHARE "org.freedesktop.network-manager-settings.user.mobile.apply-with-share"
+#define NM_POLICY_ACTION_USER_VPN_APPLY_WITH_SHARE "org.freedesktop.network-manager-settings.user.vpn.apply-with-share"
+#define NM_POLICY_ACTION_USER_DSL_APPLY_WITH_SHARE "org.freedesktop.network-manager-settings.user.dsl.apply-with-share"
+
+
+
+typedef enum {
+    NM_POLKIT_ERROR_GERNERIC = 0,
+    NM_POLKIT_ERROR_NOT_PRIVILEGED,
+} NMPolKitError;
+
+typedef struct {
+    GObjectClass parent;
+}NMPolKitClass;
+
+typedef struct NMPolKitPrivate NMPolKitPrivate;
+
+typedef struct {
+  GObject parent;
+  NMPolKitPrivate *priv;
+} NMPolKit;
+
+GType nm_polkit_get_type (void);
+GQuark nm_polkit_error_quark (void);
+
+NMPolKit       *nm_polkit_get(void);
+
+gboolean        nm_polkit_check_privileges (NMPolKit *polkit,
+                                DBusGConnection *dbus_connection,
+                                const char * dbus_sender,
+                                const char * action_id,
+                                                               GError **err);
+
+#endif /* NM_POLKIT_H */
diff --git a/system-settings/src/dbus-settings.c b/system-settings/src/dbus-settings.c
index 8119f38..e3557b0 100644
--- a/system-settings/src/dbus-settings.c
+++ b/system-settings/src/dbus-settings.c
@@ -36,6 +36,12 @@
 #include "nm-polkit-helpers.h"
 #include "nm-system-config-error.h"
 #include "nm-utils.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wireless.h"
 
 static gboolean
 impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, DBusGMethodInvocation *context);
@@ -594,7 +600,11 @@ impl_settings_add_connection (NMSysconfigSettings *self,
                               DBusGMethodInvocation *context)
 {
 	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	NMConnection *connection;
+	NMSettingConnection *s_con;
 	GError *err = NULL;
+	const char *connection_type;
+	const char *action_id;
 
 	/* Do any of the plugins support adding? */
 	if (!nm_sysconfig_settings_get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) {
@@ -604,7 +614,50 @@ impl_settings_add_connection (NMSysconfigSettings *self,
 		goto out;
 	}
 
-	if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, &err))
+       connection = nm_connection_new_from_hash (hash, &err);
+       if (!connection) {
+               /* Invalid connection hash */
+        goto out;
+       }
+
+    s_con = NM_SETTING_CONNECTION(nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION));
+    connection_type = s_con ? nm_setting_connection_get_connection_type(s_con) : NULL;
+
+    if (connection_type == NULL) {
+        err = g_error_new(NM_SYSCONFIG_SETTINGS_ERROR,
+                NM_SYSCONFIG_SETTINGS_ERROR_ADD_REQUEST_CONFUSION,
+                "%s", "Could not distinguish the type to be added.");
+        goto out;
+    }
+
+    if (!strcmp(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRED_MODIFY;
+
+    } else if (!strcmp(connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRELESS_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_VPN_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_VPN_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_PPP_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_DSL_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_CDMA_SETTING_NAME)
+            || !strcmp(connection_type, NM_SETTING_GSM_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_MOBILE_MODIFY;
+    } else {
+        err = g_error_new(NM_SYSCONFIG_SETTINGS_ERROR,
+                NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
+                "%s", "Could not distinguish the type to be added.");
+        goto out;
+    }
+
+    /* hope nm_connection_verify can detect mix settings */
+    if (nm_connection_verify(connection, &err) == FALSE) {
+        err = g_error_new(NM_SYSCONFIG_SETTINGS_ERROR,
+                NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
+                "%s", "Connection settings is invalid");
+        goto out;
+    }
+
+       if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, action_id, &err))
 		goto out;
 
 	nm_sysconfig_settings_add_new_connection (self, hash, &err);
@@ -638,7 +691,8 @@ impl_settings_save_hostname (NMSysconfigSettings *self,
 		goto out;
 	}
 
-	if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, &err))
+       //  if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, NM_SYSCONFIG_POLICY_ACTION_SYSTEM_HOSTNAME_MODIFY, &err))
+       if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, NM_SYSCONFIG_POLICY_ACTION, &err))
 		goto out;
 
 	/* Set the hostname in all plugins */
diff --git a/system-settings/src/nm-polkit-helpers.c b/system-settings/src/nm-polkit-helpers.c
index 638f2a8..fca3907 100644
--- a/system-settings/src/nm-polkit-helpers.c
+++ b/system-settings/src/nm-polkit-helpers.c
@@ -96,6 +96,7 @@ gboolean
 check_polkit_privileges (DBusGConnection *dbus_connection,
 					PolKitContext *pol_ctx,
 					DBusGMethodInvocation *context,
+					const char * action_id,
 					GError **err)
 {
 	DBusConnection *tmp;
@@ -161,7 +162,7 @@ check_polkit_privileges (DBusGConnection *dbus_connection,
 	}
 
 	pk_action = polkit_action_new ();
-	polkit_action_set_action_id (pk_action, NM_SYSCONFIG_POLICY_ACTION);
+	polkit_action_set_action_id (pk_action, action_id);
 
 #if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR < 7)
 	pk_result = polkit_context_can_caller_do_action (pol_ctx, pk_action, pk_caller);
@@ -175,7 +176,7 @@ check_polkit_privileges (DBusGConnection *dbus_connection,
 		*err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
 						NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
 						"%s %s",
-						NM_SYSCONFIG_POLICY_ACTION,
+						action_id,
 						polkit_result_to_string_representation (pk_result));
 		return FALSE;
 	}
diff --git a/system-settings/src/nm-polkit-helpers.h b/system-settings/src/nm-polkit-helpers.h
index 1382648..ae198e8 100644
--- a/system-settings/src/nm-polkit-helpers.h
+++ b/system-settings/src/nm-polkit-helpers.h
@@ -28,10 +28,17 @@
 
 #define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify"
 
+#define NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRED_MODIFY "org.freedesktop.network-manager-settings.system.wired.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRELESS_MODIFY "org.freedesktop.network-manager-settings.system.wireless.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_SYSTEM_MOBILE_MODIFY "org.freedesktop.network-manager-settings.system.mobile.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_SYSTEM_VPN_MODIFY "org.freedesktop.network-manager-settings.system.vpn.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_SYSTEM_DSL_MODIFY "org.freedesktop.network-manager-settings.system.dsl.modify"
+
 PolKitContext *create_polkit_context   (GError **error);
 gboolean       check_polkit_privileges (DBusGConnection *dbus_connection,
 								PolKitContext *pol_ctx,
 								DBusGMethodInvocation *context,
+								const char * action_id,
 								GError **err);
 
 #endif /* NM_POLKIT_HELPERS_H */
diff --git a/system-settings/src/nm-sysconfig-connection.c b/system-settings/src/nm-sysconfig-connection.c
index c98c89a..d50331c 100644
--- a/system-settings/src/nm-sysconfig-connection.c
+++ b/system-settings/src/nm-sysconfig-connection.c
@@ -18,12 +18,24 @@
  * (C) Copyright 2008 Novell, Inc.
  */
 
+#include <string.h>
 #include <NetworkManager.h>
+#include "nm-connection.h"
 #include "nm-sysconfig-connection.h"
 #include "nm-system-config-error.h"
 #include "nm-polkit-helpers.h"
 #include "nm-dbus-glib-types.h"
 
+#include "nm-setting-connection.h"
+
+#include "nm-setting-cdma.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wireless.h"
+
+
 G_DEFINE_ABSTRACT_TYPE (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION)
 
 #define NM_SYSCONFIG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionPrivate))
@@ -35,6 +47,38 @@ typedef struct {
 	DBusGProxy *proxy;
 } NMSysconfigConnectionPrivate;
 
+static const char * get_action_id(NMConnection * con, GError **err)
+{
+    NMSettingConnection *s_con;
+    const char * connection_type = NULL;
+    const char * action_id = NULL;
+    s_con = (NMSettingConnection *) nm_connection_get_setting (con, NM_TYPE_SETTING_CONNECTION);
+    if (!s_con) {
+        return NULL;
+    }
+
+    connection_type = nm_setting_connection_get_connection_type(s_con);
+    if (connection_type == NULL) {
+        return NULL;
+    }
+
+    if (!strcmp(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRED_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_WIRELESS_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_VPN_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_VPN_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_PPP_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_DSL_MODIFY;
+    } else if (!strcmp(connection_type, NM_SETTING_CDMA_SETTING_NAME)
+            || !strcmp(connection_type, NM_SETTING_GSM_SETTING_NAME)) {
+        action_id = NM_SYSCONFIG_POLICY_ACTION_SYSTEM_MOBILE_MODIFY;
+    } else {
+        return NULL;
+    }
+    return action_id;
+}
+
 static gboolean
 update (NMExportedConnection *exported,
 	   GHashTable *new_settings,
@@ -42,11 +86,20 @@ update (NMExportedConnection *exported,
 {
 	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported);
 	DBusGMethodInvocation *context;
+	NMConnection *wrapped;
+	const char * action_id;
 
 	context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION);
 	g_return_val_if_fail (context != NULL, FALSE);
 
-	return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err);
+        wrapped = nm_exported_connection_get_connection (exported);
+
+        action_id = get_action_id(wrapped, err);
+        if (action_id == NULL) {
+        	return FALSE;
+        }
+ 
+        return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, action_id, err);
 }
 
 static gboolean
@@ -54,11 +107,20 @@ do_delete (NMExportedConnection *exported, GError **err)
 {
 	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported);
 	DBusGMethodInvocation *context;
+	NMConnection *wrapped;
+        const char * action_id;
 
 	context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION);
 	g_return_val_if_fail (context != NULL, FALSE);
 
-	return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err);
+        wrapped = nm_exported_connection_get_connection (exported);
+	action_id = get_action_id(wrapped, err);
+
+	if (action_id == NULL) {
+		return FALSE;
+	}
+
+        return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, NM_SYSCONFIG_POLICY_ACTION, err);
 }
 
 static GValue *
diff --git a/system-settings/src/nm-system-config-error.c b/system-settings/src/nm-system-config-error.c
index 13d4746..a19dc1d 100644
--- a/system-settings/src/nm-system-config-error.c
+++ b/system-settings/src/nm-system-config-error.c
@@ -49,6 +49,7 @@ nm_sysconfig_settings_error_get_type (void)
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, "AddFailed"),
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "SaveHostnameNotSupported"),
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, "SaveHostnameFailed"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_ADD_REQUEST_CONFUSION, "NotValidRequest"),
 			{ 0, 0, 0 }
 		};
 
diff --git a/system-settings/src/nm-system-config-error.h b/system-settings/src/nm-system-config-error.h
index 63896fc..217ef1c 100644
--- a/system-settings/src/nm-system-config-error.h
+++ b/system-settings/src/nm-system-config-error.h
@@ -34,6 +34,7 @@ enum {
 	NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED,
 	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
 	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED,
+	NM_SYSCONFIG_SETTINGS_ERROR_ADD_REQUEST_CONFUSION,
 };
 
 #define NM_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_quark ())
--- a/system-settings/src/nm-sysconfig-connection.c	2010-06-16 15:14:21.000000000 +0200
+++ b/system-settings/src/nm-sysconfig-connection.c	2010-06-16 15:12:36.000000000 +0200
@@ -120,7 +120,7 @@
 		return FALSE;
 	}
 
-        return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, NM_SYSCONFIG_POLICY_ACTION, err);
+        return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, action_id, err);
 }
 
 static GValue *
@@ -255,6 +255,7 @@
 	GError *error = NULL;
 	guint32 requestor_uid = G_MAXUINT32;
 	GHashTable *secrets;
+	
 
 	g_return_if_fail (info != NULL);
 
@@ -266,7 +267,7 @@
 
 	/* Non-root users need PolicyKit authorization */
 	if (requestor_uid != 0) {
-		if (!check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, info->context, &error))
+		if (!check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, info->context, NM_SYSCONFIG_POLICY_ACTION, &error))
 			goto error;
 	}
 
