From 416921898aa80a0135855bd7a790053d460cf111 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Thu, 29 Mar 2007 00:46:42 -0400 Subject: [PATCH] add two tools polkit-check-caller and polkit-check-session --- configure.in | 6 + doc/api/libpolkit/libpolkit-docs.xml | 4 +- doc/man/Makefile.am | 4 +- doc/man/polkit-check-caller.1.in | 65 +++++++ doc/man/polkit-check-session.1.in | 65 +++++++ libpolkit.pc.in | 2 +- libpolkit/Makefile.am | 4 +- libpolkit/libpolkit-caller.c | 173 +++++++++++++++++-- libpolkit/libpolkit-caller.h | 26 +-- libpolkit/libpolkit-privilege.c | 2 +- libpolkit/libpolkit-resource.c | 4 +- libpolkit/libpolkit-seat.c | 2 +- libpolkit/libpolkit-session.c | 245 ++++++++++++++++++++++++++- libpolkit/libpolkit-session.h | 5 +- libpolkit/libpolkit.c | 7 + libpolkit/libpolkit.h | 2 + tools/Makefile.am | 9 +- tools/polkit-check-caller.c | 172 +++++++++++++++++++ tools/polkit-check-session.c | 180 ++++++++++++++++++++ 19 files changed, 935 insertions(+), 42 deletions(-) create mode 100644 doc/man/polkit-check-caller.1.in create mode 100644 doc/man/polkit-check-session.1.in create mode 100644 tools/polkit-check-caller.c create mode 100644 tools/polkit-check-session.c diff --git a/configure.in b/configure.in index 4cde2d3..9e12a93 100644 --- a/configure.in +++ b/configure.in @@ -121,6 +121,10 @@ PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.6.0]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) +PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.0]) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + AC_CHECK_FUNCS(getgrouplist) # DocBook Documentation @@ -187,6 +191,8 @@ doc/api/libpolkit/version.xml doc/spec/Makefile doc/spec/polkit-spec.xml.in doc/man/Makefile +doc/man/polkit-check-caller.1 +doc/man/polkit-check-session.1 ]) dnl ========================================================================== diff --git a/doc/api/libpolkit/libpolkit-docs.xml b/doc/api/libpolkit/libpolkit-docs.xml index 318d7bb..d8f2c63 100644 --- a/doc/api/libpolkit/libpolkit-docs.xml +++ b/doc/api/libpolkit/libpolkit-docs.xml @@ -64,9 +64,7 @@ PolicyKit library. - - <xi:include href="xml/libpolkit.xml"/> - + diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 56847f8..1786b5d 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -1,9 +1,9 @@ if MAN_PAGES_ENABLED -MAN_IN_FILES = +MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in -man_MANS = +man_MANS = polkit-check-caller.1 polkit-check-session.1 endif # MAN_PAGES_ENABLED diff --git a/doc/man/polkit-check-caller.1.in b/doc/man/polkit-check-caller.1.in new file mode 100644 index 0000000..952801e --- /dev/null +++ b/doc/man/polkit-check-caller.1.in @@ -0,0 +1,65 @@ +.\" +.\" polkit-check-caller manual page. +.\" Copyright (C) 2007 David Zeuthen +.\" +.TH POLKIT-CHECK-CALLER 1 +.SH NAME +polkit-check-caller \- check access +.SH SYNOPSIS +.PP +.B polkit-check-caller +[options] + +.SH DESCRIPTION + +\fIpolkit-check-caller\fP can be used to determine if a given caller +can access a given resource in a given way. For more information about +the big picture refer to the \fIPolicyKit spec\fP which can be found +in +.I "/usr/share/doc/PolicyKit-@VERSION@/spec/polkit-spec.html" +depending on the distribution. + +.SH OPTIONS +The following options are supported: +.TP +.I "--resource-type" +Type of resource. +.TP +.I "--resource" +Identifier of resource. +.TP +.I "--privilege" +The privilege to check. +.TP +.I "--caller" +The caller to check for. Must be the callers unique name on the D-Bus +system message bus. +.TP +.I "--help" +Print out usage. +.TP +.I "--version" +Print the version. + +.SH RETURN VALUE +.PP +If access is allowed, this +program exits with exit code 0. If no access is allowed or an error +occurs, the program exits with a non-zero exit code. + +.SH BUGS +.PP +Please send bug reports to either the distribution or the HAL +mailing list, see +.I "http://lists.freedesktop.org/mailman/listinfo/hal" +on how to subscribe. + +.SH SEE ALSO +.PP +\&\fIdbus-daemon\fR\|(1), +\&\fIpolkit-check-session\fR\|(1) + +.SH AUTHOR +Written by David Zeuthen with a lot of help from many +others. + diff --git a/doc/man/polkit-check-session.1.in b/doc/man/polkit-check-session.1.in new file mode 100644 index 0000000..44671d3 --- /dev/null +++ b/doc/man/polkit-check-session.1.in @@ -0,0 +1,65 @@ +.\" +.\" polkit-check-session manual page. +.\" Copyright (C) 2007 David Zeuthen +.\" +.TH POLKIT-CHECK-SESSION 1 +.SH NAME +polkit-check-session \- check access +.SH SYNOPSIS +.PP +.B polkit-check-session +[options] + +.SH DESCRIPTION + +\fIpolkit-check-session\fP can be used to determine if a given session +can access a given resource in a given way. For more information about +the big picture refer to the \fIPolicyKit spec\fP which can be found +in +.I "/usr/share/doc/PolicyKit-@VERSION@/spec/polkit-spec.html" +depending on the distribution. + +.SH OPTIONS +The following options are supported: +.TP +.I "--resource-type" +Type of resource. +.TP +.I "--resource" +Identifier of resource. +.TP +.I "--privilege" +The privilege to check. +.TP +.I "--session" +The session to check for. Must be a ConsoleKit object path. If +ommitted the current session is used. +.TP +.I "--help" +Print out usage. +.TP +.I "--version" +Print the version. + +.SH RETURN VALUE +.PP +If access is allowed, this +program exits with exit code 0. If no access is allowed or an error +occurs, the program exits with a non-zero exit code. + +.SH BUGS +.PP +Please send bug reports to either the distribution or the HAL +mailing list, see +.I "http://lists.freedesktop.org/mailman/listinfo/hal" +on how to subscribe. + +.SH SEE ALSO +.PP +\&\fIdbus-daemon\fR\|(1), +\&\fIpolkit-check-caller\fR\|(1) + +.SH AUTHOR +Written by David Zeuthen with a lot of help from many +others. + diff --git a/libpolkit.pc.in b/libpolkit.pc.in index 3f36d2d..20a2f77 100644 --- a/libpolkit.pc.in +++ b/libpolkit.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libpolkit Description: library for querying system-wide policy Version: @VERSION@ -Requires: glib-2.0 +Requires: glib-2.0 dbus-1 Libs: -L${libdir} -lpolkit Cflags: -I${includedir}/PolicyKit diff --git a/libpolkit/Makefile.am b/libpolkit/Makefile.am index 55408c1..4d1dee0 100644 --- a/libpolkit/Makefile.am +++ b/libpolkit/Makefile.am @@ -8,7 +8,7 @@ INCLUDES = \ -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ - @GLIB_CFLAGS@ + @GLIB_CFLAGS@ @DBUS_CFLAGS@ lib_LTLIBRARIES=libpolkit.la @@ -32,7 +32,7 @@ libpolkit_la_SOURCES = \ libpolkit-session.h libpolkit-session.c \ libpolkit-caller.h libpolkit-caller.c -libpolkit_la_LIBADD = @GLIB_LIBS@ +libpolkit_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/libpolkit/libpolkit-caller.c b/libpolkit/libpolkit-caller.c index 4b59c36..2982508 100644 --- a/libpolkit/libpolkit-caller.c +++ b/libpolkit/libpolkit-caller.c @@ -128,17 +128,17 @@ void libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name) { g_return_if_fail (caller != NULL); - if (caller->dbus_name == NULL) + if (caller->dbus_name != NULL) g_free (caller->dbus_name); caller->dbus_name = g_strdup (dbus_name); } /** - * libpolkit_caller_set_pid: + * libpolkit_caller_set_uid: * @caller: The caller object - * @pid: UNIX process id + * @uid: UNIX user id * - * Set the callers UNIX process id. + * Set the callers UNIX user id. **/ void libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid) @@ -172,7 +172,7 @@ void libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_context) { g_return_if_fail (caller != NULL); - if (caller->selinux_context == NULL) + if (caller->selinux_context != NULL) g_free (caller->selinux_context); caller->selinux_context = g_strdup (selinux_context); } @@ -190,7 +190,7 @@ void libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session) { g_return_if_fail (caller != NULL); - if (caller->session == NULL) + if (caller->session != NULL) libpolkit_session_unref (caller->session); caller->session = session != NULL ? libpolkit_session_ref (session) : NULL; } @@ -214,11 +214,11 @@ libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name) } /** - * libpolkit_caller_get_pid: + * libpolkit_caller_get_uid: * @caller: The caller object - * @out_pid: Returns the UNIX process id + * @out_uid: Returns the UNIX user id * - * Get the callers UNIX process id. + * Get the callers UNIX user id. * * Returns: TRUE iff the value is returned **/ @@ -254,7 +254,8 @@ libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid) * @caller: The caller object * @out_selinux_context: Returns the SELinux security context. The caller shall not free this string. * - * Get the callers SELinux security context. + * Get the callers SELinux security context. Note that this may be + * #NULL if SELinux is not available on the system. * * Returns: TRUE iff the value is returned **/ @@ -272,7 +273,8 @@ libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_c * @caller: The caller object * @out_session: Returns the session object. Caller shall not unref it. * - * Get the callers session. + * Get the callers session. Note that this may be #NULL if the caller + * is not in any session. * * Returns: TRUE iff the value is returned **/ @@ -284,3 +286,152 @@ libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_sessi *out_session = caller->session; return TRUE; } + +/** + * libpolkit_caller_new_from_dbus_name: + * @con: D-Bus system bus connection + * @dbus_name: unique system bus connection name + * @error: D-Bus error + * + * This function will construct a #PolKitCaller object by querying + * both the system bus daemon and the ConsoleKit daemon for + * information. Note that this will do a lot of blocking IO so it is + * best avoided if your process already tracks/caches all the + * information. + * + * Returns: the new object or #NULL if an error occured (in which case + * @error will be set) + **/ +PolKitCaller * +libpolkit_caller_new_from_dbus_name (DBusConnection *con, const char *dbus_name, DBusError *error) +{ + PolKitCaller *caller; + pid_t pid; + uid_t uid; + char *selinux_context; + char *ck_session_objpath; + PolKitSession *session; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter sub_iter; + char *str; + int num_elems; + + g_return_val_if_fail (con != NULL, NULL); + g_return_val_if_fail (dbus_name != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (! dbus_error_is_set (error), NULL); + + selinux_context = NULL; + ck_session_objpath = NULL; + + caller = NULL; + session = NULL; + + uid = dbus_bus_get_unix_user (con, dbus_name, error); + if (uid == ((unsigned long) -1) || dbus_error_is_set (error)) { + g_warning ("Could not get uid for connection: %s %s", error->name, error->message); + goto out; + } + + message = dbus_message_new_method_call ("org.freedesktop.DBus", + "/org/freedesktop/DBus/Bus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID"); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &dbus_name); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing GetConnectionUnixProcessID on Bus: %s: %s", error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_get_basic (&iter, &pid); + dbus_message_unref (message); + dbus_message_unref (reply); + + message = dbus_message_new_method_call ("org.freedesktop.DBus", + "/org/freedesktop/DBus/Bus", + "org.freedesktop.DBus", + "GetConnectionSELinuxSecurityContext"); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &dbus_name); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + /* SELinux might not be enabled */ + if (dbus_error_is_set (error) && + strcmp (error->name, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown") == 0) { + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + dbus_error_init (error); + } else if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing GetConnectionSELinuxSecurityContext on Bus: %s: %s", error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } else { + /* TODO: verify signature */ + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &sub_iter); + dbus_message_iter_get_fixed_array (&sub_iter, (void *) &str, &num_elems); + if (str != NULL && num_elems > 0) + selinux_context = g_strndup (str, num_elems); + dbus_message_unref (message); + dbus_message_unref (reply); + } + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForUnixProcess"); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &pid); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing GetSessionForUnixProcess on ConsoleKit: %s: %s", error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + /* OK, this is not a catastrophe; just means the caller is not a + * member of any session or that ConsoleKit is not available.. + */ + goto not_in_session; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_get_basic (&iter, &str); + ck_session_objpath = g_strdup (str); + dbus_message_unref (message); + dbus_message_unref (reply); + + session = libpolkit_session_new_from_objpath (con, ck_session_objpath, uid, error); + if (session == NULL) { + g_warning ("Got a session objpath but couldn't construct session object!"); + } + +not_in_session: + g_debug ("uid %d", uid); + g_debug ("pid %d", pid); + g_debug ("selinux context '%s'", selinux_context != NULL ? selinux_context : "(not set)"); + g_debug ("ck session '%s'", ck_session_objpath != NULL ? ck_session_objpath : "(not in a session)"); + + caller = libpolkit_caller_new (); + libpolkit_caller_set_dbus_name (caller, dbus_name); + libpolkit_caller_set_uid (caller, uid); + libpolkit_caller_set_pid (caller, pid); + libpolkit_caller_set_selinux_context (caller, selinux_context); + if (session != NULL) { + libpolkit_caller_set_ck_session (caller, session); + libpolkit_session_unref (session); /* we own this session object */ + } + +out: + g_free (selinux_context); + g_free (ck_session_objpath); + return caller; +} + diff --git a/libpolkit/libpolkit-caller.h b/libpolkit/libpolkit-caller.h index ddf0037..b2cfd11 100644 --- a/libpolkit/libpolkit-caller.h +++ b/libpolkit/libpolkit-caller.h @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -37,18 +38,19 @@ struct PolKitCaller; typedef struct PolKitCaller PolKitCaller; PolKitCaller *libpolkit_caller_new (void); -PolKitCaller *libpolkit_caller_ref (PolKitCaller *caller); -void libpolkit_caller_unref (PolKitCaller *caller); -void libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name); -void libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid); -void libpolkit_caller_set_pid (PolKitCaller *caller, pid_t pid); -void libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_context); -void libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session); -gboolean libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name); -gboolean libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid); -gboolean libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid); -gboolean libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_context); -gboolean libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_session); +PolKitCaller *libpolkit_caller_new_from_dbus_name (DBusConnection *con, const char *dbus_name, DBusError *error); +PolKitCaller *libpolkit_caller_ref (PolKitCaller *caller); +void libpolkit_caller_unref (PolKitCaller *caller); +void libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name); +void libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid); +void libpolkit_caller_set_pid (PolKitCaller *caller, pid_t pid); +void libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_context); +void libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session); +gboolean libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name); +gboolean libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid); +gboolean libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid); +gboolean libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_context); +gboolean libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_session); #endif /* LIBPOLKIT_H */ diff --git a/libpolkit/libpolkit-privilege.c b/libpolkit/libpolkit-privilege.c index f6a4634..bc18b55 100644 --- a/libpolkit/libpolkit-privilege.c +++ b/libpolkit/libpolkit-privilege.c @@ -120,7 +120,7 @@ void libpolkit_privilege_set_privilege_id (PolKitPrivilege *privilege, const char *privilege_id) { g_return_if_fail (privilege != NULL); - if (privilege->id == NULL) + if (privilege->id != NULL) g_free (privilege->id); privilege->id = g_strdup (privilege_id); } diff --git a/libpolkit/libpolkit-resource.c b/libpolkit/libpolkit-resource.c index 8e53e84..44f6fa2 100644 --- a/libpolkit/libpolkit-resource.c +++ b/libpolkit/libpolkit-resource.c @@ -127,7 +127,7 @@ libpolkit_resource_set_resource_type (PolKitResource *resource, const char *res { g_return_if_fail (resource != NULL); - if (resource->type == NULL) + if (resource->type != NULL) g_free (resource->type); resource->type = g_strdup (resource_type); } @@ -144,7 +144,7 @@ libpolkit_resource_set_resource_id (PolKitResource *resource, const char *resou { g_return_if_fail (resource != NULL); - if (resource->id == NULL) + if (resource->id != NULL) g_free (resource->id); resource->id = g_strdup (resource_id); } diff --git a/libpolkit/libpolkit-seat.c b/libpolkit/libpolkit-seat.c index 0530468..4bbadf9 100644 --- a/libpolkit/libpolkit-seat.c +++ b/libpolkit/libpolkit-seat.c @@ -120,7 +120,7 @@ void libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char *ck_objref) { g_return_if_fail (seat != NULL); - if (seat->ck_objref == NULL) + if (seat->ck_objref != NULL) g_free (seat->ck_objref); seat->ck_objref = g_strdup (ck_objref); } diff --git a/libpolkit/libpolkit-session.c b/libpolkit/libpolkit-session.c index 34ee2b8..268faf1 100644 --- a/libpolkit/libpolkit-session.c +++ b/libpolkit/libpolkit-session.c @@ -144,7 +144,7 @@ void libpolkit_session_set_ck_objref (PolKitSession *session, const char *ck_objref) { g_return_if_fail (session != NULL); - if (session->ck_objref == NULL) + if (session->ck_objref != NULL) g_free (session->ck_objref); session->ck_objref = g_strdup (ck_objref); } @@ -190,7 +190,7 @@ void libpolkit_session_set_ck_remote_host (PolKitSession *session, const char *remote_host) { g_return_if_fail (session != NULL); - if (session->remote_host == NULL) + if (session->remote_host != NULL) g_free (session->remote_host); session->remote_host = g_strdup (remote_host); } @@ -209,7 +209,7 @@ void libpolkit_session_set_seat (PolKitSession *session, PolKitSeat *seat) { g_return_if_fail (session != NULL); - if (session->seat == NULL) + if (session->seat != NULL) libpolkit_seat_unref (session->seat); session->seat = seat != NULL ? libpolkit_seat_ref (seat) : NULL; } @@ -324,3 +324,242 @@ libpolkit_session_get_seat (PolKitSession *session, PolKitSeat **out_seat) *out_seat = session->seat; return TRUE; } + +/** + * libpolkit_session_new_from_objpath: + * @con: D-Bus system bus connection + * @objpath: object path of ConsoleKit session object + * @uid: the user owning the session or -1 if unknown + * @error: D-Bus error + * + * This function will construct a #PolKitSession object by querying + * the ConsoleKit daemon for information. Note that this will do a lot + * of blocking IO so it is best avoided if your process already + * tracks/caches all the information. If you pass in @uid as a + * non-negative number, a round trip can be saved. + * + * Returns: the new object or #NULL if an error occured (in which case + * @error will be set) + **/ +PolKitSession * +libpolkit_session_new_from_objpath (DBusConnection *con, const char *objpath, uid_t uid, DBusError *error) +{ + PolKitSeat *seat; + PolKitSession *session; + DBusMessage *message; + DBusMessage *reply; + char *str; + gboolean is_active; + gboolean is_local; + char *remote_host; + char *seat_path; + + g_return_val_if_fail (con != NULL, NULL); + g_return_val_if_fail (objpath != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (! dbus_error_is_set (error), NULL); + + session = NULL; + remote_host = NULL; + seat_path = NULL; + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + objpath, + "org.freedesktop.ConsoleKit.Session", + "IsActive"); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Session.IsActive on ConsoleKit: %s: %s", error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &is_active, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid IsActive reply from CK"); + goto out; + } + dbus_message_unref (message); + dbus_message_unref (reply); + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + objpath, + "org.freedesktop.ConsoleKit.Session", + "IsLocal"); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Session.IsLocal on ConsoleKit: %s: %s", error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &is_local, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid IsLocal reply from CK"); + goto out; + } + dbus_message_unref (message); + dbus_message_unref (reply); + + if (!is_local) { + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + objpath, + "org.freedesktop.ConsoleKit.Session", + "GetRemoteHostName"); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Session.GetRemoteHostName on ConsoleKit: %s: %s", + error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_STRING, &str, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid GetRemoteHostName reply from CK"); + goto out; + } + remote_host = g_strdup (str); + dbus_message_unref (message); + dbus_message_unref (reply); + } + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + objpath, + "org.freedesktop.ConsoleKit.Session", + "GetSeatId"); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Session.GetSeatId on ConsoleKit: %s: %s", + error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_OBJECT_PATH, &str, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid GetSeatId reply from CK"); + goto out; + } + seat_path = g_strdup (str); + dbus_message_unref (message); + dbus_message_unref (reply); + + if ((int) uid == -1) { + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + objpath, + "org.freedesktop.ConsoleKit.Session", + "GetUnixUser"); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Session.GetUnixUser on ConsoleKit: %s: %s",error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid GetUnixUser reply from CK"); + goto out; + } + dbus_message_unref (message); + dbus_message_unref (reply); + } + + g_debug ("is_active %d", is_active); + g_debug ("is_local %d", is_local); + g_debug ("uid %d", uid); + if (!is_local) { + g_debug ("remote host '%s'", remote_host); + } + g_debug ("ck seat '%s'", seat_path); + + session = libpolkit_session_new (); + libpolkit_session_set_ck_is_active (session, is_active); + libpolkit_session_set_ck_is_local (session, is_local); + if (!is_local) { + libpolkit_session_set_ck_remote_host (session, remote_host); + } + seat = libpolkit_seat_new (); + libpolkit_seat_set_ck_objref (seat, seat_path); + libpolkit_session_set_seat (session, seat); + libpolkit_seat_unref (seat); /* we own this now */ + +out: + g_free (remote_host); + g_free (seat_path); + return session; +} + +/** + * libpolkit_session_new_from_cookie: + * @con: D-Bus system bus connection + * @cookie: a ConsoleKit XDG_SESSION_COOKIE + * @error: D-Bus error + * + * This function will construct a #PolKitSession object by querying + * the ConsoleKit daemon for information. Note that this will do a lot + * of blocking IO so it is best avoided if your process already + * tracks/caches all the information. + * + * Returns: the new object or #NULL if an error occured (in which case + * @error will be set) + **/ +PolKitSession * +libpolkit_session_new_from_cookie (DBusConnection *con, const char *cookie, DBusError *error) +{ + PolKitSession *session; + DBusMessage *message; + DBusMessage *reply; + char *str; + char *objpath; + + g_return_val_if_fail (con != NULL, NULL); + g_return_val_if_fail (cookie != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (! dbus_error_is_set (error), NULL); + + objpath = NULL; + session = NULL; + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForCookie"); + dbus_message_append_args (message, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, error); + if (reply == NULL || dbus_error_is_set (error)) { + g_warning ("Error doing Manager.GetSessionForCookie on ConsoleKit: %s: %s", + error->name, error->message); + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + goto out; + } + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_OBJECT_PATH, &str, + DBUS_TYPE_INVALID)) { + g_warning ("Invalid GetSessionForCookie reply from CK"); + goto out; + } + objpath = g_strdup (str); + dbus_message_unref (message); + dbus_message_unref (reply); + + session = libpolkit_session_new_from_objpath (con, objpath, -1, error); + +out: + g_free (objpath); + return session; +} + diff --git a/libpolkit/libpolkit-session.h b/libpolkit/libpolkit-session.h index ee91ec0..08000bd 100644 --- a/libpolkit/libpolkit-session.h +++ b/libpolkit/libpolkit-session.h @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -37,6 +38,8 @@ struct PolKitSession; typedef struct PolKitSession PolKitSession; PolKitSession *libpolkit_session_new (void); +PolKitSession *libpolkit_session_new_from_objpath (DBusConnection *con, const char *objpath, uid_t uid, DBusError *error); +PolKitSession *libpolkit_session_new_from_cookie (DBusConnection *con, const char *cookie, DBusError *error); PolKitSession *libpolkit_session_ref (PolKitSession *session); void libpolkit_session_unref (PolKitSession *session); void libpolkit_session_set_uid (PolKitSession *session, uid_t uid); @@ -53,5 +56,3 @@ gboolean libpolkit_session_get_ck_is_local (PolKitSession *session, gbo gboolean libpolkit_session_get_ck_remote_host (PolKitSession *session, char **out_remote_host); #endif /* LIBPOLKIT_SESSION_H */ - - diff --git a/libpolkit/libpolkit.c b/libpolkit/libpolkit.c index ae4e017..87ac370 100644 --- a/libpolkit/libpolkit.c +++ b/libpolkit/libpolkit.c @@ -23,6 +23,13 @@ * **************************************************************************/ +/** + * SECTION:libpolkit + * @short_description: Policy functions. + * + * These functions are used to query system policy. + **/ + #ifdef HAVE_CONFIG_H # include #endif diff --git a/libpolkit/libpolkit.h b/libpolkit/libpolkit.h index a5aedab..59c0352 100644 --- a/libpolkit/libpolkit.h +++ b/libpolkit/libpolkit.h @@ -38,6 +38,8 @@ #include #include + + /** * PolKitSeatVisitorCB: * @seat: the seat diff --git a/tools/Makefile.am b/tools/Makefile.am index 3f2f794..49eec4f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -8,11 +8,16 @@ INCLUDES = \ -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -I$(top_srcdir) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ @GLIB_CFLAGS@ \ @DBUS_CFLAGS@ -bin_PROGRAMS = +bin_PROGRAMS = polkit-check-caller polkit-check-session + +polkit_check_caller_SOURCES = polkit-check-caller.c +polkit_check_caller_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la + +polkit_check_session_SOURCES = polkit-check-session.c +polkit_check_session_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la clean-local : rm -f *~ diff --git a/tools/polkit-check-caller.c b/tools/polkit-check-caller.c new file mode 100644 index 0000000..abaa53c --- /dev/null +++ b/tools/polkit-check-caller.c @@ -0,0 +1,172 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-check-caller.c : check if a caller is privileged + * + * Copyright (C) 2007 David Zeuthen, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void +usage (int argc, char *argv[]) +{ + fprintf (stderr, + "\n" + "usage : polkit-check-caller\n" + " --resource-type --resource-id \n" + " --privilege --caller \n" + " [--version] [--help]\n"); + fprintf (stderr, + "\n" + " --resource-type Type of resource\n" + " --resource-id Identifier of resource\n" + " --privilege Requested privilege\n" + " --caller Unique name of caller on the system bus\n" + " --version Show version and exit\n" + " --help Show this information and exit\n" + "\n" + "Determine if a given caller can access a given resource in a given\n" + "way. If access is allowed, this program exits with exit code 0. If\n" + "no access is allowed or an error occurs, the program exits with\n" + "a non-zero exit code.\n"); +} + +int +main (int argc, char *argv[]) +{ + char *resource_type = NULL; + char *resource_id = NULL; + char *privilege_id = NULL; + char *dbus_name = NULL; + gboolean is_version = FALSE; + DBusConnection *bus; + DBusError error; + PolKitContext *pol_ctx; + PolKitCaller *caller; + PolKitResource *resource; + PolKitPrivilege *privilege; + gboolean allowed; + + if (argc <= 1) { + usage (argc, argv); + return 1; + } + + while (1) { + int c; + int option_index = 0; + const char *opt; + static struct option long_options[] = { + {"resource-type", 1, NULL, 0}, + {"resource-id", 1, NULL, 0}, + {"privilege", 1, NULL, 0}, + {"caller", 1, NULL, 0}, + {"version", 0, NULL, 0}, + {"help", 0, NULL, 0}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, "", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + opt = long_options[option_index].name; + + if (strcmp (opt, "help") == 0) { + usage (argc, argv); + return 0; + } else if (strcmp (opt, "version") == 0) { + is_version = TRUE; + } else if (strcmp (opt, "resource-type") == 0) { + resource_type = strdup (optarg); + } else if (strcmp (opt, "resource-id") == 0) { + resource_id = strdup (optarg); + } else if (strcmp (opt, "privilege") == 0) { + privilege_id = strdup (optarg); + } else if (strcmp (opt, "caller") == 0) { + dbus_name = strdup (optarg); + } + break; + + default: + usage (argc, argv); + return 1; + break; + } + } + + if (is_version) { + printf ("pk-can-caller-access-resource " PACKAGE_VERSION "\n"); + return 0; + } + + if (resource_type == NULL || resource_id == NULL || privilege_id == NULL || dbus_name == NULL) { + usage (argc, argv); + return 1; + } + + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + fprintf (stderr, "error: dbus_bus_get(): %s: %s\n", error.name, error.message); + return 1; + } + + pol_ctx = libpolkit_context_new (); + + privilege = libpolkit_privilege_new (); + libpolkit_privilege_set_privilege_id (privilege, privilege_id); + + resource = libpolkit_resource_new (); + libpolkit_resource_set_resource_type (resource, resource_type); + libpolkit_resource_set_resource_id (resource, resource_id); + + caller = libpolkit_caller_new_from_dbus_name (bus, dbus_name, &error); + if (caller == NULL) { + if (dbus_error_is_set (&error)) { + fprintf (stderr, "error: libpolkit_caller_new_from_dbus_name(): %s: %s\n", + error.name, error.message); + return 1; + } + } + + allowed = libpolkit_can_caller_access_resource (pol_ctx, privilege, resource, caller); + + if (allowed) + return 0; + else + return 1; +} diff --git a/tools/polkit-check-session.c b/tools/polkit-check-session.c new file mode 100644 index 0000000..81b2b24 --- /dev/null +++ b/tools/polkit-check-session.c @@ -0,0 +1,180 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-check-session.c : check if a session is privileged + * + * Copyright (C) 2007 David Zeuthen, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void +usage (int argc, char *argv[]) +{ + fprintf (stderr, + "\n" + "usage : polkit-check-session\n" + " --resource-type --resource-id \n" + " --privilege [--session ]\n" + " [--version] [--help]\n"); + fprintf (stderr, + "\n" + " --resource-type Type of resource\n" + " --resource-id Identifier of resource\n" + " --privilege Requested privilege\n" + " --session ConsoleKit object path of session\n" + " --version Show version and exit\n" + " --help Show this information and exit\n" + "\n" + "Determine if a given session can access a given resource in a given\n" + "way. If no session is given, the current session is used. If access\n" + "is allowed, this program exits with exit code 0. If no access is allowed\n" + "or an error occurs, the program exits with a non-zero exit code.\n"); +} + +int +main (int argc, char *argv[]) +{ + char *resource_type = NULL; + char *resource_id = NULL; + char *privilege_id = NULL; + char *session_id = NULL; + char *cookie = NULL; + gboolean is_version = FALSE; + DBusConnection *bus; + DBusError error; + PolKitContext *pol_ctx; + PolKitSession *session; + PolKitResource *resource; + PolKitPrivilege *privilege; + gboolean allowed; + + if (argc <= 1) { + usage (argc, argv); + return 1; + } + + cookie = getenv ("XDG_SESSION_COOKIE"); + + while (1) { + int c; + int option_index = 0; + const char *opt; + static struct option long_options[] = { + {"resource-type", 1, NULL, 0}, + {"resource-id", 1, NULL, 0}, + {"privilege", 1, NULL, 0}, + {"session", 1, NULL, 0}, + {"version", 0, NULL, 0}, + {"help", 0, NULL, 0}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, "", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + opt = long_options[option_index].name; + + if (strcmp (opt, "help") == 0) { + usage (argc, argv); + return 0; + } else if (strcmp (opt, "version") == 0) { + is_version = TRUE; + } else if (strcmp (opt, "resource-type") == 0) { + resource_type = strdup (optarg); + } else if (strcmp (opt, "resource-id") == 0) { + resource_id = strdup (optarg); + } else if (strcmp (opt, "privilege") == 0) { + privilege_id = strdup (optarg); + } else if (strcmp (opt, "session") == 0) { + session_id = strdup (optarg); + } + break; + + default: + usage (argc, argv); + return 1; + break; + } + } + + if (is_version) { + printf ("pk-can-caller-access-resource " PACKAGE_VERSION "\n"); + return 0; + } + + if (resource_type == NULL || resource_id == NULL || privilege_id == NULL) { + usage (argc, argv); + return 1; + } + + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + fprintf (stderr, "error: dbus_bus_get(): %s: %s\n", error.name, error.message); + return 1; + } + + pol_ctx = libpolkit_context_new (); + + if (session_id != NULL) { + session = libpolkit_session_new_from_objpath (bus, session_id, -1, &error); + } else { + if (cookie == NULL) { + fprintf (stderr, "Not part of a session. Try --session instead.\n"); + return 1; + } + session = libpolkit_session_new_from_cookie (bus, cookie, &error); + } + if (session == NULL) { + fprintf (stderr, "error: libpolkit_session_new_from_objpath: %s: %s\n", error.name, error.message); + return 1; + } + + privilege = libpolkit_privilege_new (); + libpolkit_privilege_set_privilege_id (privilege, privilege_id); + + resource = libpolkit_resource_new (); + libpolkit_resource_set_resource_type (resource, resource_type); + libpolkit_resource_set_resource_id (resource, resource_id); + + allowed = libpolkit_can_session_access_resource (pol_ctx, privilege, resource, session); + + if (allowed) + return 0; + else + return 1; +} -- GitLab