Make it possible for JS code to change details
authorDavid Zeuthen <davidz@redhat.com>
Fri, 18 May 2012 21:23:18 +0000 (17:23 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Fri, 18 May 2012 21:29:01 +0000 (17:29 -0400)
For example, to set the authentication message, a JS function can
simply do

 details["polkit.message"] = "Hey dude, XYZ, I need your password";

This can also be used to pass data back to the mechanism.

To make this work properly, we also introduce a slight change: the
a{ss} passed back to the mechanism (part of the AuthorizationResult
structure) will be initialized with the a{ss} the app passed itself in
the CheckAuthorization() call.

Signed-off-by: David Zeuthen <davidz@redhat.com>
src/polkitbackend/polkitbackendinteractiveauthority.c
src/polkitbackend/polkitbackendinteractiveauthority.h
src/polkitbackend/polkitbackendjsauthority.c
src/polkitbackend/polkitbackendlocalauthority.c
src/polkitbackend/polkitbackendlocalauthorizationstore.c
src/polkitbackend/polkitbackendlocalauthorizationstore.h
test/polkitbackend/polkitbackendlocalauthoritytest.c
test/polkitbackend/polkitbackendlocalauthorizationstoretest.c

index 5f6eea5..171e686 100644 (file)
@@ -80,6 +80,7 @@ typedef void (*AuthenticationAgentCallback) (AuthenticationAgent         *agent,
                                              PolkitSubject               *caller,
                                              PolkitBackendInteractiveAuthority *authority,
                                              const gchar                 *action_id,
+                                             PolkitDetails               *details,
                                              PolkitImplicitAuthorization  implicit_authorization,
                                              gboolean                     authentication_success,
                                              gboolean                     was_dismissed,
@@ -595,6 +596,7 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
                                   PolkitSubject               *caller,
                                   PolkitBackendInteractiveAuthority *authority,
                                   const gchar                 *action_id,
+                                  PolkitDetails               *details,
                                   PolkitImplicitAuthorization  implicit_authorization,
                                   gboolean                     authentication_success,
                                   gboolean                     was_dismissed,
@@ -610,7 +612,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
   gchar *authenticated_identity_str;
   gchar *subject_cmdline;
   gboolean is_temp;
-  PolkitDetails *details;
 
   priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
 
@@ -637,7 +638,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
            was_dismissed,
            authentication_success);
 
-  details = polkit_details_new ();
   if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
       implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
     polkit_details_insert (details, "polkit.retains_authorization_after_challenge", "true");
@@ -715,7 +715,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
 
   /* log_result (authority, action_id, subject, caller, result); */
 
-  g_object_unref (details);
   g_simple_async_result_set_op_res_gpointer (simple,
                                              result,
                                              g_object_unref);
@@ -1047,7 +1046,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   gboolean session_is_active;
   PolkitImplicitAuthorization implicit_authorization;
   const gchar *tmp_authz_id;
-  PolkitDetails *result_details;
   GList *actions;
   GList *l;
 
@@ -1061,7 +1059,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   groups_of_user = NULL;
   subject_str = NULL;
   session_for_subject = NULL;
-  result_details = NULL;
 
   session_is_local = FALSE;
   session_is_active = FALSE;
@@ -1130,8 +1127,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
       implicit_authorization = polkit_action_description_get_implicit_any (action_desc);
     }
 
-  result_details = polkit_details_new ();
-
   /* allow subclasses to rewrite implicit_authorization */
   implicit_authorization = polkit_backend_interactive_authority_check_authorization_sync (interactive_authority,
                                                                                           caller,
@@ -1141,16 +1136,14 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
                                                                                           session_is_active,
                                                                                           action_id,
                                                                                           details,
-                                                                                          implicit_authorization,
-                                                                                          result_details);
-
+                                                                                          implicit_authorization);
   /* first see if there's an implicit authorization for subject available */
   if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED)
     {
       g_debug (" is authorized (has implicit authorization local=%d active=%d)",
                session_is_local,
                session_is_active);
-      result = polkit_authorization_result_new (TRUE, FALSE, result_details);
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
       goto out;
     }
 
@@ -1162,8 +1155,8 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
     {
 
       g_debug (" is authorized (has temporary authorization)");
-      polkit_details_insert (result_details, "polkit.temporary_authorization_id", tmp_authz_id);
-      result = polkit_authorization_result_new (TRUE, FALSE, result_details);
+      polkit_details_insert (details, "polkit.temporary_authorization_id", tmp_authz_id);
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
       goto out;
     }
 
