add checks for whether someone is authorized to check authorizations
authorDavid Zeuthen <davidz@redhat.com>
Sun, 18 Jan 2009 19:20:51 +0000 (14:20 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Sun, 18 Jan 2009 19:20:51 +0000 (14:20 -0500)
data/org.freedesktop.PolicyKit1.Authority.xml
src/polkit/polkiterror.h
src/polkit/polkitsubject.c
src/polkitbackend/polkitbackendlocalauthority.c
src/polkitbackend/polkitbackendsessionmonitor.c
src/polkitbackend/polkitbackendsessionmonitor.h

index 75d9586..76f68d6 100644 (file)
@@ -65,6 +65,9 @@
     <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.NotSupported">
       <annotation name="org.gtk.EggDBus.DocString" value="Operation is not supported"/>
     </annotation>
+    <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.NotAuthorized">
+      <annotation name="org.gtk.EggDBus.DocString" value="Not authorized to perform operation"/>
+    </annotation>
   </annotation>
 
   <!-- An enumeration for results of CheckClaim() (TODO: implement this method) -->
index 5dd21dc..9ef2955 100644 (file)
@@ -42,15 +42,17 @@ GType polkit_error_get_type (void) G_GNUC_CONST;
 
 /**
  * PolkitError:
- * @POLKIT_ERROR_FAILED: The operation failed
- * @POLKIT_ERROR_NOT_SUPPORTED: Operation is not supported
+ * @POLKIT_ERROR_FAILED: The operation failed.
+ * @POLKIT_ERROR_NOT_SUPPORTED: Operation is not supported.
+ * @POLKIT_ERROR_NOT_AUTHORIZED: Not authorized to perform operation.
  *
- * Errors when using PolicyKit.
+ * Possible error when using PolicyKit.
  */
 typedef enum
 {
   POLKIT_ERROR_FAILED = 0,
   POLKIT_ERROR_NOT_SUPPORTED = 1,
+  POLKIT_ERROR_NOT_AUTHORIZED = 2,
 } PolkitError;
 
 G_END_DECLS
index d7c5434..e34bddc 100644 (file)
@@ -140,6 +140,10 @@ polkit_subject_from_string  (const gchar   *str,
             }
         }
     }
