diff options
-rw-r--r-- | data/org.freedesktop.PolicyKit1.Authority.xml | 3 | ||||
-rw-r--r-- | src/polkit/polkiterror.h | 8 | ||||
-rw-r--r-- | src/polkit/polkitsubject.c | 4 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthority.c | 174 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendsessionmonitor.c | 89 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendsessionmonitor.h | 4 |
6 files changed, 270 insertions, 12 deletions
diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml index 75d9586..76f68d6 100644 --- a/data/org.freedesktop.PolicyKit1.Authority.xml +++ b/data/org.freedesktop.PolicyKit1.Authority.xml @@ -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) --> diff --git a/src/polkit/polkiterror.h b/src/polkit/polkiterror.h index 5dd21dc..9ef2955 100644 --- a/src/polkit/polkiterror.h +++ b/src/polkit/polkiterror.h @@ -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 diff --git a/src/polkit/polkitsubject.c b/src/polkit/polkitsubject.c index d7c5434..e34bddc 100644 --- a/src/polkit/polkitsubject.c +++ b/src/polkit/polkitsubject.c @@ -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); diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c index db49f99..f6fda0b 100644 --- a/src/polkitbackend/polkitbackendlocalauthority.c +++ b/src/polkitbackend/polkitbackendlocalauthority.c @@ -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; } +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c index 5284c20..8f9783d 100644 --- a/src/polkitbackend/polkitbackendsessionmonitor.c +++ b/src/polkitbackend/polkitbackendsessionmonitor.c @@ -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; +} diff --git a/src/polkitbackend/polkitbackendsessionmonitor.h b/src/polkitbackend/polkitbackendsessionmonitor.h index e5457bb..46ca247 100644 --- a/src/polkitbackend/polkitbackendsessionmonitor.h +++ b/src/polkitbackend/polkitbackendsessionmonitor.h @@ -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 */ |