move all grant writing/checking into a separate private library
authorDavid Zeuthen <davidz@redhat.com>
Tue, 19 Jun 2007 23:59:54 +0000 (19:59 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Tue, 19 Jun 2007 23:59:54 +0000 (19:59 -0400)
modules/grant/Makefile.am
modules/grant/polkit-module-grant.c
polkit-grant/Makefile.am
polkit-grant/polkit-grant-database.c [new file with mode: 0644]
polkit-grant/polkit-grant-database.h [new file with mode: 0644]
polkit-grant/polkit-grant-helper.c

index 2cea430..52ff52a 100644 (file)
@@ -17,13 +17,9 @@ polkitmodule_LTLIBRARIES =                   \
        $(NULL)
 
 
-polkit_module_grant_la_SOURCES = \
-       $(top_srcdir)/polkit-grant/polkit-grant-database.h      $(top_srcdir)/polkit-grant/polkit-grant-database.c  \
-       polkit-module-grant.c
-
-
+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)/polkit/libpolkit.la @GLIB_LIBS@
+polkit_module_grant_la_LIBADD = $(top_builddir)/polkit/libpolkit.la @GLIB_LIBS@ $(top_builddir)/polkit-grant/libpolkit-grant-private.la
 
 clean-local :
        rm -f *~
