From a0570c50359b7044c38c46fd0527bb8bcb45e271 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Sun, 15 Apr 2007 18:51:19 -0400 Subject: [PATCH] add grant functionality + lots of other changes - Split libpolkit into three libraries - libpolkit : to be used only by mechanisms and modules - libpolkit-dbus : utility library for libpolkit to get caller, session etc. info from the bus and ConsoleKit - libpolkit-grant : client side library for obtaining privileges; uses a setgid helper internally - grant functionality - a helper library, libpolkit-grant, to gain privileges - includes a setgid $POLKIT_GROUP helper to write granted privileges - a PK module, to read and interpret granted privileges - a cmdline app, polkit-grant, using said library - Other changes - so it turns out that sizeof(bool) != sizeof(gboolean), sizeof(dbus_bool_t) This blows so define our own polkit_bool_t type - add some validation routines The grant functionality, especially the setgid helper needs thorough security review before we can release it. --- Makefile.am | 11 +- configure.in | 196 ++++++++ doc/api/Makefile.am | 2 +- doc/api/libpolkit-dbus/Makefile.am | 67 +++ doc/api/libpolkit-dbus/libpolkit-dbus-docs.xml | 109 +++++ doc/api/libpolkit-dbus/libpolkit-dbus.types | 0 doc/api/libpolkit-dbus/version.xml | 1 + doc/api/libpolkit-grant/Makefile.am | 67 +++ doc/api/libpolkit-grant/libpolkit-grant-docs.xml | 109 +++++ doc/api/libpolkit-grant/libpolkit-grant.types | 0 doc/api/libpolkit-grant/version.xml | 1 + doc/api/libpolkit/libpolkit-docs.xml | 3 + libpolkit-dbus/Makefile.am | 31 ++ libpolkit-dbus/libpolkit-dbus.c | 540 +++++++++++++++++++++++ libpolkit-dbus/libpolkit-dbus.h | 41 ++ libpolkit-grant/Makefile.am | 54 +++ libpolkit-grant/libpolkit-grant.c | 465 +++++++++++++++++++ libpolkit-grant/libpolkit-grant.h | 344 +++++++++++++++ libpolkit-grant/polkit-grant-helper.c | 514 +++++++++++++++++++++ libpolkit.pc.in | 2 +- libpolkit/Makefile.am | 8 +- libpolkit/libpolkit-action.c | 26 +- libpolkit/libpolkit-action.h | 11 +- libpolkit/libpolkit-caller.c | 220 +++------ libpolkit/libpolkit-caller.h | 34 +- libpolkit/libpolkit-context.c | 26 +- libpolkit/libpolkit-context.h | 8 +- libpolkit/libpolkit-debug.c | 12 +- libpolkit/libpolkit-error.c | 6 +- libpolkit/libpolkit-error.h | 4 + libpolkit/libpolkit-module.c | 70 +-- libpolkit/libpolkit-module.h | 18 +- libpolkit/libpolkit-policy-cache.h | 4 + libpolkit/libpolkit-policy-default.c | 22 +- libpolkit/libpolkit-policy-default.h | 16 +- libpolkit/libpolkit-policy-file-entry.h | 4 + libpolkit/libpolkit-policy-file.h | 4 + libpolkit/libpolkit-resource.c | 40 +- libpolkit/libpolkit-resource.h | 16 +- libpolkit/libpolkit-result.c | 6 +- libpolkit/libpolkit-result.h | 23 +- libpolkit/libpolkit-seat.c | 33 +- libpolkit/libpolkit-seat.h | 19 +- libpolkit/libpolkit-session.c | 339 ++++---------- libpolkit/libpolkit-session.h | 38 +- libpolkit/libpolkit-types.h | 56 +++ libpolkit/libpolkit-utils.c | 153 +++++++ libpolkit/libpolkit-utils.h | 37 ++ libpolkit/libpolkit.h | 15 + modules/Makefile.am | 2 +- modules/PolicyKit.conf | 1 + modules/allow-all/polkit-module-allow-all.c | 17 +- modules/default/polkit-module-default.c | 17 +- modules/deny-all/polkit-module-deny-all.c | 17 +- modules/grant/Makefile.am | 25 ++ modules/grant/polkit-module-grant.c | 194 ++++++++ modules/run-program/polkit-module-run-program.c | 70 +-- tools/Makefile.am | 9 +- tools/polkit-check-caller.c | 2 +- tools/polkit-check-session.c | 2 +- tools/polkit-grant.c | 425 ++++++++++++++++++ tools/polkit-policy-file-validate.c | 2 +- 62 files changed, 3950 insertions(+), 658 deletions(-) create mode 100644 doc/api/libpolkit-dbus/Makefile.am create mode 100644 doc/api/libpolkit-dbus/libpolkit-dbus-docs.xml create mode 100644 doc/api/libpolkit-dbus/libpolkit-dbus.types create mode 100644 doc/api/libpolkit-dbus/version.xml create mode 100644 doc/api/libpolkit-grant/Makefile.am create mode 100644 doc/api/libpolkit-grant/libpolkit-grant-docs.xml create mode 100644 doc/api/libpolkit-grant/libpolkit-grant.types create mode 100644 doc/api/libpolkit-grant/version.xml create mode 100644 libpolkit-dbus/Makefile.am create mode 100644 libpolkit-dbus/libpolkit-dbus.c create mode 100644 libpolkit-dbus/libpolkit-dbus.h create mode 100644 libpolkit-grant/Makefile.am create mode 100644 libpolkit-grant/libpolkit-grant.c create mode 100644 libpolkit-grant/libpolkit-grant.h create mode 100644 libpolkit-grant/polkit-grant-helper.c create mode 100644 libpolkit/libpolkit-types.h create mode 100644 libpolkit/libpolkit-utils.c create mode 100644 libpolkit/libpolkit-utils.h create mode 100644 modules/grant/Makefile.am create mode 100644 modules/grant/polkit-module-grant.c create mode 100644 tools/polkit-grant.c diff --git a/Makefile.am b/Makefile.am index 3270435..cf1dbb7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,14 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = libpolkit modules doc tools policy +SUBDIRS = libpolkit libpolkit-dbus libpolkit-grant modules doc tools policy + +pamdir = $(sysconfdir)/pam.d +pam_DATA = polkit pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libpolkit.pc +pkgconfig_DATA = libpolkit.pc libpolkit-dbus.pc libpolkit-grant.pc -DISTCLEANFILES = libpolkit.pc +DISTCLEANFILES = libpolkit.pc libpolkit-dbus.pc libpolkit-grant.pc # Creating ChangeLog from git log (taken from cairo/Makefile.am): ChangeLog: $(srcdir)/ChangeLog @@ -26,7 +29,7 @@ $(srcdir)/ChangeLog: .PHONY: ChangeLog $(srcdir)/ChangeLog -EXTRA_DIST = HACKING libpolkit.pc.in mkinstalldirs ChangeLog +EXTRA_DIST = HACKING polkit.in libpolkit.pc.in libpolkit-dbus.pc.in libpolkit-grant.pc.in mkinstalldirs ChangeLog clean-local : rm -f *~ diff --git a/configure.in b/configure.in index 6f839e8..126b9b1 100644 --- a/configure.in +++ b/configure.in @@ -161,15 +161,187 @@ if test "x$GCC" = "xyes"; then LDFLAGS="-Wl,--as-needed $LDFLAGS" fi +dnl --------------------------------------------------------------------------- +dnl - User and group +dnl --------------------------------------------------------------------------- + +AC_ARG_WITH(polkit_user,[ --with-polkit-user= user for PolicyKit]) +if test -z "$with_polkit_user" ; then + POLKIT_USER=polkit +else + POLKIT_USER=$with_polkit_user +fi +AC_SUBST(POLKIT_USER) +AC_DEFINE_UNQUOTED(POLKIT_USER, "$POLKIT_USER", [User for PolicyKit]) + +AC_ARG_WITH(polkit_group,[ --with-polkit-group= group for PolicyKit]) +if test -z "$with_polkit_group" ; then + POLKIT_GROUP=polkit +else + POLKIT_GROUP=$with_polkit_group +fi +AC_SUBST(POLKIT_GROUP) +AC_DEFINE_UNQUOTED(POLKIT_GROUP,"$POLKIT_GROUP", [Group for PolicyKit]) + +dnl --------------------------------------------------------------------------- +dnl - Check for PAM +dnl --------------------------------------------------------------------------- + +withval="" +AC_ARG_WITH(pam-prefix, +[ --with-pam-prefix= specify where pam files go],[ +if test x$withval != x; then + AC_MSG_RESULT("PAM files will be installed in prefix ${withval}.") +fi]) +if test x$withval != x; then + PAM_PREFIX_UNEXPANDED="$withval" +else + PAM_PREFIX_UNEXPANDED="$sysconfdir" +fi +PAM_PREFIX=`eval echo $PAM_PREFIX_UNEXPANDED` +AC_SUBST(PAM_PREFIX) + +have_pam=no +AC_CHECK_LIB(pam, pam_start, have_pam=yes) +if test x$have_pam = xno; then + AC_ERROR([Could not find pam/pam-devel, please install the needed packages.]) +else + AUTH_LIBS="${AUTH_LIBS} -lpam" + AC_DEFINE(HAVE_PAM, 1, [Define if PAM support is included]) + + # On Linux, sigtimedwait() is in libc; on Solaris, it's in librt. + have_timedwait=no + AC_CHECK_LIB(c, sigtimedwait, [have_timedwait=yes]) + if test "$have_timedwait" = no ; then + AC_CHECK_LIB(rt, sigtimedwait, [AUTH_LIBS="${AUTH_LIBS} -lrt"]) + fi + + AC_MSG_CHECKING(how to call pam_strerror) + AC_CACHE_VAL(ac_cv_pam_strerror_args, + [AC_TRY_COMPILE([#include + #include + #include ], + [pam_handle_t *pamh = 0; + char *s = pam_strerror(pamh, PAM_SUCCESS);], + [ac_pam_strerror_args=2], + [AC_TRY_COMPILE([#include + #include + #include ], + [char *s = + pam_strerror(PAM_SUCCESS);], + [ac_pam_strerror_args=1], + [ac_pam_strerror_args=0])]) + ac_cv_pam_strerror_args=$ac_pam_strerror_args]) + ac_pam_strerror_args=$ac_cv_pam_strerror_args + if test "$ac_pam_strerror_args" = 1 ; then + AC_MSG_RESULT(one argument) + elif test "$ac_pam_strerror_args" = 2 ; then + AC_DEFINE(PAM_STRERROR_TWO_ARGS, 1, [Define if pam_strerror takes two arguments]) + AC_MSG_RESULT(two arguments) + else + AC_MSG_RESULT(unknown) + fi + +fi + +AM_CONDITIONAL(HAVE_PAM, test x$have_pam = xyes) +AC_SUBST(HAVE_PAM) +AC_SUBST(AUTH_LIBS) + +AC_CHECK_HEADER(security/pam_modutil.h, [AC_DEFINE(HAVE_PAM_MODUTIL_H, [], "Have pam_modutil.h")]) +AC_CHECK_HEADER(security/pam_ext.h, [AC_DEFINE(HAVE_PAM_EXT_H, [], "Have pam_ext.h")]) +AC_CHECK_LIB(pam, pam_vsyslog, [AC_DEFINE(HAVE_PAM_VSYSLOG, [], "Have pam_vsyslog")]) + +AC_ARG_WITH(pam-module-dir, [ --with-pam-module-dir=[dirname] directory to install PAM security module]) +if ! test -z "$with_pam_module_dir"; then + PAM_MODULE_DIR=$with_pam_module_dir +else + PAM_MODULE_DIR="/lib/security" +fi + +AC_SUBST(PAM_MODULE_DIR) + +AC_ARG_WITH(os-type, [ --with-os-type= distribution or OS (redhat)]) + +#### Check our operating system (distro-tweaks required) +if test "z$with_os_type" = "z"; then + AC_CHECK_FILE(/etc/redhat-release,distro_type="redhat") + AC_CHECK_FILE(/etc/SuSE-release,distro_type="suse") + if test "z$distro_type" = "z"; then + echo "Linux distribution autodetection failed, specify the distribution to target using --with-os-type=" + else + operating_system=`echo ${distro_type} | tr '[[:upper:]]' '[[:lower:]]' ` + fi +fi + +#### Sort out OS (distro-tweaks required) +if test x$with_os_type = x; then + if test x$operating_system = xredhat ; then + with_os_type=redhat + elif test x$operating_system = xsuse ; then + with_os_type=suse + else + with_os_type=unknown + fi +fi + +# (distro-tweaks required) +AM_CONDITIONAL(OS_TYPE_UNKNOWN, test x$with_os_type = xunknown, [Running on unknown OS]) +AM_CONDITIONAL(OS_TYPE_RED_HAT, test x$with_os_type = xredhat, [Running on Red Hat OS'es]) +AM_CONDITIONAL(OS_TYPE_SUSE, test x$with_os_type = xsuse, [Running on SUSE OS'es]) + +AC_ARG_WITH(pam-include, [ --with-pam-include= pam file to include]) + +#### Set up pam file to include (distro-tweaks required) +if ! test -z "$with_pam_include"; then + PAM_FILE_INCLUDE_AUTH=$with_pam_include + PAM_FILE_INCLUDE_ACCOUNT=$with_pam_include + PAM_FILE_INCLUDE_PASSWORD=$with_pam_include + PAM_FILE_INCLUDE_SESSION=$with_pam_include +elif test x$with_os_type = xredhat ; then + PAM_FILE_INCLUDE_AUTH=system-auth + PAM_FILE_INCLUDE_ACCOUNT=system-auth + PAM_FILE_INCLUDE_PASSWORD=system-auth + PAM_FILE_INCLUDE_SESSION=system-auth +elif test x$with_os_type = xsuse ; then + PAM_FILE_INCLUDE_AUTH=common-auth + PAM_FILE_INCLUDE_ACCOUNT=common-account + PAM_FILE_INCLUDE_PASSWORD=common-password + PAM_FILE_INCLUDE_SESSION=common-session +else + PAM_FILE_INCLUDE_AUTH=system-auth + PAM_FILE_INCLUDE_ACCOUNT=system-auth + PAM_FILE_INCLUDE_PASSWORD=system-auth + PAM_FILE_INCLUDE_SESSION=system-auth +fi + +AC_SUBST(PAM_FILE_INCLUDE_AUTH) +AC_SUBST(PAM_FILE_INCLUDE_ACCOUNT) +AC_SUBST(PAM_FILE_INCLUDE_PASSWORD) +AC_SUBST(PAM_FILE_INCLUDE_SESSION) +AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_AUTH, "$PAM_FILE_INCLUDE_AUTH", [pam file auth]) +AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_ACCOUNT, "$PAM_FILE_INCLUDE_ACCOUNT", [pam file account]) +AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_PASSWORD, "$PAM_FILE_INCLUDE_PASSWORD", [pam file password]) +AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_SESSION, "$PAM_FILE_INCLUDE_SESSION", [pam file session]) + AC_OUTPUT([ libpolkit.pc +libpolkit-dbus.pc +libpolkit-grant.pc Makefile +polkit libpolkit/Makefile +libpolkit-dbus/Makefile +libpolkit-grant/Makefile tools/Makefile doc/Makefile doc/api/Makefile doc/api/libpolkit/Makefile doc/api/libpolkit/version.xml +doc/api/libpolkit-dbus/Makefile +doc/api/libpolkit-dbus/version.xml +doc/api/libpolkit-grant/Makefile +doc/api/libpolkit-grant/version.xml doc/spec/Makefile doc/spec/polkit-spec.xml.in doc/man/Makefile @@ -179,6 +351,7 @@ modules/default/Makefile modules/allow-all/Makefile modules/deny-all/Makefile modules/run-program/Makefile +modules/grant/Makefile ]) dnl ========================================================================== @@ -202,9 +375,32 @@ echo " xmlto: ${XMLTO} xmllint: ${XMLLINT} + user for PolicyKit: ${POLKIT_USER} + group for PolicyKit: ${POLKIT_GROUP} + + Distribution/OS: ${with_os_type} + + PAM support: ${have_pam} + PAM file auth: ${PAM_FILE_INCLUDE_AUTH} + PAM file account: ${PAM_FILE_INCLUDE_ACCOUNT} + PAM file password: ${PAM_FILE_INCLUDE_PASSWORD} + PAM file session: ${PAM_FILE_INCLUDE_SESSION} + Maintainer mode: ${USE_MAINTAINER_MODE} Building verbose mode: ${enable_verbose_mode} Building api docs: ${enable_gtk_doc} Building docs: ${enable_docbook_docs} Building man pages: ${enable_man_pages} " + +echo "NOTE: Remember to create user '${POLKIT_USER}' and group '${POLKIT_GROUP}' before 'make install'" +echo + +echo "NOTE: ${libexecdir}/polkit-grant-helper will be owner by group" +echo " '${POLKIT_USER}', and installed with mode 2755 (setgid binary)." +echo " The directories ${localstatedir}/run/PolicyKit and ${localstatedir}/lib/PolicyKit will be" +echo " owned by user '${POLKIT_USER}' and group '${POLKIT_GROUP}' and will be of mode 775." +echo + +echo "NOTE: For packaging, remember to retain the modes and ownership." +echo diff --git a/doc/api/Makefile.am b/doc/api/Makefile.am index 3c12eb0..46809b2 100644 --- a/doc/api/Makefile.am +++ b/doc/api/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in. -SUBDIRS = libpolkit +SUBDIRS = libpolkit libpolkit-dbus libpolkit-grant MAINTAINERCLEANFILES = \ *~ \ diff --git a/doc/api/libpolkit-dbus/Makefile.am b/doc/api/libpolkit-dbus/Makefile.am new file mode 100644 index 0000000..c539267 --- /dev/null +++ b/doc/api/libpolkit-dbus/Makefile.am @@ -0,0 +1,67 @@ +## Process this file with automake to create Makefile.in. + +NULL = + +AUTOMAKE_OPTIONS = 1.7 + +# The name of the module. +DOC_MODULE=libpolkit-dbus + +# The top-level SGML file. +DOC_MAIN_SGML_FILE=libpolkit-dbus-docs.xml + +# Extra options to supply to gtkdoc-scan +#SCAN_OPTIONS=--deprecated-guards="CAIRO_DISABLE_DEPRECATED" + +# The directory containing the source code. Relative to $(srcdir) +DOC_SOURCE_DIR=../../../libpolkit-dbus + +# Used for dependencies +HFILE_GLOB=$(top_srcdir)/libpolkit-dbus/*.h +CFILE_GLOB=$(top_srcdir)/libpolkit-dbus/*.c + +# Headers to ignore +IGNORE_HFILES= \ + $(NULL) + +# CFLAGS and LDFLAGS for compiling scan program. Only needed +# if $(DOC_MODULE).types is non-empty. +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(NULL) + +GTKDOC_LIBS = \ + $(GLIB_LIBS) \ + $(top_builddir)/libpolkit-dbus/libpolkit-dbus.la \ + $(NULL) + +# Extra options to supply to gtkdoc-mkdb +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +MKTMPL_OPTIONS= + +# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE) +content_files = \ + version.xml \ + $(NULL) + +# Images to copy into HTML directory +HTML_IMAGES = + +# Extra options to supply to gtkdoc-fixref +FIXXREF_OPTIONS= + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in \ + libpolkit-dbus.types \ + libpolkit-dbus-*.txt \ + $(NULL) + +include $(top_srcdir)/gtk-doc.make + +# Version information for marking the documentation +EXTRA_DIST += version.xml.in diff --git a/doc/api/libpolkit-dbus/libpolkit-dbus-docs.xml b/doc/api/libpolkit-dbus/libpolkit-dbus-docs.xml new file mode 100644 index 0000000..9dcf978 --- /dev/null +++ b/doc/api/libpolkit-dbus/libpolkit-dbus-docs.xml @@ -0,0 +1,109 @@ + + +]> + + + PolicyKit D-Bus Helper Library Reference Manual + Version &version; + + + David + Zeuthen + +
+ david@fubar.dk +
+
+
+
+ + + 2007 + The PolicyKit Authors + + + + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free + Documentation License, Version 1.1 or any later + version published by the Free Software Foundation with no + Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. You may obtain a copy of the GNU Free + Documentation License from the Free Software + Foundation by visiting their Web site or by writing + to: + +
+ The Free Software Foundation, Inc., + 59 Temple Place - Suite 330, + Boston, MA 02111-1307, + USA +
+
+ + + Many of the names used by companies to distinguish their + products and services are claimed as trademarks. Where those + names appear in any GNOME documentation, and those trademarks + are made aware to the members of the GNOME Documentation + Project, the names have been printed in caps or initial caps. + +
+
+ + + API Reference + + + + This part presents the class and function reference for the + PolicyKit D-Bus helper library. + + + + + + + Index + + + + + + License + + + This library 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 library 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 Library General Public License for + more details. + + + + You may obtain a copy of the GNU General + Public License from the Free Software Foundation by + visiting their Web + site or by writing to: + +
+ Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307 + USA +
+
+
+
diff --git a/doc/api/libpolkit-dbus/libpolkit-dbus.types b/doc/api/libpolkit-dbus/libpolkit-dbus.types new file mode 100644 index 0000000..e69de29 diff --git a/doc/api/libpolkit-dbus/version.xml b/doc/api/libpolkit-dbus/version.xml new file mode 100644 index 0000000..be58634 --- /dev/null +++ b/doc/api/libpolkit-dbus/version.xml @@ -0,0 +1 @@ +0.3 diff --git a/doc/api/libpolkit-grant/Makefile.am b/doc/api/libpolkit-grant/Makefile.am new file mode 100644 index 0000000..f65956e --- /dev/null +++ b/doc/api/libpolkit-grant/Makefile.am @@ -0,0 +1,67 @@ +## Process this file with automake to create Makefile.in. + +NULL = + +AUTOMAKE_OPTIONS = 1.7 + +# The name of the module. +DOC_MODULE=libpolkit-grant + +# The top-level SGML file. +DOC_MAIN_SGML_FILE=libpolkit-grant-docs.xml + +# Extra options to supply to gtkdoc-scan +#SCAN_OPTIONS=--deprecated-guards="CAIRO_DISABLE_DEPRECATED" + +# The directory containing the source code. Relative to $(srcdir) +DOC_SOURCE_DIR=../../../libpolkit-grant + +# Used for dependencies +HFILE_GLOB=$(top_srcdir)/libpolkit-grant/*.h +CFILE_GLOB=$(top_srcdir)/libpolkit-grant/*.c + +# Headers to ignore +IGNORE_HFILES= \ + $(NULL) + +# CFLAGS and LDFLAGS for compiling scan program. Only needed +# if $(DOC_MODULE).types is non-empty. +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(NULL) + +GTKDOC_LIBS = \ + $(GLIB_LIBS) \ + $(top_builddir)/libpolkit-grant/libpolkit-grant.la \ + $(NULL) + +# Extra options to supply to gtkdoc-mkdb +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +MKTMPL_OPTIONS= + +# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE) +content_files = \ + version.xml \ + $(NULL) + +# Images to copy into HTML directory +HTML_IMAGES = + +# Extra options to supply to gtkdoc-fixref +FIXXREF_OPTIONS= + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in \ + libpolkit-grant.types \ + libpolkit-grant-*.txt \ + $(NULL) + +include $(top_srcdir)/gtk-doc.make + +# Version information for marking the documentation +EXTRA_DIST += version.xml.in diff --git a/doc/api/libpolkit-grant/libpolkit-grant-docs.xml b/doc/api/libpolkit-grant/libpolkit-grant-docs.xml new file mode 100644 index 0000000..0ca0f9f --- /dev/null +++ b/doc/api/libpolkit-grant/libpolkit-grant-docs.xml @@ -0,0 +1,109 @@ + + +]> + + + PolicyKit Granting Library Reference Manual + Version &version; + + + David + Zeuthen + +
+ david@fubar.dk +
+
+
+
+ + + 2007 + The PolicyKit Authors + + + + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free + Documentation License, Version 1.1 or any later + version published by the Free Software Foundation with no + Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. You may obtain a copy of the GNU Free + Documentation License from the Free Software + Foundation by visiting their Web site or by writing + to: + +
+ The Free Software Foundation, Inc., + 59 Temple Place - Suite 330, + Boston, MA 02111-1307, + USA +
+
+ + + Many of the names used by companies to distinguish their + products and services are claimed as trademarks. Where those + names appear in any GNOME documentation, and those trademarks + are made aware to the members of the GNOME Documentation + Project, the names have been printed in caps or initial caps. + +
+
+ + + API Reference + + + + This part presents the class and function reference for the + PolicyKit granting helper library. + + + + + + + Index + + + + + + License + + + This library 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 library 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 Library General Public License for + more details. + + + + You may obtain a copy of the GNU General + Public License from the Free Software Foundation by + visiting their Web + site or by writing to: + +
+ Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307 + USA +
+
+
+
diff --git a/doc/api/libpolkit-grant/libpolkit-grant.types b/doc/api/libpolkit-grant/libpolkit-grant.types new file mode 100644 index 0000000..e69de29 diff --git a/doc/api/libpolkit-grant/version.xml b/doc/api/libpolkit-grant/version.xml new file mode 100644 index 0000000..be58634 --- /dev/null +++ b/doc/api/libpolkit-grant/version.xml @@ -0,0 +1 @@ +0.3 diff --git a/doc/api/libpolkit/libpolkit-docs.xml b/doc/api/libpolkit/libpolkit-docs.xml index c802ef0..b0f538f 100644 --- a/doc/api/libpolkit/libpolkit-docs.xml +++ b/doc/api/libpolkit/libpolkit-docs.xml @@ -64,6 +64,7 @@ PolicyKit library. + @@ -77,6 +78,8 @@ + + diff --git a/libpolkit-dbus/Makefile.am b/libpolkit-dbus/Makefile.am new file mode 100644 index 0000000..3a51c3a --- /dev/null +++ b/libpolkit-dbus/Makefile.am @@ -0,0 +1,31 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES = \ + -I$(top_builddir) -I$(top_srcdir) \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ + @GLIB_CFLAGS@ @DBUS_CFLAGS@ + +lib_LTLIBRARIES=libpolkit-dbus.la + +libpolkit_dbusincludedir=$(includedir)/PolicyKit/libpolkit-dbus + +libpolkit_dbusinclude_HEADERS = \ + libpolkit-dbus.h + +libpolkit_dbus_la_SOURCES = \ + libpolkit-dbus.h libpolkit-dbus.c + +libpolkit_dbus_la_LIBADD = @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la + +libpolkit_dbus_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +clean-local : + rm -f *~ $(BUILT_SOURCES) + diff --git a/libpolkit-dbus/libpolkit-dbus.c b/libpolkit-dbus/libpolkit-dbus.c new file mode 100644 index 0000000..6c4995a --- /dev/null +++ b/libpolkit-dbus/libpolkit-dbus.c @@ -0,0 +1,540 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-dbus.h : helper library for obtaining seat, session and + * caller information via D-Bus and ConsoleKit + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 + * + **************************************************************************/ + +/** + * SECTION:libpolkit-dbus + * @short_description: Helper library for obtaining seat, session and caller information via D-Bus and ConsoleKit. + * + * Helper library for obtaining seat, session and caller information + * via D-Bus and ConsoleKit. + **/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "libpolkit-dbus.h" + + +/** + * 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; + dbus_bool_t is_active; + dbus_bool_t 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); + } + + session = libpolkit_session_new (); + if (session == NULL) { + goto out; + } + if (!libpolkit_session_set_ck_objref (session, objpath)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + if (!libpolkit_session_set_ck_is_active (session, is_active)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + if (!libpolkit_session_set_ck_is_local (session, is_local)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + if (!is_local) { + if (!libpolkit_session_set_ck_remote_host (session, remote_host)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + + } + + seat = libpolkit_seat_new (); + if (seat == NULL) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + if (!libpolkit_seat_set_ck_objref (seat, seat_path)) { + libpolkit_seat_unref (seat); + seat = NULL; + libpolkit_session_unref (session); + session = NULL; + goto out; + } + if (!libpolkit_seat_validate (seat)) { + libpolkit_seat_unref (seat); + seat = NULL; + libpolkit_session_unref (session); + session = NULL; + goto out; + } + + if (!libpolkit_session_set_seat (session, seat)) { + libpolkit_seat_unref (seat); + seat = NULL; + libpolkit_session_unref (session); + session = NULL; + goto out; + } + libpolkit_seat_unref (seat); /* session object now owns this object */ + seat = NULL; + + if (!libpolkit_session_validate (session)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + +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; +} + + +/** + * 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!"); + goto out; + } + if (!libpolkit_session_validate (session)) { + libpolkit_session_unref (session); + session = NULL; + goto out; + } + +not_in_session: + + caller = libpolkit_caller_new (); + if (caller == NULL) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + goto out; + } + + if (!libpolkit_caller_set_dbus_name (caller, dbus_name)) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + if (!libpolkit_caller_set_uid (caller, uid)) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + if (!libpolkit_caller_set_pid (caller, pid)) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + if (selinux_context != NULL) { + if (!libpolkit_caller_set_selinux_context (caller, selinux_context)) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + } + if (session != NULL) { + if (!libpolkit_caller_set_ck_session (caller, session)) { + if (session != NULL) { + libpolkit_session_unref (session); + session = NULL; + } + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + libpolkit_session_unref (session); /* caller object now own this object */ + session = NULL; + } + + if (!libpolkit_caller_validate (caller)) { + libpolkit_caller_unref (caller); + caller = NULL; + goto out; + } + +out: + g_free (selinux_context); + g_free (ck_session_objpath); + return caller; +} diff --git a/libpolkit-dbus/libpolkit-dbus.h b/libpolkit-dbus/libpolkit-dbus.h new file mode 100644 index 0000000..dd8d019 --- /dev/null +++ b/libpolkit-dbus/libpolkit-dbus.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-dbus.h : helper library for obtaining seat, session and + * caller information via D-Bus and ConsoleKit + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifndef LIBPOLKIT_DBUS_H +#define LIBPOLKIT_DBUS_H + +#include +#include + +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); + +PolKitCaller *libpolkit_caller_new_from_dbus_name (DBusConnection *con, const char *dbus_name, DBusError *error); + + +#endif /* LIBPOLKIT_DBUS_H */ + + diff --git a/libpolkit-grant/Makefile.am b/libpolkit-grant/Makefile.am new file mode 100644 index 0000000..01ebcfe --- /dev/null +++ b/libpolkit-grant/Makefile.am @@ -0,0 +1,54 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES = \ + -I$(top_builddir) -I$(top_srcdir) \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ + @GLIB_CFLAGS@ @DBUS_CFLAGS@ + +lib_LTLIBRARIES=libpolkit-grant.la + +libpolkit_grantincludedir=$(includedir)/PolicyKit/libpolkit-grant + +libpolkit_grantinclude_HEADERS = \ + libpolkit-grant.h + +libpolkit_grant_la_SOURCES = \ + libpolkit-grant.h libpolkit-grant.c + +libpolkit_grant_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la + +libpolkit_grant_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +libexec_PROGRAMS = polkit-grant-helper + +polkit_grant_helper_SOURCES = polkit-grant-helper.c +polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @AUTH_LIBS@ $(top_builddir)/libpolkit/libpolkit.la $(top_builddir)/libpolkit-dbus/libpolkit-dbus.la + +polkit_grant_alwaysdir = $(localstatedir)/lib/PolicyKit +dist_polkit_grant_always_DATA = + +polkit_grant_sessiondir = $(localstatedir)/run/PolicyKit +dist_polkit_grant_session_DATA = + + +clean-local : + rm -f *~ $(BUILT_SOURCES) + +# Hmm.. we could make the directories 750 and require that all mechanisms using +# libpolkit (e.g. with a need for polkit-module-grant.so to look there) just +# be part of $(POLKIT_GROUP)... +# +install-data-local: + -chown :$(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-grant-helper + -chmod 2755 $(DESTDIR)$(libexecdir)/polkit-grant-helper + -chown $(POLKIT_USER):$(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/PolicyKit + -chown $(POLKIT_USER):$(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/run/PolicyKit + -chmod 775 $(DESTDIR)$(localstatedir)/lib/PolicyKit + -chmod 775 $(DESTDIR)$(localstatedir)/run/PolicyKit diff --git a/libpolkit-grant/libpolkit-grant.c b/libpolkit-grant/libpolkit-grant.c new file mode 100644 index 0000000..d15f8a0 --- /dev/null +++ b/libpolkit-grant/libpolkit-grant.c @@ -0,0 +1,465 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-grant.c : library for obtaining privileges + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include "libpolkit-grant.h" + +/** + * SECTION:libpolkit-grant + * @short_description: Obtain privileges through authentication. + * + * These functions are used to obtain privileges for a user that is + * able to successfully authenticate. + **/ + +/** + * PolKitGrant: + * + * Objects of this class are used to obtain privileges for a user that + * is able to successfully authenticate. + **/ +struct PolKitGrant +{ + int refcount; + + PolKitGrantAddIOWatch func_add_io_watch; + PolKitGrantAddChildWatch func_add_child_watch; + PolKitGrantRemoveWatch func_remove_watch; + PolKitGrantType func_type; + PolKitGrantConversationPromptEchoOff func_prompt_echo_off; + PolKitGrantConversationPromptEchoOn func_prompt_echo_on; + PolKitGrantConversationErrorMessage func_error_message; + PolKitGrantConversationTextInfo func_text_info; + PolKitGrantOverrideGrantType func_override_grant_type; + PolKitGrantDone func_done; + void *user_data; + + int child_stdin; + int child_stdout; + GPid child_pid; + FILE *child_stdout_f; + + int child_watch_id; + int io_watch_id; + + gboolean success; + gboolean auth_in_progress; +}; + +/** + * libpolkit_grant_new: + * @void: + * + * Creates a #PolKitGrant object. + * + * Returns: the new object or #NULL on error. + **/ +PolKitGrant * +libpolkit_grant_new (void) +{ + PolKitGrant *polkit_grant; + polkit_grant = g_new0 (PolKitGrant, 1); + polkit_grant->refcount = 1; + return polkit_grant; +} + +/** + * libpolkit_grant_ref: + * @polkit_grant: the object + * + * Increase reference count. + * + * Returns: the object. + **/ +PolKitGrant * +libpolkit_grant_ref (PolKitGrant *polkit_grant) +{ + g_return_val_if_fail (polkit_grant != NULL, NULL); + + polkit_grant->refcount++; + return polkit_grant; +} + +/** + * libpolkit_grant_unref: + * @polkit_grant: the object + * + * Decreases the reference count of the object. If it becomes zero, + * the object is freed. Before freeing, reference counts on embedded + * objects are decresed by one. + **/ +void +libpolkit_grant_unref (PolKitGrant *polkit_grant) +{ + g_return_if_fail (polkit_grant != NULL); + + polkit_grant->refcount--; + if (polkit_grant->refcount > 0) + return; + + if (polkit_grant->io_watch_id > 0) { + polkit_grant->func_remove_watch (polkit_grant, polkit_grant->io_watch_id); + } + if (polkit_grant->child_watch_id > 0) { + polkit_grant->func_remove_watch (polkit_grant, polkit_grant->child_watch_id); + } + if (polkit_grant->child_pid > 0) { + kill (polkit_grant->child_pid, SIGTERM); + } + if (polkit_grant->child_stdout_f != NULL) { + fclose (polkit_grant->child_stdout_f); + } + if (polkit_grant->child_stdout >= 0) { + close (polkit_grant->child_stdout); + } + if (polkit_grant->child_stdin >= 0) { + close (polkit_grant->child_stdin); + } + + g_free (polkit_grant); +} + +/** + * libpolkit_grant_set_functions: + * @polkit_grant: the object + * @func_add_io_watch: Callback function + * @func_add_child_watch: Callback function + * @func_remove_watch: Callback function + * @func_type: Callback function + * @func_prompt_echo_off: Callback function + * @func_prompt_echo_on: Callback function + * @func_error_message: Callback function + * @func_text_info: Callback function + * @func_override_grant_type: Callback function + * @func_done: Callback function + * @user_data: User data that will be passed to the callback functions. + * + * Set callback functions used for authentication. + **/ +void +libpolkit_grant_set_functions (PolKitGrant *polkit_grant, + PolKitGrantAddIOWatch func_add_io_watch, + PolKitGrantAddChildWatch func_add_child_watch, + PolKitGrantRemoveWatch func_remove_watch, + PolKitGrantType func_type, + PolKitGrantConversationPromptEchoOff func_prompt_echo_off, + PolKitGrantConversationPromptEchoOn func_prompt_echo_on, + PolKitGrantConversationErrorMessage func_error_message, + PolKitGrantConversationTextInfo func_text_info, + PolKitGrantOverrideGrantType func_override_grant_type, + PolKitGrantDone func_done, + void *user_data) +{ + g_return_if_fail (polkit_grant != NULL); + g_return_if_fail (func_add_io_watch != NULL); + g_return_if_fail (func_add_child_watch != NULL); + g_return_if_fail (func_remove_watch != NULL); + g_return_if_fail (func_type != NULL); + g_return_if_fail (func_prompt_echo_off != NULL); + g_return_if_fail (func_prompt_echo_on != NULL); + g_return_if_fail (func_error_message != NULL); + g_return_if_fail (func_text_info != NULL); + g_return_if_fail (func_override_grant_type != NULL); + polkit_grant->func_add_io_watch = func_add_io_watch; + polkit_grant->func_add_child_watch = func_add_child_watch; + polkit_grant->func_remove_watch = func_remove_watch; + polkit_grant->func_type = func_type; + polkit_grant->func_prompt_echo_off = func_prompt_echo_off; + polkit_grant->func_prompt_echo_on = func_prompt_echo_on; + polkit_grant->func_error_message = func_error_message; + polkit_grant->func_text_info = func_text_info; + polkit_grant->func_override_grant_type = func_override_grant_type; + polkit_grant->func_done = func_done; + polkit_grant->user_data = user_data; +} + + +/** + * libpolkit_grant_child_func: + * @polkit_grant: the object + * @pid: pid of the child + * @exit_code: exit code of the child + * + * Method that the application must call when a child process + * registered with the supplied function of type + * #PolKitGrantAddChildWatch terminates. + **/ +void +libpolkit_grant_child_func (PolKitGrant *polkit_grant, pid_t pid, int exit_code) +{ + g_return_if_fail (polkit_grant != NULL); + g_return_if_fail (polkit_grant->auth_in_progress); + + polkit_grant->success = (exit_code == 0); + polkit_grant->func_done (polkit_grant, polkit_grant->success, polkit_grant->user_data); +} + + +/** + * libpolkit_grant_io_func: + * @polkit_grant: the object + * @fd: the file descriptor passed to the supplied function of type #PolKitGrantAddIOWatch. + * + * Method that the application must call when there is data to read + * from a file descriptor registered with the supplied function of + * type #PolKitGrantAddIOWatch. + **/ +void +libpolkit_grant_io_func (PolKitGrant *polkit_grant, int fd) +{ + char *line = NULL; + size_t line_len = 0; + char *id; + size_t id_len; + char *response; + + g_return_if_fail (polkit_grant != NULL); + g_return_if_fail (polkit_grant->auth_in_progress); + + while (getline (&line, &line_len, polkit_grant->child_stdout_f) != -1) { + if (strlen (line) > 0 && + line[strlen (line) - 1] == '\n') + line[strlen (line) - 1] = '\0'; + + //printf ("from child '%s'\n", line); + + response = NULL; + + id = "PAM_PROMPT_ECHO_OFF "; + if (g_str_has_prefix (line, id)) { + id_len = strlen (id); + response = polkit_grant->func_prompt_echo_off (polkit_grant, + line + id_len, + polkit_grant->user_data); + goto processed; + } + + id = "PAM_PROMPT_ECHO_ON "; + if (g_str_has_prefix (line, id)) { + id_len = strlen (id); + response = polkit_grant->func_prompt_echo_on (polkit_grant, + line + id_len, + polkit_grant->user_data); + goto processed; + } + + id = "PAM_ERROR_MSG "; + if (g_str_has_prefix (line, id)) { + id_len = strlen (id); + polkit_grant->func_error_message (polkit_grant, + line + id_len, + polkit_grant->user_data); + goto processed; + } + + id = "PAM_TEXT_INFO "; + if (g_str_has_prefix (line, id)) { + id_len = strlen (id); + polkit_grant->func_text_info (polkit_grant, + line + id_len, + polkit_grant->user_data); + goto processed; + } + + id = "POLKIT_GRANT_HELPER_TELL_TYPE "; + if (g_str_has_prefix (line, id)) { + PolKitResult result; + id_len = strlen (id); + if (!libpolkit_result_from_string_representation (line + id_len, &result)) { + /* TODO: danger will robinson */ + } + polkit_grant->func_type (polkit_grant, + result, + polkit_grant->user_data); + goto processed; + } + + id = "POLKIT_GRANT_HELPER_ASK_OVERRIDE_GRANT_TYPE "; + if (g_str_has_prefix (line, id)) { + PolKitResult override; + PolKitResult result; + id_len = strlen (id); + if (!libpolkit_result_from_string_representation (line + id_len, &result)) { + /* TODO: danger will robinson */ + } + override = polkit_grant->func_override_grant_type (polkit_grant, + result, + polkit_grant->user_data); + response = g_strdup (libpolkit_result_to_string_representation (override)); + goto processed; + } + + processed: + if (response != NULL) { + /* add a newline if there isn't one already... */ + if (response[strlen (response) - 1] != '\n') { + char *old = response; + response = g_strdup_printf ("%s\n", response); + g_free (old); + } + write (polkit_grant->child_stdin, response, strlen (response)); + free (response); + } + } + + if (line != NULL) + free (line); +} + +/** + * libpolkit_grant_cancel_auth: + * @polkit_grant: the object + * + * Cancel an authentication in progress + **/ +void +libpolkit_grant_cancel_auth (PolKitGrant *polkit_grant) +{ + GPid pid; + g_return_if_fail (polkit_grant != NULL); + g_return_if_fail (polkit_grant->auth_in_progress); + + pid = polkit_grant->child_pid; + polkit_grant->child_pid = 0; + kill (pid, SIGTERM); + polkit_grant->func_done (polkit_grant, FALSE, polkit_grant->user_data); +} + +/** + * libpolkit_grant_initiate_auth: + * @polkit_grant: the object + * @action: Action requested by caller + * @resource: Resource in question + * @caller: Caller in question + * + * Initiate authentication to obtain the privilege for the given + * @caller to perform the specified @action on the given + * @resource. The caller of this method must have setup callback + * functions using the method libpolkit_grant_set_functions() prior to + * calling this method. + * + * Implementation-wise, this class uses a secure (e.g. as in that it + * checks all information and fundamenally don't trust the caller; + * e.g. the #PolKitGrant class) setgid helper that does all the heavy + * lifting. + * + * The caller of this method must iterate the mainloop context in + * order for authentication to make progress. + * + * Returns: #TRUE only if authentication have been initiated. + **/ +polkit_bool_t +libpolkit_grant_initiate_auth (PolKitGrant *polkit_grant, + PolKitAction *action, + PolKitResource *resource, + PolKitCaller *caller) +{ + char *dbus_name; + char *action_id; + char *resource_type; + char *resource_id; + GError *g_error; + const char *helper_argv[6]; + + g_return_val_if_fail (polkit_grant != NULL, FALSE); + /* check that callback functions have been properly set up */ + g_return_val_if_fail (polkit_grant->func_done != NULL, FALSE); + + if (!libpolkit_caller_get_dbus_name (caller, &dbus_name)) + goto error; + + if (!libpolkit_action_get_action_id (action, &action_id)) + goto error; + + if (!libpolkit_resource_get_resource_type (resource, &resource_type)) + goto error; + + if (!libpolkit_resource_get_resource_id (resource, &resource_id)) + goto error; + + /* TODO: verify incoming args */ + + //helper_argv[0] = "/home/davidz/Hacking/PolicyKit/libpolkit-grant/.libs/polkit-grant-helper"; + helper_argv[0] = PACKAGE_LIBEXEC_DIR "/polkit-grant-helper"; + helper_argv[1] = dbus_name; + helper_argv[2] = action_id; + helper_argv[3] = resource_type; + helper_argv[4] = resource_id; + helper_argv[5] = NULL; + + polkit_grant->child_stdin = -1; + polkit_grant->child_stdout = -1; + + g_error = NULL; + if (!g_spawn_async_with_pipes (NULL, + (char **) helper_argv, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD | + 0,//G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + &polkit_grant->child_pid, + &polkit_grant->child_stdin, + &polkit_grant->child_stdout, + NULL, + &g_error)) { + fprintf (stderr, "Cannot spawn helper: %s.\n", g_error->message); + g_error_free (g_error); + goto error; + } + + polkit_grant->child_watch_id = polkit_grant->func_add_child_watch (polkit_grant, polkit_grant->child_pid); + if (polkit_grant->child_watch_id == 0) + goto error; + + polkit_grant->io_watch_id = polkit_grant->func_add_io_watch (polkit_grant, polkit_grant->child_stdout); + if (polkit_grant->io_watch_id == 0) + goto error; + + /* so we can use getline... */ + polkit_grant->child_stdout_f = fdopen (polkit_grant->child_stdout, "r"); + if (polkit_grant->child_stdout_f == NULL) + goto error; + + polkit_grant->success = FALSE; + + polkit_grant->auth_in_progress = TRUE; + + return TRUE; +error: + return FALSE; +} diff --git a/libpolkit-grant/libpolkit-grant.h b/libpolkit-grant/libpolkit-grant.h new file mode 100644 index 0000000..0ba8925 --- /dev/null +++ b/libpolkit-grant/libpolkit-grant.h @@ -0,0 +1,344 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-grant.h : library for obtaining privileges + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifndef LIBPOLKIT_GRANT_H +#define LIBPOLKIT_GRANT_H + +#include + +struct PolKitGrant; +typedef struct PolKitGrant PolKitGrant; + +/** + * PolKitGrantType: + * @polkit_grant: the grant object + * @grant_type: the current type of what privilege to obtain + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that describes to what extent the + * privilege can be obtained; e.g. whether the user can keep it + * (e.g. forever, for the session or not keep it at all). + * + * See also #PolKitGrantOverrideGrantType for discussion on the type + * of user interfaces one should put up depending on the value of + * @grant_type. + **/ +typedef void (*PolKitGrantType) (PolKitGrant *polkit_grant, + PolKitResult grant_type, + void *user_data); + +/** + * PolKitGrantConversationPromptEchoOff: + * @polkit_grant: the grant object + * @prompt: prompt passed by the authentication layer; do not free this string + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that is invoked when the authentication + * layer needs to ask the user a secret and the UI should NOT echo what + * the user types on the screen. + * + * Returns: the answer obtained from the user; must be allocated with + * malloc(3) and will be freed by the #PolKitGrant class. + **/ +typedef char* (*PolKitGrantConversationPromptEchoOff) (PolKitGrant *polkit_grant, + const char *prompt, + void *user_data); + +/** + * PolKitGrantConversationPromptEchoOn: + * @polkit_grant: the grant object + * @prompt: prompt passed by the authentication layer; do not free this string + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that is invoked when the authentication + * layer needs to ask the user a secret and the UI should echo what + * the user types on the screen. + * + * Returns: the answer obtained from the user; must be allocated with + * malloc(3) and will be freed by the #PolKitGrant class. + **/ +typedef char* (*PolKitGrantConversationPromptEchoOn) (PolKitGrant *polkit_grant, + const char *prompt, + void *user_data); + +/** + * PolKitGrantConversationErrorMessage: + * @polkit_grant: the grant object + * @error_message: error message passed by the authentication layer; do not free this string + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that is invoked when the authentication + * layer produces an error message that should be displayed in the UI. + **/ +typedef void (*PolKitGrantConversationErrorMessage) (PolKitGrant *polkit_grant, + const char *error_message, + void *user_data); + +/** + * PolKitGrantConversationTextInfo: + * @polkit_grant: the grant object + * @text_info: information passed by the authentication layer; do not free this string + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that is invoked when the authentication + * layer produces an informational message that should be displayed in + * the UI. + **/ +typedef void (*PolKitGrantConversationTextInfo) (PolKitGrant *polkit_grant, + const char *text_info, + void *user_data); + +/** + * PolKitGrantOverrideGrantType: + * @polkit_grant: the grant object + * @grant_type: the current type of what privilege to obtain; this is + * the same value as passed to the callback of type #PolKitGrantType. + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * Type for callback function that enables the UI to request a lesser + * privilege than is obtainable. This callback is invoked when the + * user have successfully authenticated but before the privilege is + * granted. + * + * Basically, this callback enables a program to provide an user + * interface like this: + * + * + * +------------------------------------------------------------+ + * | You need to authenticate to access the volume 'Frobnicator | + * | Adventures Vol 2' | + * | | + * | Password: [_________________] | + * | | + * [ [x] Remember this decision | + * | [ ] for this session | + * | [*] for this and future sessions | + * | | + * | [Cancel] [Authenticate] | + * +------------------------------------------------------------+ + * + * + * This dialog assumes that @grant_type passed was + * #LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS. By ticking the + * check boxes in the dialog, the user can override this to either + * #LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION or + * #LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH. Thus, the user can + * voluntarily choose to obtain a lesser privilege. + * + * Another example, would be that the @grant_type passed was + * #LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION. Then the dialog + * should look like this: + * + * + * +------------------------------------------------------------+ + * | You need to authenticate to access the volume 'Frobnicator | + * | Adventures Vol 2' | + * | | + * | Password: [_________________] | + * | | + * [ [x] Remember this decision for the rest of the session | + * | | + * | [Cancel] [Authenticate] | + * +------------------------------------------------------------+ + * + * + * Finally, if the @grant_type value passed is + * e.g. #LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH, there are no options to + * click.: + * + * + * +------------------------------------------------------------+ + * | You need to authenticate to access the volume 'Frobnicator | + * | Adventures Vol 2' | + * | | + * | Password: [_________________] | + * | | + * | [Cancel] [Authenticate] | + * +------------------------------------------------------------+ + * + * + * Of course, these examples also applies to + * #LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH and friends. + * + * Returns: the desired type of what privilege to obtain; note that it + * won't work asking for more privileges than what @grant_type + * specifies; the passed value is properly checked in the secure + * setgid granting helper mentioned in + * libpolkit_grant_initiate_auth(). + **/ +typedef PolKitResult (*PolKitGrantOverrideGrantType) (PolKitGrant *polkit_grant, + PolKitResult grant_type, + void *user_data); + +/** + * PolKitGrantDone: + * @polkit_grant: the grant object + * @gained_privilege: whether the privilege was obtained + * @user_data: user data pointed as passed into libpolkit_grant_set_functions() + * + * This function is called when the granting process ends; either if + * successful or if it was canceled using + * e.g. libpolkit_grant_cancel_auth(). + **/ +typedef void (*PolKitGrantDone) (PolKitGrant *polkit_grant, + polkit_bool_t gained_privilege, + void *user_data); + +/** + * PolKitGrantAddChildWatch: + * @polkit_grant: the grant object + * @pid: the child pid to watch + * + * Type for function supplied by the application to integrate a watch + * on a child process into the applications main loop. The + * application must call libpolkit_grant_child_func() when the + * child dies + * + * For glib mainloop, the function will typically look like this: + * + * + * static void + * child_watch_func (GPid pid, + * gint status, + * gpointer user_data) + * { + * PolKitGrant *polkit_grant = user_data; + * libpolkit_grant_child_func (polkit_grant, pid, WEXITSTATUS (status)); + * } + * + * static int + * add_child_watch (PolKitGrant *polkit_grant, pid_t pid) + * { + * return g_child_watch_add (pid, child_watch_func, polkit_grant); + * } + * + * + * Returns: 0 if the watch couldn't be set up; otherwise an unique + * identifier for the watch. + **/ +typedef int (*PolKitGrantAddChildWatch) (PolKitGrant *polkit_grant, + pid_t pid); + +/** + * PolKitGrantAddIOWatch: + * @polkit_grant: the grant object + * @fd: the file descriptor to watch + * + * Type for function supplied by the application to integrate a watch + * on a file descriptor into the applications main loop. The + * application must call libpolkit_grant_io_func() when there is data + * to read from the file descriptor. + * + * For glib mainloop, the function will typically look like this: + * + * + * static gboolean + * io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) + * { + * int fd; + * PolKitGrant *polkit_grant = user_data; + * fd = g_io_channel_unix_get_fd (channel); + * libpolkit_grant_io_func (polkit_grant, fd); + * return TRUE; + * } + * + * static int + * add_io_watch (PolKitGrant *polkit_grant, int fd) + * { + * guint id = 0; + * GIOChannel *channel; + * channel = g_io_channel_unix_new (fd); + * if (channel == NULL) + * goto out; + * id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, polkit_grant); + * if (id == 0) { + * g_io_channel_unref (channel); + * goto out; + * } + * g_io_channel_unref (channel); + * out: + * return id; + * } + * + * + * Returns: 0 if the watch couldn't be set up; otherwise an unique + * identifier for the watch. + **/ +typedef int (*PolKitGrantAddIOWatch) (PolKitGrant *polkit_grant, + int fd); + +/** + * PolKitGrantRemoveWatch: + * @polkit_grant: the grant object + * @watch_id: the id obtained from using the supplied function + * of type #PolKitGrantAddIOWatch or #PolKitGrantAddChildWatch. + * + * Type for function supplied by the application to remove a watch set + * up via the supplied function of type #PolKitGrantAddIOWatch or type + * #PolKitGrantAddChildWatch. + * + * For glib mainloop, the function will typically look like this: + * + * + * static void + * remove_watch (PolKitGrant *polkit_auth, int watch_id) + * { + * g_source_remove (watch_id); + * } + * + * + **/ +typedef void (*PolKitGrantRemoveWatch) (PolKitGrant *polkit_grant, + int watch_id); + +PolKitGrant *libpolkit_grant_new (void); +PolKitGrant *libpolkit_grant_ref (PolKitGrant *polkit_grant); +void libpolkit_grant_unref (PolKitGrant *polkit_grant); +void libpolkit_grant_set_functions (PolKitGrant *polkit_grant, + PolKitGrantAddIOWatch func_add_io_watch, + PolKitGrantAddChildWatch func_add_child_watch, + PolKitGrantRemoveWatch func_remove_watch, + PolKitGrantType func_type, + PolKitGrantConversationPromptEchoOff func_prompt_echo_off, + PolKitGrantConversationPromptEchoOn func_prompt_echo_on, + PolKitGrantConversationErrorMessage func_error_message, + PolKitGrantConversationTextInfo func_text_info, + PolKitGrantOverrideGrantType func_override_grant_type, + PolKitGrantDone func_done, + void *user_data); +polkit_bool_t libpolkit_grant_initiate_auth (PolKitGrant *polkit_grant, + PolKitAction *action, + PolKitResource *resource, + PolKitCaller *caller); + +void libpolkit_grant_cancel_auth (PolKitGrant *polkit_grant); + +void libpolkit_grant_io_func (PolKitGrant *polkit_grant, int fd); +void libpolkit_grant_child_func (PolKitGrant *polkit_grant, pid_t pid, int exit_code); + + +#endif /* LIBPOLKIT_GRANT_H */ + + diff --git a/libpolkit-grant/polkit-grant-helper.c b/libpolkit-grant/polkit-grant-helper.c new file mode 100644 index 0000000..cd48810 --- /dev/null +++ b/libpolkit-grant/polkit-grant-helper.c @@ -0,0 +1,514 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-grant-helper.c : setgid grant helper for PolicyKit + * + * 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 + * + **************************************************************************/ + +/* TODO: FIXME: XXX: this code needs security review before it can be released! */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static int +conversation_function (int n, + const struct pam_message **msg, + struct pam_response **resp, + void *data) +{ + struct pam_response *aresp; + char buf[PAM_MAX_RESP_SIZE]; + int i; + + data = data; + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return PAM_CONV_ERR; + + if ((aresp = calloc(n, sizeof *aresp)) == NULL) + return PAM_BUF_ERR; + + for (i = 0; i < n; ++i) { + aresp[i].resp_retcode = 0; + aresp[i].resp = NULL; + switch (msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + fprintf (stdout, "PAM_PROMPT_ECHO_OFF "); + goto conv1; + case PAM_PROMPT_ECHO_ON: + fprintf (stdout, "PAM_PROMPT_ECHO_ON "); + conv1: + fputs (msg[i]->msg, stdout); + if (strlen (msg[i]->msg) > 0 && + msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') + fputc ('\n', stdout); + fflush (stdout); + + if (fgets (buf, sizeof buf, stdin) == NULL) + goto error; + if (strlen (buf) > 0 && + buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + + aresp[i].resp = strdup (buf); + if (aresp[i].resp == NULL) + goto error; + break; + + case PAM_ERROR_MSG: + fprintf (stdout, "PAM_ERROR_MSG "); + goto conv2; + + case PAM_TEXT_INFO: + fprintf (stdout, "PAM_TEXT_INFO "); + conv2: + fputs(msg[i]->msg, stdout); + if (strlen(msg[i]->msg) > 0 && + msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') + fputc ('\n', stdout); + + fflush (stdout); + break; + default: + goto error; + } + } + *resp = aresp; + return PAM_SUCCESS; + +error: + for (i = 0; i < n; ++i) { + if (aresp[i].resp != NULL) { + memset (aresp[i].resp, 0, strlen(aresp[i].resp)); + free (aresp[i].resp); + } + } + memset (aresp, 0, n * sizeof *aresp); + *resp = NULL; + return PAM_CONV_ERR; +} + +static polkit_bool_t +do_auth (const char *user_to_auth) +{ + struct pam_conv pam_conversation; + pam_handle_t *pam_h; + const void *authed_user; + int rc; + + pam_conversation.conv = conversation_function; + pam_conversation.appdata_ptr = NULL; + + /* start the pam stack */ + rc = pam_start ("polkit", + user_to_auth, + &pam_conversation, + &pam_h); + if (rc != PAM_SUCCESS) { + fprintf (stderr, "pam_start failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* is user really user? */ + rc = pam_authenticate (pam_h, 0); + if (rc != PAM_SUCCESS) { + fprintf (stderr, "pam_authenticated failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* permitted access? */ + rc = pam_acct_mgmt (pam_h, 0); + if (rc != PAM_SUCCESS) { + fprintf (stderr, "pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* did we auth the right user? */ + rc = pam_get_item (pam_h, PAM_USER, &authed_user); + if (rc != PAM_SUCCESS) { + fprintf (stderr, "pam_get_item failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + if (strcmp (authed_user, user_to_auth) != 0) { + fprintf (stderr, "Tried to auth user '%s' but we got auth for user '%s' instead", + user_to_auth, (const char *) authed_user); + goto error; + } + + return TRUE; + /* TODO: we should probably clean up */ +error: + return FALSE; +} + +static polkit_bool_t +verify_with_polkit (const char *dbus_name, + const char *action_name, + const char *resource_type, + const char *resource_name, + PolKitResult *result, + char **out_session_objpath) +{ + PolKitCaller *caller; + PolKitSession *session; + char *str; + DBusConnection *bus; + DBusError error; + PolKitContext *pol_ctx; + PolKitAction *action; + PolKitResource *resource; + + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + fprintf (stderr, "cannot connect to system bus: %s: %s\n", error.name, error.message); + dbus_error_free (&error); + goto out; + } + + action = libpolkit_action_new (); + libpolkit_action_set_action_id (action, action_name); + + if (resource_type != NULL && resource_name != NULL) { + resource = libpolkit_resource_new (); + libpolkit_resource_set_resource_type (resource, resource_type); + libpolkit_resource_set_resource_id (resource, resource_name); + } else { + resource = NULL; + } + + caller = libpolkit_caller_new_from_dbus_name (bus, dbus_name, &error); + if (caller == NULL) { + fprintf (stderr, "cannot get caller from dbus name\n"); + goto out; + } + + if (!libpolkit_caller_get_ck_session (caller, &session)) { + fprintf (stderr, "caller is not in a session\n"); + goto out; + } + if (!libpolkit_session_get_ck_objref (session, &str)) { + fprintf (stderr, "cannot get session ck objpath\n"); + goto out; + } + *out_session_objpath = g_strdup (str); + if (*out_session_objpath == NULL) + goto out; + + //libpolkit_caller_debug (caller); + + pol_ctx = libpolkit_context_new (); + if (!libpolkit_context_init (pol_ctx, NULL)) { + fprintf (stderr, "cannot init polkit\n"); + goto out; + } + + *result = libpolkit_context_can_caller_access_resource (pol_ctx, action, resource, caller); + + if (*result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH && + *result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION && + *result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS && + *result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH && + *result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION && + *result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) { + fprintf (stderr, "given auth type is bogus\n"); + goto out; + } + + return TRUE; + /* TODO: we should probably clean up */ +out: + return FALSE; +} + +static polkit_bool_t +get_and_validate_override_details (PolKitResult *result) +{ + char buf[256]; + PolKitResult desired_result; + + if (fgets (buf, sizeof buf, stdin) == NULL) + goto error; + if (strlen (buf) > 0 && + buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + + fprintf (stderr, "User said '%s'\n", buf); + + if (!libpolkit_result_from_string_representation (buf, &desired_result)) + goto error; + + fprintf (stderr, "Testing for voluntarily downgrade from '%s' to '%s'\n", + libpolkit_result_to_string_representation (*result), + libpolkit_result_to_string_representation (desired_result)); + + /* See the huge comment in main() below... + * + * it comes down to this... users can only choose a more restricted granting type... + * + */ + switch (*result) { + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH) + goto error; + break; + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION) + goto error; + break; + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS) + goto error; + break; + + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH) + goto error; + break; + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION) + goto error; + break; + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: + if (desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION && + desired_result != LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) + goto error; + break; + + default: + /* we should never reach this */ + goto error; + } + + if (*result != desired_result) { + fprintf (stderr, "Voluntarily downgrading from '%s' to '%s'\n", + libpolkit_result_to_string_representation (*result), + libpolkit_result_to_string_representation (desired_result)); + } + + *result = desired_result; + + return TRUE; +error: + return FALSE; +} + +/* synopsis: /usr/libexec/polkit-grant-helper + * + * : unique name of caller on the system message bus to grant privilege to + * : the PolicyKit action + * : resource-type + * : resource-name + * + * PAM interaction happens via stdin/stdout. + * + * If auth fails, we exit with code 1. + * If input is not valid we exit with code 2. + * If any other error occur we exit with code 3 + * If privilege was grant, we exit code 0. + */ + +int +main (int argc, char *argv[]) +{ + int ret; + uid_t invoking_user_id; + const char *invoking_user_name; + const char *dbus_name; + const char *action_name; + const char *resource_type; + const char *resource_name; + PolKitResult result; + const char *user_to_auth; + char *session_objpath; + gid_t egid; + struct group *group; + struct passwd *pw; + + ret = 3; + + if (argc != 5) { + fprintf (stderr, "wrong use\n"); + goto out; + } + + /* check user */ + invoking_user_id = getuid (); + if (invoking_user_id == 0) { + fprintf (stderr, "it only makes sense to run polkit-grant-helper as non-root\n"); + goto out; + } + pw = getpwuid (invoking_user_id); + if (pw == NULL) { + fprintf (stderr, "cannot lookup passwd info for uid %d\n", invoking_user_id); + goto out; + } + invoking_user_name = strdup (pw->pw_name); + if (invoking_user_name == NULL) { + fprintf (stderr, "OOM allocating memory for invoking user name\n"); + goto out; + } + + fprintf (stderr, "invoking user '%s'\n", invoking_user_name); + + /* check group */ + egid = getegid (); + group = getgrgid (egid); + if (group == NULL) { + fprintf (stderr, "cannot lookup group info for gid %d\n", egid); + goto out; + } + if (strcmp (group->gr_name, POLKIT_GROUP) != 0) { + fprintf (stderr, "polkit-grant-helper needs to be setgid " POLKIT_GROUP "\n"); + goto out; + } + + fprintf (stderr, "Hello world %d %d %d %d!\n", getuid(), geteuid(), getgid(), getegid()); + + /* clear the entire environment to avoid attacks using with libraries honoring environment variables */ + if (clearenv () != 0) + goto out; + /* hmm; seems like some library (libdbus) don't like environ==NULL .. TODO: file bug */ + setenv ("PATH", "/bin:/usr/bin", 1); + + dbus_name = argv[1]; + action_name = argv[2]; + resource_type = argv[3]; + resource_name = argv[4]; + + fprintf (stderr, "dbus_name = %s\n", dbus_name); + fprintf (stderr, "action_name = %s\n", action_name); + fprintf (stderr, "resource_type = %s\n", resource_type); + fprintf (stderr, "resource_name = %s\n", resource_name); + + ret = 2; + + /* we don't trust the user one bit...so.. + * + * verify that the given thing to auth for really supports grant by auth in the requested way + */ + if (!verify_with_polkit (dbus_name, action_name, resource_type, resource_name, &result, &session_objpath)) + goto out; + + /* tell user about the grant details; e.g. whether it's auth_self_keep_always or auth_self etc. */ + fprintf (stdout, "POLKIT_GRANT_HELPER_TELL_TYPE %s\n", libpolkit_result_to_string_representation (result)); + fflush (stdout); + + /* figure out what user to auth */ + if (result == LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH || + result == LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION || + result == LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS) { + user_to_auth = "root"; + } else { + user_to_auth = invoking_user_name; + } + + /* OK, start auth! */ + if (!do_auth (user_to_auth)) + goto out; + + /* ask user if he want to slim down grant type... + * e.g. he might want to go from auth_self_keep_always to auth_self_keep_session.. + * + * See docs for the PolKitGrantOverrideGrantType callback type for use cases. + */ + fprintf (stdout, "POLKIT_GRANT_HELPER_ASK_OVERRIDE_GRANT_TYPE %s\n", + libpolkit_result_to_string_representation (result)); + fflush (stdout); + + if (!get_and_validate_override_details (&result)) + goto out; + + /* TODO: FIXME: XXX: this format of storing granted privileges needs be redone + * + * this concerns these two files + * - libpolkit-grant/polkit-grant-helper.c + * - modules/grant/polkit-module-grant.c + */ + + /* + * /var/lib/PolicyKit/uid___.grant + * uid__.grant + * + * /var/run/PolicyKit/session____.grant + * session___.grant + * dbus____.grant + */ + + char *grant_file; + const char *session_name; + char *resource_str_to_hash; + guint resource_hash; + session_name = g_basename (session_objpath); + resource_str_to_hash = g_strdup_printf ("%s:%s", resource_type, resource_name); + resource_hash = g_str_hash (resource_str_to_hash); + g_free (resource_str_to_hash); + + switch (result) { + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/dbus_%s_%d_%s_%u.grant", + dbus_name, invoking_user_id, action_name, resource_hash); + break; + + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/session_%s_%d_%s_%u.grant", + session_name, invoking_user_id, action_name, resource_hash); + break; + + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/uid_%d_%s_%u.grant", + invoking_user_id, action_name, resource_hash); + break; + default: + /* should never happen */ + goto out; + } + + umask (~0464); + fprintf (stderr, "file is '%s'\n", grant_file); + FILE *f = fopen (grant_file, "w"); + fclose (f); + + ret = 0; +out: + return ret; +} diff --git a/libpolkit.pc.in b/libpolkit.pc.in index 20a2f77..3f36d2d 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 dbus-1 +Requires: glib-2.0 Libs: -L${libdir} -lpolkit Cflags: -I${includedir}/PolicyKit diff --git a/libpolkit/Makefile.am b/libpolkit/Makefile.am index f0bb035..457f07a 100644 --- a/libpolkit/Makefile.am +++ b/libpolkit/Makefile.am @@ -10,7 +10,8 @@ INCLUDES = \ -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ - @GLIB_CFLAGS@ @DBUS_CFLAGS@ + -DPOLKIT_COMPILATION \ + @GLIB_CFLAGS@ lib_LTLIBRARIES=libpolkit.la @@ -18,6 +19,7 @@ libpolkitincludedir=$(includedir)/PolicyKit/libpolkit libpolkitinclude_HEADERS = \ libpolkit.h \ + libpolkit-types.h \ libpolkit-error.h \ libpolkit-result.h \ libpolkit-context.h \ @@ -34,6 +36,7 @@ libpolkitinclude_HEADERS = \ libpolkit_la_SOURCES = \ libpolkit.h \ + libpolkit-types.h \ libpolkit-error.h libpolkit-error.c \ libpolkit-result.h libpolkit-result.c \ libpolkit-context.h libpolkit-context.c \ @@ -47,9 +50,10 @@ libpolkit_la_SOURCES = \ libpolkit-policy-cache.h libpolkit-policy-cache.c \ libpolkit-policy-default.h libpolkit-policy-default.c \ libpolkit-debug.h libpolkit-debug.c \ + libpolkit-utils.h libpolkit-utils.c \ libpolkit-module.h libpolkit-module.c -libpolkit_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ -ldl +libpolkit_la_LIBADD = @GLIB_LIBS@ -ldl libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/libpolkit/libpolkit-action.c b/libpolkit/libpolkit-action.c index 19bd3dd..34ef594 100644 --- a/libpolkit/libpolkit-action.c +++ b/libpolkit/libpolkit-action.c @@ -39,6 +39,7 @@ #include #include "libpolkit-debug.h" #include "libpolkit-action.h" +#include "libpolkit-utils.h" /** * SECTION:libpolkit-action @@ -121,14 +122,18 @@ libpolkit_action_unref (PolKitAction *action) * @action_id: action identifier * * Set the action identifier + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_action_set_action_id (PolKitAction *action, const char *action_id) { - g_return_if_fail (action != NULL); + g_return_val_if_fail (action != NULL, FALSE); + g_return_val_if_fail (_pk_validate_identifier (action_id), FALSE); if (action->id != NULL) g_free (action->id); action->id = g_strdup (action_id); + return TRUE; } /** @@ -140,7 +145,7 @@ libpolkit_action_set_action_id (PolKitAction *action, const char *action_id) * * Returns: TRUE iff the value was returned. **/ -bool +polkit_bool_t libpolkit_action_get_action_id (PolKitAction *action, char **out_action_id) { g_return_val_if_fail (action != NULL, FALSE); @@ -237,3 +242,18 @@ libpolkit_action_param_foreach (PolKitAction *action, PolKitActionParamForeachFu g_hash_table_foreach (action->params, _hash_cb, &data); } +/** + * libpolkit_action_validate: + * @action: the object + * + * Validate the object + * + * Returns: #TRUE iff the object is valid. + **/ +polkit_bool_t +libpolkit_action_validate (PolKitAction *action) +{ + g_return_val_if_fail (action != NULL, FALSE); + g_return_val_if_fail (action->id != NULL, FALSE); + return TRUE; +} diff --git a/libpolkit/libpolkit-action.h b/libpolkit/libpolkit-action.h index 1f7b192..df4888f 100644 --- a/libpolkit/libpolkit-action.h +++ b/libpolkit/libpolkit-action.h @@ -23,10 +23,14 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_ACTION_H #define LIBPOLKIT_ACTION_H -#include +#include struct PolKitAction; typedef struct PolKitAction PolKitAction; @@ -48,14 +52,15 @@ typedef void (*PolKitActionParamForeachFunc) (PolKitAction *action, PolKitAction *libpolkit_action_new (void); PolKitAction *libpolkit_action_ref (PolKitAction *action); void libpolkit_action_unref (PolKitAction *action); -void libpolkit_action_set_action_id (PolKitAction *action, const char *action_id); -bool libpolkit_action_get_action_id (PolKitAction *action, char **out_action_id); +polkit_bool_t libpolkit_action_set_action_id (PolKitAction *action, const char *action_id); +polkit_bool_t libpolkit_action_get_action_id (PolKitAction *action, char **out_action_id); void libpolkit_action_set_param (PolKitAction *action, const char *key, const char *value); const char *libpolkit_action_get_param (PolKitAction *action, const char *key); void libpolkit_action_param_foreach (PolKitAction *action, PolKitActionParamForeachFunc cb, void *user_data); void libpolkit_action_debug (PolKitAction *action); +polkit_bool_t libpolkit_action_validate (PolKitAction *action); #endif /* LIBPOLKIT_ACTION_H */ diff --git a/libpolkit/libpolkit-caller.c b/libpolkit/libpolkit-caller.c index c029d41..c9808ae 100644 --- a/libpolkit/libpolkit-caller.c +++ b/libpolkit/libpolkit-caller.c @@ -46,6 +46,7 @@ #include #include "libpolkit-debug.h" #include "libpolkit-caller.h" +#include "libpolkit-utils.h" /** * PolKitCaller: @@ -57,7 +58,7 @@ struct PolKitCaller { int refcount; char *dbus_name; - pid_t uid; + uid_t uid; pid_t pid; char *selinux_context; PolKitSession *session; @@ -124,14 +125,18 @@ libpolkit_caller_unref (PolKitCaller *caller) * @dbus_name: unique system bus connection name * * Set the callers unique system bus connection name. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name) { - g_return_if_fail (caller != NULL); + g_return_val_if_fail (caller != NULL, FALSE); + g_return_val_if_fail (_pk_validate_unique_bus_name (dbus_name), FALSE); if (caller->dbus_name != NULL) g_free (caller->dbus_name); caller->dbus_name = g_strdup (dbus_name); + return TRUE; } /** @@ -140,12 +145,15 @@ libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name) * @uid: UNIX user id * * Set the callers UNIX user id. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid) { - g_return_if_fail (caller != NULL); + g_return_val_if_fail (caller != NULL, FALSE); caller->uid = uid; + return TRUE; } /** @@ -154,12 +162,15 @@ libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid) * @pid: UNIX process id * * Set the callers UNIX process id. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_caller_set_pid (PolKitCaller *caller, pid_t pid) { - g_return_if_fail (caller != NULL); + g_return_val_if_fail (caller != NULL, FALSE); caller->pid = pid; + return TRUE; } /** @@ -168,14 +179,20 @@ libpolkit_caller_set_pid (PolKitCaller *caller, pid_t pid) * @selinux_context: SELinux security context * * Set the callers SELinux security context. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_context) { - g_return_if_fail (caller != NULL); + g_return_val_if_fail (caller != NULL, FALSE); + /* TODO: probably should have a separate validation function for SELinux contexts */ + g_return_val_if_fail (_pk_validate_identifier (selinux_context), FALSE); + if (caller->selinux_context != NULL) g_free (caller->selinux_context); caller->selinux_context = g_strdup (selinux_context); + return TRUE; } /** @@ -186,14 +203,18 @@ libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_ * Set the callers session. The reference count on the given object * will be increased by one. If an existing session object was set * already, the reference count on that one will be decreased by one. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session) { - g_return_if_fail (caller != NULL); + g_return_val_if_fail (caller != NULL, FALSE); + g_return_val_if_fail (libpolkit_session_validate (session), FALSE); if (caller->session != NULL) libpolkit_session_unref (caller->session); caller->session = session != NULL ? libpolkit_session_ref (session) : NULL; + return TRUE; } /** @@ -205,7 +226,7 @@ libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name) { g_return_val_if_fail (caller != NULL, FALSE); @@ -223,7 +244,7 @@ libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid) { g_return_val_if_fail (caller != NULL, FALSE); @@ -241,7 +262,7 @@ libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid) { g_return_val_if_fail (caller != NULL, FALSE); @@ -260,7 +281,7 @@ libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_context) { g_return_val_if_fail (caller != NULL, FALSE); @@ -279,7 +300,7 @@ libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_c * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_session) { g_return_val_if_fail (caller != NULL, FALSE); @@ -289,154 +310,6 @@ libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_sessi } /** - * 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: - _pk_debug ("uid %d", uid); - _pk_debug ("pid %d", pid); - _pk_debug ("selinux context '%s'", selinux_context != NULL ? selinux_context : "(not set)"); - _pk_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; -} - -/** * libpolkit_caller_debug: * @caller: the object * @@ -451,3 +324,22 @@ libpolkit_caller_debug (PolKitCaller *caller) if (caller->session != NULL) libpolkit_session_debug (caller->session); } + + +/** + * libpolkit_caller_validate: + * @caller: the object + * + * Validate the object + * + * Returns: #TRUE iff the object is valid. + **/ +polkit_bool_t +libpolkit_caller_validate (PolKitCaller *caller) +{ + g_return_val_if_fail (caller != NULL, FALSE); + g_return_val_if_fail (caller->pid > 0, FALSE); + g_return_val_if_fail (caller->dbus_name != NULL, FALSE); + /* NOTE TODO FIXME: remove need to have a dbus name set */ + return TRUE; +} diff --git a/libpolkit/libpolkit-caller.h b/libpolkit/libpolkit-caller.h index 2c9d93e..bb91f6e 100644 --- a/libpolkit/libpolkit-caller.h +++ b/libpolkit/libpolkit-caller.h @@ -23,35 +23,35 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_CALLER_H #define LIBPOLKIT_CALLER_H -#include -#include -#include - +#include #include +#include struct PolKitCaller; typedef struct PolKitCaller PolKitCaller; PolKitCaller *libpolkit_caller_new (void); -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); -bool libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name); -bool libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid); -bool libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid); -bool libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_context); -bool libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_session); +polkit_bool_t libpolkit_caller_set_dbus_name (PolKitCaller *caller, const char *dbus_name); +polkit_bool_t libpolkit_caller_set_uid (PolKitCaller *caller, uid_t uid); +polkit_bool_t libpolkit_caller_set_pid (PolKitCaller *caller, pid_t pid); +polkit_bool_t libpolkit_caller_set_selinux_context (PolKitCaller *caller, const char *selinux_context); +polkit_bool_t libpolkit_caller_set_ck_session (PolKitCaller *caller, PolKitSession *session); +polkit_bool_t libpolkit_caller_get_dbus_name (PolKitCaller *caller, char **out_dbus_name); +polkit_bool_t libpolkit_caller_get_uid (PolKitCaller *caller, uid_t *out_uid); +polkit_bool_t libpolkit_caller_get_pid (PolKitCaller *caller, pid_t *out_pid); +polkit_bool_t libpolkit_caller_get_selinux_context (PolKitCaller *caller, char **out_selinux_context); +polkit_bool_t libpolkit_caller_get_ck_session (PolKitCaller *caller, PolKitSession **out_session); void libpolkit_caller_debug (PolKitCaller *caller); +polkit_bool_t libpolkit_caller_validate (PolKitCaller *caller); #endif /* LIBPOLKIT_H */ - - diff --git a/libpolkit/libpolkit-context.c b/libpolkit/libpolkit-context.c index 61a3599..49f70f4 100644 --- a/libpolkit/libpolkit-context.c +++ b/libpolkit/libpolkit-context.c @@ -94,7 +94,7 @@ libpolkit_context_new (void) return pk_context; } -static bool +static polkit_bool_t unload_modules (PolKitContext *pk_context) { GSList *i; @@ -109,11 +109,11 @@ unload_modules (PolKitContext *pk_context) return TRUE; } -static bool +static polkit_bool_t load_modules (PolKitContext *pk_context, PolKitError **error) { const char *config_file; - bool ret; + polkit_bool_t ret; char *buf; char *end; char line[256]; @@ -272,7 +272,7 @@ _policy_dir_events (PolKitContext *pk_context, * * Returns: #FALSE if @error was set, otherwise #TRUE **/ -bool +polkit_bool_t libpolkit_context_init (PolKitContext *pk_context, PolKitError **error) { const char *dirname; @@ -508,7 +508,7 @@ libpolkit_context_is_resource_associated_with_seat (PolKitContext *pk_context, */ PolKitResult libpolkit_context_can_session_access_resource (PolKitContext *pk_context, - PolKitAction *action, + PolKitAction *action, PolKitResource *resource, PolKitSession *session) { @@ -520,13 +520,18 @@ libpolkit_context_can_session_access_resource (PolKitContext *pk_context, current_result = LIBPOLKIT_RESULT_NO; + /* resource may actually by NULL */ + if (action == NULL || session == NULL) + goto out; + cache = libpolkit_context_get_policy_cache (pk_context); if (cache == NULL) goto out; _pk_debug ("entering libpolkit_can_session_access_resource()"); libpolkit_action_debug (action); - libpolkit_resource_debug (resource); + if (resource != NULL) + libpolkit_resource_debug (resource); libpolkit_session_debug (session); pfe = libpolkit_policy_cache_get_entry (cache, action); @@ -629,7 +634,7 @@ out: */ PolKitResult libpolkit_context_can_caller_access_resource (PolKitContext *pk_context, - PolKitAction *action, + PolKitAction *action, PolKitResource *resource, PolKitCaller *caller) { @@ -641,13 +646,18 @@ libpolkit_context_can_caller_access_resource (PolKitContext *pk_context, current_result = LIBPOLKIT_RESULT_NO; + /* resource may actually by NULL */ + if (action == NULL || caller == NULL) + goto out; + cache = libpolkit_context_get_policy_cache (pk_context); if (cache == NULL) goto out; _pk_debug ("entering libpolkit_can_caller_access_resource()"); libpolkit_action_debug (action); - libpolkit_resource_debug (resource); + if (resource != NULL) + libpolkit_resource_debug (resource); libpolkit_caller_debug (caller); pfe = libpolkit_policy_cache_get_entry (cache, action); diff --git a/libpolkit/libpolkit-context.h b/libpolkit/libpolkit-context.h index b16e598..cf0f2c4 100644 --- a/libpolkit/libpolkit-context.h +++ b/libpolkit/libpolkit-context.h @@ -23,10 +23,14 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_CONTEXT_H #define LIBPOLKIT_CONTEXT_H -#include +#include #include #include #include @@ -136,7 +140,7 @@ void libpolkit_context_set_config_changed (PolKitContext void libpolkit_context_set_file_monitor (PolKitContext *pk_context, PolKitContextFileMonitorAddWatch add_watch_func, PolKitContextFileMonitorRemoveWatch remove_watch_func); -bool libpolkit_context_init (PolKitContext *pk_context, +polkit_bool_t libpolkit_context_init (PolKitContext *pk_context, PolKitError **error); PolKitContext *libpolkit_context_ref (PolKitContext *pk_context); void libpolkit_context_unref (PolKitContext *pk_context); diff --git a/libpolkit/libpolkit-debug.c b/libpolkit/libpolkit-debug.c index 37a8fb2..d81b7e7 100644 --- a/libpolkit/libpolkit-debug.c +++ b/libpolkit/libpolkit-debug.c @@ -25,7 +25,7 @@ /** * SECTION:libpolkit-debug - * @short_description: Debug functions. + * @short_description: Internal debug functions for libpolkit. * * These functions are used for debug purposes **/ @@ -34,13 +34,13 @@ # include #endif -#include #include #include #include #include #include +#include "libpolkit-types.h" #include "libpolkit-debug.h" /** @@ -53,13 +53,13 @@ void _pk_debug (const char *format, ...) { va_list args; - static bool show_debug = false; - static bool init = false; + static polkit_bool_t show_debug = FALSE; + static polkit_bool_t init = FALSE; if (!init) { - init = true; + init = TRUE; if (getenv ("POLKIT_DEBUG") != NULL) { - show_debug = true; + show_debug = TRUE; } } diff --git a/libpolkit/libpolkit-error.c b/libpolkit/libpolkit-error.c index 1ca8c4e..e6cf33b 100644 --- a/libpolkit/libpolkit-error.c +++ b/libpolkit/libpolkit-error.c @@ -34,7 +34,6 @@ # include #endif -#include #include #include #include @@ -46,6 +45,7 @@ #include +#include "libpolkit-types.h" #include "libpolkit-error.h" /** @@ -55,7 +55,7 @@ **/ struct PolKitError { - bool is_static; + polkit_bool_t is_static; PolKitErrorCode error_code; char *error_message; }; @@ -127,7 +127,7 @@ polkit_error_set_error (PolKitError **error, PolKitErrorCode error_code, const c return; e = g_new0 (PolKitError, 1); - e->is_static = false; + e->is_static = FALSE; e->error_code = error_code; va_start (args, format); e->error_message = g_strdup_vprintf (format, args); diff --git a/libpolkit/libpolkit-error.h b/libpolkit/libpolkit-error.h index eaaf827..d5d5e8e 100644 --- a/libpolkit/libpolkit-error.h +++ b/libpolkit/libpolkit-error.h @@ -23,6 +23,10 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_ERROR_H #define LIBPOLKIT_ERROR_H diff --git a/libpolkit/libpolkit-module.c b/libpolkit/libpolkit-module.c index 505a0b7..7e1440f 100644 --- a/libpolkit/libpolkit-module.c +++ b/libpolkit/libpolkit-module.c @@ -64,7 +64,7 @@ struct PolKitModuleInterface PolKitModuleCanSessionAccessResource func_can_session_access_resource; PolKitModuleCanCallerAccessResource func_can_caller_access_resource; - bool builtin_have_action_regex; + polkit_bool_t builtin_have_action_regex; regex_t builtin_action_regex_compiled; GSList *builtin_users; @@ -109,13 +109,13 @@ _parse_builtin_remove_option (int *argc, char *argv[], int position) (*argc)--; } -static bool +static polkit_bool_t _parse_builtin (PolKitModuleInterface *mi, int *argc, char *argv[]) { int n; - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; for (n = 1; n < *argc; ) { if (g_str_has_prefix (argv[n], "action=")) { @@ -131,7 +131,7 @@ _parse_builtin (PolKitModuleInterface *mi, int *argc, char *argv[]) _pk_debug ("Regex '%s' didn't compile", regex); goto error; } - mi->builtin_have_action_regex = true; + mi->builtin_have_action_regex = TRUE; _pk_debug ("Compiled regex '%s' for option 'action=' OK", regex); @@ -165,7 +165,7 @@ _parse_builtin (PolKitModuleInterface *mi, int *argc, char *argv[]) } } - ret = true; + ret = TRUE; error: return ret; @@ -187,7 +187,7 @@ libpolkit_module_interface_load_module (const char *name, PolKitModuleControl mo { void *handle; PolKitModuleInterface *mi; - bool (*func) (PolKitModuleInterface *); + polkit_bool_t (*func) (PolKitModuleInterface *); mi = NULL; @@ -556,12 +556,12 @@ libpolkit_module_control_to_string_representation (PolKitModuleControl module_co * * Returns: TRUE if the textual representation was valid, otherwise FALSE **/ -bool +polkit_bool_t libpolkit_module_control_from_string_representation (const char *string, PolKitModuleControl *out_module_control) { int n; - g_return_val_if_fail (out_module_control != NULL, false); + g_return_val_if_fail (out_module_control != NULL, FALSE); for (n = 0; n < LIBPOLKIT_MODULE_CONTROL_N_CONTROLS; n++) { if (mapping[n].str == NULL) @@ -572,9 +572,9 @@ libpolkit_module_control_from_string_representation (const char *string, PolKitM } } - return false; + return FALSE; found: - return true; + return TRUE; } @@ -609,23 +609,23 @@ libpolkit_module_get_user_data (PolKitModuleInterface *module_interface) return module_interface->module_user_data; } -static bool +static polkit_bool_t _check_action (PolKitModuleInterface *module_interface, PolKitAction *action) { - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; if (module_interface->builtin_have_action_regex) { char *action_name; if (libpolkit_action_get_action_id (action, &action_name)) { if (regexec (&module_interface->builtin_action_regex_compiled, action_name, 0, NULL, 0) == 0) { - ret = true; + ret = TRUE; } } } else { - ret = true; + ret = TRUE; } return ret; @@ -633,7 +633,7 @@ _check_action (PolKitModuleInterface *module_interface, PolKitAction *action) /*----*/ -static bool +static polkit_bool_t _check_uid_in_list (GSList *list, uid_t given_uid) { GSList *i; @@ -641,36 +641,36 @@ _check_uid_in_list (GSList *list, uid_t given_uid) for (i = list; i != NULL; i = g_slist_next (i)) { uid_t uid = GPOINTER_TO_INT (i->data); if (given_uid == uid) - return true; + return TRUE; } - return false; + return FALSE; } -static bool +static polkit_bool_t _check_users_for_session (PolKitModuleInterface *module_interface, PolKitSession *session) { uid_t uid; GSList *list; if ((list = module_interface->builtin_users) == NULL) - return true; + return TRUE; if (session == NULL) - return false; + return FALSE; if (!libpolkit_session_get_uid (session, &uid)) - return false; + return FALSE; return _check_uid_in_list (list, uid); } -static bool +static polkit_bool_t _check_users_for_caller (PolKitModuleInterface *module_interface, PolKitCaller *caller) { uid_t uid; GSList *list; if ((list = module_interface->builtin_users) == NULL) - return true; + return TRUE; if (caller == NULL) - return false; + return FALSE; if (!libpolkit_caller_get_uid (caller, &uid)) - return false; + return FALSE; return _check_uid_in_list (list, uid); } @@ -688,15 +688,15 @@ _check_users_for_caller (PolKitModuleInterface *module_interface, PolKitCaller * * * Returns: TRUE if, and only if, the module is confined from handling the request **/ -bool +polkit_bool_t libpolkit_module_interface_check_builtin_confinement_for_session (PolKitModuleInterface *module_interface, PolKitContext *pk_context, PolKitAction *action, PolKitResource *resource, PolKitSession *session) { - bool ret; - ret = true; + polkit_bool_t ret; + ret = TRUE; g_return_val_if_fail (module_interface != NULL, ret); @@ -706,7 +706,7 @@ libpolkit_module_interface_check_builtin_confinement_for_session (PolKitModuleIn goto out; /* not confined */ - ret = false; + ret = FALSE; out: return ret; } @@ -724,15 +724,15 @@ out: * * Returns: TRUE if, and only if, the module is confined from handling the request **/ -bool +polkit_bool_t libpolkit_module_interface_check_builtin_confinement_for_caller (PolKitModuleInterface *module_interface, PolKitContext *pk_context, PolKitAction *action, PolKitResource *resource, PolKitCaller *caller) { - bool ret; - ret = true; + polkit_bool_t ret; + ret = TRUE; g_return_val_if_fail (module_interface != NULL, ret); @@ -742,7 +742,7 @@ libpolkit_module_interface_check_builtin_confinement_for_caller (PolKitModuleInt goto out; /* not confined */ - ret = false; + ret = FALSE; out: return ret; } diff --git a/libpolkit/libpolkit-module.h b/libpolkit/libpolkit-module.h index 7088491..bb4bbc9 100644 --- a/libpolkit/libpolkit-module.h +++ b/libpolkit/libpolkit-module.h @@ -23,10 +23,14 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_MODULE_H #define LIBPOLKIT_MODULE_H -#include +#include #include struct PolKitModuleInterface; @@ -42,9 +46,9 @@ typedef struct PolKitModuleInterface PolKitModuleInterface; * * Returns: Whether the module was initialized. **/ -typedef bool (*PolKitModuleInitialize) (PolKitModuleInterface *module_interface, - int argc, - char *argv[]); +typedef polkit_bool_t (*PolKitModuleInitialize) (PolKitModuleInterface *module_interface, + int argc, + char *argv[]); /** * PolKitModuleShutdown: @@ -176,7 +180,7 @@ typedef enum const char * libpolkit_module_control_to_string_representation (PolKitModuleControl module_control); -bool +polkit_bool_t libpolkit_module_control_from_string_representation (const char *string, PolKitModuleControl *out_module_control); PolKitModuleInterface *libpolkit_module_interface_load_module (const char *name, @@ -186,14 +190,14 @@ PolKitModuleInterface *libpolkit_module_interface_load_module (const char *name, PolKitModuleControl libpolkit_module_interface_get_control (PolKitModuleInterface *module_interface); -bool +polkit_bool_t libpolkit_module_interface_check_builtin_confinement_for_session (PolKitModuleInterface *module_interface, PolKitContext *pk_context, PolKitAction *action, PolKitResource *resource, PolKitSession *session); -bool +polkit_bool_t libpolkit_module_interface_check_builtin_confinement_for_caller (PolKitModuleInterface *module_interface, PolKitContext *pk_context, PolKitAction *action, diff --git a/libpolkit/libpolkit-policy-cache.h b/libpolkit/libpolkit-policy-cache.h index 92378a7..12cf00e 100644 --- a/libpolkit/libpolkit-policy-cache.h +++ b/libpolkit/libpolkit-policy-cache.h @@ -23,6 +23,10 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_POLICY_CACHE_H #define LIBPOLKIT_POLICY_CACHE_H diff --git a/libpolkit/libpolkit-policy-default.c b/libpolkit/libpolkit-policy-default.c index 852c3aa..1cba253 100644 --- a/libpolkit/libpolkit-policy-default.c +++ b/libpolkit/libpolkit-policy-default.c @@ -228,19 +228,18 @@ libpolkit_policy_default_debug (PolKitPolicyDefault *policy_default) **/ PolKitResult libpolkit_policy_default_can_session_access_resource (PolKitPolicyDefault *policy_default, - PolKitAction *action, - PolKitResource *resource, - PolKitSession *session) + PolKitAction *action, + PolKitResource *resource, + PolKitSession *session) { - bool is_local; - bool is_active; + polkit_bool_t is_local; + polkit_bool_t is_active; PolKitResult ret; ret = LIBPOLKIT_RESULT_NO; g_return_val_if_fail (policy_default != NULL, ret); g_return_val_if_fail (action != NULL, ret); - g_return_val_if_fail (resource != NULL, ret); g_return_val_if_fail (session != NULL, ret); if (!libpolkit_session_get_ck_is_local (session, &is_local)) @@ -280,12 +279,12 @@ out: **/ PolKitResult libpolkit_policy_default_can_caller_access_resource (PolKitPolicyDefault *policy_default, - PolKitAction *action, - PolKitResource *resource, - PolKitCaller *caller) + PolKitAction *action, + PolKitResource *resource, + PolKitCaller *caller) { - bool is_local; - bool is_active; + polkit_bool_t is_local; + polkit_bool_t is_active; PolKitSession *session; PolKitResult ret; @@ -293,7 +292,6 @@ libpolkit_policy_default_can_caller_access_resource (PolKitPolicyDefault *policy g_return_val_if_fail (policy_default != NULL, ret); g_return_val_if_fail (action != NULL, ret); - g_return_val_if_fail (resource != NULL, ret); g_return_val_if_fail (caller != NULL, ret); if (!libpolkit_caller_get_ck_session (caller, &session)) diff --git a/libpolkit/libpolkit-policy-default.h b/libpolkit/libpolkit-policy-default.h index 9daaee1..19cce21 100644 --- a/libpolkit/libpolkit-policy-default.h +++ b/libpolkit/libpolkit-policy-default.h @@ -23,6 +23,10 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_POLICY_DEFAULT_H #define LIBPOLKIT_POLICY_DEFAULT_H @@ -41,13 +45,13 @@ void libpolkit_policy_default_unref (PolKitPolicyDefault *pol void libpolkit_policy_default_debug (PolKitPolicyDefault *policy_default); PolKitResult libpolkit_policy_default_can_session_access_resource (PolKitPolicyDefault *policy_default, - PolKitAction *action, - PolKitResource *resource, - PolKitSession *session); + PolKitAction *action, + PolKitResource *resource, + PolKitSession *session); PolKitResult libpolkit_policy_default_can_caller_access_resource (PolKitPolicyDefault *policy_default, - PolKitAction *action, - PolKitResource *resource, - PolKitCaller *caller); + PolKitAction *action, + PolKitResource *resource, + PolKitCaller *caller); /* TODO: export knobs for "default policy" */ diff --git a/libpolkit/libpolkit-policy-file-entry.h b/libpolkit/libpolkit-policy-file-entry.h index 1d76f83..f9aeb01 100644 --- a/libpolkit/libpolkit-policy-file-entry.h +++ b/libpolkit/libpolkit-policy-file-entry.h @@ -23,6 +23,10 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_POLICY_FILE_ENTRY_H #define LIBPOLKIT_POLICY_FILE_ENTRY_H diff --git a/libpolkit/libpolkit-policy-file.h b/libpolkit/libpolkit-policy-file.h index b09f508..cdd9096 100644 --- a/libpolkit/libpolkit-policy-file.h +++ b/libpolkit/libpolkit-policy-file.h @@ -23,6 +23,10 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_POLICY_FILE_H #define LIBPOLKIT_POLICY_FILE_H diff --git a/libpolkit/libpolkit-resource.c b/libpolkit/libpolkit-resource.c index f401eb1..dd68b72 100644 --- a/libpolkit/libpolkit-resource.c +++ b/libpolkit/libpolkit-resource.c @@ -39,6 +39,7 @@ #include #include "libpolkit-debug.h" #include "libpolkit-resource.h" +#include "libpolkit-utils.h" /** * SECTION:libpolkit-resource @@ -122,15 +123,18 @@ libpolkit_resource_unref (PolKitResource *resource) * @resource_type: type of resource * * Set the type of the resource. TODO: link to wtf this is. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_resource_set_resource_type (PolKitResource *resource, const char *resource_type) { - g_return_if_fail (resource != NULL); - + g_return_val_if_fail (resource != NULL, FALSE); + g_return_val_if_fail (_pk_validate_identifier (resource_type), FALSE); if (resource->type != NULL) g_free (resource->type); resource->type = g_strdup (resource_type); + return TRUE; } /** @@ -139,15 +143,18 @@ libpolkit_resource_set_resource_type (PolKitResource *resource, const char *res * @resource_id: identifier of resource * * set the identifier of the resource. TODO: link to wtf this is. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_resource_set_resource_id (PolKitResource *resource, const char *resource_id) { - g_return_if_fail (resource != NULL); - + g_return_val_if_fail (resource != NULL, FALSE); + g_return_val_if_fail (_pk_validate_identifier (resource_id), FALSE); if (resource->id != NULL) g_free (resource->id); resource->id = g_strdup (resource_id); + return TRUE; } /** @@ -159,7 +166,7 @@ libpolkit_resource_set_resource_id (PolKitResource *resource, const char *resou * * Returns: TRUE iff the value was returned. **/ -bool +polkit_bool_t libpolkit_resource_get_resource_type (PolKitResource *resource, char **out_resource_type) { g_return_val_if_fail (resource != NULL, FALSE); @@ -181,7 +188,7 @@ libpolkit_resource_get_resource_type (PolKitResource *resource, char **out_resou * * Returns: TRUE iff the value was returned. **/ -bool +polkit_bool_t libpolkit_resource_get_resource_id (PolKitResource *resource, char **out_resource_id) { g_return_val_if_fail (resource != NULL, FALSE); @@ -206,3 +213,20 @@ libpolkit_resource_debug (PolKitResource *resource) g_return_if_fail (resource != NULL); _pk_debug ("PolKitResource: refcount=%d type=%s id=%s", resource->refcount, resource->type, resource->id); } + +/** + * libpolkit_resource_validate: + * @resource: the object + * + * Validate the object + * + * Returns: #TRUE iff the object is valid. + **/ +polkit_bool_t +libpolkit_resource_validate (PolKitResource *resource) +{ + g_return_val_if_fail (resource != NULL, FALSE); + g_return_val_if_fail (resource->type != NULL, FALSE); + g_return_val_if_fail (resource->id != NULL, FALSE); + return TRUE; +} diff --git a/libpolkit/libpolkit-resource.h b/libpolkit/libpolkit-resource.h index e050b86..427b6e7 100644 --- a/libpolkit/libpolkit-resource.h +++ b/libpolkit/libpolkit-resource.h @@ -23,10 +23,14 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_RESOURCE_H #define LIBPOLKIT_RESOURCE_H -#include +#include struct PolKitResource; typedef struct PolKitResource PolKitResource; @@ -34,13 +38,15 @@ typedef struct PolKitResource PolKitResource; PolKitResource *libpolkit_resource_new (void); PolKitResource *libpolkit_resource_ref (PolKitResource *resource); void libpolkit_resource_unref (PolKitResource *resource); -void libpolkit_resource_set_resource_type (PolKitResource *resource, const char *resource_type); -void libpolkit_resource_set_resource_id (PolKitResource *resource, const char *resource_id); -bool libpolkit_resource_get_resource_type (PolKitResource *resource, char **out_resource_type); -bool libpolkit_resource_get_resource_id (PolKitResource *resource, char **out_resource_id); +polkit_bool_t libpolkit_resource_set_resource_type (PolKitResource *resource, const char *resource_type); +polkit_bool_t libpolkit_resource_set_resource_id (PolKitResource *resource, const char *resource_id); +polkit_bool_t libpolkit_resource_get_resource_type (PolKitResource *resource, char **out_resource_type); +polkit_bool_t libpolkit_resource_get_resource_id (PolKitResource *resource, char **out_resource_id); void libpolkit_resource_debug (PolKitResource *resource); +polkit_bool_t libpolkit_resource_validate (PolKitResource *resource); + #endif /* LIBPOLKIT_RESOURCE_H */ diff --git a/libpolkit/libpolkit-result.c b/libpolkit/libpolkit-result.c index 393c96d..05d787e 100644 --- a/libpolkit/libpolkit-result.c +++ b/libpolkit/libpolkit-result.c @@ -94,7 +94,7 @@ libpolkit_result_to_string_representation (PolKitResult result) * * Returns: TRUE if the textual representation was valid, otherwise FALSE **/ -bool +polkit_bool_t libpolkit_result_from_string_representation (const char *string, PolKitResult *out_result) { int n; @@ -110,7 +110,7 @@ libpolkit_result_from_string_representation (const char *string, PolKitResult *o } } - return false; + return FALSE; found: - return true; + return TRUE; } diff --git a/libpolkit/libpolkit-result.h b/libpolkit/libpolkit-result.h index bb76b9b..74da794 100644 --- a/libpolkit/libpolkit-result.h +++ b/libpolkit/libpolkit-result.h @@ -23,10 +23,14 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_RESULT_H #define LIBPOLKIT_RESULT_H -#include +#include /** * PolKitResult: @@ -34,17 +38,17 @@ * @LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW: The caller of libpolkit is not sufficiently privilege to know the answer. * @LIBPOLKIT_RESULT_NO: Access denied. * @LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: Access denied, but authentication of the caller as - * root will grant access to only that caller. + * root will grant access to the resource... but the access isn't permanent * @LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: Access denied, but authentication of the caller as - * root will grant access for the remainder of the session the caller stems from. + * root will grant access to the resource for the remainder of the session * @LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: Access denied, but authentication of the caller as - * root will grant access to the user of the caller in the future. + * root will grant access to the resource in the future. * @LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: Access denied, but authentication of the caller as - * his user will grant access to only that caller. + * himself will grant access to the resource... but the access isn't permanent * @LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: Access denied, but authentication of the caller as - * his user will grant access for the remainder of the session the caller stems from. + * himself will grant access to the resource for the remainder of the session * @LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: Access denied, but authentication of the caller as - * his user will grant access to the user of the caller in the future. + * himself will grant access to the resource in the future. * @LIBPOLKIT_RESULT_YES: Access granted. * @LIBPOLKIT_RESULT_N_RESULTS: Number of result codes * @@ -58,12 +62,15 @@ typedef enum LIBPOLKIT_RESULT_UNKNOWN_ACTION, LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW, LIBPOLKIT_RESULT_NO, + LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH, LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION, LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS, + LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH, LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION, LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS, + LIBPOLKIT_RESULT_YES, LIBPOLKIT_RESULT_N_RESULTS } PolKitResult; @@ -71,7 +78,7 @@ typedef enum const char * libpolkit_result_to_string_representation (PolKitResult result); -bool +polkit_bool_t libpolkit_result_from_string_representation (const char *string, PolKitResult *out_result); #endif /* LIBPOLKIT_RESULT_H */ diff --git a/libpolkit/libpolkit-seat.c b/libpolkit/libpolkit-seat.c index 0af95dc..8a51991 100644 --- a/libpolkit/libpolkit-seat.c +++ b/libpolkit/libpolkit-seat.c @@ -39,6 +39,7 @@ #include #include "libpolkit-debug.h" #include "libpolkit-seat.h" +#include "libpolkit-utils.h" /** * SECTION:libpolkit-seat @@ -116,14 +117,18 @@ libpolkit_seat_unref (PolKitSeat *seat) * @ck_objref: the D-Bus object path to the ConsoleKit seat object * * Set the D-Bus object path to the ConsoleKit seat object. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char *ck_objref) { - g_return_if_fail (seat != NULL); + g_return_val_if_fail (seat != NULL, FALSE); + g_return_val_if_fail (_pk_validate_identifier (ck_objref), FALSE); if (seat->ck_objref != NULL) g_free (seat->ck_objref); seat->ck_objref = g_strdup (ck_objref); + return TRUE; } /** @@ -135,13 +140,13 @@ libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char *ck_objref) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_seat_get_ck_objref (PolKitSeat *seat, char **out_ck_objref) { - g_return_val_if_fail (seat != NULL, false); - g_return_val_if_fail (out_ck_objref != NULL, false); + g_return_val_if_fail (seat != NULL, FALSE); + g_return_val_if_fail (out_ck_objref != NULL, FALSE); *out_ck_objref = seat->ck_objref; - return true; + return TRUE; } /** @@ -156,3 +161,19 @@ libpolkit_seat_debug (PolKitSeat *seat) g_return_if_fail (seat != NULL); _pk_debug ("PolKitSeat: refcount=%d objpath=%s", seat->refcount, seat->ck_objref); } + +/** + * libpolkit_seat_validate: + * @seat: the object + * + * Validate the object + * + * Returns: #TRUE iff the object is valid. + **/ +polkit_bool_t +libpolkit_seat_validate (PolKitSeat *seat) +{ + g_return_val_if_fail (seat != NULL, FALSE); + g_return_val_if_fail (seat->ck_objref != NULL, FALSE); + return TRUE; +} diff --git a/libpolkit/libpolkit-seat.h b/libpolkit/libpolkit-seat.h index 046f9f6..7de9fe9 100644 --- a/libpolkit/libpolkit-seat.h +++ b/libpolkit/libpolkit-seat.h @@ -23,21 +23,26 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_SEAT_H #define LIBPOLKIT_SEAT_H -#include +#include struct PolKitSeat; typedef struct PolKitSeat PolKitSeat; -PolKitSeat *libpolkit_seat_new (void); -PolKitSeat *libpolkit_seat_ref (PolKitSeat *seat); -void libpolkit_seat_unref (PolKitSeat *seat); -void libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char *ck_objref); -bool libpolkit_seat_get_ck_objref (PolKitSeat *seat, char **out_ck_objref); +PolKitSeat *libpolkit_seat_new (void); +PolKitSeat *libpolkit_seat_ref (PolKitSeat *seat); +void libpolkit_seat_unref (PolKitSeat *seat); +polkit_bool_t libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char *ck_objref); +polkit_bool_t libpolkit_seat_get_ck_objref (PolKitSeat *seat, char **out_ck_objref); -void libpolkit_seat_debug (PolKitSeat *seat); +void libpolkit_seat_debug (PolKitSeat *seat); +polkit_bool_t libpolkit_seat_validate (PolKitSeat *seat); #endif /* LIBPOLKIT_SEAT_H */ diff --git a/libpolkit/libpolkit-session.c b/libpolkit/libpolkit-session.c index a5d0a9f..c93019c 100644 --- a/libpolkit/libpolkit-session.c +++ b/libpolkit/libpolkit-session.c @@ -39,7 +39,7 @@ #include #include "libpolkit-debug.h" #include "libpolkit-session.h" - +#include "libpolkit-utils.h" /** * SECTION:libpolkit-session @@ -60,8 +60,8 @@ struct PolKitSession uid_t uid; PolKitSeat *seat; char *ck_objref; - bool is_active; - bool is_local; + polkit_bool_t is_active; + polkit_bool_t is_local; char *remote_host; }; @@ -126,12 +126,15 @@ libpolkit_session_unref (PolKitSession *session) * @uid: UNIX user id * * Set the UNIX user id of the user owning the session. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_session_set_uid (PolKitSession *session, uid_t uid) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); session->uid = uid; + return TRUE; } /** @@ -140,14 +143,18 @@ libpolkit_session_set_uid (PolKitSession *session, uid_t uid) * @ck_objref: D-Bus object path * * Set the D-Bus object path to the ConsoleKit session object. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_session_set_ck_objref (PolKitSession *session, const char *ck_objref) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); + g_return_val_if_fail (_pk_validate_identifier (ck_objref), FALSE); if (session->ck_objref != NULL) g_free (session->ck_objref); session->ck_objref = g_strdup (ck_objref); + return TRUE; } /** @@ -156,12 +163,15 @@ libpolkit_session_set_ck_objref (PolKitSession *session, const char *ck_objref) * @is_active: whether ConsoleKit reports the session as active * * Set whether ConsoleKit regard the session as active. + * + * Returns: #TRUE only if the value validated and was set **/ -void -libpolkit_session_set_ck_is_active (PolKitSession *session, bool is_active) +polkit_bool_t +libpolkit_session_set_ck_is_active (PolKitSession *session, polkit_bool_t is_active) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); session->is_active = is_active; + return TRUE; } /** @@ -170,12 +180,15 @@ libpolkit_session_set_ck_is_active (PolKitSession *session, bool is_active) * @is_local: whether ConsoleKit reports the session as local * * Set whether ConsoleKit regard the session as local. + * + * Returns: #TRUE only if the value validated and was set **/ -void -libpolkit_session_set_ck_is_local (PolKitSession *session, bool is_local) +polkit_bool_t +libpolkit_session_set_ck_is_local (PolKitSession *session, polkit_bool_t is_local) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); session->is_local = is_local; + return TRUE; } /** @@ -186,14 +199,19 @@ libpolkit_session_set_ck_is_local (PolKitSession *session, bool is_local) * * Set the remote host/display that ConsoleKit reports the session to * occur at. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_session_set_ck_remote_host (PolKitSession *session, const char *remote_host) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); + /* TODO: FIXME: probably need to allow a lot more here */ + g_return_val_if_fail (_pk_validate_identifier (remote_host), FALSE); if (session->remote_host != NULL) g_free (session->remote_host); session->remote_host = g_strdup (remote_host); + return TRUE; } /** @@ -205,14 +223,18 @@ libpolkit_session_set_ck_remote_host (PolKitSession *session, const char *remote * the given object will be increased by one. If an existing seat * object was set already, the reference count on that one will be * decreased by one. + * + * Returns: #TRUE only if the value validated and was set **/ -void +polkit_bool_t libpolkit_session_set_seat (PolKitSession *session, PolKitSeat *seat) { - g_return_if_fail (session != NULL); + g_return_val_if_fail (session != NULL, FALSE); + g_return_val_if_fail (libpolkit_seat_validate (seat), FALSE); if (session->seat != NULL) libpolkit_seat_unref (session->seat); session->seat = seat != NULL ? libpolkit_seat_ref (seat) : NULL; + return TRUE; } /** @@ -224,7 +246,7 @@ libpolkit_session_set_seat (PolKitSession *session, PolKitSeat *seat) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_session_get_uid (PolKitSession *session, uid_t *out_uid) { g_return_val_if_fail (session != NULL, FALSE); @@ -242,7 +264,7 @@ libpolkit_session_get_uid (PolKitSession *session, uid_t *out_uid) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_session_get_ck_objref (PolKitSession *session, char **out_ck_objref) { g_return_val_if_fail (session != NULL, FALSE); @@ -260,8 +282,8 @@ libpolkit_session_get_ck_objref (PolKitSession *session, char **out_ck_objref) * * Returns: TRUE iff the value is returned **/ -bool -libpolkit_session_get_ck_is_active (PolKitSession *session, bool *out_is_active) +polkit_bool_t +libpolkit_session_get_ck_is_active (PolKitSession *session, polkit_bool_t *out_is_active) { g_return_val_if_fail (session != NULL, FALSE); g_return_val_if_fail (out_is_active != NULL, FALSE); @@ -278,8 +300,8 @@ libpolkit_session_get_ck_is_active (PolKitSession *session, bool *out_is_active) * * Returns: TRUE iff the value is returned **/ -bool -libpolkit_session_get_ck_is_local (PolKitSession *session, bool *out_is_local) +polkit_bool_t +libpolkit_session_get_ck_is_local (PolKitSession *session, polkit_bool_t *out_is_local) { g_return_val_if_fail (session != NULL, FALSE); g_return_val_if_fail (out_is_local != NULL, FALSE); @@ -298,7 +320,7 @@ libpolkit_session_get_ck_is_local (PolKitSession *session, bool *out_is_local) * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_session_get_ck_remote_host (PolKitSession *session, char **out_remote_host) { g_return_val_if_fail (session != NULL, FALSE); @@ -317,7 +339,7 @@ libpolkit_session_get_ck_remote_host (PolKitSession *session, char **out_remote_ * * Returns: TRUE iff the value is returned **/ -bool +polkit_bool_t libpolkit_session_get_seat (PolKitSession *session, PolKitSeat **out_seat) { g_return_val_if_fail (session != NULL, FALSE); @@ -327,245 +349,6 @@ libpolkit_session_get_seat (PolKitSession *session, PolKitSeat **out_seat) } /** - * 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; - bool is_active; - bool 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); - } - - _pk_debug ("is_active %d", is_active); - _pk_debug ("is_local %d", is_local); - _pk_debug ("uid %d", uid); - if (!is_local) { - _pk_debug ("remote host '%s'", remote_host); - } - _pk_debug ("ck seat '%s'", seat_path); - - session = libpolkit_session_new (); - libpolkit_session_set_ck_objref (session, objpath); - 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; -} - -/** * libpolkit_session_debug: * @session: the object * @@ -581,3 +364,31 @@ libpolkit_session_debug (PolKitSession *session) if (session->seat != NULL) libpolkit_seat_debug (session->seat); } + + +/** + * libpolkit_session_validate: + * @session: the object + * + * Validate the object + * + * Returns: #TRUE iff the object is valid. + **/ +polkit_bool_t +libpolkit_session_validate (PolKitSession *session) +{ + polkit_bool_t ret; + g_return_val_if_fail (session != NULL, FALSE); + + ret = FALSE; + if (session->is_local) { + if (session->remote_host != NULL) + goto error; + } else { + if (session->remote_host == NULL) + goto error; + } + ret = TRUE; +error: + return TRUE; +} diff --git a/libpolkit/libpolkit-session.h b/libpolkit/libpolkit-session.h index 44821a9..2ee4bda 100644 --- a/libpolkit/libpolkit-session.h +++ b/libpolkit/libpolkit-session.h @@ -23,36 +23,38 @@ * **************************************************************************/ +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + #ifndef LIBPOLKIT_SESSION_H #define LIBPOLKIT_SESSION_H -#include -#include -#include - +#include #include +#include + 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); -void libpolkit_session_set_seat (PolKitSession *session, PolKitSeat *seat); -void libpolkit_session_set_ck_objref (PolKitSession *session, const char *ck_objref); -void libpolkit_session_set_ck_is_active (PolKitSession *session, bool is_active); -void libpolkit_session_set_ck_is_local (PolKitSession *session, bool is_local); -void libpolkit_session_set_ck_remote_host (PolKitSession *session, const char *remote_host); -bool libpolkit_session_get_uid (PolKitSession *session, uid_t *out_uid); -bool libpolkit_session_get_seat (PolKitSession *session, PolKitSeat **out_seat); -bool libpolkit_session_get_ck_objref (PolKitSession *session, char **out_ck_objref); -bool libpolkit_session_get_ck_is_active (PolKitSession *session, bool *out_is_active); -bool libpolkit_session_get_ck_is_local (PolKitSession *session, bool *out_is_local); -bool libpolkit_session_get_ck_remote_host (PolKitSession *session, char **out_remote_host); +polkit_bool_t libpolkit_session_set_uid (PolKitSession *session, uid_t uid); +polkit_bool_t libpolkit_session_set_seat (PolKitSession *session, PolKitSeat *seat); +polkit_bool_t libpolkit_session_set_ck_objref (PolKitSession *session, const char *ck_objref); +polkit_bool_t libpolkit_session_set_ck_is_active (PolKitSession *session, polkit_bool_t is_active); +polkit_bool_t libpolkit_session_set_ck_is_local (PolKitSession *session, polkit_bool_t is_local); +polkit_bool_t libpolkit_session_set_ck_remote_host (PolKitSession *session, const char *remote_host); +polkit_bool_t libpolkit_session_get_uid (PolKitSession *session, uid_t *out_uid); +polkit_bool_t libpolkit_session_get_seat (PolKitSession *session, PolKitSeat **out_seat); +polkit_bool_t libpolkit_session_get_ck_objref (PolKitSession *session, char **out_ck_objref); +polkit_bool_t libpolkit_session_get_ck_is_active (PolKitSession *session, polkit_bool_t *out_is_active); +polkit_bool_t libpolkit_session_get_ck_is_local (PolKitSession *session, polkit_bool_t *out_is_local); +polkit_bool_t libpolkit_session_get_ck_remote_host (PolKitSession *session, char **out_remote_host); void libpolkit_session_debug (PolKitSession *session); +polkit_bool_t libpolkit_session_validate (PolKitSession *session); #endif /* LIBPOLKIT_SESSION_H */ diff --git a/libpolkit/libpolkit-types.h b/libpolkit/libpolkit-types.h new file mode 100644 index 0000000..75b4679 --- /dev/null +++ b/libpolkit/libpolkit-types.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-types.h : fundamental types such as polkit_bool_t + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef LIBPOLKIT_TYPES_H +#define LIBPOLKIT_TYPES_H + +/** + * SECTION:libpolkit-types + * @short_description: Basic types. + * + * Typedefs for common primitive types. + **/ + +/** + * polkit_bool_t: + * + * A boolean, valid values are #TRUE and #FALSE. + */ +typedef int polkit_bool_t; + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#endif /* LIBPOLKIT_TYPES_H */ + + diff --git a/libpolkit/libpolkit-utils.c b/libpolkit/libpolkit-utils.c new file mode 100644 index 0000000..c0aca7d --- /dev/null +++ b/libpolkit/libpolkit-utils.c @@ -0,0 +1,153 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-utils.c : internal utilities used in libpolkit + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 "libpolkit-utils.h" +#include "libpolkit-debug.h" + +/** + * SECTION:libpolkit-utils + * @short_description: Internal utility functions for libpolkit. + * + * Internal utility functions for libpolkit. + **/ + +/** + * _pk_validate_identifier: + * @identifier: the NUL-terminated string to validate + * + * Validates strings used for an identifier; PolicyKit conventions + * state that identifiers must be NUL-terminated ASCII strings less + * than 256 bytes and only contain the characters "[a-z][A-Z]0-9]._-:/" + * + * Returns: #TRUE iff the identifier validates + **/ +polkit_bool_t +_pk_validate_identifier (const char *identifier) +{ + unsigned int n; + polkit_bool_t ret; + + g_return_val_if_fail (identifier != NULL, FALSE); + + ret = FALSE; + for (n = 0; identifier[n] != '\0'; n++) { + char c = identifier[n]; + + if (n >= 255) { + _pk_debug ("identifier too long"); + goto out; + } + + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '.' || + c == '_' || + c == '-' || + c == ':' || + c == '/') + continue; + + _pk_debug ("invalid character in identifier"); + goto out; + } + + ret = TRUE; +out: + return ret; +} + + +/* Determine wether the given character is valid as a second or later character in a bus name */ +#define VALID_BUS_NAME_CHARACTER(c) \ + ( ((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z') || \ + ((c) == '_') || ((c) == '-')) + +polkit_bool_t +_pk_validate_unique_bus_name (const char *unique_bus_name) +{ + int len; + const char *s; + const char *end; + const char *last_dot; + polkit_bool_t ret; + + ret = FALSE; + + if (unique_bus_name == NULL) + goto error; + + len = strlen (unique_bus_name); + if (len == 0) + goto error; + + end = unique_bus_name + len; + last_dot = NULL; + + s = unique_bus_name; + + /* check special cases of first char so it doesn't have to be done + * in the loop. Note we know len > 0 + */ + if (*s == ':') { + /* unique name */ + ++s; + while (s != end) { + if (*s == '.') { + if (G_UNLIKELY ((s + 1) == end)) + goto error; + if (G_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) + goto error; + ++s; /* we just validated the next char, so skip two */ + } else if (G_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) { + goto error; + } + ++s; + } + } else { + goto error; + } + + ret = TRUE; + +error: + if (!ret) + _pk_debug ("name '%s' did not validate", unique_bus_name); + return ret; +} diff --git a/libpolkit/libpolkit-utils.h b/libpolkit/libpolkit-utils.h new file mode 100644 index 0000000..00512c6 --- /dev/null +++ b/libpolkit/libpolkit-utils.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * libpolkit-utils.h : internal utilities used in libpolkit + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifndef LIBPOLKIT_UTILS_H +#define LIBPOLKIT_UTILS_H + +#include + +polkit_bool_t _pk_validate_identifier (const char *identifier); + +polkit_bool_t _pk_validate_unique_bus_name (const char *unique_bus_name); + +#endif /* LIBPOLKIT_UTILS_H */ + + diff --git a/libpolkit/libpolkit.h b/libpolkit/libpolkit.h index 4088a8e..889b00d 100644 --- a/libpolkit/libpolkit.h +++ b/libpolkit/libpolkit.h @@ -26,7 +26,22 @@ #ifndef LIBPOLKIT_H #define LIBPOLKIT_H +#define _POLKIT_INSIDE_POLKIT_H 1 +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef _POLKIT_INSIDE_POLKIT_H #endif /* LIBPOLKIT_H */ diff --git a/modules/Makefile.am b/modules/Makefile.am index b4eee78..010ed66 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS = default allow-all deny-all run-program +SUBDIRS = default allow-all deny-all run-program grant polkitconfdir = $(sysconfdir)/PolicyKit dist_polkitconf_DATA = PolicyKit.conf diff --git a/modules/PolicyKit.conf b/modules/PolicyKit.conf index ee8120b..c3c6dd9 100644 --- a/modules/PolicyKit.conf +++ b/modules/PolicyKit.conf @@ -3,3 +3,4 @@ # NOTE: Changes made to this file may be applied instantly advise polkit-module-default.so +advise polkit-module-grant.so diff --git a/modules/allow-all/polkit-module-allow-all.c b/modules/allow-all/polkit-module-allow-all.c index eddee16..3da56c2 100644 --- a/modules/allow-all/polkit-module-allow-all.c +++ b/modules/allow-all/polkit-module-allow-all.c @@ -27,15 +27,16 @@ # include #endif -#include +#include +#include /* The symbol that libpolkit looks up when loading this module */ -bool libpolkit_module_set_functions (PolKitModuleInterface *module_interface); +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface); -static bool +static polkit_bool_t _module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) { - return true; + return TRUE; } static void @@ -63,12 +64,12 @@ _module_can_caller_access_resource (PolKitModuleInterface *module_interface, return LIBPOLKIT_RESULT_YES; } -bool +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface) { - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; if (module_interface == NULL) goto out; @@ -77,7 +78,7 @@ libpolkit_module_set_functions (PolKitModuleInterface *module_interface) libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource); libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource); - ret = true; + ret = TRUE; out: return ret; } diff --git a/modules/default/polkit-module-default.c b/modules/default/polkit-module-default.c index 09b25e3..86a0635 100644 --- a/modules/default/polkit-module-default.c +++ b/modules/default/polkit-module-default.c @@ -27,17 +27,18 @@ # include #endif -#include +#include +#include /* The symbol that libpolkit looks up when loading this module */ -bool libpolkit_module_set_functions (PolKitModuleInterface *module_interface); +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface); -static bool +static polkit_bool_t _module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) { - return true; + return TRUE; } static void @@ -87,12 +88,12 @@ _module_can_caller_access_resource (PolKitModuleInterface *module_interface, caller); } -bool +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface) { - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; if (module_interface == NULL) goto out; @@ -101,7 +102,7 @@ libpolkit_module_set_functions (PolKitModuleInterface *module_interface) libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource); libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource); - ret = true; + ret = TRUE; out: return ret; } diff --git a/modules/deny-all/polkit-module-deny-all.c b/modules/deny-all/polkit-module-deny-all.c index 7562312..e2eb517 100644 --- a/modules/deny-all/polkit-module-deny-all.c +++ b/modules/deny-all/polkit-module-deny-all.c @@ -27,15 +27,16 @@ # include #endif -#include +#include +#include /* The symbol that libpolkit looks up when loading this module */ -bool libpolkit_module_set_functions (PolKitModuleInterface *module_interface); +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface); -static bool +static polkit_bool_t _module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) { - return true; + return TRUE; } static void @@ -63,12 +64,12 @@ _module_can_caller_access_resource (PolKitModuleInterface *module_interface, return LIBPOLKIT_RESULT_NO; } -bool +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface) { - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; if (module_interface == NULL) goto out; @@ -77,7 +78,7 @@ libpolkit_module_set_functions (PolKitModuleInterface *module_interface) libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource); libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource); - ret = true; + ret = TRUE; out: return ret; } diff --git a/modules/grant/Makefile.am b/modules/grant/Makefile.am new file mode 100644 index 0000000..0b7c5f1 --- /dev/null +++ b/modules/grant/Makefile.am @@ -0,0 +1,25 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES = \ + -I$(top_builddir) -I$(top_srcdir) \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ + @GLIB_CFLAGS@ @DBUS_CFLAGS@ + +polkitmoduledir = $(libdir)/PolicyKit/modules +polkitmodule_LTLIBRARIES = \ + polkit-module-grant.la \ + $(NULL) + + +polkit_module_grant_la_SOURCES = polkit-module-grant.c +polkit_module_grant_la_LDFLAGS = -no-undefined -module -avoid-version +polkit_module_grant_la_LIBADD = $(top_builddir)/libpolkit/libpolkit.la @GLIB_LIBS@ + +clean-local : + rm -f *~ diff --git a/modules/grant/polkit-module-grant.c b/modules/grant/polkit-module-grant.c new file mode 100644 index 0000000..15a06c0 --- /dev/null +++ b/modules/grant/polkit-module-grant.c @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-module-grant.c : determine policy by looking at grants + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * 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 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +/* The symbol that libpolkit looks up when loading this module */ +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface); + +static polkit_bool_t +_module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) +{ + return TRUE; +} + +static void +_module_shutdown (PolKitModuleInterface *module_interface) +{ +} + + + +static PolKitResult +_module_can_session_access_resource (PolKitModuleInterface *module_interface, + PolKitContext *pk_context, + PolKitAction *action, + PolKitResource *resource, + PolKitSession *session) +{ + return LIBPOLKIT_RESULT_UNKNOWN_ACTION; +} + +static PolKitResult +_module_can_caller_access_resource (PolKitModuleInterface *module_interface, + PolKitContext *pk_context, + PolKitAction *action, + PolKitResource *resource, + PolKitCaller *caller) +{ + char *grant_file; + PolKitSession *session; + PolKitResult result; + + result = LIBPOLKIT_RESULT_UNKNOWN_ACTION; + + /* file format: + * + * file: /var/[lib,run]/PolicyKit/grant/.grant + * + * contents: + * [ ]\n # only makes sense for run + * \n + * ... + * + * - run is used for temporarily granted privileges + * - lib is used for permanently granted privileges + * + * FHS guarantees that the files /var/run/PolicyKit are + * deleted upon reboots so we just need to ensure that + * ConsoleKit session id's are unique per system (TODO: Ask Jon + * to make ConsoleKit guarantee this). + */ + + uid_t invoking_user_id; + char *action_name; + char *session_objpath; + const char *session_name; + char *resource_type; + char *resource_id; + char *resource_str_to_hash; + char *dbus_name; + guint resource_hash; + + if (!libpolkit_action_get_action_id (action, &action_name)) + goto out; + if (!libpolkit_caller_get_uid (caller, &invoking_user_id)) + goto out; + + if (resource == NULL) + goto out; + if (!libpolkit_resource_get_resource_type (resource, &resource_type)) + goto out; + if (!libpolkit_resource_get_resource_id (resource, &resource_id)) + goto out; + + session_name = NULL; + if (!libpolkit_caller_get_ck_session (caller, &session)) + goto out; + if (!libpolkit_caller_get_dbus_name (caller, &dbus_name)) + goto out; + if (!libpolkit_session_get_ck_objref (session, &session_objpath)) + goto out; + + session_name = g_basename (session_objpath); + resource_str_to_hash = g_strdup_printf ("%s:%s", resource_type, resource_id); + resource_hash = g_str_hash (resource_str_to_hash); + g_free (resource_str_to_hash); + + /* TODO: FIXME: XXX: this format of storing granted privileges needs be redone + * + * this concerns these two files + * - libpolkit-grant/polkit-grant-helper.c + * - modules/grant/polkit-module-grant.c + */ + + /* + * /var/lib/PolicyKit/uid___.grant + * uid__.grant + * + * /var/run/PolicyKit/session____.grant + * session___.grant + * dbus____.grant + */ + + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/dbus_%s_%d_%s_%u.grant", + dbus_name, invoking_user_id, action_name, resource_hash); + if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) { + result = LIBPOLKIT_RESULT_YES; + g_free (grant_file); + goto out; + } + g_free (grant_file); + + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/session_%s_%d_%s_%u.grant", + session_name, invoking_user_id, action_name, resource_hash); + if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) { + result = LIBPOLKIT_RESULT_YES; + g_free (grant_file); + goto out; + } + g_free (grant_file); + + grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/uid_%d_%s_%u.grant", + invoking_user_id, action_name, resource_hash); + if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) { + result = LIBPOLKIT_RESULT_YES; + g_free (grant_file); + goto out; + } + g_free (grant_file); + + +out: + return result; +} + +polkit_bool_t +libpolkit_module_set_functions (PolKitModuleInterface *module_interface) +{ + polkit_bool_t ret; + + ret = FALSE; + if (module_interface == NULL) + goto out; + + libpolkit_module_set_func_initialize (module_interface, _module_init); + libpolkit_module_set_func_shutdown (module_interface, _module_shutdown); + libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource); + libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource); + + ret = TRUE; +out: + return ret; +} diff --git a/modules/run-program/polkit-module-run-program.c b/modules/run-program/polkit-module-run-program.c index 8f02e57..ecbc126 100644 --- a/modules/run-program/polkit-module-run-program.c +++ b/modules/run-program/polkit-module-run-program.c @@ -27,18 +27,18 @@ # include #endif -#include +#include #include /* The symbol that libpolkit looks up when loading this module */ -bool libpolkit_module_set_functions (PolKitModuleInterface *module_interface); +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface); typedef struct { int program_argc; char **program_argv; } UserData; -static bool +static polkit_bool_t _module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) { int n; @@ -77,12 +77,12 @@ _module_init (PolKitModuleInterface *module_interface, int argc, char *argv[]) libpolkit_module_set_user_data (module_interface, user_data); - return true; + return TRUE; error: if (user_data->program_argv != NULL) g_strfreev (user_data->program_argv); g_free (user_data); - return false; + return FALSE; } static void @@ -120,7 +120,7 @@ _add_action_param_to_env (PolKitAction *action, const char *key, const char *val g_free (upper); } -static bool +static polkit_bool_t _add_action_to_env (PolKitAction *action, GPtrArray *envp) { char *p_id; @@ -129,12 +129,12 @@ _add_action_to_env (PolKitAction *action, GPtrArray *envp) g_ptr_array_add (envp, g_strdup_printf ("POLKIT_ACTION_ID=%s", p_id)); libpolkit_action_param_foreach (action, _add_action_param_to_env, envp); - return true; + return TRUE; error: - return false; + return FALSE; } -static bool +static polkit_bool_t _add_resource_to_env (PolKitResource *resource, GPtrArray *envp) { char *r_type; @@ -145,30 +145,30 @@ _add_resource_to_env (PolKitResource *resource, GPtrArray *envp) goto error; g_ptr_array_add (envp, g_strdup_printf ("POLKIT_RESOURCE_TYPE=%s", r_type)); g_ptr_array_add (envp, g_strdup_printf ("POLKIT_RESOURCE_ID=%s", r_id)); - return true; + return TRUE; error: - return false; + return FALSE; } -static bool +static polkit_bool_t _add_seat_to_env (PolKitSeat *seat, GPtrArray *envp) { char *s_ck_objref; if (!libpolkit_seat_get_ck_objref (seat, &s_ck_objref)) goto error; g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SEAT_CK_OBJREF=%s", s_ck_objref)); - return true; + return TRUE; error: - return false; + return FALSE; } -static bool +static polkit_bool_t _add_session_to_env (PolKitSession *session, GPtrArray *envp) { uid_t s_uid; char *s_ck_objref; - bool s_ck_is_active; - bool s_ck_is_local; + polkit_bool_t s_ck_is_active; + polkit_bool_t s_ck_is_local; char *s_ck_remote_host; PolKitSeat *s_seat; @@ -194,12 +194,12 @@ _add_session_to_env (PolKitSession *session, GPtrArray *envp) g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_IS_LOCAL=%d", s_ck_is_local)); if (!s_ck_is_local) g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_REMOTE_HOST=%s", s_ck_remote_host)); - return true; + return TRUE; error: - return false; + return FALSE; } -static bool +static polkit_bool_t _add_caller_to_env (PolKitCaller *caller, GPtrArray *envp) { uid_t c_uid; @@ -227,23 +227,23 @@ _add_caller_to_env (PolKitCaller *caller, GPtrArray *envp) g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_DBUS_NAME=%s", c_dbus_name)); if (c_selinux_context != NULL) g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_SELINUX_CONTEXT=%s", c_selinux_context)); - return true; + return TRUE; error: - return false; + return FALSE; } -static bool +static polkit_bool_t _run_program (UserData *user_data, char **envp, PolKitResult *result) { int n; int exit_status; GError *g_error; char *prog_stdout; - bool ret; + polkit_bool_t ret; g_error = NULL; prog_stdout = NULL; - ret = false; + ret = FALSE; if (!g_spawn_sync ("/", user_data->program_argv, @@ -274,7 +274,7 @@ _run_program (UserData *user_data, char **envp, PolKitResult *result) goto error; } - ret = true; + ret = TRUE; error: g_free (prog_stdout); return ret; @@ -301,8 +301,9 @@ _module_can_session_access_resource (PolKitModuleInterface *module_interface, if (!_add_action_to_env (action, envp)) goto error; - if (!_add_resource_to_env (resource, envp)) - goto error; + if (resource != NULL) + if (!_add_resource_to_env (resource, envp)) + goto error; if (!_add_session_to_env (session, envp)) goto error; g_ptr_array_add (envp, g_strdup ("PATH=/usr/bin:/bin")); @@ -338,8 +339,9 @@ _module_can_caller_access_resource (PolKitModuleInterface *module_interface, envp = g_ptr_array_new (); if (!_add_action_to_env (action, envp)) goto error; - if (!_add_resource_to_env (resource, envp)) - goto error; + if (resource != NULL) + if (!_add_resource_to_env (resource, envp)) + goto error; if (!_add_caller_to_env (caller, envp)) goto error; g_ptr_array_add (envp, g_strdup ("PATH=/usr/bin:/bin")); @@ -356,12 +358,12 @@ error: return result; } -bool +polkit_bool_t libpolkit_module_set_functions (PolKitModuleInterface *module_interface) { - bool ret; + polkit_bool_t ret; - ret = false; + ret = FALSE; if (module_interface == NULL) goto out; @@ -370,7 +372,7 @@ libpolkit_module_set_functions (PolKitModuleInterface *module_interface) libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource); libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource); - ret = true; + ret = TRUE; out: return ret; } diff --git a/tools/Makefile.am b/tools/Makefile.am index 8b8475b..4524d70 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -11,17 +11,20 @@ INCLUDES = \ @GLIB_CFLAGS@ \ @DBUS_CFLAGS@ -bin_PROGRAMS = polkit-check-caller polkit-check-session polkit-policy-file-validate +bin_PROGRAMS = polkit-check-caller polkit-check-session polkit-policy-file-validate polkit-grant polkit_check_caller_SOURCES = polkit-check-caller.c -polkit_check_caller_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la +polkit_check_caller_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la $(top_builddir)/libpolkit-dbus/libpolkit-dbus.la polkit_check_session_SOURCES = polkit-check-session.c -polkit_check_session_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la +polkit_check_session_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la $(top_builddir)/libpolkit-dbus/libpolkit-dbus.la polkit_policy_file_validate_SOURCES = polkit-policy-file-validate.c polkit_policy_file_validate_LDADD = $(top_builddir)/libpolkit/libpolkit.la +polkit_grant_SOURCES = polkit-grant.c +polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libpolkit/libpolkit.la $(top_builddir)/libpolkit-grant/libpolkit-grant.la $(top_builddir)/libpolkit-dbus/libpolkit-dbus.la + clean-local : rm -f *~ diff --git a/tools/polkit-check-caller.c b/tools/polkit-check-caller.c index 49c6f03..32a2a94 100644 --- a/tools/polkit-check-caller.c +++ b/tools/polkit-check-caller.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include diff --git a/tools/polkit-check-session.c b/tools/polkit-check-session.c index cbde113..0b8472c 100644 --- a/tools/polkit-check-session.c +++ b/tools/polkit-check-session.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include diff --git a/tools/polkit-grant.c b/tools/polkit-grant.c new file mode 100644 index 0000000..d993b5f --- /dev/null +++ b/tools/polkit-grant.c @@ -0,0 +1,425 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-grant.c : grant privileges to a user through authentication + * + * 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 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static void +usage (int argc, char *argv[]) +{ + fprintf (stderr, + "\n" + "usage : polkit-grant\n" + " --action \n" + " --resource-type --resource-id \n" + " [--version] [--help]\n"); + fprintf (stderr, + "\n" + " --action Requested action\n" + " --resource-type Type of resource\n" + " --resource-id Identifier of resource\n" + " --version Show version and exit\n" + " --help Show this information and exit\n" + "\n" + "TODO.\n"); +} + +typedef struct { + gboolean gained_privilege; + GMainLoop *loop; +} UserData; + +static void +conversation_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data) +{ + switch (auth_type) { + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: + printf ("Authentication as root is required.\n"); + break; + + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: + printf ("Authentication is required.\n"); + break; + + default: + /* should never happen */ + exit (1); + } +} + +static char * +conversation_pam_prompt_echo_off (PolKitGrant *polkit_grant, const char *request, void *user_data) +{ + char *lineptr = NULL; + size_t linelen = 0; + struct termios old, new; + char *result; + + printf ("%s", request); + + /* Turn echo off */ + if (tcgetattr (fileno (stdout), &old) != 0) { + exit (1); + } + new = old; + new.c_lflag &= ~ECHO; + if (tcsetattr (fileno (stdout), TCSAFLUSH, &new) != 0) { + exit (1); + } + + getline (&lineptr, &linelen, stdin); + + /* Restore terminal. */ + tcsetattr (fileno (stdout), TCSAFLUSH, &old); + + result = strdup (lineptr); + free (lineptr); + return result; +} + +static char * +conversation_pam_prompt_echo_on (PolKitGrant *polkit_grant, const char *request, void *user_data) +{ + char *lineptr = NULL; + size_t linelen = 0; + char *result; + printf ("%s", request); + getline (&lineptr, &linelen, stdin); + result = strdup (lineptr); + free (lineptr); + return result; +} + +static void +conversation_pam_error_msg (PolKitGrant *polkit_grant, const char *msg, void *user_data) +{ + printf ("error_msg='%s'\n", msg); +} + +static void +conversation_pam_text_info (PolKitGrant *polkit_grant, const char *msg, void *user_data) +{ + printf ("text_info='%s'\n", msg); +} + +static PolKitResult +conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data) +{ + char *lineptr = NULL; + size_t linelen = 0; + polkit_bool_t keep_session = FALSE; + polkit_bool_t keep_always = FALSE; + PolKitResult overridden_auth_type; + + switch (auth_type) { + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: + break; + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: + printf ("Keep this privilege for the session? [no/session]?\n"); + getline (&lineptr, &linelen, stdin); + if (g_str_has_prefix (lineptr, "no")) { + ; + } else if (g_str_has_prefix (lineptr, "session")) { + keep_session = TRUE; + } else { + printf ("Valid responses are 'no' and 'session'. Exiting.\n"); + exit (1); + } + free (lineptr); + break; + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: + printf ("Keep this privilege for the session or always? [no/session/always]?\n"); + getline (&lineptr, &linelen, stdin); + if (g_str_has_prefix (lineptr, "no")) { + ; + } else if (g_str_has_prefix (lineptr, "session")) { + keep_session = TRUE; + } else if (g_str_has_prefix (lineptr, "always")) { + keep_always = TRUE; + } else { + printf ("Valid responses are 'no', 'session' and 'always'. Exiting.\n"); + exit (1); + } + free (lineptr); + break; + default: + /* should never happen */ + exit (1); + } + + switch (auth_type) { + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS: + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH; + if (keep_session) + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION; + else if (keep_always) + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS; + break; + + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION: + case LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH; + if (keep_session) + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION; + else if (keep_always) + overridden_auth_type = LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS; + break; + + default: + /* should never happen */ + exit (1); + } + + return overridden_auth_type; +} + +static void +conversation_done (PolKitGrant *polkit_grant, polkit_bool_t gained_privilege, void *user_data) +{ + UserData *ud = user_data; + ud->gained_privilege = gained_privilege; + g_main_loop_quit (ud->loop); +} + + + + +static void +child_watch_func (GPid pid, + gint status, + gpointer user_data) +{ + PolKitGrant *polkit_grant = user_data; + libpolkit_grant_child_func (polkit_grant, pid, WEXITSTATUS (status)); +} + +static int +add_child_watch (PolKitGrant *polkit_grant, pid_t pid) +{ + return g_child_watch_add (pid, child_watch_func, polkit_grant); +} + +static gboolean +io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + int fd; + PolKitGrant *polkit_grant = user_data; + fd = g_io_channel_unix_get_fd (channel); + libpolkit_grant_io_func (polkit_grant, fd); + return TRUE; +} + +static int +add_io_watch (PolKitGrant *polkit_grant, int fd) +{ + guint id = 0; + GIOChannel *channel; + channel = g_io_channel_unix_new (fd); + if (channel == NULL) + goto out; + id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, polkit_grant); + if (id == 0) { + g_io_channel_unref (channel); + goto out; + } + g_io_channel_unref (channel); +out: + return id; +} + +static void +remove_watch (PolKitGrant *polkit_auth, int watch_id) +{ + g_source_remove (watch_id); +} + +int +main (int argc, char *argv[]) +{ + char *action_id = NULL; + char *resource_type = NULL; + char *resource_id = NULL; + gboolean is_version = FALSE; + DBusConnection *bus; + DBusError error; + PolKitContext *pol_ctx; + PolKitCaller *caller; + PolKitAction *action; + PolKitResource *resource; + PolKitError *p_error; + PolKitGrant *polkit_grant; + int ret; + UserData ud; + + ret = 2; + + if (argc <= 1) { + usage (argc, argv); + return 1; + } + + while (1) { + int c; + int option_index = 0; + const char *opt; + static struct option long_options[] = { + {"action", 1, NULL, 0}, + {"resource-type", 1, NULL, 0}, + {"resource-id", 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, "action") == 0) { + action_id = strdup (optarg); + } else if (strcmp (opt, "resource-type") == 0) { + resource_type = strdup (optarg); + } else if (strcmp (opt, "resource-id") == 0) { + resource_id = strdup (optarg); + } + break; + + default: + usage (argc, argv); + goto error; + } + } + + if (is_version) { + printf ("polkit-grant " PACKAGE_VERSION "\n"); + return 0; + } + + if (action_id == NULL || resource_type == NULL || resource_id == NULL) { + usage (argc, argv); + goto error; + } + + ud.loop = g_main_loop_new (NULL, TRUE); + + 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); + goto error; + } + + p_error = NULL; + pol_ctx = libpolkit_context_new (); + if (!libpolkit_context_init (pol_ctx, &p_error)) { + fprintf (stderr, "error: libpolkit_context_init: %s\n", polkit_error_get_error_message (p_error)); + polkit_error_free (p_error); + goto error; + } + + action = libpolkit_action_new (); + libpolkit_action_set_action_id (action, action_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_bus_get_unique_name (bus), &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); + goto error; + } + } + + polkit_grant = libpolkit_grant_new (); + libpolkit_grant_set_functions (polkit_grant, + add_io_watch, + add_child_watch, + remove_watch, + conversation_type, + conversation_pam_prompt_echo_off, + conversation_pam_prompt_echo_on, + conversation_pam_error_msg, + conversation_pam_text_info, + conversation_override_grant_type, + conversation_done, + &ud); + + if (!libpolkit_grant_initiate_auth (polkit_grant, + action, + resource, + caller)) { + printf ("Failed to initiate privilege grant.\n"); + ret = 1; + goto error; + } + g_main_loop_run (ud.loop); + libpolkit_grant_unref (polkit_grant); + + printf ("Privilege grant done.. result=%d\n", ud.gained_privilege); + + ret = ud.gained_privilege ? 0 : 1; + +error: + return ret; +} diff --git a/tools/polkit-policy-file-validate.c b/tools/polkit-policy-file-validate.c index 604d7c4..3d2353d 100644 --- a/tools/polkit-policy-file-validate.c +++ b/tools/polkit-policy-file-validate.c @@ -36,7 +36,7 @@ #include #include -#include +#include static void usage (int argc, char *argv[]) -- 2.7.4