libnm-glib: add secret agent base class

This commit is contained in:
Dan Williams
2010-12-14 00:03:22 -06:00
parent 62a2c34e27
commit 1496f8056f
5 changed files with 875 additions and 3 deletions

View File

@@ -55,6 +55,9 @@
#define NM_DBUS_INTERFACE_AGENT_MANAGER NM_DBUS_INTERFACE ".AgentManager"
#define NM_DBUS_PATH_AGENT_MANAGER "/org/freedesktop/NetworkManager/AgentManager"
#define NM_DBUS_INTERFACE_SECRET_AGENT NM_DBUS_INTERFACE ".SecretAgent"
#define NM_DBUS_PATH_SECRET_AGENT "/org/freedesktop/NetworkManager/SecretAgent"
/*
* Types of NetworkManager states
*/

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.SecretAgent">
<tp:docstring>
Private D-Bus interface used by secret agents that store and provide
secrets to NetworkManager.
</tp:docstring>
<method name="GetSecrets">
<tp:docstring>
Retrieve and return stored secrets, if any, or request new
secrets from the agent's user.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_secret_agent_get_secrets"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
<tp:docstring>
Nested settings maps containing the connection for which
secrets are being requested.
</tp:docstring>
</arg>
<arg name="connection_path" type="o" direction="in">
<tp:docstring>
Object path of the connection for which secrets are being
requested.
</tp:docstring>
</arg>
<arg name="setting_name" type="s" direction="in">
<tp:docstring>
Setting name for which secrets are being requested.
</tp:docstring>
</arg>
<arg name="hints" type="as" direction="in">
<tp:docstring>
Array of strings of key names in the requested setting for
which NetworkManager thinks a secrets may be required. The
Agent should return any secrets it has, or that it thinks
are required, regardless of what hints NetworkManager sends
in this request.
</tp:docstring>
</arg>
<arg name="request_new" type="b" direction="in">
<tp:docstring>
If true, new secrets are assumed to be invalid or incorrect,
and the agent should ask the user for new secrets. If false,
existing secrets should be retrieved from storage and
returned without interrupting the user.
</tp:docstring>
</arg>
<arg name="secrets" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
<tp:docstring>
Nested settings maps containing secrets. Each setting MUST
contain at least the 'name' field, containing the name of
the setting, and one or more secrets.
</tp:docstring>
</arg>
</method>
<method name="SaveSecrets">
<tp:docstring>
Save given secrets to backing storage.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_secret_agent_save_secrets"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
<tp:docstring>
Nested settings maps containing the entire connection
(including secrets), for which the agent should save the
secrets to backing storage.
</tp:docstring>
</arg>
<arg name="connection_path" type="o" direction="in">
<tp:docstring>
Object path of the connection for which the agent should
save secrets to backing storage.
</tp:docstring>
</arg>
</method>
<method name="DeleteSecrets">
<tp:docstring>
Delete secrets from backing storage.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_secret_agent_delete_secrets"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
<tp:docstring>
Nested settings maps containing the entire connection
(including secrets), for which the agent should delete the
secrets from backing storage.
</tp:docstring>
</arg>
<arg name="connection_path" type="o" direction="in">
<tp:docstring>
Object path of the connection for which the agent should
delete secrets from backing storage.
</tp:docstring>
</arg>
</method>
</interface>
</node>

View File

