summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2012-04-12 13:54:27 -0400
committerDavid Zeuthen <davidz@redhat.com>2012-04-12 14:00:26 -0400
commit2dd284eb425535445f0be6e9dd7d45e8ccd3ffa6 (patch)
tree2df3f5169bde212bb49890e3b145fef3f927f1bd
parentbda0fc1de3361fc6f377d041ce2088118048fdf7 (diff)
downloadpolkit-2dd284eb425535445f0be6e9dd7d45e8ccd3ffa6.tar.gz
Make it possible to influence agent registration with an a{sv} parameter
Additionally, add a "fallback" option. Also add support in this in the pkttyagent(1) program. This slightly breaks libpolkit-backend API by adding a GVariant* param to one of the class vfuncs... but that API is already declared unstable so that's fine. Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--docs/man/pkttyagent.xml11
-rw-r--r--docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml18
-rw-r--r--docs/polkit/polkit-1-sections.txt4
-rw-r--r--src/polkit/polkitauthority.c164
-rw-r--r--src/polkit/polkitauthority.h22
-rw-r--r--src/polkitagent/polkitagentlistener.c98
-rw-r--r--src/polkitagent/polkitagentlistener.h8
-rw-r--r--src/polkitbackend/polkitbackendauthority.c70
-rw-r--r--src/polkitbackend/polkitbackendauthority.h2
-rw-r--r--src/polkitbackend/polkitbackendinteractiveauthority.c52
-rw-r--r--src/programs/pkttyagent.c31
11 files changed, 427 insertions, 53 deletions
diff --git a/docs/man/pkttyagent.xml b/docs/man/pkttyagent.xml
index f0f328e..a5bab8a 100644
--- a/docs/man/pkttyagent.xml
+++ b/docs/man/pkttyagent.xml
@@ -56,6 +56,12 @@
</arg>
</group>
+ <group>
+ <arg choice="plain">
+ <option>--fallback</option>
+ </arg>
+ </group>
+
</cmdsynopsis>
</refsynopsisdiv>
@@ -78,6 +84,11 @@
program. This file descriptor will then be closed when the
authentication agent has been successfully registered.
</para>
+ <para>
+ If <option>--fallback</option> is used, the textual
+ authentication agent will not replace an existing authentication
+ agent.
+ </para>
</refsect1>
<refsect1 id="pkttyagent-return-value">
diff --git a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
index d4894f5..49173f8 100644
--- a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
+++ b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
@@ -34,6 +34,10 @@ Structure <link linkend="eggdbus-struct-TemporaryAuthorization">TemporaryAuth
<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
IN String locale,
IN String object_path)
+<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgentWithOptions">RegisterAuthenticationAgentWithOptions</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
+ IN String locale,
+ IN String object_path,
+ IN Dict&lt;String,Variant&gt; options)
<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.UnregisterAuthenticationAgent">UnregisterAuthenticationAgent</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
IN String object_path)
<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse</link> (IN String cookie,
@@ -724,6 +728,20 @@ The object path of authentication agent object on the unique name of the caller.
</varlistentry>
</variablelist>
</refsect2>
+
+ <refsect2 role="function" id="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgentWithOptions">
+ <title>RegisterAuthenticationAgentWithOptions ()</title>
+ <programlisting>
+RegisterAuthenticationAgent (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
+ IN String locale,
+ IN String object_path,
+ IN Dict&lt;String,Variant&gt; options)
+ </programlisting>
+ <para>
+<para>Like <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent</link> but takes additional options. If the option <literal>fallback</literal> (of type <literal>Boolean</literal>) is TRUE, then the authentcation agent will only be used as a fallback, e.g. if another agent (without the <literal>fallback</literal> option set TRUE) is available, it will be used instead.</para>
+ </para>
+ </refsect2>
+
<refsect2 role="function" id="eggdbus-method-org.freedesktop.PolicyKit1.Authority.UnregisterAuthenticationAgent">
<title>UnregisterAuthenticationAgent ()</title>
<programlisting>
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index ff6a301..3881004 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -38,6 +38,9 @@ polkit_authority_enumerate_actions_sync
polkit_authority_register_authentication_agent
polkit_authority_register_authentication_agent_finish
polkit_authority_register_authentication_agent_sync
+polkit_authority_register_authentication_agent_with_options
+polkit_authority_register_authentication_agent_with_options_finish
+polkit_authority_register_authentication_agent_with_options_sync
polkit_authority_unregister_authentication_agent
polkit_authority_unregister_authentication_agent_finish
polkit_authority_unregister_authentication_agent_sync
@@ -394,6 +397,7 @@ polkit_agent_listener_initiate_authentication
polkit_agent_listener_initiate_authentication_finish
PolkitAgentRegisterFlags
polkit_agent_listener_register
+polkit_agent_listener_register_with_options
polkit_agent_listener_unregister
<SUBSECTION Standard>
POLKIT_AGENT_LISTENER
diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c
index 468421e..9947cf3 100644
--- a/src/polkit/polkitauthority.c
+++ b/src/polkit/polkitauthority.c
@@ -1167,6 +1167,170 @@ polkit_authority_register_authentication_agent_sync (PolkitAuthority *author
/* ---------------------------------------------------------------------------------------------------- */
/**
+ * polkit_authority_register_authentication_agent_with_options:
+ * @authority: A #PolkitAuthority.
+ * @subject: The subject the authentication agent is for, typically a #PolkitUnixSession object.
+ * @locale: The locale of the authentication agent.
+ * @object_path: The object path for the authentication agent.
+ * @options: (allow-none): A #GVariant with options or %NULL.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously registers an authentication agent.
+ *
+ * When the operation is finished, @callback will be invoked in the
+ * <link linkend="g-main-context-push-thread-default">thread-default
+ * main loop</link> of the thread you are calling this method
+ * from. You can then call
+ * polkit_authority_register_authentication_agent_with_options_finish() to get the
+ * result of the operation.
+ **/
+void
+polkit_authority_register_authentication_agent_with_options (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *locale,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVariant *subject_value;
+
+ g_return_if_fail (POLKIT_IS_AUTHORITY (authority));
+ g_return_if_fail (POLKIT_IS_SUBJECT (subject));
+ g_return_if_fail (locale != NULL);
+ g_return_if_fail (g_variant_is_object_path (object_path));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ subject_value = polkit_subject_to_gvariant (subject);
+ g_variant_ref_sink (subject_value);
+ if (options != NULL)
+ {
+ g_dbus_proxy_call (authority->proxy,
+ "RegisterAuthenticationAgentWithOptions",
+ g_variant_new ("(@(sa{sv})ss@a{sv})",
+ subject_value,
+ locale,
+ object_path,
+ options),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ generic_async_cb,
+ g_simple_async_result_new (G_OBJECT (authority),
+ callback,
+ user_data,
+ polkit_authority_register_authentication_agent_with_options));
+ }
+ else
+ {
+ g_dbus_proxy_call (authority->proxy,
+ "RegisterAuthenticationAgent",
+ g_variant_new ("(@(sa{sv})ss)",
+ subject_value,
+ locale,
+ object_path),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ generic_async_cb,
+ g_simple_async_result_new (G_OBJECT (authority),
+ callback,
+ user_data,
+ polkit_authority_register_authentication_agent_with_options));
+ }
+ g_variant_unref (subject_value);
+}
+
+/**
+ * polkit_authority_register_authentication_agent_with_options_finish:
+ * @authority: A #PolkitAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: (allow-none): Return location for error or %NULL.
+ *
+ * Finishes registering an authentication agent.
+ *
+ * Returns: %TRUE if the authentication agent was successfully registered, %FALSE if @error is set.
+ **/
+gboolean
+polkit_authority_register_authentication_agent_with_options_finish (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GError **error)
+{
+ gboolean ret;
+ GVariant *value;
+ GAsyncResult *_res;
+
+ g_return_val_if_fail (POLKIT_IS_AUTHORITY (authority), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ ret = FALSE;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (res)) == polkit_authority_register_authentication_agent_with_options);
+ _res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+
+ value = g_dbus_proxy_call_finish (authority->proxy, _res, error);
+ if (value == NULL)
+ goto out;
+ ret = TRUE;
+ g_variant_unref (value);
+
+ out:
+ return ret;
+}
+
+
+/**
+ * polkit_authority_register_authentication_agent_with_options_sync:
+ * @authority: A #PolkitAuthority.
+ * @subject: The subject the authentication agent is for, typically a #PolkitUnixSession object.
+ * @locale: The locale of the authentication agent.
+ * @object_path: The object path for the authentication agent.
+ * @options: (allow-none): A #GVariant with options or %NULL.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: (allow-none): Return location for error or %NULL.
+ *
+ * Registers an authentication agent. The calling thread is blocked
+ * until a reply is received. See
+ * polkit_authority_register_authentication_agent_with_options() for the
+ * asynchronous version.
+ *
+ * Returns: %TRUE if the authentication agent was successfully registered, %FALSE if @error is set.
+ **/
+gboolean
+polkit_authority_register_authentication_agent_with_options_sync (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *locale,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret;
+ CallSyncData *data;
+
+ g_return_val_if_fail (POLKIT_IS_AUTHORITY (authority), FALSE);
+ g_return_val_if_fail (POLKIT_IS_SUBJECT (subject), FALSE);
+ g_return_val_if_fail (locale != NULL, FALSE);
+ g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ data = call_sync_new ();
+ polkit_authority_register_authentication_agent_with_options (authority, subject, locale, object_path, options, cancellable, call_sync_cb, data);
+ call_sync_block (data);
+ ret = polkit_authority_register_authentication_agent_with_options_finish (authority, data->res, error);
+ call_sync_free (data);
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
* polkit_authority_unregister_authentication_agent:
* @authority: A #PolkitAuthority.
* @subject: The subject the authentication agent is for, typically a #PolkitUnixSession object.
diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h
index edd8a62..921b712 100644
--- a/src/polkit/polkitauthority.h
+++ b/src/polkit/polkitauthority.h
@@ -83,6 +83,14 @@ gboolean polkit_authority_register_authentication_agent_sync (
GCancellable *cancellable,
GError **error);
+gboolean polkit_authority_register_authentication_agent_with_options_sync (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *locale,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GError **error);
+
gboolean polkit_authority_unregister_authentication_agent_sync (PolkitAuthority *authority,
PolkitSubject *subject,
const gchar *object_path,
@@ -142,10 +150,24 @@ void polkit_authority_register_authentication_agent (Polki
GAsyncReadyCallback callback,
gpointer user_data);
+
gboolean polkit_authority_register_authentication_agent_finish (PolkitAuthority *authority,
GAsyncResult *res,
GError **error);
+gboolean polkit_authority_register_authentication_agent_with_options_finish (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
+
+void polkit_authority_register_authentication_agent_with_options (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *locale,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
void polkit_authority_unregister_authentication_agent (PolkitAuthority *authority,
PolkitSubject *subject,
const gchar *object_path,
diff --git a/src/polkitagent/polkitagentlistener.c b/src/polkitagent/polkitagentlistener.c
index dbbfd63..0d97501 100644
--- a/src/polkitagent/polkitagentlistener.c
+++ b/src/polkitagent/polkitagentlistener.c
@@ -43,7 +43,8 @@
* evidence that the user is one of the requested identities.
*
* To register a #PolkitAgentListener with the PolicyKit daemon, use
- * polkit_agent_listener_register().
+ * polkit_agent_listener_register() or
+ * polkit_agent_listener_register_with_options().
*/
typedef struct
@@ -62,6 +63,8 @@ typedef struct
PolkitAgentListener *listener;
+ GVariant *registration_options;
+
PolkitSubject *subject;
gchar *object_path;
@@ -104,6 +107,9 @@ server_free (Server *server)
if (server->interface_info != NULL)
g_dbus_interface_info_unref (server->interface_info);
+ if (server->registration_options != NULL)
+ g_variant_unref (server->registration_options);
+
if (server->listener != NULL)
g_object_unref (server->listener);
@@ -143,12 +149,13 @@ server_register (Server *server,
locale = "en_US.UTF-8";
local_error = NULL;
- if (!polkit_authority_register_authentication_agent_sync (server->authority,
- server->subject,
- locale,
- server->object_path,
- NULL,
- &local_error))
+ if (!polkit_authority_register_authentication_agent_with_options_sync (server->authority,
+ server->subject,
+ locale,
+ server->object_path,
+ server->registration_options,
+ NULL,
+ &local_error))
{
g_warning ("Unable to register authentication agent: %s", local_error->message);
g_propagate_error (error, local_error);
@@ -360,42 +367,30 @@ server_thread_func (gpointer user_data)
}
/**
- * polkit_agent_listener_register:
+ * polkit_agent_listener_register_with_options:
* @listener: A #PolkitAgentListener.
* @flags: A set of flags from the #PolkitAgentRegisterFlags enumeration.
* @subject: The subject to become an authentication agent for, typically a #PolkitUnixSession object.
* @object_path: The D-Bus object path to use for the authentication agent or %NULL for the default object path.
+ * @options: (allow-none): A #GVariant with options or %NULL.
* @cancellable: A #GCancellable or %NULL.
* @error: Return location for error.
*
- * Registers @listener with the PolicyKit daemon as an authentication
- * agent for @subject. This is implemented by registering a D-Bus
- * object at @object_path on the unique name assigned by the system
- * message bus.
- *
- * Whenever the PolicyKit daemon needs to authenticate a processes
- * that is related to @subject, the methods
- * polkit_agent_listener_initiate_authentication() and
- * polkit_agent_listener_initiate_authentication_finish() will be
- * invoked on @listener.
- *
- * Note that registration of an authentication agent can fail; for
- * example another authentication agent may already be registered for
- * @subject.
- *
- * Note that the calling thread is blocked until a reply is received.
+ * Like polkit_agent_listener_register() but takes options to influence registration. See the
+ * <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgentWithOptions">RegisterAuthenticationAgentWithOptions()</link> D-Bus method for details.
*
* Returns: (transfer full): %NULL if @error is set, otherwise a
* registration handle that can be used with
* polkit_agent_listener_unregister().
*/
gpointer
-polkit_agent_listener_register (PolkitAgentListener *listener,
- PolkitAgentRegisterFlags flags,
- PolkitSubject *subject,
- const gchar *object_path,
- GCancellable *cancellable,
- GError **error)
+polkit_agent_listener_register_with_options (PolkitAgentListener *listener,
+ PolkitAgentRegisterFlags flags,
+ PolkitSubject *subject,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GError **error)
{
Server *server;
GDBusNodeInfo *node_info;
@@ -425,6 +420,8 @@ polkit_agent_listener_register (PolkitAgentListener *listener,
server->listener = g_object_ref (listener);
+ server->registration_options = options != NULL ? g_variant_ref_sink (options) : NULL;
+
if (flags & POLKIT_AGENT_REGISTER_FLAGS_RUN_IN_THREAD)
{
server->thread = g_thread_create (server_thread_func,
@@ -472,6 +469,47 @@ polkit_agent_listener_register (PolkitAgentListener *listener,
}
/**
+ * polkit_agent_listener_register:
+ * @listener: A #PolkitAgentListener.
+ * @flags: A set of flags from the #PolkitAgentRegisterFlags enumeration.
+ * @subject: The subject to become an authentication agent for, typically a #PolkitUnixSession object.
+ * @object_path: The D-Bus object path to use for the authentication agent or %NULL for the default object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error.
+ *
+ * Registers @listener with the PolicyKit daemon as an authentication
+ * agent for @subject. This is implemented by registering a D-Bus
+ * object at @object_path on the unique name assigned by the system
+ * message bus.
+ *
+ * Whenever the PolicyKit daemon needs to authenticate a processes
+ * that is related to @subject, the methods
+ * polkit_agent_listener_initiate_authentication() and
+ * polkit_agent_listener_initiate_authentication_finish() will be
+ * invoked on @listener.
+ *
+ * Note that registration of an authentication agent can fail; for
+ * example another authentication agent may already be registered for
+ * @subject.
+ *
+ * Note that the calling thread is blocked until a reply is received.
+ *
+ * Returns: (transfer full): %NULL if @error is set, otherwise a
+ * registration handle that can be used with
+ * polkit_agent_listener_unregister().
+ */
+gpointer
+polkit_agent_listener_register (PolkitAgentListener *listener,
+ PolkitAgentRegisterFlags flags,
+ PolkitSubject *subject,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return polkit_agent_listener_register_with_options (listener, flags, subject, object_path, NULL, cancellable, error);
+}
+
+/**
* polkit_agent_listener_unregister:
* @registration_handle: A handle obtained from polkit_agent_listener_register().
*
diff --git a/src/polkitagent/polkitagentlistener.h b/src/polkitagent/polkitagentlistener.h
index 191b265..c3cbcfb 100644
--- a/src/polkitagent/polkitagentlistener.h
+++ b/src/polkitagent/polkitagentlistener.h
@@ -134,6 +134,14 @@ gpointer polkit_agent_listener_register (PolkitAgentList
GCancellable *cancellable,
GError **error);
+gpointer polkit_agent_listener_register_with_options (PolkitAgentListener *listener,
+ PolkitAgentRegisterFlags flags,
+ PolkitSubject *subject,
+ const gchar *object_path,
+ GVariant *options,
+ GCancellable *cancellable,
+ GError **error);
+
void polkit_agent_listener_unregister (gpointer registration_handle);
G_END_DECLS
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index 44b7493..fd4f161 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -268,6 +268,7 @@ polkit_backend_authority_check_authorization_finish (PolkitBackendAuthority *au
* @subject: The subject the authentication agent wants to register for.
* @locale: The locale of the authentication agent.
* @object_path: The object path for the authentication agent.
+ * @options: A #GVariant with options or %NULL.
* @error: Return location for error or %NULL.
*
* Registers an authentication agent.
@@ -280,6 +281,7 @@ polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority
PolkitSubject *subject,
const gchar *locale,
const gchar *object_path,
+ GVariant *options,
GError **error)
{
PolkitBackendAuthorityClass *klass;
@@ -296,7 +298,7 @@ polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority
}
else
{
- return klass->register_authentication_agent (authority, caller, subject, locale, object_path, error);
+ return klass->register_authentication_agent (authority, caller, subject, locale, object_path, options, error);
}
}
@@ -571,6 +573,12 @@ static const gchar *server_introspection_data =
" <arg type='s' name='locale' direction='in'/>"
" <arg type='s' name='object_path' direction='in'/>"
" </method>"
+ " <method name='RegisterAuthenticationAgentWithOptions'>"
+ " <arg type='(sa{sv})' name='subject' direction='in'/>"
+ " <arg type='s' name='locale' direction='in'/>"
+ " <arg type='s' name='object_path' direction='in'/>"
+ " <arg type='a{sv}' name='options' direction='in'/>"
+ " </method>"
" <method name='UnregisterAuthenticationAgent'>"
" <arg type='(sa{sv})' name='subject' direction='in'/>"
" <arg type='s' name='object_path' direction='in'/>"
@@ -873,6 +881,62 @@ server_handle_register_authentication_agent (Server *server,
subject,
locale,
object_path,
+ NULL,
+ &error))
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+
+ out:
+ if (subject != NULL)
+ g_object_unref (subject);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+server_handle_register_authentication_agent_with_options (Server *server,
+ GVariant *parameters,
+ PolkitSubject *caller,
+ GDBusMethodInvocation *invocation)
+{
+ GVariant *subject_gvariant;
+ GError *error;
+ PolkitSubject *subject;
+ const gchar *locale;
+ const gchar *object_path;
+ GVariant *options;
+
+ subject = NULL;
+
+ g_variant_get (parameters,
+ "(@(sa{sv})&s&s@a{sv})",
+ &subject_gvariant,
+ &locale,
+ &object_path,
+ &options);
+
+ error = NULL;
+ subject = polkit_subject_new_for_gvariant (subject_gvariant, &error);
+ if (subject == NULL)
+ {
+ g_prefix_error (&error, "Error getting subject: ");
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ error = NULL;
+ if (!polkit_backend_authority_register_authentication_agent (server->authority,
+ caller,
+ subject,
+ locale,
+ object_path,
+ options,
&error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
@@ -883,6 +947,8 @@ server_handle_register_authentication_agent (Server *server,
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
out:
+ if (options != NULL)
+ g_variant_unref (options);
if (subject != NULL)
g_object_unref (subject);
}
@@ -1150,6 +1216,8 @@ server_handle_method_call (GDBusConnection *connection,
server_handle_cancel_check_authorization (server, parameters, caller, invocation);
else if (g_strcmp0 (method_name, "RegisterAuthenticationAgent") == 0)
server_handle_register_authentication_agent (server, parameters, caller, invocation);
+ else if (g_strcmp0 (method_name, "RegisterAuthenticationAgentWithOptions") == 0)
+ server_handle_register_authentication_agent_with_options (server, parameters, caller, invocation);
else if (g_strcmp0 (method_name, "UnregisterAuthenticationAgent") == 0)
server_handle_unregister_authentication_agent (server, parameters, caller, invocation);
else if (g_strcmp0 (method_name, "AuthenticationAgentResponse") == 0)
diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
index bfc0480..a564054 100644
--- a/src/polkitbackend/polkitbackendauthority.h
+++ b/src/polkitbackend/polkitbackendauthority.h
@@ -143,6 +143,7 @@ struct _PolkitBackendAuthorityClass
PolkitSubject *subject,
const gchar *locale,
const gchar *object_path,
+ GVariant *options,
GError **error);
gboolean (*unregister_authentication_agent) (PolkitBackendAuthority *authority,
@@ -244,6 +245,7 @@ gboolean polkit_backend_authority_register_authentication_agent (PolkitBackendAu
PolkitSubject *subject,
const gchar *locale,
const gchar *object_path,
+ GVariant *options,
GError **error);
gboolean polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index f523782..b237e9d 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -156,6 +156,7 @@ static gboolean polkit_backend_interactive_authority_register_authentication_age
PolkitSubject *subject,
const gchar *locale,
const gchar *object_path,
+ GVariant *options,
GError **error);
static gboolean polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
@@ -431,6 +432,7 @@ struct AuthenticationAgent
PolkitSubject *scope;
gchar *locale;
+ GVariant *registration_options;
gchar *object_path;
gchar *unique_system_bus_name;
@@ -1541,11 +1543,12 @@ authentication_agent_unref (AuthenticationAgent *agent)
{
if (agent->proxy != NULL)
g_object_unref (agent->proxy);
-
g_object_unref (agent->scope);
g_free (agent->locale);
g_free (agent->object_path);
g_free (agent->unique_system_bus_name);
+ if (agent->registration_options != NULL)
+ g_variant_unref (agent->registration_options);
g_free (agent);
}
}
@@ -1554,7 +1557,8 @@ static AuthenticationAgent *
authentication_agent_new (PolkitSubject *scope,
const gchar *unique_system_bus_name,
const gchar *locale,
- const gchar *object_path)
+ const gchar *object_path,
+ GVariant *registration_options)
{
AuthenticationAgent *agent;
GError *error;
@@ -1566,6 +1570,7 @@ authentication_agent_new (PolkitSubject *scope,
agent->object_path = g_strdup (object_path);
agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
agent->locale = g_strdup (locale);
+ agent->registration_options = registration_options != NULL ? g_variant_ref (registration_options) : NULL;
error = NULL;
agent->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
@@ -1592,19 +1597,16 @@ get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authori
PolkitSubject *subject)
{
PolkitBackendInteractiveAuthorityPrivate *priv;
- PolkitSubject *session_for_subject;
- AuthenticationAgent *agent;
+ PolkitSubject *session_for_subject = NULL;
+ AuthenticationAgent *agent = NULL;
+ AuthenticationAgent *agent_fallback = NULL;
+ gboolean fallback = FALSE;
priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
- agent = NULL;
- session_for_subject = NULL;
-
agent = g_hash_table_lookup (priv->hash_scope_to_authentication_agent, subject);
- if (agent != NULL)
- goto out;
- if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
+ if (agent == NULL && POLKIT_IS_SYSTEM_BUS_NAME (subject))
{
PolkitSubject *process;
process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject),
@@ -1613,15 +1615,27 @@ get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authori
if (process != NULL)
{
agent = g_hash_table_lookup (priv->hash_scope_to_authentication_agent, process);
- if (agent != NULL)
- {
- g_object_unref (process);
- goto out;
- }
g_object_unref (process);
}
}
+ if (agent != NULL)
+ {
+ /* We have an agent! Now see if we should use this as a fallback only */
+ if (agent->registration_options != NULL &&
+ g_variant_lookup (agent->registration_options, "fallback", "b", &fallback) &&
+ fallback)
+ {
+ agent_fallback = agent;
+ agent = NULL;
+ }
+ else
+ {
+ /* Nope, use it */
+ goto out;
+ }
+ }
+
/* Now, we should also cover the case where @subject is a
* UnixProcess but the agent is a SystemBusName. However, this can't
* happen because we only allow registering agents for UnixProcess
@@ -1636,6 +1650,10 @@ get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authori
agent = g_hash_table_lookup (priv->hash_scope_to_authentication_agent, session_for_subject);
+ /* use fallback, if available */
+ if (agent == NULL && agent_fallback != NULL)
+ agent = agent_fallback;
+
out:
if (session_for_subject != NULL)
g_object_unref (session_for_subject);
@@ -2194,6 +2212,7 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
PolkitSubject *subject,
const gchar *locale,
const gchar *object_path,
+ GVariant *options,
GError **error)
{
PolkitBackendInteractiveAuthority *interactive_authority;
@@ -2302,7 +2321,8 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
agent = authentication_agent_new (subject,
polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
locale,
- object_path);
+ object_path,
+ options);
g_hash_table_insert (priv->hash_scope_to_authentication_agent,
g_object_ref (subject),
diff --git a/src/programs/pkttyagent.c b/src/programs/pkttyagent.c
index 1c170f4..488ca8b 100644
--- a/src/programs/pkttyagent.c
+++ b/src/programs/pkttyagent.c
@@ -52,15 +52,18 @@ main (int argc, char *argv[])
{
gboolean opt_show_help = FALSE;
gboolean opt_show_version = FALSE;
+ gboolean opt_fallback = FALSE;
PolkitAuthority *authority = NULL;
PolkitSubject *subject = NULL;
gpointer local_agent_handle = NULL;
PolkitAgentListener *listener = NULL;
+ GVariant *options = NULL;
GError *error;
GMainLoop *loop = NULL;
guint n;
guint ret = 126;
gint notify_fd = -1;
+ GVariantBuilder builder;
g_type_init ();
@@ -74,6 +77,10 @@ main (int argc, char *argv[])
{
opt_show_version = TRUE;
}
+ else if (g_strcmp0 (argv[n], "--fallback") == 0)
+ {
+ opt_fallback = TRUE;
+ }
else if (g_strcmp0 (argv[n], "--notify-fd") == 0)
{
n++;
@@ -180,6 +187,13 @@ main (int argc, char *argv[])
goto out;
}
+ if (opt_fallback)
+ {
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&builder, "{sv}", "fallback", g_variant_new_boolean (TRUE));
+ options = g_variant_builder_end (&builder);
+ }
+
error = NULL;
/* this will fail if we can't find a controlling terminal */
listener = polkit_agent_text_listener_new (NULL, &error);
@@ -191,12 +205,14 @@ main (int argc, char *argv[])
ret = 127;
goto out;
}
- local_agent_handle = polkit_agent_listener_register (listener,
- POLKIT_AGENT_REGISTER_FLAGS_RUN_IN_THREAD,
- subject,
- NULL, /* object_path */
- NULL, /* GCancellable */
- &error);
+ local_agent_handle = polkit_agent_listener_register_with_options (listener,
+ POLKIT_AGENT_REGISTER_FLAGS_RUN_IN_THREAD,
+ subject,
+ NULL, /* object_path */
+ options,
+ NULL, /* GCancellable */
+ &error);
+ options = NULL; /* consumed */
g_object_unref (listener);
if (local_agent_handle == NULL)
{
@@ -225,6 +241,9 @@ main (int argc, char *argv[])
if (local_agent_handle != NULL)
polkit_agent_listener_unregister (local_agent_handle);
+ if (options != NULL)
+ g_variant_unref (options);
+
if (subject != NULL)
g_object_unref (subject);