diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/infopipe/infopipe.c | 46 | ||||
-rw-r--r-- | server/infopipe/infopipe.h | 81 | ||||
-rw-r--r-- | server/infopipe/infopipe_groups.c | 54 | ||||
-rw-r--r-- | server/infopipe/infopipe_users.c | 59 | ||||
-rw-r--r-- | server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml | 275 | ||||
-rw-r--r-- | server/infopipe/org.freeipa.sssd.infopipe.conf | 11 | ||||
-rw-r--r-- | server/infopipe/sysbus.c | 105 | ||||
-rw-r--r-- | server/infopipe/sysbus.h | 10 | ||||
-rw-r--r-- | server/sbus/sssd_dbus.h | 31 | ||||
-rw-r--r-- | server/sbus/sssd_dbus_connection.c | 28 | ||||
-rw-r--r-- | server/sbus/sssd_dbus_private.h | 6 | ||||
-rw-r--r-- | server/server.mk | 2 | ||||
-rw-r--r-- | server/tests/sysdb-tests.c | 18 |
13 files changed, 675 insertions, 51 deletions
diff --git a/server/infopipe/infopipe.c b/server/infopipe/infopipe.c index 81541d82..8fe7ee72 100644 --- a/server/infopipe/infopipe.c +++ b/server/infopipe/infopipe.c @@ -22,13 +22,14 @@ #include <stdlib.h> #include <stdio.h> #include "popt.h" -#include "infopipe.h" #include "util/util.h" +#include "util/btreemap.h" #include "sbus/sssd_dbus.h" #include "sbus/sbus_client.h" #include "monitor/monitor_sbus.h" #include "monitor/monitor_interfaces.h" #include "infopipe/sysbus.h" +#include "infopipe.h" struct infp_ctx { struct event_context *ev; @@ -37,11 +38,6 @@ struct infp_ctx { struct sysbus_ctx *sysbus; }; -struct sbus_method infp_methods[] = { - { SYSBUS_GET_PARAM, sysbus_get_param }, - { NULL, NULL } -}; - static int service_identity(DBusMessage *message, void *data, DBusMessage **r) { dbus_uint16_t version = INFOPIPE_VERSION; @@ -134,6 +130,21 @@ static int infp_monitor_init(struct infp_ctx *infp_ctx) return EOK; } +struct sbus_method infp_methods[] = { + INFP_USER_METHODS + INFP_GROUP_METHODS + { NULL, NULL } +}; + +int infp_introspect(DBusMessage *message, void *data, DBusMessage **r) +{ + /* Return the Introspection XML */ + + /* TODO: actually return the file */ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + static int infp_process_init(TALLOC_CTX *mem_ctx, struct event_context *ev, struct confdb_ctx *cdb) @@ -153,14 +164,33 @@ static int infp_process_init(TALLOC_CTX *mem_ctx, ret = infp_monitor_init(infp_ctx); if (ret != EOK) { DEBUG(0, ("Fatal error setting up monitor bus\n")); + return EIO; + } + + /* Connect to the D-BUS system bus and set up methods */ + ret = sysbus_init(infp_ctx, &infp_ctx->sysbus, + infp_ctx->ev, INFOPIPE_DBUS_NAME, + INFOPIPE_INTERFACE, INFOPIPE_PATH, + infp_methods, infp_introspect); + if (ret != EOK) { + DEBUG(0, ("Failed to connect to the system message bus\n")); + return EIO; } - /* Connect to the D-BUS system bus */ - ret = sysbus_init(infp_ctx, &infp_ctx->sysbus, infp_methods); + /* Add the infp_ctx to the sbus_conn_ctx private data + * so we can pass it into message handler functions + */ + sbus_conn_set_private_data(sysbus_get_sbus_conn(infp_ctx->sysbus), infp_ctx); return ret; } +int infp_check_permissions(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + int main(int argc, const char *argv[]) { int opt; diff --git a/server/infopipe/infopipe.h b/server/infopipe/infopipe.h index 259729aa..8492c1b1 100644 --- a/server/infopipe/infopipe.h +++ b/server/infopipe/infopipe.h @@ -22,8 +22,87 @@ #ifndef INFOPIPE_H_ #define INFOPIPE_H_ -#define INFOPIPE_DBUS_NAME "org.freeipa.sssd.infopipe" +#define INFOPIPE_DBUS_NAME "org.freeipa.sssd.infopipe1" +#define INFOPIPE_INTERFACE "org.freeipa.sssd.infopipe1" +#define INFOPIPE_PATH "/org/freeipa/sssd/infopipe1" #define INFOPIPE_VERSION 0x0001 #define INFOPIPE_SERVICE_NAME "infp" +/* InfoPipe Methods + * NOTE: Any changes to the method names and arguments for these calls + * must also be updated in the org.freeipa.sssd.infopipe.Introspect.xml + * or clients may not behave properly. + */ + +/********************************************************** + * Introspection Methods (from infopipe.c) * + **********************************************************/ + +/* This function must be exposed through the + * org.freedesktop.DBus.Introspectable interface + */ +#define INFP_INTROSPECT "Introspect" +int infp_introspect(DBusMessage *message, void *data, DBusMessage **r); + +/********************************************************** + * Permission Methods (from infopipe.c) * + **********************************************************/ +#define INFP_CHECK_PERMISSIONS "CheckPermissions1" +int infp_check_permissions(DBusMessage *message, void *data, DBusMessage **r); + +/********************************************************** + * User Methods (from infopipe_users.c) * + **********************************************************/ +#define INFP_USERS_GET_CACHED "GetCachedUsers1" +int infp_users_get_cached(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USERS_CREATE "CreateUser1" +int infp_users_create(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USERS_DELETE "DeleteUser1" +int infp_users_delete(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USERS_GET_ATTR "GetUserAttributes1" +int infp_users_get_attr(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USERS_SET_ATTR "SetUserAttributes1" +int infp_users_set_attr(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USERS_SET_UID "Set_YouReallyDoNotWantToUseThisFunction_UserUID1" +int infp_users_set_uid(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_USER_METHODS \ + {INFP_USERS_GET_CACHED, infp_users_get_cached}, \ + {INFP_USERS_CREATE, infp_users_create}, \ + {INFP_USERS_DELETE, infp_users_delete}, \ + {INFP_USERS_GET_ATTR, infp_users_get_attr}, \ + {INFP_USERS_SET_ATTR, infp_users_set_attr}, \ + {INFP_USERS_SET_UID, infp_users_set_uid}, + +/********************************************************** + * Group Methods (from infopipe_groups.c) * + **********************************************************/ + +#define INFP_GROUPS_CREATE "CreateGroup1" +int infp_groups_create(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_GROUPS_DELETE "DeleteGroup1" +int infp_groups_delete(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_GROUPS_ADD_MEMBERS "AddGroupMembers1" +int infp_groups_add_members(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_GROUPS_REMOVE_MEMBERS "RemoveGroupMembers1" +int infp_groups_remove_members(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_GROUPS_SET_GID "Set_YouReallyDoNotWantToUseThisFunction_GroupGID1" +int infp_groups_set_gid(DBusMessage *message, void *data, DBusMessage **r); + +#define INFP_GROUP_METHODS \ + {INFP_GROUPS_CREATE, infp_groups_create}, \ + {INFP_GROUPS_DELETE, infp_groups_delete}, \ + {INFP_GROUPS_ADD_MEMBERS, infp_groups_add_members}, \ + {INFP_GROUPS_REMOVE_MEMBERS, infp_groups_remove_members}, \ + {INFP_GROUPS_SET_GID, infp_groups_set_gid}, + #endif /* INFOPIPE_H_ */ diff --git a/server/infopipe/infopipe_groups.c b/server/infopipe/infopipe_groups.c new file mode 100644 index 00000000..4b9cfc22 --- /dev/null +++ b/server/infopipe/infopipe_groups.c @@ -0,0 +1,54 @@ +/* + 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 <dbus/dbus.h> +#include "util/util.h" +#include "infopipe.h" + +int infp_groups_create(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_groups_delete(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_groups_add_members(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_groups_remove_members(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_groups_set_gid(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} diff --git a/server/infopipe/infopipe_users.c b/server/infopipe/infopipe_users.c new file mode 100644 index 00000000..632e624f --- /dev/null +++ b/server/infopipe/infopipe_users.c @@ -0,0 +1,59 @@ +/* + 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 <dbus/dbus.h> +#include "util/util.h" +#include "infopipe.h" + +int infp_users_get_cached(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_users_create(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_users_delete(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_users_get_attr(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_users_set_attr(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} + +int infp_users_set_uid(DBusMessage *message, void *data, DBusMessage **r) +{ + *r = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + return EOK; +} diff --git a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml new file mode 100644 index 00000000..5c50cfe8 --- /dev/null +++ b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml @@ -0,0 +1,275 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/org/freeipa/sssd/infopipe1"> + <interface name="org.freeipa.sssd.infopipe"> + <annotation + name="org.freeipa.sssd.infopipe.DocString.Summary" + value="InfoPipe Interface version 1" + /> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="This is a D-BUS interface used for reading and writing POSIX and extended user attributes within the System Security Services Daemon." + /> + +<!-- +************************************************************************** +* Permission Methods * +************************************************************************** +--> + <method name="CheckPermissions1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Determine whether the caller has permissions on one or more instances of domain objects + @param domain The domain to query + @param object An object type in the domain + Object Types: + user + group + @param instance A particular instance of an object (a username or group name). An empty string will be interpreted as all instances. + @param actions A list of actions to check the permissions of. Each action is described as a pair of (action_type, attribute). If attribute is left as an empty string, the query is for a global value (such as create or delete user) If the attribute value does not make sense for a particular object/instance/action, it will be ignored. Action types not applicable to an object/instance will return false (such as addmember on users). + Available action types: + create + delete + modify + addmember + removemember + @return permissions A list of boolean values returned in the same order as the action list, one for each requested action. True means permission on that action is granted. + @note some examples: + Can I create new users in domain LOCAL?: + CheckPermissions(domain=>'LOCAL', object=>'user', instance=>'', actions=>[('create','')]) + returns permissions=>[0] + Can I create new groups in domain LOCAL? + CheckPermissions(domain=>'LOCAL', object=>'group', instance=>'', actions=>[('create','')]) + returns permissions=>[0] + Can I modify user testuser1's userpic and full name? + CheckPermissions(domain=>'LOCAL', object=>'user', instance=>'testuser1', actions=>[('modify','userpic'),('modify','fullname')]) + returns permissions=>[1,0] + Can I add members to group wheel? + CheckPermissions(domain=>'LOCAL', object=>'user', instance=>'wheel', actions=>[('addmember','somearg')]) + returns permissions=>[1] + The argument 'somearg' is ignored, since it does not apply to addmember." + /> + <arg name="domain" type="s" direction="in" /> + <arg name="object" type="s" direction="in" /> + <arg name="instance" type="s" direction="in" /> + <arg name="actions" type="a(ss)" direction="in" /> + <arg name="permissions" type="ab" direction="out" /> + </method> +<!-- +************************************************************************** +* User Methods * +************************************************************************** +--> + <method name="GetCachedUsers1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Get a list of users stored locally in SSSD for this system. This is not a complete user listing for remote domains, only a listing of domain members that have logged in locally. + @param domain The domain to query. + @param minlastlogin Return only users who have logged in successfully since this UNIX timestamp. For all cached users in a domain, set to 0. + @return users Returns a string array of usernames. + @error DBUS_ERROR_INVALID_ARGS One or more specified domains do not exist." + /> + <arg name="domain" type="s" direction="in" /> + <arg name="minlastlogin" type="t" direction="in" /> + <arg name="users" type="as" /> + </method> + + <method name="CreateUser1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Create a new user in a particular domain. User will initially have a disabled password. + @param domain The domain in which to add the user + @param username Username for the new user. Must be unique within a domain. + @param defaultgroup Default group name for the user. + @param fullname Full (display) name for the user. Will set both 'fullname' and 'gecos' to this value initially. + @param homedir Home directory path for the user. Must be a parsable path, but does not need to exist or be mounted. + @param shell Login shell. Must exist in /etc/shells. + @return Returns an empty D-BUS reply to indicate success. Failure will return an error. + @error DBUS_ERROR_INVALID_ARGS See parameter requirements. Reason will be included in the error message. + @error DBUS_ERROR_ACCESS_DENIED Caller did not have permission to create a new user on the specified domain + @note CreateUser will ignore users that already exist. + @note This function will automatically generate an appropriate UID for the user." + /> + <arg name="domain" type="s" direction="in" /> + <arg name="username" type="s" direction="in" /> + <arg name="defaultgroup" type="s" direction="in" /> + <arg name="fullname" type="s" direction="in" /> + <arg name="homedir" type="s" direction="in" /> + <arg name="shell" type="s" direction="in" /> + </method> + + <method name="DeleteUser1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Delete a user by UID from a specified domain. + @param username The user to delete. + @param domain The domain from which to delete the user. + @return Returns an empty D-BUS reply if the deletion was successful. Failure will return an error. + @error DBUS_ERROR_INVALID_ARGS No such username or domain. See error message for details. + @error DBUS_ACCESS_DENIED Caller did not have permission to delete this user." + /> + <arg name="username" type="s" direction="in" /> + <arg name="domain" type="s" direction="in" /> + </method> + + <method name="GetUserAttributes1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Get user information + @param usernames An array of unique usernames. + @param domain The domain from which to query user information. + @param filter An array of strings containing a list of requested attributes. A zero-length array will indicate to return all authorized parameters. + attributes(value type): + defaultgroup(STRING) + gecos(STRING) + homedir(STRING) + shell(STRSING) + fullname(STRING) + locale(STRING) + keyboard(STRING) + session(STRING) + last_login(UINT64) + userpic(BYTE ARRAY) + @return attributes An array of extended user information dicts, one for each requested username. Only attributes that the caller had read authorization for will be returned. + @error DBUS_ERROR_INVALID_ARGS Usernames or filter entries were not unique or one or more filter entries were invalid. + @note For standard POSIX attributes, use getpwnam(). + @note The attribute userpic may contain very large binary data. It is advisable to request this data separately from other attributes to avoid D-BUS message size limits." + /> + <arg name="usernames" type="as" direction="in" /> + <arg name="domain" type="as" direction="in" /> + <arg name="filter" type="as" direction="in" /> + <arg name="attributes" type="a{sv}" direction="out" /> + </method> + + <method name="SetUserAttributes1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Set user attributes for one or more users + @param usernames An array of unique usernames. + @param domain The domain of the users to edit. + @param attributes An array of dict(string, variant), either exactly one dict (meaning use the same values for all UIDs), or one dict for each username. An empty value for the variant means delete the attribute. + attributes(value type): + defaultgroup(STRING) + gecos(STRING) + homedir(STRING) + shell(STRING) + fullname(STRING) + locale(STRING) + keyboard(STRING) + session(STRING) + last_login(UINT64) + userpic(BYTE ARRAY) + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS Usernames were not unique + @note The attribute userpic may contain very large binary data. It is advisable to set this data separately from other attributes to avoid D-BUS message size limits." + /> + <arg name="usernames" type="as" direction="in" /> + <arg name="domain" type="s" direction="in" /> + <arg name="attributes" type="a{sv}" direction="in" /> + </method> + + <method name="Set_YouReallyDoNotWantToUseThisFunction_UserUID1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Change the User ID for a user. + @param username The username + @param domain The user's domain + @param uid The new UID + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS Domain or user did not exist + @error DBUS_ERROR_ACCESS_DENIED Caller did not have permission to edit this user + @note This function should be used sparingly. The automatically-generated user id from CreateUser should be sufficient for most cases." + /> + <arg name="username" type="s" direction="in" /> + <arg name="domain" type="s" direction="in" /> + <arg name="uid" type="t" direction="in" /> + </method> + +<!-- +************************************************************************** +* Group Methods * +************************************************************************** +--> + <method name="CreateGroup1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Create new user groups + @param groupnames A list of new groups to add. + @param domain The domain in which to create the groups. + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS Domain does not exist. + @error DBUS_ERROR_ACCESS_DENIED The caller does not have authorization to create groups in the specified domain. + @note CreateGroup ignores groups that already exist. + @note This function will automatically generate an appropriate group ID for this group." + /> + <arg name="groupnames" type="as" direction="in" /> + <arg name="domain" type="s" direction="in" /> + </method> + + <method name="DeleteGroup1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Delete a user group + @param groupname A group to delete. + @param domain The domain from which to delete the group. + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS Domain does not exist. + @error DBUS_ERROR_ACCESS_DENIED The caller does not have authorization to delete groups from the specified domain. + @note DeleteGroup ignores groups that don't exist." + /> + <arg name="groupname" type="s" direction="in" /> + <arg name="domain" type="s" direction="out" /> + </method> + + <method name="AddGroupMembers1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Add members to a group + @param group Group being modified. + @domain The domain the group belongs to. + @members Array of member strings to add to the group. + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS The domain does not exist + @error DBUS_ERROR_ACCESS_DENIED The caller does not have authorization to modify the group. + @note AddGroupMembers ignores members that don't exist" + /> + <arg name="group" type="s" direction="in" /> + <arg name="domain" type="s" direction="in" /> + <arg name="members" type="as" direction="in" /> + </method> + + <method name="RemoveGroupMembers1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Remove members from a group + @param group Group being modified. + @domain The domain the group belongs to. + @members Array of member strings to remove from the group. + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS The domain does not exist + @error DBUS_ERROR_ACCESS_DENIED The caller does not have authorization to modify the group. + @note RemoveGroupMembers ignores members that don't exist" + /> + <arg name="group" type="s" direction="in" /> + <arg name="domain" type="s" direction="in" /> + <arg name="members" type="as" direction="in" /> + </method> + + <method name="Set_YouReallyDoNotWantToUseThisFunction_GroupGID1"> + <annotation + name="org.freeipa.sssd.infopipe.DocString" + value="Change the User ID for a user. + @param group The group name + @param domain The group's domain + @param gid The new GID + @return Returns an empty D-BUS reply on success. Will return an error on failure. + @error DBUS_ERROR_INVALID_ARGS Domain or group did not exist + @error DBUS_ERROR_ACCESS_DENIED Caller did not have permission to edit this group + @note This function should be used sparingly. The automatically-generated group id from CreateGroup should be sufficient for most cases." + /> + <arg name="group" type="s" direction="in" /> + <arg name="domain" type="s" direction="in" /> + <arg name="guid" type="t" direction="in" /> + </method> + </interface> +</node> diff --git a/server/infopipe/org.freeipa.sssd.infopipe.conf b/server/infopipe/org.freeipa.sssd.infopipe.conf index e33eb30c..b9ca5588 100644 --- a/server/infopipe/org.freeipa.sssd.infopipe.conf +++ b/server/infopipe/org.freeipa.sssd.infopipe.conf @@ -8,14 +8,15 @@ <!-- Only root can own the SSSD service --> <policy user="root"> - <allow own="org.freeipa.sssd.infopipe"/> + <allow own="org.freeipa.sssd.infopipe1"/> + <allow send_interface="org.freeipa.sssd.infopipe1"/> </policy> - <!-- Allow anyone to invoke methods on the infopipe - This is temporary. Real rules will be established - later --> + <!-- Allow all methods on the interface --> + <!-- Right now, this will be handled by a limited ACL + within the InfoPipe Daemon. --> <policy context="default"> - <allow send_interface="org.freeipa.sssd.infopipe"/> + <allow send_interface="org.freeipa.sssd.infopipe1"/> </policy> </busconfig> diff --git a/server/infopipe/sysbus.c b/server/infopipe/sysbus.c index 2c28bacc..a6b352fa 100644 --- a/server/infopipe/sysbus.c +++ b/server/infopipe/sysbus.c @@ -28,20 +28,73 @@ #include "infopipe/infopipe.h" struct sysbus_ctx { - DBusConnection *conn; - struct sbus_method_ctx *method_ctx_list; + struct sbus_conn_ctx *sconn; + struct sbus_method_ctx *service_methods; void *pvt_data; }; static int sysbus_destructor(TALLOC_CTX *ctx) { struct sysbus_ctx *system_bus = talloc_get_type(ctx, struct sysbus_ctx); - dbus_connection_unref(system_bus->conn); + dbus_connection_unref(sbus_get_connection(system_bus->sconn)); return EOK; } -int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, struct sbus_method *methods) +static int sysbus_init_methods(TALLOC_CTX *mem_ctx, + struct sysbus_ctx *sysbus, + const char *interface, + const char *path, + struct sbus_method *methods, + sbus_msg_handler_fn introspect_method, + struct sbus_method_ctx **sm_ctx) +{ + int ret; + TALLOC_CTX *tmp_ctx; + struct sbus_method_ctx *method_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if(!tmp_ctx) { + return ENOMEM; + } + + method_ctx = talloc_zero(tmp_ctx, struct sbus_method_ctx); + if (!method_ctx) { + ret = ENOMEM; + goto done; + } + + method_ctx->interface = talloc_strdup(method_ctx, interface); + if (method_ctx->interface == NULL) { + ret = ENOMEM; + goto done; + } + + method_ctx->path = talloc_strdup(method_ctx, path); + if (method_ctx->path == NULL) { + ret = ENOMEM; + goto done; + } + + method_ctx->methods = methods; + method_ctx->introspect_fn = introspect_method; + method_ctx->message_handler = sbus_message_handler; + + *sm_ctx = method_ctx; + talloc_steal(mem_ctx, method_ctx); + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + +int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, + struct event_context *ev, const char *dbus_name, + const char *interface, const char *path, + struct sbus_method *methods, + sbus_msg_handler_fn introspect_method) { DBusError dbus_error; + DBusConnection *conn; struct sysbus_ctx *system_bus; int ret; @@ -53,18 +106,18 @@ int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, struct sbus_met dbus_error_init(&dbus_error); /* Connect to the well-known system bus */ - system_bus->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error); - if (system_bus->conn == NULL) { + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error); + if (conn == NULL) { DEBUG(0, ("Failed to connect to D-BUS system bus.\n")); talloc_free(system_bus); return EIO; } - dbus_connection_set_exit_on_disconnect(system_bus->conn, FALSE); + dbus_connection_set_exit_on_disconnect(conn, FALSE); talloc_set_destructor((TALLOC_CTX *)system_bus, sysbus_destructor); - ret = dbus_bus_request_name(system_bus->conn, - INFOPIPE_DBUS_NAME, + ret = dbus_bus_request_name(conn, + dbus_name, /* We want exclusive access */ DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error @@ -76,14 +129,38 @@ int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, struct sbus_met return EIO; } - DEBUG(1, ("Listening on %s\n", INFOPIPE_DBUS_NAME)); + DEBUG(1, ("Listening on %s\n", dbus_name)); + + /* Integrate with TEvent loop */ + ret = sbus_add_connection(system_bus, ev, conn, &system_bus->sconn, SBUS_CONN_TYPE_SHARED); + if (ret != EOK) { + DEBUG(0, ("Could not integrate D-BUS into mainloop.\n")); + talloc_free(system_bus); + return ret; + } + + /* Set up methods */ + ret = sysbus_init_methods(system_bus, system_bus, interface, path, + methods, introspect_method, + &system_bus->service_methods); + if (ret != EOK) { + DEBUG(0, ("Could not set up service methods.\n")); + talloc_free(system_bus); + return ret; + } + + ret = sbus_conn_add_method_ctx(system_bus->sconn, system_bus->service_methods); + if (ret != EOK) { + DEBUG(0, ("Could not add service methods to the connection.\n")); + talloc_free(system_bus); + return ret; + } *sysbus = system_bus; return EOK; } -int sysbus_get_param(DBusMessage *message, void *data, DBusMessage **r) { - /* TODO: remove this */ - DEBUG(0, ("Received message. Printing this garbage.\n")); - return EOK; +struct sbus_conn_ctx *sysbus_get_sbus_conn(struct sysbus_ctx *sysbus) +{ + return sysbus->sconn; } diff --git a/server/infopipe/sysbus.h b/server/infopipe/sysbus.h index f47219b7..f591365e 100644 --- a/server/infopipe/sysbus.h +++ b/server/infopipe/sysbus.h @@ -22,12 +22,14 @@ #ifndef SYSBUS_H_ #define SYSBUS_H_ -#define SYSBUS_GET_PARAM "getParam" - struct sysbus_ctx; -int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, struct sbus_method *methods); +int sysbus_init(TALLOC_CTX *mem_ctx, struct sysbus_ctx **sysbus, + struct event_context *ev, const char *dbus_name, + const char *interface, const char *path, + struct sbus_method *methods, + sbus_msg_handler_fn introspect_method); -int sysbus_get_param(DBusMessage *message, void *data, DBusMessage **r); +struct sbus_conn_ctx *sysbus_get_sbus_conn(struct sysbus_ctx *sysbus); #endif /* SYSBUS_H_ */ diff --git a/server/sbus/sssd_dbus.h b/server/sbus/sssd_dbus.h index 51a16e20..c75bbc93 100644 --- a/server/sbus/sssd_dbus.h +++ b/server/sbus/sssd_dbus.h @@ -48,6 +48,10 @@ enum { SBUS_CONN_TYPE_SHARED }; +/* Special interface and method for D-BUS introspection */ +#define DBUS_INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable" +#define DBUS_INTROSPECT_METHOD "Introspect" + struct sbus_method { const char *method; sbus_msg_handler_fn fn; @@ -59,6 +63,7 @@ struct sbus_method_ctx { char *path; DBusObjectPathMessageFunction message_handler; struct sbus_method *methods; + sbus_msg_handler_fn introspect_fn; }; struct sbus_message_handler_ctx { @@ -73,11 +78,37 @@ int sbus_new_server(TALLOC_CTX *mem_ctx, sbus_server_conn_init_fn init_fn, void *init_pvt_data); /* Connection Functions */ + +/* sbus_new_connection + * Use this function when connecting a new process to + * the standard SSSD interface. + * This will connect to the address specified and then + * call sbus_add_connection to integrate with the main + * loop. + */ int sbus_new_connection(TALLOC_CTX *ctx, struct event_context *ev, const char *address, struct sbus_conn_ctx **conn_ctx, sbus_conn_destructor_fn destructor); +/* sbus_add_connection + * Integrates a D-BUS connection with the TEvent main + * loop. Use this function when you already have a + * DBusConnection object (for example from dbus_bus_get) + * Connection type can be either: + * SBUS_CONN_TYPE_PRIVATE: Used only from within a D-BUS + * server such as the Monitor in the + * new_connection_callback + * SBUS_CONN_TYPE_SHARED: Used for all D-BUS client + * connections, including those retrieved from + * dbus_bus_get + */ +int sbus_add_connection(TALLOC_CTX *ctx, + struct event_context *ev, + DBusConnection *dbus_conn, + struct sbus_conn_ctx **dct_ctx, + int connection_type); + void sbus_conn_set_destructor(struct sbus_conn_ctx *conn_ctx, sbus_conn_destructor_fn destructor); diff --git a/server/sbus/sssd_dbus_connection.c b/server/sbus/sssd_dbus_connection.c index 601ca009..d02dc6c8 100644 --- a/server/sbus/sssd_dbus_connection.c +++ b/server/sbus/sssd_dbus_connection.c @@ -499,12 +499,12 @@ DBusHandlerResult sbus_message_handler(DBusConnection *conn, if (!method || !path || !msg_interface) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - /* Validate the method interface */ - if (strcmp(msg_interface, ctx->method_ctx->interface) != 0) + /* Validate the D-BUS path */ + if (strcmp(path, ctx->method_ctx->path) != 0) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - /* Validate the D-BUS path */ - if (strcmp(path, ctx->method_ctx->path) == 0) { + /* Validate the method interface */ + if (strcmp(msg_interface, ctx->method_ctx->interface) == 0) { found = 0; for (i = 0; ctx->method_ctx->methods[i].method != NULL; i++) { if (strcmp(method, ctx->method_ctx->methods[i].method) == 0) { @@ -521,6 +521,24 @@ DBusHandlerResult sbus_message_handler(DBusConnection *conn, reply = dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, NULL); } } + else { + /* Special case: check for Introspection request + * This is usually only useful for system bus connections + */ + if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 && + strcmp(method, DBUS_INTROSPECT_METHOD) == 0) + { + if (ctx->method_ctx->introspect_fn) { + /* If we have been asked for introspection data and we have + * an introspection function registered, user that. + */ + ret = ctx->method_ctx->introspect_fn(message, ctx, &reply); + if (ret != EOK) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } DEBUG(5, ("Method %s complete. Reply was %ssent.\n", method, reply?"":"not ")); @@ -548,6 +566,7 @@ int sbus_conn_add_method_ctx(struct sbus_conn_ctx *dct_ctx, } if (_method_list_contains_path(dct_ctx->method_ctx_list, method_ctx)) { + DEBUG(0, ("Cannot add method context with identical path.\n")); return EINVAL; } @@ -579,6 +598,7 @@ int sbus_conn_add_method_ctx(struct sbus_conn_ctx *dct_ctx, dbret = dbus_connection_register_object_path(dct_ctx->conn, method_ctx->path, connection_vtable, msg_handler_ctx); if (!dbret) { + DEBUG(0, ("Could not register object path to the connection.\n")); return ENOMEM; } diff --git a/server/sbus/sssd_dbus_private.h b/server/sbus/sssd_dbus_private.h index d102c8c9..bcaee62c 100644 --- a/server/sbus/sssd_dbus_private.h +++ b/server/sbus/sssd_dbus_private.h @@ -1,12 +1,6 @@ #ifndef _SSSD_DBUS_PRIVATE_H_ #define _SSSD_DBUS_PRIVATE_H_ -int sbus_add_connection(TALLOC_CTX *ctx, - struct event_context *ev, - DBusConnection *dbus_conn, - struct sbus_conn_ctx **dct_ctx, - int connection_type); - struct timeval _dbus_timeout_get_interval_tv(int interval); void sbus_remove_watch(DBusWatch *watch, void *data); void sbus_remove_timeout(DBusTimeout *timeout, void *data); diff --git a/server/server.mk b/server/server.mk index 40d2f5a5..c256477e 100644 --- a/server/server.mk +++ b/server/server.mk @@ -34,6 +34,8 @@ NSSSRV_OBJ = \ INFOPIPE_OBJ = \ infopipe/infopipe.o \ + infopipe/infopipe_users.o \ + infopipe/infopipe_groups.o \ infopipe/sysbus.o POLKIT_OBJ = \ diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index a24ae181..f809f554 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -104,7 +104,7 @@ START_TEST (test_sysdb_store_local_account_posix) const char *username = talloc_asprintf(test_ctx, "testuser%d", _i); const char *home = talloc_asprintf(test_ctx, "/home/testuser%d", _i); - ret = sysdb_posix_store_user(test_ctx, test_ctx->sysdb, + ret = sysdb_legacy_store_user(test_ctx, test_ctx->sysdb, "LOCAL", username, "password", _i, _i, "Test User", @@ -132,7 +132,7 @@ START_TEST (test_sysdb_store_local_group_posix) group_name = talloc_asprintf(test_ctx, "%s%d", SYSDB_POSIX_TEST_GROUP, _i); fail_if(group_name == NULL, "Could not allocate group name"); - ret = sysdb_posix_store_group(test_ctx, test_ctx->sysdb, + ret = sysdb_legacy_store_group(test_ctx, test_ctx->sysdb, "LOCAL", group_name, _i, NULL); fail_if(ret != EOK, "Could not store POSIX group"); @@ -238,7 +238,7 @@ START_TEST (test_sysdb_add_acct_to_posix_group) username = talloc_asprintf(test_ctx, "testuser%d", _i); group = talloc_asprintf(test_ctx, "%s%d",SYSDB_POSIX_TEST_GROUP, _i); - ret = sysdb_posix_add_user_to_group(test_ctx, + ret = sysdb_add_user_to_group(test_ctx, test_ctx->sysdb, "LOCAL", group, @@ -403,7 +403,7 @@ START_TEST (test_sysdb_add_invalid_member) /* Add nonexistent user to test group */ username = talloc_asprintf(test_ctx, "nonexistentuser%d", _i); - ret = sysdb_posix_add_user_to_group(test_ctx, + ret = sysdb_add_user_to_group(test_ctx, test_ctx->sysdb, "LOCAL", group, @@ -481,7 +481,7 @@ START_TEST (test_sysdb_remove_acct_from_posix_group) username = talloc_asprintf(test_ctx, "testuser%d", _i); group = talloc_asprintf(test_ctx, "%s%d",SYSDB_POSIX_TEST_GROUP, _i); - ret = sysdb_posix_remove_user_from_group(test_ctx, + ret = sysdb_remove_user_from_group(test_ctx, test_ctx->sysdb, "LOCAL", group, @@ -511,7 +511,7 @@ START_TEST (test_sysdb_remove_local_acct_posix) */ const char *username = talloc_asprintf(test_ctx, "testuser%d", _i); - ret = sysdb_posix_remove_user(test_ctx, test_ctx->sysdb, "LOCAL", username); + ret = sysdb_delete_user(test_ctx, test_ctx->sysdb, "LOCAL", username); fail_if(ret != EOK, "Could not remove POSIX user %s", username); talloc_free(test_ctx); @@ -530,7 +530,7 @@ START_TEST (test_sysdb_remove_local_acct_posix_by_uid) return; } - ret = sysdb_posix_remove_user_by_uid(test_ctx, test_ctx->sysdb, "LOCAL", _i); + ret = sysdb_delete_user_by_uid(test_ctx, test_ctx->sysdb, "LOCAL", _i); fail_if(ret != EOK, "Could not remove POSIX group"); talloc_free(test_ctx); @@ -553,7 +553,7 @@ START_TEST (test_sysdb_remove_local_group_posix) group_name = talloc_asprintf(test_ctx, "%s%d", SYSDB_POSIX_TEST_GROUP, _i); fail_if(group_name == NULL, "Could not allocate group name"); - ret = sysdb_posix_remove_group(test_ctx, test_ctx->sysdb, + ret = sysdb_delete_group(test_ctx, test_ctx->sysdb, "LOCAL", group_name); fail_if(ret != EOK, "Could not remove POSIX group"); @@ -573,7 +573,7 @@ START_TEST (test_sysdb_remove_local_group_posix_by_gid) return; } - ret = sysdb_posix_remove_group_by_gid(test_ctx, test_ctx->sysdb, + ret = sysdb_delete_group_by_gid(test_ctx, test_ctx->sysdb, "LOCAL", _i); fail_if(ret != EOK, "Could not remove POSIX group"); |