@@ -1210,7 +1203,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
                               g_debug (" is authorized (implied by %s)", imply_action_id);
                               result = implied_result;
                               /* cleanup */
-                              g_object_unref (result_details);
                               g_strfreev (tokens);
                               goto out;
                             }
@@ -1230,10 +1222,10 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
       if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
           implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
         {
-          polkit_details_insert (result_details, "polkit.retains_authorization_after_challenge", "1");
+          polkit_details_insert (details, "polkit.retains_authorization_after_challenge", "1");
         }
 
-      result = polkit_authorization_result_new (FALSE, TRUE, result_details);
+      result = polkit_authorization_result_new (FALSE, TRUE, details);
 
       /* return implicit_authorization so the caller can use an authentication agent if applicable */
       if (out_implicit_authorization != NULL)
@@ -1244,7 +1236,7 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
     }
   else
     {
-      result = polkit_authorization_result_new (FALSE, FALSE, result_details);
+      result = polkit_authorization_result_new (FALSE, FALSE, details);
       g_debug (" not authorized");
     }
  out:
@@ -1265,9 +1257,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   if (action_desc != NULL)
     g_object_unref (action_desc);
 
-  if (result_details != NULL)
-    g_object_unref (result_details);
-
   g_debug (" ");
 
   return result;
@@ -1332,12 +1321,10 @@ polkit_backend_interactive_authority_get_admin_identities (PolkitBackendInteract
  * @action_id: The action we are checking an authorization for.
  * @details: Details about the action.
  * @implicit: A #PolkitImplicitAuthorization value computed from the policy file and @subject.
- * @out_details: A #PolkitDetails object that will be return to @caller.
  *
  * Checks whether @subject is authorized to perform the action
- * specified by @action_id and @details. The implementation may
- * append key/value pairs to @out_details to return extra information
- * to @caller.
+ * specified by @action_id and @details. The implementation may append
+ * key/value pairs to @details to return extra information to @caller.
  *
  * The default implementation of this method simply returns @implicit.
  *
@@ -1353,8 +1340,7 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte
                                                                gboolean                           subject_is_active,
                                                                const gchar                       *action_id,
                                                                PolkitDetails                     *details,
-                                                               PolkitImplicitAuthorization        implicit,
-                                                               PolkitDetails                     *out_details)
+                                                               PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendInteractiveAuthorityClass *klass;
   PolkitImplicitAuthorization ret;
@@ -1375,8 +1361,7 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte
                                              subject_is_active,
                                              action_id,
                                              details,
-                                             implicit,
-                                             out_details);
+                                             implicit);
     }
 
   return ret;
@@ -1402,6 +1387,8 @@ struct AuthenticationSession
 
   gchar                       *action_id;
 
+  PolkitDetails               *details;
+
   gchar                       *initiated_by_system_bus_unique_name;
 
   PolkitImplicitAuthorization  implicit_authorization;
@@ -1436,6 +1423,7 @@ authentication_session_new (AuthenticationAgent         *agent,
                             PolkitBackendInteractiveAuthority *authority,
                             GList                       *identities,
                             const gchar                 *action_id,
+                            PolkitDetails               *details,
                             const gchar                 *initiated_by_system_bus_unique_name,
                             PolkitImplicitAuthorization  implicit_authorization,
                             GCancellable                *cancellable,
@@ -1454,6 +1442,7 @@ authentication_session_new (AuthenticationAgent         *agent,
   session->identities = g_list_copy (identities);
   g_list_foreach (session->identities, (GFunc) g_object_ref, NULL);
   session->action_id = g_strdup (action_id);
+  session->details = g_object_ref (details);
   session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name);
   session->implicit_authorization = implicit_authorization;
   session->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
@@ -1483,6 +1472,7 @@ authentication_session_free (AuthenticationSession *session)
   g_object_unref (session->caller);
   g_object_unref (session->authority);
   g_free (session->action_id);
+  g_object_unref (session->details);
   g_free (session->initiated_by_system_bus_unique_name);
   if (session->cancellable_signal_handler_id > 0)
     g_signal_handler_disconnect (session->cancellable, session->cancellable_signal_handler_id);
@@ -1832,6 +1822,7 @@ authentication_agent_begin_cb (GDBusProxy   *proxy,
                      session->caller,
                      session->authority,
                      session->action_id,
+                     session->details,
                      session->implicit_authorization,
                      gained_authorization,
                      was_dismissed,
@@ -2228,6 +2219,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
                                         authority,
                                         identities,
                                         action_id,
+                                        details,
                                         polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
                                         implicit_authorization,
                                         cancellable,
index 408c3e4..9820dac 100644 (file)
@@ -83,8 +83,7 @@ struct _PolkitBackendInteractiveAuthorityClass
                                                            gboolean                           subject_is_active,
                                                            const gchar                       *action_id,
                                                            PolkitDetails                     *details,
-                                                           PolkitImplicitAuthorization        implicit,
-                                                           PolkitDetails                     *out_details);
+                                                           PolkitImplicitAuthorization        implicit);
 
   /*< private >*/
   /* Padding for future expansion */