+  else if (g_str_has_prefix (str, "unix-session:"))
+    {
+      subject = polkit_unix_session_new (str + sizeof "unix-session:" - 1);
+    }
   else if (g_str_has_prefix (str, "system-bus-name:"))
     {
       subject = polkit_system_bus_name_new (str + sizeof "system-bus-name:" - 1);
index db49f99..f6fda0b 100644 (file)
@@ -55,6 +55,10 @@ static void polkit_backend_local_authority_check_claim        (PolkitBackendAuth
                                                                PolkitAuthorizationClaim *claim,
                                                                PolkitBackendPendingCall *pending_call);
 
+static PolkitAuthorizationResult check_claim_sync (PolkitBackendAuthority     *authority,
+                                                   PolkitAuthorizationClaim   *claim,
+                                                   GError                    **error);
+
 G_DEFINE_TYPE (PolkitBackendLocalAuthority, polkit_backend_local_authority, POLKIT_BACKEND_TYPE_AUTHORITY);
 
 #define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityPrivate))
@@ -256,11 +260,32 @@ polkit_backend_local_authority_check_claim (PolkitBackendAuthority   *authority,
                                             PolkitAuthorizationClaim *claim,
                                             PolkitBackendPendingCall *pending_call)
 {
-  gchar *inquirer_str;
-  gchar *subject_str;
+  PolkitBackendLocalAuthority *local_authority;
+  PolkitBackendLocalAuthorityPrivate *priv;
   PolkitSubject *inquirer;
   PolkitSubject *subject;
+  gchar *inquirer_str;
+  gchar *subject_str;
+  PolkitSubject *user_of_inquirer;
+  PolkitSubject *user_of_subject;
+  gchar *user_of_inquirer_str;
+  gchar *user_of_subject_str;
+  PolkitAuthorizationResult result;
   const gchar *action_id;
+  GError *error;
+
+  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
+  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
+
+  error = NULL;
+  inquirer = NULL;
+  subject = NULL;
+  inquirer_str = NULL;
+  subject_str = NULL;
+  user_of_inquirer = NULL;
+  user_of_subject = NULL;
+  user_of_inquirer_str = NULL;
+  user_of_subject_str = NULL;
 
   inquirer = polkit_backend_pending_call_get_caller (pending_call);
   subject = polkit_authorization_claim_get_subject (claim);
@@ -274,17 +299,148 @@ polkit_backend_local_authority_check_claim (PolkitBackendAuthority   *authority,
            subject_str,
            action_id);
 
-  /* TODO: temp */
-  polkit_backend_authority_check_claim_finish (pending_call, POLKIT_AUTHORIZATION_RESULT_AUTHORIZED);
+  user_of_inquirer = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+                                                                          inquirer,
+                                                                          &error);
+  if (error != NULL)
+    {
+      polkit_backend_pending_call_return_gerror (pending_call, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  user_of_inquirer_str = polkit_subject_to_string (user_of_inquirer);
+  g_debug (" user of inquirer is %s", user_of_inquirer_str);
+
+  user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+                                                                         subject,
+                                                                         &error);
+  if (error != NULL)
+    {
+      polkit_backend_pending_call_return_gerror (pending_call, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  user_of_subject_str = polkit_subject_to_string (user_of_subject);
+  g_debug (" user of subject is %s", user_of_subject_str);
+
+  /* if the user of the inquirer and the user of the subject isn't the same, then
+   * the org.freedesktop.policykit.read authorization is required for the inquirer
+   */
+  if (!polkit_subject_equal (user_of_inquirer, user_of_subject))
+    {
+      PolkitAuthorizationClaim *read_claim;
+
+      read_claim = polkit_authorization_claim_new (user_of_inquirer, "org.freedesktop.policykit.read");
+      result = check_claim_sync (authority, read_claim, &error);
+      g_object_unref (read_claim);
+
+      if (error != NULL)
+        {
+          polkit_backend_pending_call_return_gerror (pending_call, error);
+          g_error_free (error);
+          goto out;
+        }
+      else if (result != POLKIT_AUTHORIZATION_RESULT_AUTHORIZED)
+        {
+          polkit_backend_pending_call_return_error (pending_call,
+                                                    POLKIT_ERROR,
+                                                    POLKIT_ERROR_NOT_AUTHORIZED,
+                                                    "%s is not authorized to know about authorizations for %s (requires org.freedesktop.policykit.read authorization)",
+                                                    user_of_inquirer_str,
+                                                    subject_str);
+          goto out;
+        }
+    }
+
+  result = check_claim_sync (authority, claim, &error);
+  if (error != NULL)
+    {
+      polkit_backend_pending_call_return_gerror (pending_call, error);
+      g_error_free (error);
+    }
+  else
+    {
+      polkit_backend_authority_check_claim_finish (pending_call, result);
+    }
+
+ out:
+
+  if (user_of_inquirer != NULL)
+    g_object_unref (user_of_inquirer);
+
+  if (user_of_subject != NULL)
+    g_object_unref (user_of_subject);
+
+  g_free (inquirer_str);
+  g_free (subject_str);
+  g_free (user_of_inquirer_str);
+  g_free (user_of_subject_str);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static PolkitAuthorizationResult
+check_claim_sync (PolkitBackendAuthority    *authority,
+                  PolkitAuthorizationClaim  *claim,
+                  GError                   **error)
+{
+  PolkitBackendLocalAuthority *local_authority;
+  PolkitBackendLocalAuthorityPrivate *priv;
+  PolkitAuthorizationResult result;
+  PolkitSubject *subject;
+  PolkitSubject *user_of_subject;
+  gchar *subject_str;
+  const gchar *action_id;
+
+  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
+  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
+
+  result = POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED;
+  user_of_subject = NULL;
+  subject_str = NULL;
+
+  subject = polkit_authorization_claim_get_subject (claim);
+  action_id = polkit_authorization_claim_get_action_id (claim);
+
+  subject_str = polkit_subject_to_string (subject);
+
+  g_debug ("checking whether %s is authorized for %s",
+           subject_str,
+           action_id);
+
+  user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+                                                                         subject,
+                                                                         error);
+  if (user_of_subject == NULL)
+      goto out;
+
+  if (POLKIT_IS_UNIX_USER (user_of_subject) && polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_subject)) == 0)
+    {
+      /* uid 0, root, is _always_ authorized for anything */
+      result = POLKIT_AUTHORIZATION_RESULT_AUTHORIZED;
+      goto out;
+    }
 
 #if 0
-  polkit_backend_pending_call_return_error (pending_call,
-                                            POLKIT_ERROR,
-                                            POLKIT_ERROR_NOT_SUPPORTED,
-                                            "Not implemented");
+  g_set_error (error,
+               POLKIT_ERROR,
+               POLKIT_ERROR_NOT_SUPPORTED,
+               "Not implemented (subject=%s action_id=%s)",
+               subject_str, action_id);
 #endif
 
-  g_free (inquirer_str);
+  /* TODO */
+  result = POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED;
+
+ out:
   g_free (subject_str);
+
+  if (user_of_subject != NULL)
+    g_object_unref (user_of_subject);
+
+  return result;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
index 5284c20..8f9783d 100644 (file)
@@ -333,6 +333,8 @@ get_sessions_foreach_cb (EggDBusHashMap *map,
   return FALSE;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
 GList *
 polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor)
 {
@@ -349,3 +351,90 @@ polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monito
   return l;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * polkit_backend_session_monitor_get_user:
+ * @monitor: A #PolkitBackendSessionMonitor.
+ * @subject: A #PolkitSubject.
+ * @error: Return location for error.
+ *
+ * Gets the user corresponding to @subject or %NULL if no user exists.
+ *
+ * Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref().
+ */
+PolkitSubject *
+polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor  *monitor,
+                                                     PolkitSubject                *subject,
+                                                     GError                      **error)
+{
+  PolkitSubject *user;
+  uid_t uid;
+
+  user = NULL;
+
+  if (POLKIT_IS_UNIX_USER (subject))
+    {
+      user = g_object_ref (subject);
+    }
+  else if (POLKIT_IS_UNIX_PROCESS (subject))
+    {
+      pid_t pid;
+
+      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
+      uid = 500; /* TODO */
+
+      user = polkit_unix_user_new (uid);
+    }
+  else if (POLKIT_IS_UNIX_SESSION (subject))
+    {
+      const gchar *session_id;
+      EggDBusObjectProxy *session_object_proxy;
+      CkSession *session;
+
+      session_id = polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject));
+
+      session_object_proxy = egg_dbus_hash_map_lookup (monitor->session_object_path_to_object_proxy,
+                                                       session_id);
+      if (session_object_proxy == NULL)
+        {
+          g_set_error (error,
+                       POLKIT_ERROR,
+                       POLKIT_ERROR_FAILED,
+                       "No ConsoleKit session with id %s",
+                       session_id);
+          goto out;
+        }
+
+      session = CK_QUERY_INTERFACE_SESSION (session_object_proxy);
+
+      uid = (uid_t) ck_session_get_user (session);
+
+      user = polkit_unix_user_new (uid);
+    }
+  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
+    {
+      /* TODO: cache this stuff */
+      if (!egg_dbus_bus_get_connection_unix_user_sync (egg_dbus_connection_get_bus (monitor->system_bus),
+                                                       EGG_DBUS_CALL_FLAGS_NONE,
+                                                       polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject)),
+                                                       &uid,
+                                                       NULL,
+                                                       error))
+        goto out;
+
+      user = polkit_unix_user_new (uid);
+    }
+  else
+    {
+      g_set_error (error,
+                   POLKIT_ERROR,
+                   POLKIT_ERROR_NOT_SUPPORTED,
+                   "Cannot get user for subject of type %s",
+                   g_type_name (G_TYPE_FROM_INSTANCE (subject)));
+    }
+
+ out:
+
+  return user;
+}
index e5457bb..46ca247 100644 (file)
@@ -47,6 +47,10 @@ GType                        polkit_backend_session_monitor_get_type     (void)
 PolkitBackendSessionMonitor *polkit_backend_session_monitor_new          (void);
 GList                       *polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor);
 
+PolkitSubject               *polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor *monitor,
+                                                                                  PolkitSubject               *subject,
+                                                                                  GError                     **error);
+
 G_END_DECLS
 
 #endif /* __POLKIT_BACKEND_SESSION_MONITOR_H */