diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/Makefile.in | 13 | ||||
-rw-r--r-- | server/infopipe/infopipe.c | 256 | ||||
-rw-r--r-- | server/infopipe/infopipe.h | 3 | ||||
-rw-r--r-- | server/infopipe/infopipe_private.h | 64 | ||||
-rw-r--r-- | server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml | 2 | ||||
-rw-r--r-- | server/infopipe/org.freeipa.sssd.infopipe.conf | 1 | ||||
-rw-r--r-- | server/server.mk | 7 | ||||
-rw-r--r-- | server/tests/infopipe-tests.c | 320 | ||||
-rw-r--r-- | server/util/usertools.c | 35 | ||||
-rw-r--r-- | server/util/util.h | 3 |
10 files changed, 696 insertions, 8 deletions
diff --git a/server/Makefile.in b/server/Makefile.in index f281ba41..1cde271e 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -96,7 +96,9 @@ ifneq (x$(HAVE_POLICYKIT), x) LIBEXECBINS += sbin/sssd_pk endif BINS = sbin/sssd $(LIBEXECBINS) -TESTS = tests/sysdb-tests + +TESTS = tests/sysdb-tests tests/infopipe-tests +TESTS_DATA = tests/tests.ldb tests/tests_conf.ldb tests/introspect.ref SOLIBS = lib/$(MEMBEROF_SOLIB) lib/$(PROXY_BE_SOLIB) SONAMELIBS = lib/$(PROXY_BE_SONAME) lib/$(MEMBEROF_SONAME) @@ -109,15 +111,15 @@ all: showflags dirs $(OBJS) $(BINS) $(SOBASELIBS) shared-build: all tests: all $(TESTS) + cp $(INFP_INTROSPECT_XML) tests/introspect.ref dirs: @mkdir -p $(DIRS) -clean:: +clean:: testclean rm -f $(OBJS) $(BINS) $(MODULES) rm -f *.o */*.o */*/*.o - rm -f $(BINS) $(TESTS) - rm -f $(BINS) $(TESTS) + rm -f $(BINS) rm -f $(SOBASELIBS) $(SONAMELIBS) $(SOLIBS) distclean:: clean @@ -128,6 +130,9 @@ distclean:: clean realdistclean:: distclean rm -f configure config.h.in +testclean:: + rm -f $(TESTS) $(TESTS_DATA) + install:: all installdirs installheaders installlibs installbin installsupport ${INSTALLCMD} -d $(DESTDIR)$(sbindir) ${INSTALLCMD} -m 755 sbin/sssd $(DESTDIR)$(sbindir) diff --git a/server/infopipe/infopipe.c b/server/infopipe/infopipe.c index 9c129d26..80b1bef0 100644 --- a/server/infopipe/infopipe.c +++ b/server/infopipe/infopipe.c @@ -29,7 +29,8 @@ #include "monitor/monitor_sbus.h" #include "monitor/monitor_interfaces.h" #include "infopipe/sysbus.h" -#include "infopipe.h" +#include "infopipe/infopipe.h" +#include "infopipe/infopipe_private.h" struct infp_ctx { struct event_context *ev; @@ -127,12 +128,13 @@ static int infp_monitor_init(struct infp_ctx *infp_ctx) } struct sbus_method infp_methods[] = { + INFP_PERMISSION_METHODS INFP_USER_METHODS INFP_GROUP_METHODS { NULL, NULL } }; -#define INTROSPECT_CHUNK_SIZE 128 +#define INTROSPECT_CHUNK_SIZE 4096 /* Read in one memory page at a time */ int infp_introspect(DBusMessage *message, struct sbus_message_ctx *reply) { @@ -250,9 +252,257 @@ static int infp_process_init(TALLOC_CTX *mem_ctx, return ret; } +int get_object_type(const char *obj) +{ + int object_type = INFP_OBJ_TYPE_INVALID; + + if (strcasecmp(obj, "user") == 0) + object_type = INFP_OBJ_TYPE_USER; + else if (strcasecmp(obj, "group") == 0) + object_type = INFP_OBJ_TYPE_GROUP; + + return object_type; +} + +int get_action_type(const char *action) +{ + int action_type = INFP_ACTION_TYPE_INVALID; + + if (strcasecmp(action, "create") == 0) + action_type = INFP_ACTION_TYPE_CREATE; + else if ((strcasecmp(action, "delete") == 0)) + action_type = INFP_ACTION_TYPE_DELETE; + else if ((strcasecmp(action, "modify") == 0)) + action_type = INFP_ACTION_TYPE_MODIFY; + else if ((strcasecmp(action, "addmember") == 0)) + action_type = INFP_ACTION_TYPE_ADDMEMBER; + else if ((strcasecmp(action, "removemember") == 0)) + action_type = INFP_ACTION_TYPE_REMOVEMEMBER; + + return action_type; +} + +int get_attribute_type(const char *attribute) +{ + int attribute_type = INFP_ATTR_TYPE_INVALID; + + if(strcasecmp(attribute, "defaultgroup") == 0) + attribute_type = INFP_ATTR_TYPE_DEFAULTGROUP; + else if (strcasecmp(attribute, "gecos") == 0) { + attribute_type = INFP_ATTR_TYPE_GECOS; + } + else if (strcasecmp(attribute, "homedir") == 0) { + attribute_type = INFP_ATTR_TYPE_HOMEDIR; + } + else if (strcasecmp(attribute, "shell") == 0) { + attribute_type = INFP_ATTR_TYPE_SHELL; + } + else if (strcasecmp(attribute, "fullname") == 0) { + attribute_type = INFP_ATTR_TYPE_FULLNAME; + } + else if (strcasecmp(attribute, "locale") == 0) { + attribute_type = INFP_ATTR_TYPE_LOCALE; + } + else if (strcasecmp(attribute, "keyboard") == 0) { + attribute_type = INFP_ATTR_TYPE_KEYBOARD; + } + else if (strcasecmp(attribute, "session") == 0) { + attribute_type = INFP_ATTR_TYPE_SESSION; + } + else if (strcasecmp(attribute, "last_login") == 0) { + attribute_type = INFP_ATTR_TYPE_LAST_LOGIN; + } + else if (strcasecmp(attribute, "userpic") == 0) { + attribute_type = INFP_ATTR_TYPE_USERPIC; + } + + return attribute_type; +} + +bool infp_get_permissions(const char *username, + const char *domain, + int object_type, + const char *instance, + int action_type, + int action_attribute) +{ + /* TODO: have a real ACL mechanism. + * For right now, root is God and no one else can do anything. + * Note: this is buggy. It will return true for ALL requests, + * even the nonsensical ones. + */ + if (strcmp(username, "root") == 0) + return true; + return false; +} + +/* CheckPermissions(STRING domain, STRING object, STRING instance + * ARRAY(STRING action_type, STRING attribute) actions) + */ int infp_check_permissions(DBusMessage *message, struct sbus_message_ctx *reply) { - reply->reply_message = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + TALLOC_CTX *tmp_ctx; + int current_type; + DBusConnection *conn; + const char *conn_name; + uid_t uid; + char *username; + DBusMessageIter iter; + DBusMessageIter action_array_iter; + DBusMessageIter action_struct_iter; + DBusError error; + int object_type; + const char *einval_msg; + const char *domain; + const char *object; + const char *instance; + const char *action; + const char *attribute; + int action_type, attribute_type; + dbus_bool_t *permissions; + size_t count; + + tmp_ctx = talloc_new(reply); + if(tmp_ctx == NULL) { + return ENOMEM; + } + + /* Get the connection UID */ + conn = sbus_get_connection(reply->mh_ctx->conn_ctx); + conn_name = dbus_message_get_sender(message); + if (conn_name == NULL) { + DEBUG(0, ("Critical error: D-BUS client has no unique name\n")); + return EIO; + } + dbus_error_init(&error); + uid = dbus_bus_get_unix_user(conn, conn_name, &error); + if (uid == -1) { + DEBUG(0, ("Could not identify unix user. Error message was '%s:%s'\n", error.name, error.message)); + dbus_error_free(&error); + return EIO; + } + username = get_username_from_uid(tmp_ctx, uid); + if (username == NULL) { + DEBUG(0, ("No username matched the connected UID\n")); + return EIO; + } + + if (!dbus_message_iter_init(message, &iter)) { + einval_msg = talloc_strdup(tmp_ctx, "No arguments received."); + goto einval; + } + + /* domain */ + current_type = dbus_message_iter_get_arg_type (&iter); + if (current_type != DBUS_TYPE_STRING) { + einval_msg = talloc_strdup(tmp_ctx, "Expected domain"); + goto einval; + } + dbus_message_iter_get_basic(&iter, &domain); + DEBUG(9, ("Domain: %s\n", domain)); + + /* Object */ + dbus_message_iter_next(&iter); + current_type = dbus_message_iter_get_arg_type (&iter); + if (current_type != DBUS_TYPE_STRING) { + einval_msg = talloc_strdup(tmp_ctx, "Expected object"); + goto einval; + } + dbus_message_iter_get_basic(&iter, &object); + DEBUG(9, ("Object: %s\n", object)); + object_type = get_object_type(object); + if (object_type == INFP_OBJ_TYPE_INVALID) { + einval_msg = talloc_strdup(tmp_ctx, "Invalid object type"); + goto einval; + } + + /* Instance */ + dbus_message_iter_next(&iter); + current_type = dbus_message_iter_get_arg_type (&iter); + if (current_type != DBUS_TYPE_STRING) { + einval_msg = talloc_strdup(tmp_ctx, "Expected instance"); + goto einval; + } + dbus_message_iter_get_basic(&iter, &instance); + DEBUG(9, ("Instance: %s\n", instance)); + if(strcmp(instance,"")==0) { + instance = NULL; + } + + /* Actions */ + dbus_message_iter_next(&iter); + current_type = dbus_message_iter_get_arg_type (&iter); + if (current_type != DBUS_TYPE_ARRAY) { + einval_msg = talloc_strdup(tmp_ctx, "Expected array of actions"); + goto einval; + } + + dbus_message_iter_recurse(&iter, &action_array_iter); + count = 0; + while((current_type=dbus_message_iter_get_arg_type(&action_array_iter)) != DBUS_TYPE_INVALID) { + if (current_type != DBUS_TYPE_STRUCT) { + einval_msg = talloc_strdup(tmp_ctx, "Action array entry was not a struct"); + goto einval; + } + dbus_message_iter_recurse(&action_array_iter, &action_struct_iter); + /* action_type */ + if (dbus_message_iter_get_arg_type(&action_struct_iter) != DBUS_TYPE_STRING) { + einval_msg = talloc_strdup(tmp_ctx, "Missing action_type"); + goto einval; + } + dbus_message_iter_get_basic(&action_struct_iter, &action); + DEBUG(9, ("Action type: %s\n", action)); + action_type = get_action_type(action); + if(action_type == INFP_ACTION_TYPE_INVALID) { + einval_msg = talloc_asprintf(tmp_ctx, "Action type [%s] is not valid", action); + goto einval; + } + + /* attribute */ + dbus_message_iter_next(&action_struct_iter); + if (dbus_message_iter_get_arg_type(&action_struct_iter) != DBUS_TYPE_STRING) { + einval_msg = talloc_strdup(tmp_ctx, "Missing attribute"); + goto einval; + } + dbus_message_iter_get_basic(&action_struct_iter, &attribute); + DEBUG(9, ("Action attribute: %s\n", attribute)); + attribute_type = get_attribute_type(attribute); + if(attribute_type == INFP_ATTR_TYPE_INVALID) { + einval_msg = talloc_asprintf(tmp_ctx, "Attribute [%s] is not valid", attribute); + goto einval; + } + + if (dbus_message_iter_has_next(&action_struct_iter)) { + einval_msg = talloc_strdup(tmp_ctx, "Unexpected value in action struct"); + goto einval; + } + + /* Process the actions */ + count++; + permissions=talloc_realloc(tmp_ctx, permissions,dbus_bool_t, count); + permissions[count-1] = infp_get_permissions(username, domain, + object_type, instance, + action_type, attribute_type); + + dbus_message_iter_next(&action_array_iter); + } + + /* Create response message */ + reply->reply_message = dbus_message_new_method_return(message); + if (reply->reply_message == NULL) return ENOMEM; + + talloc_steal(reply, permissions); + dbus_message_append_args(reply->reply_message, + DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &permissions, count, + DBUS_TYPE_INVALID); + + talloc_free(tmp_ctx); + return EOK; + +einval: + talloc_steal(reply, einval_msg); + reply->reply_message = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, einval_msg); + talloc_free(tmp_ctx); return EOK; } diff --git a/server/infopipe/infopipe.h b/server/infopipe/infopipe.h index 83a3d8d4..9db5c0d1 100644 --- a/server/infopipe/infopipe.h +++ b/server/infopipe/infopipe.h @@ -55,6 +55,9 @@ int infp_introspect(DBusMessage *message, struct sbus_message_ctx *reply); #define INFP_CHECK_PERMISSIONS "CheckPermissions1" int infp_check_permissions(DBusMessage *message, struct sbus_message_ctx *reply); +#define INFP_PERMISSION_METHODS \ + {INFP_CHECK_PERMISSIONS,infp_check_permissions}, + /********************************************************** * User Methods (from infopipe_users.c) * **********************************************************/ diff --git a/server/infopipe/infopipe_private.h b/server/infopipe/infopipe_private.h new file mode 100644 index 00000000..afac334b --- /dev/null +++ b/server/infopipe/infopipe_private.h @@ -0,0 +1,64 @@ +/* + SSSD + + InfoPipe + + Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009 + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INFOPIPE_PRIVATE_H_ +#define INFOPIPE_PRIVATE_H_ + +enum object_types { + INFP_OBJ_TYPE_INVALID = 0, + INFP_OBJ_TYPE_USER, + INFP_OBJ_TYPE_GROUP +}; +int get_object_type(const char *obj); + +enum action_types { + INFP_ACTION_TYPE_INVALID = 0, + INFP_ACTION_TYPE_CREATE, + INFP_ACTION_TYPE_DELETE, + INFP_ACTION_TYPE_MODIFY, + INFP_ACTION_TYPE_ADDMEMBER, + INFP_ACTION_TYPE_REMOVEMEMBER +}; +int get_action_type(const char *action); + +enum attribute_types { + INFP_ATTR_TYPE_INVALID = 0, + INFP_ATTR_TYPE_DEFAULTGROUP, + INFP_ATTR_TYPE_GECOS, + INFP_ATTR_TYPE_HOMEDIR, + INFP_ATTR_TYPE_SHELL, + INFP_ATTR_TYPE_FULLNAME, + INFP_ATTR_TYPE_LOCALE, + INFP_ATTR_TYPE_KEYBOARD, + INFP_ATTR_TYPE_SESSION, + INFP_ATTR_TYPE_LAST_LOGIN, + INFP_ATTR_TYPE_USERPIC +}; +int get_attribute_type(const char *attribute); + +bool infp_get_permissions(const char *username, + const char *domain, + int object_type, + const char *instance, + int action_type, + int action_attribute); + +#endif /* INFOPIPE_PRIVATE_H_ */ diff --git a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml index 5c50cfe8..41220606 100644 --- a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml +++ b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml @@ -123,7 +123,7 @@ defaultgroup(STRING) gecos(STRING) homedir(STRING) - shell(STRSING) + shell(STRING) fullname(STRING) locale(STRING) keyboard(STRING) diff --git a/server/infopipe/org.freeipa.sssd.infopipe.conf b/server/infopipe/org.freeipa.sssd.infopipe.conf index b9ca5588..2ed3cf1b 100644 --- a/server/infopipe/org.freeipa.sssd.infopipe.conf +++ b/server/infopipe/org.freeipa.sssd.infopipe.conf @@ -16,6 +16,7 @@ <!-- Right now, this will be handled by a limited ACL within the InfoPipe Daemon. --> <policy context="default"> + <allow own="org.freeipa.sssd.infopipe1.test"/> <allow send_interface="org.freeipa.sssd.infopipe1"/> </policy> diff --git a/server/server.mk b/server/server.mk index b37be9fa..744dc243 100644 --- a/server/server.mk +++ b/server/server.mk @@ -4,6 +4,7 @@ UTIL_OBJ = \ util/server.o \ util/memory.o \ util/btreemap.o \ + util/usertools.o \ monitor/monitor_sbus.o \ providers/dp_sbus.o \ sbus/sssd_dbus_common.o \ @@ -47,6 +48,9 @@ MEMBEROF_OBJ = \ SYSDB_TEST_OBJ = \ tests/sysdb-tests.o +INFP_TEST_OBJ = \ + tests/infopipe-tests.o + sbin/sssd: $(SERVER_OBJ) $(UTIL_OBJ) $(CC) -o sbin/sssd $(SERVER_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS) @@ -76,3 +80,6 @@ lib/$(MEMBEROF_SOBASE): $(MEMBEROF_OBJ) #Tests tests/sysdb-tests: $(SYSDB_TEST_OBJ) $(UTIL_OBJ) $(CC) -o tests/sysdb-tests $(SYSDB_TEST_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS) $(CHECK_LIBS) + +tests/infopipe-tests: $(INFP_TEST_OBJ) $(UTIL_OBJ) + $(CC) -o tests/infopipe-tests $(INFP_TEST_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS) $(CHECK_LIBS) diff --git a/server/tests/infopipe-tests.c b/server/tests/infopipe-tests.c new file mode 100644 index 00000000..2aaa653a --- /dev/null +++ b/server/tests/infopipe-tests.c @@ -0,0 +1,320 @@ +/* + SSSD + + InfoPipe + + Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009 + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <check.h> +#include <talloc.h> +#include <tevent.h> +#include <popt.h> +#include <dbus/dbus.h> +#include "util/util.h" +#include "confdb/confdb.h" +#include "sbus/sssd_dbus.h" +#include "infopipe/infopipe.h" + +#define INFP_TEST_DBUS_NAME "org.freeipa.sssd.infopipe1.test" +#define TEST_TIMEOUT 30000 /* 30 seconds */ + +static int setup_infp_tests(DBusConnection **bus) +{ + DBusError error; + int ret; + + /* Connect to the system bus */ + dbus_error_init(&error); + *bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (*bus == NULL) { + fail("Could not connect to the system bus. %s:%s", error.name, error.message); + dbus_error_free(&error); + return EIO; + } + + /* Abort the tests if disconnect occurs */ + dbus_connection_set_exit_on_disconnect(*bus, TRUE); + + ret = dbus_bus_request_name(*bus, + INFP_TEST_DBUS_NAME, + /* We want exclusive access */ + DBUS_NAME_FLAG_DO_NOT_QUEUE, + &error); + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + /* We were unable to register on the system bus */ + fail("Unable to request name on the system bus. Error: %s:%s\n", error.name, error.message); + dbus_error_free(&error); + return EIO; + } + return EOK; +} + +static int teardown_infp_tests(DBusConnection *bus) +{ + dbus_connection_unref(bus); + return EOK; +} + +#define INTROSPECT_CHUNK_SIZE 4096 +START_TEST(test_infp_introspect) +{ + TALLOC_CTX *tmp_ctx; + DBusConnection *bus; + DBusError error; + DBusMessage *introspect_req; + DBusMessage *reply; + FILE *xml_stream; + char *chunk; + char *introspect_xml; + char *returned_xml; + unsigned long xml_size; + size_t chunk_size; + int type; + + if (setup_infp_tests(&bus) != EOK) { + fail("Could not set up the tests"); + return; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + fail("Could not create temporary talloc context"); + goto done; + } + + /* Create introspection method call */ + introspect_req = dbus_message_new_method_call(INFOPIPE_DBUS_NAME, + INFOPIPE_PATH, + DBUS_INTROSPECT_INTERFACE, + DBUS_INTROSPECT_METHOD); + if(!introspect_req) { + fail("Could not create new method call message"); + goto done; + } + + /* Send the message */ + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(bus, + introspect_req, + TEST_TIMEOUT, + &error); + if(!reply) { + fail("Could not send message. Error: %s:%s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + type = dbus_message_get_type(reply); + switch (type) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + /* Read in the reference Introspection XML */ + xml_stream = fopen("introspect.ref", "r"); + if(xml_stream == NULL) { + DEBUG(0, ("Could not open the introspection XML for reading: [%d].\n", errno)); + return; + } + + chunk = talloc_size(tmp_ctx, INTROSPECT_CHUNK_SIZE); + if (chunk == NULL) goto done; + + xml_size = 0; + introspect_xml = NULL; + do { + chunk_size = fread(chunk, 1, INTROSPECT_CHUNK_SIZE, xml_stream); + introspect_xml = talloc_realloc_size(tmp_ctx, introspect_xml, xml_size+chunk_size+1); + if (introspect_xml == NULL) goto done; + + memcpy(introspect_xml+xml_size, chunk, chunk_size); + xml_size += chunk_size; + } while(chunk_size == INTROSPECT_CHUNK_SIZE); + introspect_xml[xml_size] = '\0'; + talloc_free(chunk); + + /* Get the XML from the message */ + dbus_message_get_args(reply, &error, + DBUS_TYPE_STRING, &returned_xml, + DBUS_TYPE_INVALID); + + /* Verify that the reply matches the reference file */ + if (strcmp(introspect_xml, returned_xml) != 0) { + fail("Verify Introspection XML: FAILED"); + } + break; + case DBUS_MESSAGE_TYPE_ERROR: + fail("Error: %s\n", dbus_message_get_error_name(reply)); + goto done; + } + +done: + talloc_free(tmp_ctx); + teardown_infp_tests(bus); +} +END_TEST + +START_TEST(test_infp_check_permissions) +{ + TALLOC_CTX *tmp_ctx; + DBusConnection *bus; + DBusError error; + DBusMessage *permission_req; + DBusMessage *reply; + DBusMessageIter msg_iter; + DBusMessageIter array_iter; + DBusMessageIter struct_iter; + dbus_bool_t *permission_array; + int permission_count; + char *domain; + char *object; + char *instance; + char *action; + char *attribute; + int type, i; + + if (setup_infp_tests(&bus) != EOK) { + fail("Could not set up the tests"); + return; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + fail("Could not create temporary talloc context"); + goto done; + } + + /* Create permission request message */ + permission_req = dbus_message_new_method_call(INFOPIPE_DBUS_NAME, + INFOPIPE_PATH, + INFOPIPE_INTERFACE, + INFP_CHECK_PERMISSIONS); + if(!permission_req) { + fail("Could not create new method call message"); + goto done; + } + + /* Add arguments */ + domain = talloc_strdup(tmp_ctx, "LOCAL"); + object = talloc_strdup(tmp_ctx, "user"); + instance = talloc_strdup(tmp_ctx, "testuser1"); + action = talloc_strdup(tmp_ctx, "modify"); + attribute = talloc_strdup(tmp_ctx, "userpic"); + + dbus_message_append_args(permission_req, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_STRING, &object, + DBUS_TYPE_STRING, &instance, + DBUS_TYPE_INVALID); + + dbus_message_iter_init_append(permission_req, &msg_iter); + dbus_message_iter_open_container(&msg_iter, + DBUS_TYPE_ARRAY, "(ss)", /* Array of structs */ + &array_iter); + dbus_message_iter_open_container(&array_iter, + DBUS_TYPE_STRUCT, NULL, + &struct_iter); + dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &action); + dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &attribute); + dbus_message_iter_close_container(&array_iter, &struct_iter); + dbus_message_iter_close_container(&msg_iter, &array_iter); + + + /* Send the message */ + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(bus, + permission_req, + TEST_TIMEOUT, + &error); + if(!reply) { + fail("Could not send message. Error: %s:%s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + type = dbus_message_get_type(reply); + switch (type) { + case DBUS_MESSAGE_TYPE_ERROR: + fail("Error: %s\n", dbus_message_get_error_name(reply)); + goto done; + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + dbus_message_get_args(reply, &error, + DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &permission_array, &permission_count, + DBUS_TYPE_INVALID); + } + + i = 0; + while(i < permission_count) { + if (permission_array[i] == true) { + fail("User was granted permission unexpectedly"); + goto done; + } + i++; + } + +done: + talloc_free(tmp_ctx); + teardown_infp_tests(bus); +} +END_TEST + +Suite *create_infopipe_suite(void) +{ + Suite *s = suite_create("infopipe"); + + TCase *tc_infp = tcase_create("InfoPipe Tests"); + + /* Test the Introspection XML */ + tcase_add_test(tc_infp, test_infp_introspect); + tcase_add_test(tc_infp, test_infp_check_permissions); + +/* Add all test cases to the test suite */ + suite_add_tcase(s, tc_infp); + + return s; +} + +int main(int argc, const char *argv[]) { + int opt; + poptContext pc; + int failure_count; + Suite *infopipe_suite; + SRunner *sr; + + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_MAIN_OPTS + { NULL } + }; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + infopipe_suite = create_infopipe_suite(); + sr = srunner_create(infopipe_suite); + srunner_run_all(sr, CK_VERBOSE); + failure_count = srunner_ntests_failed(sr); + srunner_free(sr); + return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/server/util/usertools.c b/server/util/usertools.c new file mode 100644 index 00000000..07930613 --- /dev/null +++ b/server/util/usertools.c @@ -0,0 +1,35 @@ +/* + SSSD + + User tools + + Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009 + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <pwd.h> +#include <talloc.h> + +char *get_username_from_uid(TALLOC_CTX *mem_ctx, uid_t uid) +{ + char *username; + struct passwd *pwd; + + pwd = getpwuid(uid); + if (!pwd) return NULL; + + username = talloc_strdup(mem_ctx, pwd->pw_name); + return username; +} diff --git a/server/util/util.h b/server/util/util.h index 1c3fa2e7..7388febd 100644 --- a/server/util/util.h +++ b/server/util/util.h @@ -65,4 +65,7 @@ TALLOC_CTX *sssd_mem_takeover(TALLOC_CTX *mem_ctx, void *ptr, int (*destructor)(void **)); +/* from usertools.c */ +char *get_username_from_uid(TALLOC_CTX *mem_ctx, uid_t uid); + #endif /* __SSSD_UTIL_H__ */ |