@@ -139,8 +138,7 @@ PolkitImplicitAuthorization polkit_backend_interactive_authority_check_authoriza
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_END_DECLS
 
index b3669d5..81cccd0 100644 (file)
@@ -100,8 +100,7 @@ static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorizati
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_DEFINE_TYPE_WITH_CODE (PolkitBackendJsAuthority,
                          polkit_backend_js_authority,
@@ -193,7 +192,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
   if (dir == NULL)
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error opening rules directory: %s (%s, %d)\n",
+                                    "Error opening rules directory: %s (%s, %d)",
                                     error->message, g_quark_to_string (error->domain), error->code);
       g_clear_error (&error);
       goto out;
@@ -858,8 +857,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
                                                       gboolean                           subject_is_active,
                                                       const gchar                       *action_id,
                                                       PolkitDetails                     *details,
-                                                      PolkitImplicitAuthorization        implicit,
-                                                      PolkitDetails                     *out_details)
+                                                      PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   PolkitImplicitAuthorization ret = implicit;
@@ -871,6 +869,9 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
   gboolean good = FALSE;
+  JSIdArray *ids;
+  JSObject *details_obj;
+  gint n;
 
   action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
   argv[0] = STRING_TO_JSVAL (action_id_jstr);
@@ -931,11 +932,58 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   if (!polkit_implicit_authorization_from_string (ret_str, &ret))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Returned result `%s' is not valid\n",
+                                    "Returned result `%s' is not valid",
                                     ret_str);
       goto out;
     }
 
+
+  /* the JS code may have modifed @details - update PolkitDetails
+   * object accordingly
+   */
+  details_obj = JSVAL_TO_OBJECT (argv[2]);
+  ids = JS_Enumerate (authority->priv->cx, details_obj);
+  if (ids == NULL)
+    {
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Failed to enumerate properties of Details object");
+      goto out;
+    }
+  for (n = 0; n < ids->length; n++)
+    {
+      jsval id_val;
+      jsval value_val;
+      char *id_s = NULL;
+      char *value_s = NULL;
+
+      if (!JS_IdToValue (authority->priv->cx, ids->vector[n], &id_val))
+        {
+          g_warning ("Error getting string for property id %d", n);
+          goto cont;
+        }
+      id_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (id_val));
+
+      if (!JS_GetPropertyById (authority->priv->cx, details_obj, ids->vector[n], &value_val))
+        {
+          g_warning ("Error getting value string for property value %s", id_s);
+          goto cont;
+        }
+
+      /* skip e.g. functions */
+      if (!JSVAL_IS_STRING (value_val) && !JSVAL_IS_NULL (value_val))
+        goto cont;
+
+      value_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (value_val));
+
+      polkit_details_insert (details, id_s, value_s);
+    cont:
+      if (id_s != NULL)
+        JS_free (authority->priv->cx, id_s);
+      if (value_s != NULL)
+        JS_free (authority->priv->cx, value_s);
+    }
+  JS_DestroyIdArray (authority->priv->cx, ids);
+
   good = TRUE;
 
  out:
index b53eda3..2e5e8fe 100644 (file)
@@ -100,8 +100,7 @@ static PolkitImplicitAuthorization polkit_backend_local_authority_check_authoriz
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority,
                          polkit_backend_local_authority,
@@ -543,8 +542,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                          gboolean                           subject_is_active,
                                                          const gchar                       *action_id,
                                                          PolkitDetails                     *details,
