Commit 2dd284eb authored by David Zeuthen's avatar David Zeuthen

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: 's avatarDavid Zeuthen <davidz@redhat.com>
parent bda0fc1d
......@@ -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">
......
......@@ -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>
......
......@@ -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
......
......@@ -1166,6 +1166,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.
......
......@@ -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,
......
......@@ -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,
......@@ -471,6 +468,47 @@ polkit_agent_listener_register (PolkitAgentListener *listener,
return server;
}
/**
* 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().
......
......@@ -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
......
......@@ -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)
......
......@@ -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,
......
......@@ -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),
......
......@@ -52,15 +52,18 @@ main (int argc, char *argv[])