@@ -18,7 +18,8 @@ BUILT_SOURCES = \
nm-ip4-config-bindings.h \
nm-dhcp4-config-bindings.h \
nm-ip6-config-bindings.h \
nm-dhcp6-config-bindings.h
nm-dhcp6-config-bindings.h \
nm-secret-agent-glue.h
#####################################################
# Deprecated original libnm_glib bits
@@ -76,7 +77,8 @@ libnminclude_HEADERS = \
nm-ip6-config.h \
nm-dhcp6-config.h \
nm-remote-connection.h \
nm-remote-settings.h
nm-remote-settings.h \
nm-secret-agent.h
libnm_glib_la_SOURCES = \
nm-object.c \
@@ -105,7 +107,8 @@ libnm_glib_la_SOURCES = \
nm-dhcp6-config.c \
nm-remote-connection.c \
nm-remote-connection-private.h \
nm-remote-settings.c
nm-remote-settings.c \
nm-secret-agent.c
libnm_glib_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
@@ -178,6 +181,9 @@ nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
$(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
nm-secret-agent-glue.h: $(top_srcdir)/introspection/nm-secret-agent.xml
$(AM_V_GEN) dbus-binding-tool --prefix=nm_secret_agent --mode=glib-server --output=$@ $<
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnm-glib.pc libnm-glib-vpn.pc

View File

@@ -0,0 +1,638 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010 Red Hat, Inc.
*/
#include <config.h>
#include <ctype.h>
#include <string.h>
#include <NetworkManager.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "nm-secret-agent.h"
#include "nm-marshal.h"
#include "NetworkManager.h"
static void impl_secret_agent_get_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
const char *setting_name,
const char **hints,
gboolean request_new,
DBusGMethodInvocation *context);
static void impl_secret_agent_save_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
DBusGMethodInvocation *context);
static void impl_secret_agent_delete_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
DBusGMethodInvocation *context);
#include "nm-secret-agent-glue.h"
G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
#define NM_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_SECRET_AGENT, \
NMSecretAgentPrivate))
typedef struct {
gboolean registered;
DBusGConnection *bus;
DBusGProxy *dbus_proxy;
DBusGProxy *manager_proxy;
DBusGProxyCall *reg_call;
char *nm_owner;
char *identifier;
gboolean disposed;
} NMSecretAgentPrivate;
enum {
PROP_0,
PROP_IDENTIFIER,
LAST_PROP
};
enum {
REGISTRATION_RESULT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/********************************************************************/
GQuark
nm_secret_agent_error_quark (void)
{
static GQuark ret = 0;
if (G_UNLIKELY (ret == 0))
ret = g_quark_from_static_string ("nm-secret-agent-error");
return ret;
}
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
nm_secret_agent_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* Sender is not authorized to make this request */
ENUM_ENTRY (NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED, "NotAuthorized"),
/* Given connection details do not make a valid connection */
ENUM_ENTRY (NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, "InvalidConnection"),
/* The request was canceled explicitly by the user */
ENUM_ENTRY (NM_SECRET_AGENT_ERROR_USER_CANCELED, "UserCanceled"),
/* The request was canceled, but not by the user */
ENUM_ENTRY (NM_SECRET_AGENT_ERROR_AGENT_CANCELED, "AgentCanceled"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMSecretAgentError", values);
}
return etype;
}
/*************************************************************/
static const char *
get_nm_owner (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
GError *error = NULL;
char *owner;
if (!priv->nm_owner) {
if (!dbus_g_proxy_call_with_timeout (priv->dbus_proxy,
"GetNameOwner", 2000, &error,
G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_INVALID,
G_TYPE_STRING, &owner,
G_TYPE_INVALID))
return NULL;
priv->nm_owner = g_strdup (owner);
g_free (owner);
}
return priv->nm_owner;
}
static void
name_owner_changed (DBusGProxy *proxy,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
{
NMSecretAgent *self = NM_SECRET_AGENT (user_data);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
if (strcmp (name, NM_DBUS_SERVICE) == 0) {
g_free (priv->nm_owner);
priv->nm_owner = g_strdup (new_owner);
}
}
static NMConnection *
verify_request (NMSecretAgent *self,
DBusGMethodInvocation *context,
GHashTable *connection_hash,
GError **error)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
NMConnection *connection = NULL;
DBusConnection *bus;
char *sender;
const char *nm_owner;
DBusError dbus_error;
uid_t sender_uid = G_MAXUINT;
GError *local = NULL;
g_return_val_if_fail (context != NULL, NULL);
g_return_val_if_fail (connection_hash != NULL, NULL);
/* Verify the sender's UID is 0, and that the sender is the same as
* NetworkManager's bus name owner.
*/
nm_owner = get_nm_owner (self);
if (!nm_owner) {
g_set_error_literal (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"NetworkManager bus name owner unknown.");
return FALSE;
}
bus = dbus_g_connection_get_connection (priv->bus);
if (!bus) {
g_set_error_literal (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"Failed to get DBus connection.");
return FALSE;
}
sender = dbus_g_method_get_sender (context);
if (!sender) {
g_set_error_literal (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"Failed to get request sender.");
return FALSE;
}
/* Check that the sender matches the current NM bus name owner */
if (strcmp (sender, nm_owner) != 0) {
g_set_error_literal (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"Request sender does not match NetworkManager bus name owner.");
goto out;
}
dbus_error_init (&dbus_error);
sender_uid = dbus_bus_get_unix_user (bus, sender, &dbus_error);
if (dbus_error_is_set (&dbus_error)) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"Failed to get request unix user: (%s) %s.",
dbus_error.name, dbus_error.message);
dbus_error_free (&dbus_error);
goto out;
}
if (0 != sender_uid) {
g_set_error_literal (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
"Request sender is not root.");
goto out;
}
/* And make sure the connection is actually valid */
connection = nm_connection_new_from_hash (connection_hash, &local);
if (!connection) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
"Invalid connection: (%d) %s",
local ? local->code : -1,
(local && local->message) ? local->message : "(unknown)");
g_clear_error (&local);
}
out:
g_free (sender);
return connection;
}
static void
impl_secret_agent_get_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
const char *setting_name,
const char **hints,
gboolean request_new,
DBusGMethodInvocation *context)
{
GError *error = NULL;
NMConnection *connection;
/* Make sure the request comes from NetworkManager and is valid */
connection = verify_request (self, context, connection_hash, &error);
if (!connection) {
dbus_g_method_return_error (context, error);
g_clear_error (&error);
return;
}
NM_SECRET_AGENT_GET_CLASS (self)->get_secrets (self,
connection,
connection_path,
setting_name,
hints,
request_new,
context);
g_object_unref (connection);
}
static void
impl_secret_agent_save_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
DBusGMethodInvocation *context)
{
GError *error = NULL;
NMConnection *connection;
/* Make sure the request comes from NetworkManager and is valid */
connection = verify_request (self, context, connection_hash, &error);
if (!connection) {
dbus_g_method_return_error (context, error);
g_clear_error (&error);
return;
}
NM_SECRET_AGENT_GET_CLASS (self)->save_secrets (self,
connection,
connection_path,
context);
g_object_unref (connection);
}
static void
impl_secret_agent_delete_secrets (NMSecretAgent *self,
GHashTable *connection_hash,
const char *connection_path,
DBusGMethodInvocation *context)
{
GError *error = NULL;
NMConnection *connection;
/* Make sure the request comes from NetworkManager and is valid */
connection = verify_request (self, context, connection_hash, &error);
if (!connection) {
dbus_g_method_return_error (context, error);
g_clear_error (&error);
return;
}
NM_SECRET_AGENT_GET_CLASS (self)->delete_secrets (self,
connection,
connection_path,
context);
g_object_unref (connection);
}
/**************************************************************/
static void
reg_request_cb (DBusGProxy *proxy,
DBusGProxyCall *call,
gpointer user_data)
{
NMSecretAgent *self = NM_SECRET_AGENT (user_data);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
GError *error = NULL;
priv->reg_call = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
priv->registered = TRUE;
else {
/* If registration failed we shouldn't expose ourselves on the bus */
dbus_g_connection_unregister_g_object (priv->bus, G_OBJECT (self));
}
g_signal_emit (self, signals[REGISTRATION_RESULT], 0, error);
g_clear_error (&error);
}
/**
* nm_secret_agent_register:
*
* Registers the #NMSecretAgent with the NetworkManager secret manager,
* indicating to NetworkManager that the agent is able to provide and save
* secrets for connections on behalf of its user. Registration is an
* asynchronous operation and its success or failure is indicated via the
* 'registration-result' signal.
*
* Returns: a new %TRUE if registration was successfully requested (this does
* not mean registration itself was successful), %FALSE if registration was not
* successfully requested.
**/
gboolean
nm_secret_agent_register (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv;
NMSecretAgentClass *class;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
g_return_val_if_fail (priv->registered == FALSE, FALSE);
g_return_val_if_fail (priv->reg_call == NULL, FALSE);
g_return_val_if_fail (priv->bus != NULL, FALSE);
g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
/* Also make sure the subclass can actually respond to secrets requests */
class = NM_SECRET_AGENT_GET_CLASS (self);
g_return_val_if_fail (class->get_secrets != NULL, FALSE);
g_return_val_if_fail (class->save_secrets != NULL, FALSE);
g_return_val_if_fail (class->delete_secrets != NULL, FALSE);
/* Export our secret agent interface before registering with the manager */
dbus_g_connection_register_g_object (priv->bus,
NM_DBUS_PATH_SECRET_AGENT,
G_OBJECT (self));
priv->reg_call = dbus_g_proxy_begin_call_with_timeout (priv->manager_proxy,
"Register",
reg_request_cb,
self,
NULL,
G_USEC_PER_SEC * 5,
G_TYPE_STRING, priv->identifier,
G_TYPE_INVALID);
return TRUE;
}
/**
* nm_secret_agent_unregister:
*
* Unregisters the #NMSecretAgent with the NetworkManager secret manager,
* indicating to NetworkManager that the agent is will no longer provide or
* store secrets on behalf of this user.
*
* Returns: a new %TRUE if unregistration was successful, %FALSE if it was not.
**/
gboolean
nm_secret_agent_unregister (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
g_return_val_if_fail (priv->registered == TRUE, FALSE);
g_return_val_if_fail (priv->bus != NULL, FALSE);
g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
dbus_g_proxy_call_no_reply (priv->manager_proxy, "Unregister", G_TYPE_INVALID);
return TRUE;
}
/**************************************************************/
static gboolean
validate_identifier (const char *identifier)
{
const char *p = identifier;
size_t id_len;
/* Length between 3 and 255 characters inclusive */
id_len = strlen (identifier);
if (id_len < 3 || id_len > 255)
return FALSE;
if ((identifier[0] == '.') || (identifier[id_len - 1] == '.'))
return FALSE;
/* FIXME: do complete validation here */
while (p && *p) {
if (!isalnum (*p) && (*p != '_') && (*p != '-'))
return FALSE;
if ((*p == '.') && (*(p + 1) == '.'))
return FALSE;
}
return TRUE;
}
static void
nm_secret_agent_init (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
GError *error = NULL;
priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (!priv->bus) {
g_warning ("Couldn't connect to system bus: %s", error->message);
g_error_free (error);
return;
}
priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!priv->dbus_proxy) {
g_warning ("Couldn't create messagebus proxy.");
return;
}
dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged",
G_CALLBACK (name_owner_changed),
self, NULL);
priv->manager_proxy = dbus_g_proxy_new_for_name (priv->bus,
NM_DBUS_SERVICE,
NM_DBUS_PATH_AGENT_MANAGER,
NM_DBUS_INTERFACE_AGENT_MANAGER);
if (!priv->manager_proxy) {
g_warning ("Couldn't create NM agent manager proxy.");
return;
}
}
static void
get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
switch (prop_id) {
case PROP_IDENTIFIER:
g_value_set_string (value, priv->identifier);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
const char *identifier;
switch (prop_id) {
case PROP_IDENTIFIER:
identifier = g_value_get_string (value);
g_return_if_fail (validate_identifier (identifier));
g_free (priv->identifier);
priv->identifier = g_strdup (identifier);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dispose (GObject *object)
{
NMSecretAgent *self = NM_SECRET_AGENT (object);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
if (!priv->disposed) {
priv->disposed = TRUE;
if (priv->registered)
nm_secret_agent_unregister (self);
g_free (priv->identifier);
g_free (priv->nm_owner);
if (priv->dbus_proxy)
g_object_unref (priv->dbus_proxy);
if (priv->manager_proxy)
g_object_unref (priv->manager_proxy);
if (priv->bus)
dbus_g_connection_unref (priv->bus);
}
G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
}
static void
nm_secret_agent_class_init (NMSecretAgentClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (NMSecretAgentPrivate));
/* Virtual methods */
object_class->dispose = dispose;
object_class->get_property = get_property;
object_class->set_property = set_property;
/**
* NMSecretAgent:identifier:
*
* Identifies this agent; only one agent in each user session may use the
* same identifier. Identifier formatting follows the same rules as
* D-Bus bus names with the exception that the ':' character is not
* allowed. The valid set of characters is "[A-Z][a-z][0-9]_-." and the
* identifier is limited in length to 255 characters with a minimum
* of 3 characters. An example valid identifier is 'org.gnome.nm-applet'
* (without quotes).
**/
g_object_class_install_property
(object_class, PROP_IDENTIFIER,
g_param_spec_string (NM_SECRET_AGENT_IDENTIFIER,
"Identifier",
"Identifier",
NULL,
G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
/**
* NMSecretAgent::registration-result:
* @agent: the agent that received the signal
* @error: the error, if any, that occured while registering
*
* Indicates the result of a registration request; if @error is NULL the
* request was successful.
**/
signals[REGISTRATION_RESULT] =
g_signal_new (REGISTRATION_RESULT,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
&dbus_glib_nm_secret_agent_object_info);
dbus_g_error_domain_register (NM_SECRET_AGENT_ERROR,
NM_DBUS_INTERFACE_SECRET_AGENT,
NM_TYPE_SECRET_AGENT_ERROR);
}

View File

@@ -0,0 +1,119 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010 Red Hat, Inc.
*/
#ifndef NM_SECRET_AGENT_H
#define NM_SECRET_AGENT_H
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <nm-connection.h>
G_BEGIN_DECLS
#define NM_SECRET_AGENT_ERROR (nm_secret_agent_error_quark ())
#define NM_TYPE_SECRET_AGENT_ERROR (nm_secret_agent_error_get_type ())
GQuark nm_secret_agent_error_quark (void);
GType nm_secret_agent_error_get_type (void);
typedef enum {
NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED = 0,
NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
NM_SECRET_AGENT_ERROR_USER_CANCELED,
NM_SECRET_AGENT_ERROR_AGENT_CANCELED
} NMSecretAgentError;
#define NM_TYPE_SECRET_AGENT (nm_secret_agent_get_type ())
#define NM_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgent))
#define NM_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT, NMSecretAgentClass))
#define NM_IS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT))
#define NM_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SECRET_AGENT))
#define NM_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentClass))
#define NM_SECRET_AGENT_IDENTIFIER "identifier"
#define NM_SECRET_AGENT_REGISTRATION_RESULT "registration-result"
typedef struct {
GObject parent;
} NMSecretAgent;
typedef struct {
GObjectClass parent;
/* Virtual methods for subclasses */
/* Called when the subclass should retrieve and return secrets. Subclass
* must copy or reference any arguments it may require after returning from
* this method, as the arguments will freed (except for 'agent' and
* 'context' of course).
*/
void (*get_secrets) (NMSecretAgent *agent,
NMConnection *connection,
const char *connection_path,
const char *setting_name,
const char **hints,
gboolean request_new,
DBusGMethodInvocation *context);
/* Called when the subclass should save the secrets contained in the
* connection to backing storage. Subclass must copy or reference any
* arguments it may require after returning from this method, as the
* arguments will freed (except for 'agent' and 'context' of course).
*/
void (*save_secrets) (NMSecretAgent *agent,
NMConnection *connection,
const char *connection_path,
DBusGMethodInvocation *context);
/* Called when the subclass should delete the secrets contained in the
* connection from backing storage. Subclass must copy or reference any
* arguments it may require after returning from this method, as the
* arguments will freed (except for 'agent' and 'context' of course).
*/
void (*delete_secrets) (NMSecretAgent *agent,
NMConnection *connection,
const char *connection_path,
DBusGMethodInvocation *context);
/* Signals */
void (*registration_result) (NMSecretAgent *agent, GError *error);
/* Padding for future expansion */
void (*_reserved1) (void);
void (*_reserved2) (void);
void (*_reserved3) (void);
void (*_reserved4) (void);
void (*_reserved5) (void);
void (*_reserved6) (void);
} NMSecretAgentClass;
GType nm_secret_agent_get_type (void);
NMSecretAgent *nm_secret_agent_new (const char *identifier);
gboolean nm_secret_agent_register (NMSecretAgent *self);
gboolean nm_secret_agent_unregister (NMSecretAgent *self);
G_END_DECLS
#endif /* NM_SECRET_AGENT_H */