Commit 5863ec81 authored by David Zeuthen's avatar David Zeuthen
Browse files

create an API for interfacing with the Authorization Database

This is necessary to make UI like this

 http://people.freedesktop.org/~david/Screenshot-Manage%20Authorizations.png

export some useful actions such as granting, revoking and displaying
authorizations.

Previously this API was internal, polkit/polkit-grant-database.[ch],
and linked into polkit-grant(1) and libpolkit-grant(3) through a
static library libpolkit-private.so.

Only polkit-grant have not been ported; libpolkit-grant(3) uses this
API natively now. Internally, right now, the new API just uses
polkit-grant-database.[ch] directly but that is about to change...
parent b9137e65
......@@ -89,6 +89,8 @@
<xi:include href="xml/polkit-policy-file-entry.xml"/>
<xi:include href="xml/polkit-policy-default.xml"/>
<xi:include href="xml/polkit-policy-cache.xml"/>
<xi:include href="xml/polkit-authorization.xml"/>
<xi:include href="xml/polkit-authorization-db.xml"/>
</reference>
<reference id="ref-convenience">
......
......@@ -29,7 +29,7 @@ libpolkit_grant_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE
libexec_PROGRAMS = polkit-grant-helper polkit-grant-helper-pam
polkit_grant_helper_SOURCES = polkit-grant-helper.c
polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit/libpolkit-grant-private.la
polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
polkit_grant_helper_pam_SOURCES = polkit-grant-helper-pam.c
polkit_grant_helper_pam_LDADD = @AUTH_LIBS@
......
......@@ -44,7 +44,7 @@
#include <glib.h>
#include <polkit-dbus/polkit-dbus.h>
#include <polkit/polkit-grant-database.h>
// #include <polkit/polkit-grant-database.h>
/* Development aid: define PGH_DEBUG to get debugging output. Do _NOT_
* enable this in production builds; it may leak passwords and other
......@@ -243,10 +243,9 @@ out:
/**
* verify_with_polkit:
* @caller_pid: the process id of the caller
* @action_name: name of the action
* @result: return location for result AKA how the user can auth
* @out_session_objpath: return location for ConsoleKit session identifier
* @caller: the caller
* @action: the action
* @out_result: return location for result AKA how the user can auth
* @out_admin_users: return location for a NULL-terminated array of
* strings that can be user to auth as admin. Is set to NULL if the
* super user (e.g. uid 0) should be user to auth as admin.
......@@ -258,70 +257,26 @@ out:
* configuration file; see the PolicyKit.conf(5) manual page for
* details.
*
* Returns: TRUE if, and only if, the given caller can authenticate to
* Returns: #TRUE if, and only if, the given caller can authenticate to
* gain a privilege to do the given action.
*/
static polkit_bool_t
verify_with_polkit (pid_t caller_pid,
const char *action_name,
PolKitResult *result,
char **out_session_objpath,
verify_with_polkit (PolKitContext *pol_ctx,
PolKitCaller *caller,
PolKitAction *action,
PolKitResult *out_result,
char ***out_admin_users)
{
PolKitCaller *caller;
PolKitSession *session;
char *str;
DBusConnection *bus;
DBusError error;
PolKitContext *pol_ctx;
PolKitAction *action;
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
fprintf (stderr, "polkit-grant-helper: cannot connect to system bus: %s: %s\n",
error.name, error.message);
dbus_error_free (&error);
goto error;
}
action = polkit_action_new ();
polkit_action_set_action_id (action, action_name);
caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
if (caller == NULL) {
fprintf (stderr, "polkit-grant-helper: cannot get caller from pid\n");
goto error;
}
if (!polkit_caller_get_ck_session (caller, &session)) {
fprintf (stderr, "polkit-grant-helper: caller is not in a session\n");
goto error;
}
if (!polkit_session_get_ck_objref (session, &str)) {
fprintf (stderr, "polkit-grant-helper: cannot get session ck objpath\n");
goto error;
}
*out_session_objpath = g_strdup (str);
if (*out_session_objpath == NULL)
goto error;
pol_ctx = polkit_context_new ();
if (!polkit_context_init (pol_ctx, NULL)) {
fprintf (stderr, "polkit-grant-helper: cannot initialize polkit\n");
goto error;
}
*result = polkit_context_can_caller_do_action (pol_ctx, action, caller);
if (*result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
*result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION &&
*result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS &&
*result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
*result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION &&
*result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) {
*out_result = polkit_context_is_caller_authorized (pol_ctx, action, caller, FALSE);
if (*out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
*out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION &&
*out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS &&
*out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
*out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION &&
*out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) {
fprintf (stderr, "polkit-grant-helper: given auth type (%d -> %s) is bogus\n",
*result, polkit_result_to_string_representation (*result));
*out_result, polkit_result_to_string_representation (*out_result));
goto error;
}
......@@ -330,9 +285,9 @@ verify_with_polkit (pid_t caller_pid,
/* for admin auth, get a list of users that can be used - this is basically evaluating the
* <define_admin_auth/> directives in the config file...
*/
if (*result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
*result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
*result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
if (*out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
*out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
*out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
PolKitConfig *pk_config;
PolKitConfigAdminAuthType admin_auth_type;
const char *admin_auth_data;
......@@ -535,11 +490,20 @@ main (int argc, char *argv[])
const char *invoking_user_name;
const char *action_name;
PolKitResult result;
PolKitResult original_result;
const char *user_to_auth;
uid_t uid_of_user_to_auth;
char *session_objpath;
struct passwd *pw;
polkit_bool_t dbres;
char **admin_users;
DBusError error;
DBusConnection *bus;
PolKitContext *context;
PolKitAction *action;
PolKitCaller *caller;
uid_t caller_uid;
PolKitSession *session;
ret = 3;
......@@ -610,12 +574,49 @@ main (int argc, char *argv[])
ret = 2;
context = polkit_context_new ();
if (!polkit_context_init (context, NULL)) {
fprintf (stderr, "polkit-grant-helper: cannot initialize polkit\n");
goto out;
}
action = polkit_action_new ();
polkit_action_set_action_id (action, action_name);
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
fprintf (stderr, "polkit-grant-helper: cannot connect to system bus: %s: %s\n",
error.name, error.message);
dbus_error_free (&error);
goto out;
}
caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
if (caller == NULL) {
fprintf (stderr, "polkit-grant-helper: cannot get caller from pid: %s: %s\n",
error.name, error.message);
goto out;
}
if (!polkit_caller_get_uid (caller, &caller_uid)) {
fprintf (stderr, "polkit-grant-helper: no uid for caller\n");
goto out;
}
if (!polkit_caller_get_ck_session (caller, &session)) {
fprintf (stderr, "polkit-grant-helper: caller is not in a session\n");
goto out;
}
if (!polkit_session_get_ck_objref (session, &session_objpath)) {
fprintf (stderr, "polkit-grant-helper: caller is not in a session\n");
goto out;
}
/* Use libpolkit to
*
* - figure out if the caller can really auth to do the action
* - learn what ConsoleKit session the caller belongs to
*/
if (!verify_with_polkit (caller_pid, action_name, &result, &session_objpath, &admin_users))
if (!verify_with_polkit (context, caller, action, &result, &admin_users))
goto out;
#ifdef PGH_DEBUG
......@@ -699,6 +700,19 @@ main (int argc, char *argv[])
}
}
if (strcmp (user_to_auth, "root") == 0) {
uid_of_user_to_auth = 0;
} else {
struct passwd *passwd;
passwd = getpwnam (user_to_auth);
if (passwd == NULL) {
fprintf (stderr, "polkit-grant-helper: can not look up uid for user '%s'\n", user_to_auth);
goto out;
}
uid_of_user_to_auth = passwd->pw_uid;
}
ret = 1;
/* Start authentication */
......@@ -706,6 +720,8 @@ main (int argc, char *argv[])
goto out;
}
original_result = result;
/* Ask caller 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..
......@@ -731,28 +747,41 @@ main (int argc, char *argv[])
switch (result) {
case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
dbres = _polkit_grantdb_write_pid (action_name, caller_pid);
dbres = polkit_authorization_db_add_entry_process (polkit_context_get_authorization_db (context),
action,
caller,
original_result,
uid_of_user_to_auth);
if (dbres) {
syslog (LOG_INFO, "granted use of action='%s' to pid '%d' [uid=%d] [auth='%s']",
syslog (LOG_INFO, "granted authorization for %s to pid %d [uid=%d] [auth=%s]",
action_name, caller_pid, invoking_user_id, user_to_auth);
}
break;
case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
dbres = _polkit_grantdb_write_keep_session (action_name, session_objpath);
dbres = polkit_authorization_db_add_entry_session (polkit_context_get_authorization_db (context),
action,
session,
original_result,
uid_of_user_to_auth);
if (dbres) {
syslog (LOG_INFO, "granted use of action='%s' to session '%s' [uid=%d] [auth='%s']",
syslog (LOG_INFO, "granted authorization for %s to session %s [uid=%d] [auth=%s]",
action_name, session_objpath, invoking_user_id, user_to_auth);
}
break;
case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
dbres = _polkit_grantdb_write_keep_always (action_name, invoking_user_id);
dbres = polkit_authorization_db_add_entry_always (polkit_context_get_authorization_db (context),
action,
caller_uid,
original_result,
uid_of_user_to_auth);
if (dbres) {
syslog (LOG_INFO, "granted use of action='%s' to uid %d [auth='%s']",
action_name, invoking_user_id, user_to_auth);
syslog (LOG_INFO, "granted authorization for %s to uid %d [auth=%s]",
action_name, caller_uid, user_to_auth);
}
break;
......
......@@ -13,12 +13,6 @@ INCLUDES = \
-DPOLKIT_COMPILATION \
@GLIB_CFLAGS@
noinst_LTLIBRARIES=libpolkit-grant-private.la
libpolkit_grant_private_la_SOURCES = \
polkit-grant-database.h polkit-grant-database.c
lib_LTLIBRARIES=libpolkit.la
libpolkitincludedir=$(includedir)/PolicyKit/polkit
......@@ -37,7 +31,9 @@ libpolkitinclude_HEADERS = \
polkit-policy-file.h \
polkit-policy-cache.h \
polkit-policy-default.h \
polkit-config.h
polkit-config.h \
polkit-authorization.h \
polkit-authorization-db.h
libpolkit_la_SOURCES = \
polkit.h \
......@@ -55,9 +51,13 @@ libpolkit_la_SOURCES = \
polkit-policy-default.h polkit-policy-default.c \
polkit-debug.h polkit-debug.c \
polkit-utils.h polkit-utils.c \
polkit-config.h polkit-config.c
polkit-config.h polkit-config.c \
polkit-authorization.h polkit-authorization.c \
polkit-authorization-db.h polkit-authorization-db.c \
polkit-grant-database.h polkit-grant-database.c
libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@ libpolkit-grant-private.la
libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@
libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/***************************************************************************
*
* polkit-authorization-db.c : Represents the authorization database
*
* Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
*
* 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 <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <errno.h>
#include <glib.h>
#include "polkit-debug.h"
#include "polkit-authorization-db.h"
#include "polkit-utils.h"
/* For now, redirect to the old stuff */
#include "polkit-grant-database.h"
/**
* SECTION:polkit-authorization-db
* @title: Authorization Database
* @short_description: An interface to the database storing authorizations
*
* This class is used to represent entries in the authorization
* database. TODO: needs to be pluggable
*
* Since: 0.7
**/
/**
* PolKitAuthorizationDB:
*
* Objects of this class are used to represent entries in the
* authorization database.
*
* Since: 0.7
**/
struct _PolKitAuthorizationDB
{
int refcount;
};
/**
* polkit_authorization_db_new:
*
* Create a new #PolKitAuthorizationDB object.
*
* Returns: the new object
*
* Since: 0.7
**/
PolKitAuthorizationDB *
polkit_authorization_db_new (void)
{
PolKitAuthorizationDB *authdb;
authdb = g_new0 (PolKitAuthorizationDB, 1);
authdb->refcount = 1;
return authdb;
}
/**
* polkit_authorization_db_ref:
* @authdb: the object
*
* Increase reference count.
*
* Returns: the object
*
* Since: 0.7
**/
PolKitAuthorizationDB *
polkit_authorization_db_ref (PolKitAuthorizationDB *authdb)
{
g_return_val_if_fail (authdb != NULL, authdb);
authdb->refcount++;
return authdb;
}
/**
* polkit_authorization_db_unref:
* @authdb: 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.
*
* Since: 0.7
**/
void
polkit_authorization_db_unref (PolKitAuthorizationDB *authdb)
{
g_return_if_fail (authdb != NULL);
authdb->refcount--;
if (authdb->refcount > 0)
return;
g_free (authdb);
}
/**
* polkit_authorization_db_debug:
* @authdb: the object
*
* Print debug details
*
* Since: 0.7
**/
void
polkit_authorization_db_debug (PolKitAuthorizationDB *authdb)
{
g_return_if_fail (authdb != NULL);
_pk_debug ("PolKitAuthorizationDB: refcount=%d", authdb->refcount);
}
/**
* polkit_authorization_db_validate:
* @authdb: the object
*
* Validate the object
*
* Returns: #TRUE iff the object is valid.
*
* Since: 0.7
**/
polkit_bool_t
polkit_authorization_db_validate (PolKitAuthorizationDB *authdb)
{
g_return_val_if_fail (authdb != NULL, FALSE);
return TRUE;
}
/**
* polkit_authorization_db_is_session_authorized:
* @authdb: the authorization database
* @action: the action to check for
* @session: the session to check for
* @out_is_authorized: return location
*
* Looks in the authorization database and determine if a processes
* from the given session are authorized to do the given specific
* action.
*
* Returns: #TRUE if the look up was performed; #FALSE if the caller
* of this function lacks privileges to ask this question (e.g. asking
* about a user that is not himself).
*
* Since: 0.7
*/
polkit_bool_t
polkit_authorization_db_is_session_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitSession *session,
polkit_bool_t *out_is_authorized)
{
return FALSE;
}
/**
* polkit_authorization_db_is_caller_authorized:
* @authdb: the authorization database
* @action: the action to check for
* @caller: the caller to check for
* @out_is_authorized: return location
*
* Looks in the authorization database if the given caller is
* authorized to do the given action.
*
* Returns: #TRUE if the look up was performed; #FALSE if the caller
* of this function lacks privileges to ask this question (e.g. asking
* about a user that is not himself).
*
* Since: 0.7
*/
polkit_bool_t
polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitCaller *caller,
polkit_bool_t *out_is_authorized)
{
g_return_val_if_fail (out_is_authorized != NULL, FALSE);
*out_is_authorized = _polkit_grantdb_check_can_caller_do_action (action, caller);
return TRUE;
}
/**
* polkit_authorization_db_add_entry_process:
* @authdb: the authorization database
* @action: the action
* @caller: the caller
* @how: the value from "defaults" section of the
* <literal>.policy</literal> file
* @user_authenticated_as: the user that was authenticated
*
* Write an entry to the authorization database to indicate that the
* given caller is authorized for the given action.
*
* Note that this function should only be used by
* <literal>libpolkit-grant</literal> or other sufficiently privileged
* processes that deals with managing authorizations. It should never
* be used by mechanisms or applications.
*
* Returns: #TRUE if an entry was written to the authorization
* database, #FALSE if the caller of this function is not sufficiently
* privileged.
*
* Since: 0.7
*/
polkit_bool_t
polkit_authorization_db_add_entry_process (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitCaller *caller,
PolKitResult how,
uid_t user_authenticated_as)
{
char *action_id;
pid_t caller_pid;
g_return_val_if_fail (authdb != NULL, FALSE);
g_return_val_if_fail (action != NULL, FALSE);
g_return_val_if_fail (caller != NULL, FALSE);
if (!polkit_action_get_action_id (action, &action_id))
return FALSE;
if (!polkit_caller_get_pid (caller, &caller_pid))
return FALSE;
return _polkit_grantdb_write_pid (action_id, caller_pid);;
}
/**
* polkit_authorization_db_add_entry_session:
* @authdb: the authorization database
* @action: the action
* @session: the session
* @how: the value from "defaults" section of the
* <literal>.policy</literal> file
* @user_authenticated_as: the user that was authenticated
*
* Write an entry to the authorization database to indicate that the
* given session is authorized for the given action.
*
* Note that this function should only be used by
* <literal>libpolkit-grant</literal> or other sufficiently privileged
* processes that deals with managing authorizations. It should never
* be used by mechanisms or applications.
*
* Returns: #TRUE if an entry was written to the authorization
* database, #FALSE if the caller of this function is not sufficiently
* privileged.
*
* Since: 0.7
*/
polkit_bool_t
polkit_authorization_db_add_entry_session (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitSession *session,
PolKitResult how,
uid_t user_authenticated_as)
{
char *action_id;
char *session_objpath;
g_return_val_if_fail (authdb != NULL, FALSE);
g_return_val_if_fail (action != NULL, FALSE);
g_return_val_if_fail (session != NULL, FALSE);
if (!polkit_action_get_action_id (action, &action_id))