index d1c3691..c0ea67b 100644 (file)
@@ -65,13 +65,15 @@ _module_can_caller_do_action (PolKitModuleInterface *module_interface,
                               PolKitAction          *action,
                               PolKitCaller          *caller)
 {
+        return _polkit_grantdb_check_can_caller_do_action (pk_context, action, caller);
+
+#if 0
         char *grant_file;
         PolKitSession *session;
         PolKitResult result;
 
         result = POLKIT_RESULT_UNKNOWN_ACTION;
 
-#if 0
         /* file format:
          *
          * file: /var/[lib,run]/PolicyKit/grant/<action-name>.grant
@@ -184,9 +186,6 @@ _module_can_caller_do_action (PolKitModuleInterface *module_interface,
         }
         g_free (grant_file);
 #endif
-
-out:
-        return result;
 }
 
 polkit_bool_t
index d8a39d7..4e1bc1c 100644 (file)
@@ -12,6 +12,11 @@ INCLUDES = \
        -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \
        @GLIB_CFLAGS@ @DBUS_CFLAGS@
 
+noinst_LTLIBRARIES=libpolkit-grant-private.la
+
+libpolkit_grant_private_la_SOURCES =                           \
+       polkit-grant-database.h polkit-grant-database.c
+
 lib_LTLIBRARIES=libpolkit-grant.la
 
 libpolkit_grantincludedir=$(includedir)/PolicyKit/polkit-grant
@@ -20,7 +25,6 @@ libpolkit_grantinclude_HEADERS =                                      \
        polkit-grant.h
 
 libpolkit_grant_la_SOURCES =                                   \
-       polkit-grant-database.h polkit-grant-database.c         \
        polkit-grant.h          polkit-grant.c
 
 libpolkit_grant_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la
@@ -30,7 +34,7 @@ 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)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
+polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @AUTH_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit-grant/libpolkit-grant-private.la
 
 polkit_grant_alwaysdir = $(localstatedir)/lib/PolicyKit
 dist_polkit_grant_always_DATA =
diff --git a/polkit-grant/polkit-grant-database.c b/polkit-grant/polkit-grant-database.c
new file mode 100644 (file)
index 0000000..c6f96de
--- /dev/null
@@ -0,0 +1,303 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-grant-database.c : simple interface for storing and checking grants
+ * 
+ * (This is an internal and private interface to PolicyKit. Do not use.)
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include <polkit-grant/polkit-grant-database.h>
+
+/* TODO FIXME: this is Linux specific */
+static unsigned long long 
+get_start_time_for_pid (pid_t pid)
+{
+        char *filename;
+        char *contents;
+        gsize length;
+        unsigned long long start_time;
+        GError *error = NULL;
+        char **tokens;
+        char *p;
+        char *endp;
+
+        start_time = 0;
+        contents = NULL;
+
+        filename = g_strdup_printf ("/proc/%d/stat", pid);
+        if (filename == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        if (!g_file_get_contents (filename, &contents, &length, &error)) {
+                fprintf (stderr, "Cannot get contents of '%s': %s\n", filename, error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        /* start time is the 19th token after the '(process name)' entry */
+
+        p = strchr (contents, ')');
+        if (p == NULL) {
+                goto out;
+        }
+        p += 2; /* skip ') ' */
+        if (p - contents >= (int) length) {
+                goto out;
+        }
+
+        tokens = g_strsplit (p, " ", 0);
+        if (g_strv_length (tokens) < 20) {
+                goto out;
+        }
+
+        start_time = strtoll (tokens[19], &endp, 10);
+        if (endp == tokens[19]) {
+                goto out;
+        }
+
+        g_strfreev (tokens);
+
+out:
+        g_free (filename);
+        g_free (contents);
+        return start_time;
+}
+
+#if 0
+static polkit_bool_t
+ensure_dir (const char *file)
+{
+        char *dirname;
+        polkit_bool_t ret;
+
+        ret = FALSE;
+
+        dirname = g_path_get_dirname (file);
+        if (dirname == NULL)
+                goto out;
+
+        if (g_file_test (dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
+                /* TODO: check permissions? */
+                ret = TRUE;
+                goto out;
+        }
+
+        if (mkdir (dirname, 0570) != 0) {
+                fprintf (stderr, "Cannot create directory '%s': %s\n", dirname, strerror (errno));
+                goto out;
+        }
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+#endif
+
+static polkit_bool_t 
+_polkit_grantdb_write (const char *grant_file)
+{
+        int fd;
+        polkit_bool_t ret;
+
+        ret = FALSE;
+
+#if 0
+        if (!ensure_dir (grant_file))
+                goto out;
+#endif
+
+        fd = open (grant_file, O_CREAT | O_RDWR, 0460);
+        if (fd < 0) {
+                fprintf (stderr, "Cannot create file '%s': %s\n", grant_file, strerror (errno));
+                goto out;
+        }
+        /* Yessir, the file is empty */
+        close (fd);
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+
+polkit_bool_t 
+_polkit_grantdb_write_pid (const char *action_id, pid_t pid)
+{
+        char *grant_file;
+        polkit_bool_t ret = FALSE;
+        unsigned long long pid_start_time;
+
+        pid_start_time = get_start_time_for_pid (pid);
+        if (pid_start_time == 0)
+                goto out;
+
+        grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/uid%d-pid-%d@%Lu-%s.grant", 
+                                      getuid(), pid, pid_start_time, action_id);
+        if (grant_file == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        ret = _polkit_grantdb_write (grant_file);
+out:
+        return ret;
+}
+
+polkit_bool_t 
+_polkit_grantdb_write_keep_session (const char *action_id, const char *session_id)
+{
+        char *grant_file;
+        polkit_bool_t ret = FALSE;
+
+        grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/uid%d-session-%s-%s.grant", 
+                                      getuid(), g_basename (session_id), action_id);
+        if (grant_file == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        ret = _polkit_grantdb_write (grant_file);
+out:
+        return ret;
+}
+
+polkit_bool_t
+_polkit_grantdb_write_keep_always (const char *action_id, uid_t uid)
+{
+        char *grant_file;
+        polkit_bool_t ret = FALSE;
+
+        grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/uid%d/%s.grant", 
+                                      getuid(), action_id);
+        if (grant_file == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        ret = _polkit_grantdb_write (grant_file);
+out:
+        return ret;
+}
+
+PolKitResult 
+_polkit_grantdb_check_can_caller_do_action (PolKitContext         *pk_context,
+                                            PolKitAction          *action,
+                                            PolKitCaller          *caller)
+{
+        char *grant_file;
+        PolKitResult result;
+        char *action_id;
+        uid_t invoking_user_id;
+        pid_t invoking_process_id;
+        PolKitSession *session;
+        char *session_objpath;
+        unsigned long long pid_start_time;
+
+        grant_file = NULL;
+        result = POLKIT_RESULT_UNKNOWN_ACTION;
+
+        if (caller == NULL)
+                goto out;
+
+        if (!polkit_action_get_action_id (action, &action_id))
+                goto out;
+
+        if (!polkit_caller_get_uid (caller, &invoking_user_id))
+                goto out;
+
+        if (!polkit_caller_get_pid (caller, &invoking_process_id))
+                goto out;
+
+        session_objpath = NULL;
+        if (polkit_caller_get_ck_session (caller, &session)) {
+                if (!polkit_session_get_ck_objref (session, &session_objpath))
+                        session_objpath = NULL;
+        }
+
+        pid_start_time = get_start_time_for_pid (invoking_process_id);
+        if (pid_start_time == 0)
+                goto out;
+
+        /* first check what _write_pid may have left */
+        grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/uid%d-pid-%d@%Lu-%s.grant", 
+                                      invoking_user_id, invoking_process_id, pid_start_time, action_id);
+        if (grant_file == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                g_free (grant_file);
+                goto out;
+        }
+        if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) {
+                result = POLKIT_RESULT_YES;
+                g_free (grant_file);
+                goto out;
+        }
+        g_free (grant_file);
+
+        /* second, check what _keep_session may have left */
+        if (session_objpath != NULL) {
+                grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/uid%d-session-%s-%s.grant", 
+                                              invoking_user_id, g_basename (session_objpath), action_id);
+                if (grant_file == NULL) {
+                        fprintf (stderr, "Out of memory\n");
+                        g_free (grant_file);
+                        goto out;
+                }
+                if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) {
+                        result = POLKIT_RESULT_YES;
+                        g_free (grant_file);
+                        goto out;
+                }
+                g_free (grant_file);
+        }
+
+        /* finally, check what _keep_always may have left */
+        if (session_objpath != NULL) {
+                grant_file = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/uid%d/%s.grant", 
+                                              invoking_user_id, action_id);
+                if (grant_file == NULL) {
+                        fprintf (stderr, "Out of memory\n");
+                        g_free (grant_file);
+                        goto out;
+                }
+                if (g_file_test (grant_file, G_FILE_TEST_EXISTS)) {
+                        result = POLKIT_RESULT_YES;
+                        g_free (grant_file);
+                        goto out;
+                }
+                g_free (grant_file);
+        }
+
+out:
+        return result;
+}
diff --git a/polkit-grant/polkit-grant-database.h b/polkit-grant/polkit-grant-database.h
new file mode 100644 (file)
index 0000000..dd53e8e
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-grant-database.h : simple interface for storing and checking grants
+ * 
+ * (This is an internal and private interface to PolicyKit. Do not use.)
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef POLKIT_GRANT_DATABASE_H
+#define POLKIT_GRANT_DATABASE_H
+
+#include <polkit/polkit.h>
+
+PolKitResult _polkit_grantdb_check_can_caller_do_action (PolKitContext         *pk_context,
+                                                         PolKitAction          *action,
+                                                         PolKitCaller          *caller);
+
+polkit_bool_t _polkit_grantdb_write_keep_always (const char *action_id, uid_t uid);
+
+polkit_bool_t _polkit_grantdb_write_keep_session (const char *action_id, const char *session_id);
+
+polkit_bool_t _polkit_grantdb_write_pid (const char *action_id, pid_t pid);
+
+#endif /* POLKIT_GRANT_DATABASE_H */
index 7cbe07f..8d12f40 100644 (file)
@@ -363,6 +363,7 @@ main (int argc, char *argv[])
         gid_t egid;
         struct group *group;
         struct passwd *pw;
+        polkit_bool_t dbres;
 
         ret = 3;
 
@@ -461,7 +462,35 @@ main (int argc, char *argv[])
                 goto out;
         }
 
-        fprintf (stderr, "OK; TODO: write to database\n");
+        fprintf (stderr, "OK; TODO: write to database: action_id=%s session_id=%s pid=%d\n", 
+                 action_name, session_objpath, caller_pid);
+
+        switch (result) {
+        case POLKIT_RESULT_ONLY_VIA_ROOT_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+                dbres = _polkit_grantdb_write_pid (action_name, caller_pid);
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+                dbres = _polkit_grantdb_write_keep_session (action_name, session_objpath);
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_ALWAYS:
+                dbres = _polkit_grantdb_write_keep_always (action_name, invoking_user_id);
+                break;
+
+        default:
+                /* should never happen */
+                goto out;
+        }
+
+        if (!dbres) {
+                fprintf (stderr, "polkit-grant-helper: failed to write to grantdb\n");
+                goto out;
+        }
+
 #if 0
         /* TODO: FIXME: XXX: this format of storing granted privileges needs be redone
          *