honor implicit authorizations
authorDavid Zeuthen <davidz@redhat.com>
Tue, 20 Jan 2009 23:04:49 +0000 (18:04 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Tue, 20 Jan 2009 23:04:49 +0000 (18:04 -0500)
Yay, only major bit remaining now is to call out to the authentication
agent on CHALLENGE...

src/polkit/polkitimplicitauthorization.c
src/polkitbackend/polkitbackendlocalauthority.c
src/polkitbackend/polkitbackendsessionmonitor.c
src/polkitbackend/polkitbackendsessionmonitor.h

index a691160..d2b59fb 100644 (file)
@@ -85,8 +85,6 @@ polkit_implicit_authorization_from_string (const gchar *string,
   if (out_implicit_authorization != NULL)
     *out_implicit_authorization = result;
 
-  g_debug ("parsed '%s' to %d", string, result);
-
   return ret;
 }
 
index e3f14d3..976d9fc 100644 (file)
@@ -118,6 +118,7 @@ static PolkitAuthorizationResult check_authorization_sync (PolkitBackendAuthorit
                                                            PolkitSubject                  *subject,
                                                            const gchar                    *action_id,
                                                            PolkitCheckAuthorizationFlags   flags,
+                                                           PolkitImplicitAuthorization    *out_implicit_authorization,
                                                            GError                        **error);
 
 static void polkit_backend_local_authority_enumerate_authorizations (PolkitBackendAuthority   *authority,
@@ -358,6 +359,7 @@ polkit_backend_local_authority_check_authorization (PolkitBackendAuthority
   gchar *user_of_inquirer_str;
   gchar *user_of_subject_str;
   PolkitAuthorizationResult result;
+  PolkitImplicitAuthorization implicit_authorization;
   GError *error;
 
   local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
@@ -420,6 +422,7 @@ polkit_backend_local_authority_check_authorization (PolkitBackendAuthority
                                          inquirer,
                                          "org.freedesktop.policykit.read",
                                          POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, /* no user interaction */
+                                         NULL,
                                          &error);
 
       if (error != NULL)
@@ -440,16 +443,20 @@ polkit_backend_local_authority_check_authorization (PolkitBackendAuthority
         }
     }
 
-  result = check_authorization_sync (authority, subject, action_id, flags, &error);
+  result = check_authorization_sync (authority,
+                                     subject,
+                                     action_id,
+                                     flags,
+                                     &implicit_authorization,
+                                     &error);
   if (error != NULL)
     {
       polkit_backend_pending_call_return_gerror (pending_call, error);
       g_error_free (error);
+      goto out;
     }
-  else
-    {
-      polkit_backend_authority_check_authorization_finish (pending_call, result);
-    }
+
+  polkit_backend_authority_check_authorization_finish (pending_call, result);
 
  out:
 
@@ -472,15 +479,21 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
                           PolkitSubject                  *subject,
                           const gchar                    *action_id,
                           PolkitCheckAuthorizationFlags   flags,
+                          PolkitImplicitAuthorization    *out_implicit_authorization,
                           GError                        **error)
 {
   PolkitBackendLocalAuthority *local_authority;
   PolkitBackendLocalAuthorityPrivate *priv;
   PolkitAuthorizationResult result;
   PolkitIdentity *user_of_subject;
+  PolkitSubject *session_for_subject;
   gchar *subject_str;
   GList *groups_of_user;
   GList *l;
+  PolkitActionDescription *action_desc;
+  gboolean session_is_local;
+  gboolean session_is_active;
+  PolkitImplicitAuthorization implicit_authorization;
 
   local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
   priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
@@ -490,6 +503,10 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   user_of_subject = NULL;
   groups_of_user = NULL;
   subject_str = NULL;
+  session_for_subject = NULL;
+
+  session_is_local = FALSE;
+  session_is_active = FALSE;
 
   subject_str = polkit_subject_to_string (subject);
 
@@ -497,6 +514,21 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
            subject_str,
            action_id);
 
+  /* get the action description */
+  action_desc = polkit_backend_action_pool_get_action (priv->action_pool,
+                                                       action_id,
+                                                       NULL);
+
+  if (action_desc == NULL)
+    {
+      g_set_error (error,
+                   POLKIT_ERROR,
+                   POLKIT_ERROR_FAILED,
+                   "Action %s is not registered",
+                   action_id);
+      goto out;
+    }
+
   /* every subject has a user */
   user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
                                                                          subject,
@@ -511,7 +543,44 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
       goto out;
     }
 
-  /* TODO: first see if there's an implicit authorization for subject available */
+  /* a subject *may* be in a session */
+  session_for_subject = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+                                                                                subject,
+                                                                                NULL);
+  g_debug ("  %p", session_for_subject);
+  if (session_for_subject != NULL)
+    {
+      session_is_local = polkit_backend_session_monitor_is_session_local (priv->session_monitor, session_for_subject);
+      session_is_active = polkit_backend_session_monitor_is_session_active (priv->session_monitor, session_for_subject);
+
+      g_debug (" subject is in session %s (local=%d active=%d)",
+               polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session_for_subject)),
+               session_is_local,
+               session_is_active);
+    }
+
+  /* find the implicit authorization to use; it depends on is_local and is_active */
+  if (session_is_local)
+    {
+      if (session_is_active)
+        implicit_authorization = polkit_action_description_get_implicit_active (action_desc);
+      else
+        implicit_authorization = polkit_action_description_get_implicit_inactive (action_desc);
+    }
+  else
+    {
+      implicit_authorization = polkit_action_description_get_implicit_any (action_desc);
+    }
+
+  /* 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_AUTHORIZED;
+      goto out;
+    }
 
   /* then see if there's a temporary authorization for the subject */
   if (check_temporary_authorization_for_identity (local_authority, user_of_subject, subject, action_id))
