hal/libhal-policy Makefile.am, NONE, 1.1 libhal-policy-test.c, NONE,
1.1 libhal-policy.c, NONE, 1.1 libhal-policy.h, NONE, 1.1
David Zeuthen
david at kemper.freedesktop.org
Sat Feb 25 08:32:30 PST 2006
Update of /cvs/hal/hal/libhal-policy
In directory kemper:/tmp/cvs-serv32725/libhal-policy
Added Files:
Makefile.am libhal-policy-test.c libhal-policy.c
libhal-policy.h
Log Message:
2006-02-25 David Zeuthen <davidz at redhat.com>
* hal-policy.pc.in: New file
* libhal-policy/libhal-policy-test.c: New file
* libhal-policy/libhal-policy.[ch]: New files
* libhal-policy/Makefile.am: New file
* hald/Makefile.am: Uncomment hald-test as this is currently
somewhat broken
* doc/api/Doxyfile.in: Add libhal-policy to INPUT
* configure.in: Add stuff of libhal-policy
* Makefile.am: Add libhal-policy to SUBDIRS and hal-policy.pc to
pkgconfig_DATA and hal-policy.pc.in to EXTRA_DIST
--- NEW FILE: Makefile.am ---
## Process this file with automake to produce Makefile.in
INCLUDES = \
-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
-DPACKAGE_SCRIPT_DIR=\""$(datadir)/hal/scripts"\" \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
@GLIB_CFLAGS@
lib_LTLIBRARIES=libhal-policy.la
libhal_policyincludedir=$(includedir)/hal
libhal_policyinclude_HEADERS = \
libhal-policy.h
libhal_policy_la_SOURCES = \
libhal-policy.c libhal-policy.h
libhal_policy_la_LIBADD = @GLIB_LIBS@
libhal_policy_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
check_PROGRAMS = libhal-policy-test
libhal_policy_test_SOURCES = \
libhal-policy-test.c
libhal_policy_test_LDADD = @GLIB_LIBS@ libhal-policy.la
TESTS = libhal-policy-test
clean-local :
rm -f *~
--- NEW FILE: libhal-policy-test.c ---
/***************************************************************************
*
* libhal-policy-test.c : Test harness for libhal-policy
*
* Copyright (C) 2006 David Zeuthen, <david at 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
*
**************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib/gstdio.h>
#include "libhal-policy.h"
static LibHalPolicyContext *ctx;
static char *testdir;
static void
my_exit (int exit_code)
{
int rc;
GDir *dir;
GError *err;
const char *f;
g_print ("Removing tmpdir '%s'\n", testdir);
err = NULL;
if ((dir = g_dir_open (testdir, 0, &err)) == NULL) {
g_warning ("Unable to open %s: %s", testdir, err->message);
g_error_free (err);
goto error;
}
while ((f = g_dir_read_name (dir)) != NULL) {
char *file;
file = g_strdup_printf ("%s/%s", testdir, f);
rc = g_unlink (file);
if (rc != 0) {
g_warning ("Unable to unlink %s: %d (%s)", file, errno, strerror (errno));
goto error;
}
g_free (file);
}
g_dir_close (dir);
rc = g_rmdir (testdir);
if (rc != 0) {
g_warning ("Unable to rmdir %s: %d (%s)", testdir, errno, strerror (errno));
goto error;
}
error:
exit (exit_code);
}
static void
do_check (const char *policy,
uid_t uid,
int num_gids,
gid_t *gids,
const char *resource,
gboolean expected)
{
int i;
gboolean allowed;
char *gidstring;
GString *str;
str = g_string_new ("");
for (i = 0; i < num_gids; i++) {
if (i != 0)
g_string_append (str, ", ");
g_string_append_printf (str, "%d", gids[i]);
}
gidstring = g_string_free (str, FALSE);
if (LIBHAL_POLICY_RESULT_OK != libhal_policy_is_uid_gid_allowed_for_policy (
ctx, uid, num_gids, gids, policy, resource, &allowed)) {
g_warning ("fail: no policy %s", policy);
my_exit (1);
}
if (allowed != expected) {
g_warning ("fail: for uid %d (gids %s) expected %s on policy '%s' for resource '%s' but got %s",
uid, gidstring,
expected ? "TRUE" : "FALSE",
policy,
(char*) (resource != NULL ? resource : ""),
allowed ? "TRUE" : "FALSE");
my_exit (1);
}
g_print ("pass: uid %d (gids %s) got %s on policy '%s' for resource '%s'\n",
uid, gidstring,
expected ? "TRUE " : "FALSE",
policy,
(char*) (resource != NULL ? resource : ""));
g_free (gidstring);
}
static void
write_test_policy (const char *policy, const char *allow_rule, const char *deny_rule)
{
char *file;
FILE *f;
file = g_strdup_printf ("%s/%s.policy", testdir, policy);
f = fopen (file, "w");
if (f == NULL) {
g_warning ("Cannot created test policy '%s'", file);
my_exit (1);
}
fprintf (f,
"[Policy]\n"
"Allow=%s\n"
"Deny=%s\n",
allow_rule, deny_rule);
fclose (f);
g_print ("Created test policy '%s' at '%s'\n"
" Allow '%s'\n"
" Deny '%s'\n",
policy, file, allow_rule, deny_rule);
g_free (file);
}
static void
do_read_tests (void)
{
gid_t gid500[1] = {500};
int gid500_len = sizeof (gid500) / sizeof (gid_t);
gid_t gid501[1] = {501};
int gid501_len = sizeof (gid501) / sizeof (gid_t);
gid_t gid502[1] = {502};
int gid502_len = sizeof (gid502) / sizeof (gid_t);
gid_t gid500_1[2] = {500, 1};
int gid500_1_len = sizeof (gid500_1) / sizeof (gid_t);
gid_t gid501_1[2] = {501, 1};
int gid501_1_len = sizeof (gid501_1) / sizeof (gid_t);
gid_t gid502_1[2] = {502, 1};
int gid502_1_len = sizeof (gid502_1) / sizeof (gid_t);
/* feel free to add more tests here */
write_test_policy ("test0", "uid:__none__ uid:500", "");
do_check ("test0", 500, gid500_len, gid500, NULL, TRUE);
do_check ("test0", 501, gid501_len, gid501, NULL, FALSE);
do_check ("test0", 502, gid502_len, gid502, NULL, FALSE);
write_test_policy ("test1", "uid:__all__", "uid:500:res0");
do_check ("test1", 500, gid500_len, gid500, NULL, TRUE);
do_check ("test1", 501, gid501_len, gid501, NULL, TRUE);
do_check ("test1", 502, gid502_len, gid502, NULL, TRUE);
do_check ("test1", 500, gid500_len, gid500, "res0", FALSE);
do_check ("test1", 501, gid501_len, gid501, "res0", TRUE);
do_check ("test1", 502, gid502_len, gid502, "res0", TRUE);
do_check ("test1", 500, gid500_len, gid500, "res1", TRUE);
do_check ("test1", 501, gid501_len, gid501, "res1", TRUE);
do_check ("test1", 502, gid502_len, gid502, "res1", TRUE);
write_test_policy ("test2", "gid:1", "uid:501");
do_check ("test2", 500, gid500_len, gid500, NULL, FALSE);
do_check ("test2", 501, gid501_len, gid501, NULL, FALSE);
do_check ("test2", 502, gid502_len, gid502, NULL, FALSE);
do_check ("test2", 500, gid500_1_len, gid500_1, NULL, TRUE);
do_check ("test2", 501, gid501_1_len, gid501_1, NULL, FALSE);
do_check ("test2", 502, gid502_1_len, gid502_1, NULL, TRUE);
write_test_policy ("test3", "gid:1 uid:502:res1", "uid:501 uid:500:res0");
do_check ("test3", 500, gid500_1_len, gid500_1, "res0", FALSE);
do_check ("test3", 501, gid501_1_len, gid501_1, "res0", FALSE);
do_check ("test3", 502, gid502_1_len, gid502_1, "res0", TRUE);
do_check ("test3", 500, gid500_1_len, gid500_1, "res1", TRUE);
do_check ("test3", 501, gid501_1_len, gid501_1, "res1", FALSE);
do_check ("test3", 502, gid502_1_len, gid502_1, "res1", TRUE);
do_check ("test3", 500, gid500_len, gid500, "res1", FALSE);
do_check ("test3", 501, gid501_len, gid501, "res1", FALSE);
do_check ("test3", 502, gid502_len, gid502, "res1", TRUE);
write_test_policy ("test4", "gid:1:res1 uid:500:res2", "gid:502:res2");
do_check ("test4", 500, gid500_1_len, gid500_1, "res0", FALSE);
do_check ("test4", 501, gid501_1_len, gid501_1, "res0", FALSE);
do_check ("test4", 502, gid502_1_len, gid502_1, "res0", FALSE);
do_check ("test4", 500, gid500_1_len, gid500_1, "res1", TRUE);
do_check ("test4", 501, gid501_1_len, gid501_1, "res1", TRUE);
do_check ("test4", 502, gid502_1_len, gid502_1, "res1", TRUE);
do_check ("test4", 500, gid500_len, gid500, "res2", TRUE);
do_check ("test4", 501, gid501_len, gid501, "res2", FALSE);
do_check ("test4", 502, gid502_len, gid502, "res2", FALSE);
write_test_policy ("test5", "gid:1", "uid:500:res-has-:colon-in-name");
do_check ("test5", 500, gid500_1_len, gid500_1, "res-has-:colon-in-name", FALSE);
do_check ("test5", 501, gid501_1_len, gid501_1, "res-has-:colon-in-name", TRUE);
do_check ("test5", 502, gid502_1_len, gid502_1, "res-has-:colon-in-name", TRUE);
do_check ("test5", 500, gid500_len, gid500, "res-has-:colon-in-name", FALSE);
do_check ("test5", 501, gid501_len, gid501, "res-has-:colon-in-name", FALSE);
do_check ("test5", 502, gid502_len, gid502, "res-has-:colon-in-name", FALSE);
}
int
main (int argc, char *argv[])
{
int i;
GList *l;
GList *policies;
testdir = g_strdup ("/tmp/libhal-policy-test-XXXXXX");
testdir = mkdtemp (testdir);
if (testdir == NULL) {
g_warning ("Cannot create tmpdir, errno %d (%s)", errno, strerror (errno));
g_free (testdir);
exit (1);
}
g_message ("libhal-policy-test started; using tmpdir=%s", testdir);
ctx = libhal_policy_new_context ();
if (ctx == NULL) {
g_message ("Cannot create context");
my_exit (1);
}
if (!libhal_policy_context_set_txt_source (ctx, testdir)) {
g_message ("Cannot set text source to '%s'", testdir);
my_exit (1);
}
do_read_tests ();
if (libhal_policy_get_policies (ctx, &policies) != LIBHAL_POLICY_RESULT_OK) {
g_message ("Cannot get policies");
goto fail;
}
g_print ("Loaded %d policies\n", g_list_length (policies));
for (l = policies, i = 0; l != NULL; l = g_list_next (l), i++) {
const char *policy;
policy = (const char *) l->data;
g_print (" policy %d: '%s'\n", i, policy);
}
g_list_foreach (policies, (GFunc) g_free, NULL);
g_list_free (policies);
if (!libhal_policy_free_context (ctx)) {
g_warning ("Cannot free context");
goto fail;
}
g_print ("libhal-policy-test completed\n");
my_exit (0);
fail:
my_exit (1);
return 1;
}
--- NEW FILE: libhal-policy.c ---
/***************************************************************************
*
* libhal-policy.c : Simple library for hald to query policy and UI shells
* to query and modify policy
*
* Copyright (C) 2006 David Zeuthen, <david at 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 "libhal-policy.h"
/**
* @defgroup LibHalPolicy HAL policy library
* @brief Simple library for hald to query policy and UI shells to query and modify policy
*
* @{
*/
#define LIBHAL_POLICY_MAGIC 0x3117beef
/** Checks if LibHalContext *ctx == NULL */
#define LIBHAL_POLICY_CHECK_CONTEXT(_ctx_, _ret_) \
do { \
if (_ctx_ == NULL) { \
g_warning ("%s: given LibHalPolicyContext is NULL", \
__FUNCTION__); \
return _ret_; \
} \
if (_ctx_->magic != LIBHAL_POLICY_MAGIC) { \
g_warning ("%s: given LibHalPolicyContext is invalid", \
__FUNCTION__); \
return _ret_; \
} \
} while(0)
struct LibHalPolicyContext_s
{
guint32 magic;
char *txt_backend_source;
};
struct LibHalPolicyElement_s
{
LibHalPolicyContext *ctx;
LibHalPolicyElementType type;
union {
uid_t uid;
gid_t gid;
};
gboolean include_all;
gboolean exclude_all;
char *resource;
};
/** Get a new context.
*
* @return Pointer to new context or NULL if an error occured
*/
LibHalPolicyContext *
libhal_policy_new_context (void)
{
LibHalPolicyContext *ctx;
ctx = g_new0 (LibHalPolicyContext, 1);
ctx->magic = LIBHAL_POLICY_MAGIC;
ctx->txt_backend_source = g_strdup (PACKAGE_SYSCONF_DIR "/hal/policy");
return ctx;
}
gboolean
libhal_policy_context_set_txt_source (LibHalPolicyContext *ctx,
const char *directory)
{
LIBHAL_POLICY_CHECK_CONTEXT (ctx, FALSE);
g_free (ctx->txt_backend_source);
ctx->txt_backend_source = g_strdup (directory);
return TRUE;
}
/** Free a context
*
* @param ctx The context obtained from libhal_policy_new_context
* @return Pointer to new context or NULL if an error occured
*/
gboolean
libhal_policy_free_context (LibHalPolicyContext *ctx)
{
LIBHAL_POLICY_CHECK_CONTEXT (ctx, FALSE);
ctx->magic = 0;
g_free (ctx->txt_backend_source);
g_free (ctx);
return TRUE;
}
static LibHalPolicyResult
txt_backend_read_policy (LibHalPolicyContext *ctx,
const char *policy,
const char *key,
GList **result)
{
int i;
GKeyFile *keyfile;
GError *error;
LibHalPolicyResult rc;
char *path;
char *value = NULL;
char **tokens = NULL;
char *ttype = NULL;
char *tvalue = NULL;
char *tresource = NULL;
LibHalPolicyElement *elem = NULL;
GList *res;
GList *l;
char *token;
error = NULL;
rc = LIBHAL_POLICY_RESULT_ERROR;
res = NULL;
*result = NULL;
keyfile = g_key_file_new ();
path = g_strdup_printf ("%s/%s.policy", ctx->txt_backend_source, policy);
/*g_message ("Loading %s", path);*/
if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) {
g_warning ("Couldn't open key-file '%s': %s", path, error->message);
g_error_free (error);
rc = LIBHAL_POLICY_RESULT_NO_SUCH_POLICY;
goto out;
}
value = g_key_file_get_string (keyfile, "Policy", key, &error);
if (value == NULL) {
g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
g_error_free (error);
rc = LIBHAL_POLICY_RESULT_ERROR;
goto out;
}
/*g_message ("value = '%s'", value);*/
tokens = g_strsplit (value, " ", 0);
for (i = 0; tokens[i] != NULL; i++) {
char **components;
int num_components;
token = tokens[i];
/*g_message (" token = '%s'", token);*/
ttype = NULL;
tvalue = NULL;
tresource = NULL;
elem = libhal_policy_element_new (ctx);
components = g_strsplit (token, ":", 3);
num_components = g_strv_length (components);
if (num_components == 2) {
ttype = g_strdup (components[0]);
tvalue = g_strdup (components[1]);
tresource = NULL;
} else if (num_components == 3) {
ttype = g_strdup (components[0]);
tvalue = g_strdup (components[1]);
tresource = g_strdup (components[2]);
} else {
g_strfreev (components);
goto malformed_token;
}
g_strfreev (components);
/*g_message (" type='%s' value='%s' resource='%s'", ttype, tvalue, tresource != NULL ? tresource : "None");*/
if (strcmp (ttype, "uid") == 0) {
libhal_policy_element_set_type (elem, LIBHAL_POLICY_ELEMENT_TYPE_UID);
if (strcmp (tvalue, "__all__") == 0) {
libhal_policy_element_set_include_all (elem, TRUE);
} else if (strcmp (tvalue, "__none__") == 0) {
libhal_policy_element_set_exclude_all (elem, TRUE);
} else {
uid_t uid;
char *endp;
uid = (uid_t) g_ascii_strtoull (tvalue, &endp, 0);
if (endp[0] != '\0') {
uid = libhal_policy_util_name_to_uid (ctx, tvalue, NULL);
if (uid == (uid_t) -1) {
g_warning ("User '%s' does not exist", tvalue);
goto malformed_token;
}
}
libhal_policy_element_set_uid (elem, uid);
}
} else if (strcmp (ttype, "gid") == 0) {
libhal_policy_element_set_type (elem, LIBHAL_POLICY_ELEMENT_TYPE_GID);
if (strcmp (tvalue, "__all__") == 0) {
libhal_policy_element_set_include_all (elem, TRUE);
} else if (strcmp (tvalue, "__none__") == 0) {
libhal_policy_element_set_exclude_all (elem, TRUE);
} else {
gid_t gid;
char *endp;
gid = (gid_t) g_ascii_strtoull (tvalue, &endp, 0);
if (endp[0] != '\0') {
gid = libhal_policy_util_name_to_gid (ctx, tvalue);
if (gid == (gid_t) -1) {
g_warning ("Group '%s' does not exist", tvalue);
goto malformed_token;
}
}
libhal_policy_element_set_gid (elem, gid);
}
} else {
g_warning ("Token '%s' in key '%s' in group 'Policy' in file '%s' malformed",
token, key, path);
goto malformed_token;
}
if (tresource != NULL) {
libhal_policy_element_set_resource (elem, tresource);
}
g_free (ttype);
g_free (tvalue);
g_free (tresource);
res = g_list_append (res, elem);
/*libhal_policy_element_dump (elem, stderr);*/
}
*result = res;
rc = LIBHAL_POLICY_RESULT_OK;
goto out;
malformed_token:
g_warning ("Token '%s' in key '%s' in group 'Policy' in file '%s' malformed", token, key, path);
for (l = res; l != NULL; l = g_list_next (l)) {
libhal_policy_free_element ((LibHalPolicyElement *) l->data);
}
g_list_free (res);
libhal_policy_free_element (elem);
g_free (ttype);
g_free (tvalue);
g_free (tresource);
out:
g_strfreev (tokens);
g_free (value);
g_key_file_free (keyfile);
g_free (path);
return rc;
}
static void
afp_process_elem(LibHalPolicyElement *elem, gboolean *flag, uid_t uid, guint num_gids, gid_t *gid_list)
{
/*libhal_policy_element_dump (elem, stderr);*/
switch (elem->type) {
case LIBHAL_POLICY_ELEMENT_TYPE_UID:
if (elem->include_all) {
*flag = TRUE;
} else if (elem->exclude_all) {
*flag = FALSE;
}else {
if (elem->uid == uid)
*flag = TRUE;
}
break;
case LIBHAL_POLICY_ELEMENT_TYPE_GID:
if (elem->include_all) {
*flag = TRUE;
} else if (elem->exclude_all) {
*flag = FALSE;
}else {
guint i;
for (i = 0; i < num_gids; i++) {
if (elem->gid == gid_list[i])
*flag = TRUE;
}
}
break;
}
}
LibHalPolicyResult
libhal_policy_is_uid_gid_allowed_for_policy (LibHalPolicyContext *ctx,
uid_t uid,
guint num_gids,
gid_t *gid_list,
const char *policy,
const char *resource,
gboolean *result)
{
gboolean is_in_whitelist;
gboolean is_in_blacklist;
GList *l;
GList *whitelist;
GList *blacklist;
LibHalPolicyResult res;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, LIBHAL_POLICY_RESULT_INVALID_CONTEXT);
whitelist = NULL;
blacklist = NULL;
res = LIBHAL_POLICY_RESULT_ERROR;
res = libhal_policy_get_whitelist (ctx, policy, &whitelist);
if (res != LIBHAL_POLICY_RESULT_OK)
goto out;
res = libhal_policy_get_blacklist (ctx, policy, &blacklist);
if (res != LIBHAL_POLICY_RESULT_OK)
goto out;
is_in_whitelist = FALSE;
is_in_blacklist = FALSE;
/* Algorithm: To succeed.. we must be in the whitelist.. and not in the blacklist */
for (l = whitelist; l != NULL; l = g_list_next (l)) {
LibHalPolicyElement *elem;
elem = (LibHalPolicyElement *) l->data;
if ((elem->resource == NULL) ||
((resource != NULL) && (strcmp (elem->resource, resource) == 0))) {
afp_process_elem (elem, &is_in_whitelist, uid, num_gids, gid_list);
}
}
for (l = blacklist; l != NULL; l = g_list_next (l)) {
LibHalPolicyElement *elem;
elem = (LibHalPolicyElement *) l->data;
if ((elem->resource == NULL) ||
((resource != NULL) && (strcmp (elem->resource, resource) == 0))) {
afp_process_elem (elem, &is_in_blacklist, uid, num_gids, gid_list);
}
}
*result = is_in_whitelist && (!is_in_blacklist);
res = LIBHAL_POLICY_RESULT_OK;
out:
if (whitelist != NULL)
libhal_policy_free_element_list (whitelist);
if (blacklist != NULL)
libhal_policy_free_element_list (blacklist);
return res;
}
char *
libhal_policy_util_uid_to_name (LibHalPolicyContext *ctx, uid_t uid, gid_t *default_gid)
{
int rc;
char *res;
char *buf = NULL;
unsigned int bufsize;
struct passwd pwd;
struct passwd *pwdp;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, NULL);
res = NULL;
bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
buf = g_new0 (char, bufsize);
rc = getpwuid_r (uid, &pwd, buf, bufsize, &pwdp);
if (rc != 0 || pwdp == NULL) {
/*g_warning ("getpwuid_r() returned %d", rc);*/
goto out;
}
res = g_strdup (pwdp->pw_name);
if (default_gid != NULL)
*default_gid = pwdp->pw_gid;
out:
g_free (buf);
return res;
}
char *
libhal_policy_util_gid_to_name (LibHalPolicyContext *ctx, gid_t gid)
{
int rc;
char *res;
char *buf = NULL;
unsigned int bufsize;
struct group gbuf;
struct group *gbufp;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, NULL);
res = NULL;
bufsize = sysconf (_SC_GETGR_R_SIZE_MAX);
buf = g_new0 (char, bufsize);
rc = getgrgid_r (gid, &gbuf, buf, bufsize, &gbufp);
if (rc != 0 || gbufp == NULL) {
/*g_warning ("getgrgid_r() returned %d", rc);*/
goto out;
}
res = g_strdup (gbufp->gr_name);
out:
g_free (buf);
return res;
}
uid_t
libhal_policy_util_name_to_uid (LibHalPolicyContext *ctx, const char *username, gid_t *default_gid)
{
int rc;
uid_t res;
char *buf = NULL;
unsigned int bufsize;
struct passwd pwd;
struct passwd *pwdp;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, (uid_t) -1);
res = (uid_t) -1;
bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
buf = g_new0 (char, bufsize);
rc = getpwnam_r (username, &pwd, buf, bufsize, &pwdp);
if (rc != 0 || pwdp == NULL) {
/*g_warning ("getpwnam_r() returned %d", rc);*/
goto out;
}
res = pwdp->pw_uid;
if (default_gid != NULL)
*default_gid = pwdp->pw_gid;
out:
g_free (buf);
return res;
}
gid_t
libhal_policy_util_name_to_gid (LibHalPolicyContext *ctx, const char *groupname)
{
int rc;
gid_t res;
char *buf = NULL;
unsigned int bufsize;
struct group gbuf;
struct group *gbufp;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, (gid_t) -1);
res = (gid_t) -1;
bufsize = sysconf (_SC_GETGR_R_SIZE_MAX);
buf = g_new0 (char, bufsize);
rc = getgrnam_r (groupname, &gbuf, buf, bufsize, &gbufp);
if (rc != 0 || gbufp == NULL) {
/*g_warning ("getgrnam_r() returned %d", rc);*/
goto out;
}
res = gbufp->gr_gid;
out:
g_free (buf);
return res;
}
LibHalPolicyResult
libhal_policy_is_uid_allowed_for_policy (LibHalPolicyContext *ctx,
uid_t uid,
const char *policy,
const char *resource,
gboolean *result)
{
int num_groups = 0;
gid_t *groups = NULL;
char *username;
gid_t default_gid;
LibHalPolicyResult r;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, LIBHAL_POLICY_RESULT_INVALID_CONTEXT);
r = LIBHAL_POLICY_RESULT_ERROR;
if ((username = libhal_policy_util_uid_to_name (ctx, uid, &default_gid)) == NULL)
goto out;
/* TODO: this is glibc only at the moment... */
if (getgrouplist(username, default_gid, NULL, &num_groups) < 0) {
groups = (gid_t *) g_new0 (gid_t, num_groups);
if (getgrouplist(username, default_gid, groups, &num_groups) < 0) {
g_warning ("getgrouplist() failed");
goto out;
}
}
/*
{
int i;
g_debug ("uid %d (%s)", uid, username);
for (i = 0; i < num_groups; i++) {
char *group_name;
group_name = libhal_policy_util_gid_to_name (groups[i]);
g_debug (" gid %d (%s)", groups[i], group_name);
g_free (group_name);
}
}
*/
r = libhal_policy_is_uid_gid_allowed_for_policy (ctx,
uid,
num_groups,
groups,
policy,
resource,
result);
out:
g_free (username);
g_free (groups);
return r;
}
/** Return all elements in the white-list for a policy
*
* @param ctx The context obtained from libhal_policy_new_context
* @param policy Name of policy
* @param results On success set to a list of dynamically allocated LibHalPolicyElement structures.
* Must be freed by the caller
* @return Whether the operation succeeded
*/
LibHalPolicyResult
libhal_policy_get_whitelist (LibHalPolicyContext *ctx,
const char *policy,
GList **result)
{
LIBHAL_POLICY_CHECK_CONTEXT (ctx, LIBHAL_POLICY_RESULT_INVALID_CONTEXT);
return txt_backend_read_policy (ctx, policy, "Allow", result);
}
/** Return all elements in the black-list for a policy
*
* @param ctx The context obtained from libhal_policy_new_context
* @param policy Name of policy
* @param results On success set to a list of dynamically allocated LibHalPolicyElement structures.
* Must be freed by the caller
* @return Whether the operation succeeded
*/
LibHalPolicyResult
libhal_policy_get_blacklist (LibHalPolicyContext *ctx,
const char *policy,
GList **result)
{
LIBHAL_POLICY_CHECK_CONTEXT (ctx, LIBHAL_POLICY_RESULT_INVALID_CONTEXT);
return txt_backend_read_policy (ctx, policy, "Deny", result);
}
/** Return all elements in the white-list for a policy
*
* @param ctx The context obtained from libhal_policy_new_context
* @param result On success set to a list of dynamically allocated strings.
* Must be freed by the caller.
* @return Whether the operation succeeded
*/
LibHalPolicyResult
libhal_policy_get_policies (LibHalPolicyContext *ctx,
GList **result)
{
GDir *dir;
GError *error;
const char *f;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, LIBHAL_POLICY_RESULT_INVALID_CONTEXT);
error = NULL;
*result = NULL;
if ((dir = g_dir_open (ctx->txt_backend_source, 0, &error)) == NULL) {
g_critical ("Unable to open %s: %s", ctx->txt_backend_source, error->message);
g_error_free (error);
goto error;
}
while ((f = g_dir_read_name (dir)) != NULL) {
if (g_str_has_suffix (f, ".policy")) {
char *s;
int pos;
s = g_strdup (f);
pos = strlen (s) - 7;
if (pos > 0)
s[pos] = '\0';
*result = g_list_append (*result, s);
}
}
g_dir_close (dir);
return LIBHAL_POLICY_RESULT_OK;
error:
return LIBHAL_POLICY_RESULT_ERROR;
}
LibHalPolicyElement *
libhal_policy_element_new (LibHalPolicyContext *ctx)
{
LibHalPolicyElement *elem;
LIBHAL_POLICY_CHECK_CONTEXT (ctx, NULL);
elem = g_new0 (LibHalPolicyElement, 1);
elem->ctx = ctx;
return elem;
}
void
libhal_policy_element_set_type (LibHalPolicyElement *elem,
LibHalPolicyElementType type)
{
elem->type = type;
}
void
libhal_policy_element_set_include_all (LibHalPolicyElement *elem,
gboolean value)
{
elem->include_all = value;
}
void
libhal_policy_element_set_exclude_all (LibHalPolicyElement *elem,
gboolean value)
{
elem->exclude_all = value;
}
void
libhal_policy_element_set_uid (LibHalPolicyElement *elem,
uid_t uid)
{
elem->uid = uid;
}
void
libhal_policy_element_set_gid (LibHalPolicyElement *elem,
gid_t gid)
{
elem->gid = gid;
}
void
libhal_policy_element_set_resource (LibHalPolicyElement *elem,
const char *resource)
{
g_free (elem->resource);
elem->resource = g_strdup (resource);
}
void
libhal_policy_free_element (LibHalPolicyElement *elem)
{
g_free (elem->resource);
g_free (elem);
}
void
libhal_policy_free_element_list (GList *policy_element_list)
{
GList *l;
for (l = policy_element_list; l != NULL; l = g_list_next (l)) {
LibHalPolicyElement *elem = (LibHalPolicyElement *) l->data;
libhal_policy_free_element (elem);
}
g_list_free (policy_element_list);
}
LibHalPolicyElementType
libhal_policy_element_get_type (LibHalPolicyElement *elem)
{
return elem->type;
}
gboolean
libhal_policy_element_get_include_all (LibHalPolicyElement *elem)
{
return elem->include_all;
}
gboolean
libhal_policy_element_get_exclude_all (LibHalPolicyElement *elem)
{
return elem->exclude_all;
}
uid_t
libhal_policy_element_get_uid (LibHalPolicyElement *elem)
{
return elem->uid;
}
gid_t
libhal_policy_element_get_gid (LibHalPolicyElement *elem)
{
return elem->gid;
}
const char *
libhal_policy_element_get_resource (LibHalPolicyElement *elem)
{
return elem->resource;
}
void
libhal_policy_element_dump (LibHalPolicyElement *elem, FILE* fp)
{
char *t;
if (elem->type == LIBHAL_POLICY_ELEMENT_TYPE_UID)
t = "uid";
else if (elem->type == LIBHAL_POLICY_ELEMENT_TYPE_GID)
t = "gid";
else
t = "(Unknown)";
fprintf (fp, "type: %s\n", t);
if (elem->type == LIBHAL_POLICY_ELEMENT_TYPE_UID) {
if (elem->include_all) {
fprintf (fp, "uid: all\n");
} else if (elem->exclude_all) {
fprintf (fp, "uid: none\n");
} else {
fprintf (fp, "uid: %d\n", (int) elem->uid);
}
} else if (elem->type == LIBHAL_POLICY_ELEMENT_TYPE_GID) {
if (elem->include_all) {
fprintf (fp, "gid: all\n");
} else if (elem->exclude_all) {
fprintf (fp, "gid: none\n");
} else {
fprintf (fp, "gid: %d\n", (int) elem->gid);
}
}
fprintf (fp, "resource: %s\n", elem->resource != NULL ? elem->resource : "(None)");
}
/** @} */
--- NEW FILE: libhal-policy.h ---
/***************************************************************************
*
* libhal-policy.h : Simple library for hald to query policy and UI shells
* to query and modify policy
*
* Copyright (C) 2006 David Zeuthen, <david at 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef LIBHAL_POLICY_H
#define LIBHAL_POLICY_H
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <glib.h>
typedef enum {
LIBHAL_POLICY_RESULT_OK,
LIBHAL_POLICY_RESULT_ERROR,
LIBHAL_POLICY_RESULT_INVALID_CONTEXT,
LIBHAL_POLICY_RESULT_PERMISSON_DENIED,
LIBHAL_POLICY_RESULT_NO_SUCH_POLICY
} LibHalPolicyResult;
struct LibHalPolicyContext_s;
typedef struct LibHalPolicyContext_s LibHalPolicyContext;
typedef enum {
LIBHAL_POLICY_ELEMENT_TYPE_UID,
LIBHAL_POLICY_ELEMENT_TYPE_GID
} LibHalPolicyElementType;
struct LibHalPolicyElement_s;
typedef struct LibHalPolicyElement_s LibHalPolicyElement;
LibHalPolicyContext *libhal_policy_new_context (void);
gboolean libhal_policy_context_set_txt_source (LibHalPolicyContext *ctx,
const char *directory);
gboolean libhal_policy_free_context (LibHalPolicyContext *ctx);
LibHalPolicyResult libhal_policy_get_policies (LibHalPolicyContext *ctx,
GList **result);
LibHalPolicyResult libhal_policy_is_uid_allowed_for_policy (LibHalPolicyContext *ctx,
uid_t uid,
const char *policy,
const char *resource,
gboolean *result);
LibHalPolicyResult libhal_policy_is_uid_gid_allowed_for_policy (LibHalPolicyContext *ctx,
uid_t uid,
guint num_gids,
gid_t *gid_list,
const char *policy,
const char *resource,
gboolean *result);
LibHalPolicyResult libhal_policy_get_whitelist (LibHalPolicyContext *ctx,
const char *policy,
GList **result);
LibHalPolicyResult libhal_policy_get_blacklist (LibHalPolicyContext *ctx,
const char *policy,
GList **result);
LibHalPolicyResult libhal_policy_set_whitelist (LibHalPolicyContext *ctx,
const char *policy,
GList *whitelist);
LibHalPolicyResult libhal_policy_set_blacklist (LibHalPolicyContext *ctx,
const char *policy,
GList *blacklist);
LibHalPolicyElementType libhal_policy_element_get_type (LibHalPolicyElement *elem);
gboolean libhal_policy_element_get_include_all (LibHalPolicyElement *elem);
gboolean libhal_policy_element_get_exclude_all (LibHalPolicyElement *elem);
uid_t libhal_policy_element_get_uid (LibHalPolicyElement *elem);
gid_t libhal_policy_element_get_gid (LibHalPolicyElement *elem);
const char *libhal_policy_element_get_resource (LibHalPolicyElement *elem);
LibHalPolicyElement *libhal_policy_element_new (LibHalPolicyContext *ctx);
void libhal_policy_element_set_type (LibHalPolicyElement *elem,
LibHalPolicyElementType type);
void libhal_policy_element_set_include_all (LibHalPolicyElement *elem,
gboolean value);
void libhal_policy_element_set_exclude_all (LibHalPolicyElement *elem,
gboolean value);
void libhal_policy_element_set_uid (LibHalPolicyElement *elem,
uid_t uid);
void libhal_policy_element_set_gid (LibHalPolicyElement *elem,
gid_t gid);
void libhal_policy_element_set_resource (LibHalPolicyElement *elem,
const char *resource);
void libhal_policy_free_element (LibHalPolicyElement *elem);
void libhal_policy_free_element_list (GList *policy_element_list);
char *libhal_policy_util_uid_to_name (LibHalPolicyContext *ctx, uid_t uid, gid_t *default_gid);
char *libhal_policy_util_gid_to_name (LibHalPolicyContext *ctx, gid_t gid);
uid_t libhal_policy_util_name_to_uid (LibHalPolicyContext *ctx, const char *username, gid_t *default_gid);
gid_t libhal_policy_util_name_to_gid (LibHalPolicyContext *ctx, const char *groupname);
void libhal_policy_element_dump (LibHalPolicyElement *elem, FILE* fp);
#endif /* LIBHAL_POLICY_H */
More information about the hal-commit
mailing list