-                                                         PolkitImplicitAuthorization        implicit,
-                                                         PolkitDetails                     *out_details)
+                                                         PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendLocalAuthority *local_authority;
   PolkitBackendLocalAuthorityPrivate *priv;
@@ -583,8 +581,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                                details,
                                                                &ret_any,
                                                                &ret_inactive,
-                                                               &ret_active,
-                                                               out_details))
+                                                               &ret_active))
             {
               if (subject_is_local && subject_is_active)
                 {
@@ -618,8 +615,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                            details,
                                                            &ret_any,
                                                            &ret_inactive,
-                                                           &ret_active,
-                                                           out_details))
+                                                           &ret_active))
         {
           if (subject_is_local && subject_is_active)
             {
index 2ddfe75..f40a943 100644 (file)
@@ -669,9 +669,10 @@ polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorization
  * @out_result_any: Return location for the result for any subjects if the look up matched.
  * @out_result_inactive: Return location for the result for subjects in local inactive sessions if the look up matched.
  * @out_result_active: Return location for the result for subjects in local active sessions if the look up matched.
- * @out_details: %NULL or a #PolkitDetails object to append key/value pairs to on a positive match.
  *
- * Checks if an authorization entry from @store matches @identity, @action_id and @details.
+ * Checks if an authorization entry from @store matches @identity,
+ * @action_id and @details. May append information to @details if
+ * found.
  *
  * Returns: %TRUE if @store has an authorization entry that matches
  *     @identity, @action_id and @details. Otherwise %FALSE.
@@ -683,8 +684,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
                                                  PolkitDetails                        *details,
                                                  PolkitImplicitAuthorization          *out_result_any,
                                                  PolkitImplicitAuthorization          *out_result_inactive,
-                                                 PolkitImplicitAuthorization          *out_result_active,
-                                                 PolkitDetails                        *out_details)
+                                                 PolkitImplicitAuthorization          *out_result_active)
 {
   GList *l, *ll;
   gboolean ret;
@@ -749,7 +749,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
       *out_result_active = authorization->result_active;
       ret = TRUE;
 
-      if (out_details != NULL && authorization->return_value != NULL)
+      if (details != NULL && authorization->return_value != NULL)
         {
           GHashTableIter iter;
           const gchar *key;
@@ -758,7 +758,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
           g_hash_table_iter_init (&iter, authorization->return_value);
           while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
             {
-              polkit_details_insert (out_details, key, value);
+              polkit_details_insert (details, key, value);
             }
         }
 
index c15d9a6..4f198e9 100644 (file)
@@ -78,8 +78,7 @@ gboolean  polkit_backend_local_authorization_store_lookup   (PolkitBackendLocalA
                                                              PolkitDetails                        *details,
                                                              PolkitImplicitAuthorization          *out_result_any,
                                                              PolkitImplicitAuthorization          *out_result_inactive,
-                                                             PolkitImplicitAuthorization          *out_result_active,
-                                                             PolkitDetails                        *out_details);
+                                                             PolkitImplicitAuthorization          *out_result_active);
 
 G_END_DECLS
 
index 617c254..9fc7848 100644 (file)
@@ -66,9 +66,6 @@ test_check_authorization_sync (const void *_ctx)
   PolkitDetails *details = polkit_details_new ();
   g_assert (details);
 
-  PolkitDetails *out_details = polkit_details_new ();
-  g_assert (out_details);
-
   PolkitImplicitAuthorization auth;
 
   auth = polkit_backend_interactive_authority_check_authorization_sync (
@@ -80,8 +77,7 @@ test_check_authorization_sync (const void *_ctx)
       ctx->subject_is_active,
       ctx->action_id,
       details,
-      ctx->implicit,
-      out_details);
+      ctx->implicit);
 
   g_assert_cmpint (auth, ==, ctx->expect);
 
@@ -90,7 +86,6 @@ test_check_authorization_sync (const void *_ctx)
   g_object_unref (subject);
   g_object_unref (user_for_subject);
   g_object_unref (details);
-  g_object_unref (out_details);
 }
 
 static void
index 945e163..e787c17 100644 (file)
@@ -89,8 +89,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (ok);
   g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
   g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
@@ -109,8 +108,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (ok);
   g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
   g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
@@ -124,8 +122,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (!ok);
 }