@@ -543,8 +612,21 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
         }
     }
 
-  g_debug (" not authorized");
+  if (implicit_authorization != POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED)
+    {
+      result = POLKIT_AUTHORIZATION_RESULT_CHALLENGE;
+
+      /* return implicit_authorization so the caller can use an authentication agent if applicable */
+      if (out_implicit_authorization != NULL)
+        *out_implicit_authorization = implicit_authorization;
 
+      g_debug (" challenge (implicit_authorization = %s)",
+               polkit_implicit_authorization_to_string (implicit_authorization));
+    }
+  else
+    {
+      g_debug (" not authorized");
+    }
  out:
   g_free (subject_str);
 
@@ -554,6 +636,12 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   if (user_of_subject != NULL)
     g_object_unref (user_of_subject);
 
+  if (session_for_subject != NULL)
+    g_object_unref (session_for_subject);
+
+  if (action_desc != NULL)
+    g_object_unref (action_desc);
+
   g_debug (" ");
 
   return result;
index 61fc86a..5e47f0a 100644 (file)
@@ -141,7 +141,7 @@ manager_seat_added (CkManager   *manager,
 {
   PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
 
-  g_debug ("seat %s added", object_path);
+  //g_debug ("seat %s added", object_path);
 
   add_seat (monitor, object_path);
 }
@@ -153,7 +153,7 @@ manager_seat_removed (CkManager   *manager,
 {
   PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
 
-  g_debug ("seat %s removed", object_path);
+  //g_debug ("seat %s removed", object_path);
 
   remove_seat (monitor, object_path);
 }
@@ -165,7 +165,7 @@ seat_session_added (CkSeat      *seat,
 {
   PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
 
-  g_debug ("session %s added", object_path);
+  //g_debug ("session %s added", object_path);
 
   add_session (monitor, object_path);
 }
@@ -177,7 +177,7 @@ seat_session_removed (CkSeat      *seat,
 {
   PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
 
-  g_debug ("session %s removed", object_path);
+  //g_debug ("session %s removed", object_path);
 
   remove_session (monitor, object_path);
 }
@@ -191,9 +191,7 @@ session_active_changed (CkSession   *session,
 
   object_proxy = egg_dbus_interface_proxy_get_object_proxy (EGG_DBUS_INTERFACE_PROXY (session));
 
-  g_debug ("session %s active changed to %d",
-           egg_dbus_object_proxy_get_object_path (object_proxy),
-           is_active);
+  //g_debug ("session %s active changed to %d", egg_dbus_object_proxy_get_object_path (object_proxy), is_active);
 
   egg_dbus_object_proxy_invalidate_properties (object_proxy);
 }
@@ -452,7 +450,23 @@ polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMoni
 
   session = NULL;
 
-  if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
+  if (POLKIT_IS_UNIX_PROCESS (subject))
+    {
+      gchar *session_id;
+
+      if (!ck_manager_get_session_for_unix_process_sync (monitor->ck_manager,
+                                                         EGG_DBUS_CALL_FLAGS_NONE,
+                                                         polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)),
+                                                         &session_id,
+                                                         NULL,
+                                                         error))
+        goto out;
+
+      session = polkit_unix_session_new (session_id);
+
+      g_free (session_id);
+    }
+  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
     {
       pid_t pid;
       gchar *session_id;
@@ -492,3 +506,58 @@ polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMoni
   return session;
 }
 
+gboolean
+polkit_backend_session_monitor_is_session_local  (PolkitBackendSessionMonitor *monitor,
+                                                  PolkitSubject               *session)
+{
+  EggDBusObjectProxy *object_proxy;
+  const gchar *session_id;
+  CkSession *ck_session;
+  gboolean ret;
+
+  g_return_val_if_fail (POLKIT_IS_UNIX_SESSION (session), FALSE);
+
+  ret = FALSE;
+
+  session_id = polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session));
+
+  object_proxy = egg_dbus_hash_map_lookup (monitor->session_object_path_to_object_proxy, session_id);
+  if (object_proxy == NULL)
+    goto out;
+
+  ck_session = CK_QUERY_INTERFACE_SESSION (object_proxy);
+
+  ret = ck_session_get_is_local (ck_session);
+
+ out:
+  return ret;
+}
+
+
+gboolean
+polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor,
+                                                  PolkitSubject               *session)
+{
+  EggDBusObjectProxy *object_proxy;
+  const gchar *session_id;
+  CkSession *ck_session;
+  gboolean ret;
+
+  g_return_val_if_fail (POLKIT_IS_UNIX_SESSION (session), FALSE);
+
+  ret = FALSE;
+
+  session_id = polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session));
+
+  object_proxy = egg_dbus_hash_map_lookup (monitor->session_object_path_to_object_proxy, session_id);
+  if (object_proxy == NULL)
+    goto out;
+
+  ck_session = CK_QUERY_INTERFACE_SESSION (object_proxy);
+
+  ret = ck_session_get_active (ck_session);
+
+ out:
+  return ret;
+}
+
index a4194a9..e498598 100644 (file)
@@ -55,6 +55,12 @@ PolkitSubject               *polkit_backend_session_monitor_get_session_for_subj
                                                                                      PolkitSubject               *subject,
                                                                                      GError                     **error);
 
+gboolean                     polkit_backend_session_monitor_is_session_local  (PolkitBackendSessionMonitor *monitor,
+                                                                               PolkitSubject               *session);
+
+gboolean                     polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor,
+                                                                               PolkitSubject               *session);
+
 G_END_DECLS
 
 #endif /* __POLKIT_BACKEND_SESSION_MONITOR_H */