summaryrefslogtreecommitdiff
path: root/server/infopipe/infopipe_groups.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/infopipe/infopipe_groups.c')
-rw-r--r--server/infopipe/infopipe_groups.c262
1 files changed, 254 insertions, 8 deletions
diff --git a/server/infopipe/infopipe_groups.c b/server/infopipe/infopipe_groups.c
index ec02c575..bb3741c9 100644
--- a/server/infopipe/infopipe_groups.c
+++ b/server/infopipe/infopipe_groups.c
@@ -385,30 +385,276 @@ error:
return ret;
}
-int infp_groups_add_members(DBusMessage *message, struct sbus_conn_ctx *sconn)
+enum infp_gr_member_types {
+ INFP_GR_MEM_USER = 0,
+ INFP_GR_MEM_GROUP
+};
+
+struct infp_groupmember_ctx {
+ struct infp_req_ctx *infp_req;
+ struct ldb_dn *group_dn;
+ char **membernames;
+ uint32_t member_count;
+ uint32_t index;
+ uint8_t member_type;
+ uint8_t modify_type;
+ struct sysdb_req *sysdb_req;
+};
+
+static void infp_do_member(struct sysdb_req *req, void *pvt);
+
+static void infp_do_member_callback(void *pvt, int status,
+ struct ldb_result *res)
{
- DBusMessage *reply;
+ char *fail_msg;
+ DBusMessage *reply = NULL;
+ struct infp_groupmember_ctx *grmod_req =
+ talloc_get_type(pvt, struct infp_groupmember_ctx);
- reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ /* Check the results of the current add */
+ if(status != EOK) goto fail;
- /* send reply */
- sbus_conn_send_reply(sconn, reply);
+ /* Check if there are more members to process */
+ grmod_req->index++;
+ if(grmod_req->index < grmod_req->member_count) {
+ infp_do_member(grmod_req->sysdb_req, grmod_req);
+ return;
+ }
+ /* This was the last member. Commit the transaction */
+ sysdb_transaction_done(grmod_req->sysdb_req, EOK);
+
+ /* Send an ack reply */
+ reply = dbus_message_new_method_return(grmod_req->infp_req->req_message);
+ if(reply) {
+ sbus_conn_send_reply(grmod_req->infp_req->sconn, reply);
+ dbus_message_unref(reply);
+ }
+
+ talloc_free(grmod_req);
+ return;
+
+fail:
+sysdb_transaction_done(grmod_req->sysdb_req, status);
+ fail_msg = talloc_asprintf(grmod_req, "Could not modify group");
+ reply = dbus_message_new_error(grmod_req->infp_req->req_message,
+ DBUS_ERROR_FAILED,
+ fail_msg);
+ sbus_conn_send_reply(grmod_req->infp_req->sconn, reply);
dbus_message_unref(reply);
- return EOK;
+ talloc_free(grmod_req);
+ return;
+}
+
+static void infp_do_member(struct sysdb_req *req, void *pvt)
+{
+ int ret;
+ struct ldb_dn *member_dn;
+ struct infp_groupmember_ctx *grmod_req =
+ talloc_get_type(pvt, struct infp_groupmember_ctx);
+
+ grmod_req->sysdb_req = req;
+
+ if (grmod_req->member_type == INFP_GR_MEM_USER) {
+ member_dn =
+ sysdb_user_dn(grmod_req->infp_req->infp->sysdb,
+ grmod_req,
+ grmod_req->infp_req->domain->name,
+ grmod_req->membernames[grmod_req->index]);
+ if (member_dn == NULL) goto error;
+ }
+ else if (grmod_req->member_type == INFP_GR_MEM_GROUP) {
+ member_dn =
+ sysdb_group_dn(grmod_req->infp_req->infp->sysdb,
+ grmod_req,
+ grmod_req->infp_req->domain->name,
+ grmod_req->membernames[grmod_req->index]);
+ if (member_dn == NULL) goto error;
+ }
+ else goto error;
+
+ if (grmod_req->modify_type == INFP_ACTION_TYPE_ADDMEMBER) {
+ ret = sysdb_add_group_member(grmod_req->sysdb_req,
+ member_dn,
+ grmod_req->group_dn,
+ infp_do_member_callback,
+ grmod_req);
+ }
+ else if (grmod_req->modify_type == INFP_ACTION_TYPE_REMOVEMEMBER) {
+ ret = sysdb_remove_group_member(grmod_req->sysdb_req,
+ member_dn,
+ grmod_req->group_dn,
+ infp_do_member_callback,
+ grmod_req);
+ }
+ if (ret != EOK) goto error;
+
+ return;
+
+error:
+ talloc_free(grmod_req);
+ return;
}
-int infp_groups_remove_members(DBusMessage *message, struct sbus_conn_ctx *sconn)
+static int infp_groups_modify_members(DBusMessage *message,
+ struct sbus_conn_ctx *sconn,
+ uint8_t modify_type)
{
DBusMessage *reply;
+ DBusError error;
+ struct infp_groupmember_ctx *grmod_req;
+ char *einval_msg;
+ int ret, i;
- reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ /* Arguments */
+ const char *arg_group;
+ const char *arg_domain;
+ char **arg_members = NULL;
+ int arg_member_count;
+ uint8_t arg_membertype;
+
+ grmod_req = talloc_zero(NULL, struct infp_groupmember_ctx);
+ if (grmod_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ /* Create an infp_req_ctx */
+ grmod_req->infp_req = infp_req_init(grmod_req, message, sconn);
+ if(grmod_req->infp_req == NULL) {
+ ret = EIO;
+ goto error;
+ }
+ dbus_error_init(&error);
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &arg_group,
+ DBUS_TYPE_STRING, &arg_domain,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &arg_members, &arg_member_count,
+ DBUS_TYPE_BYTE, &arg_membertype,
+ DBUS_TYPE_INVALID)) {
+ DEBUG(0, ("Parsing arguments to %s failed: %s:%s\n",
+ INFP_GROUPS_ADD_MEMBERS, error.name, error.message));
+ einval_msg = talloc_strdup(grmod_req, error.message);
+ dbus_error_free(&error);
+ goto einval;
+ }
+
+ /* FIXME: Allow modifying groups on domains other than LOCAL */
+ if (strcasecmp(arg_domain, "LOCAL") != 0) {
+ goto denied;
+ }
+
+ grmod_req->infp_req->domain =
+ btreemap_get_value(grmod_req->infp_req->infp->domain_map,
+ (const void *)arg_domain);
+ /* Check for a valid domain */
+ if(grmod_req->infp_req->domain == NULL) {
+ einval_msg = talloc_strdup(grmod_req, "Invalid domain.");
+ goto einval;
+ }
+
+ /* Check permissions */
+ if (!infp_get_permissions(grmod_req->infp_req->caller,
+ grmod_req->infp_req->domain,
+ INFP_OBJ_TYPE_GROUP,
+ arg_group,
+ modify_type,
+ INFP_ATTR_TYPE_INVALID)) goto denied;
+
+ grmod_req->member_count = arg_member_count;
+ grmod_req->membernames = talloc_array(grmod_req, char *,
+ arg_member_count);
+ if (grmod_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ for (i = 0; i < arg_member_count; i++) {
+ grmod_req->membernames[i] = talloc_strdup(grmod_req->membernames,
+ arg_members[i]);
+ if(grmod_req->membernames[i] == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ }
+ dbus_free_string_array(arg_members);
+ arg_members = NULL;
+
+ grmod_req->group_dn =
+ sysdb_group_dn(grmod_req->infp_req->infp->sysdb,
+ grmod_req,
+ grmod_req->infp_req->domain->name,
+ arg_group);
+ if (grmod_req->group_dn == NULL) {
+ ret = EIO;
+ goto error;
+ }
+
+ grmod_req->index = 0;
+ grmod_req->modify_type = modify_type;
+ grmod_req->member_type = arg_membertype;
+ if ((grmod_req->member_type != INFP_GR_MEM_USER) &&
+ (grmod_req->member_type != INFP_GR_MEM_GROUP)) {
+ einval_msg = talloc_strdup(grmod_req,
+ "Invalid member type");
+ goto einval;
+ }
+
+ ret = sysdb_transaction(grmod_req,
+ grmod_req->infp_req->infp->sysdb,
+ infp_do_member,
+ grmod_req);
+ if (ret != EOK) goto error;
+
+ return EOK;
+
+denied:
+ reply = dbus_message_new_error(message, DBUS_ERROR_ACCESS_DENIED, NULL);
+ if(reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
/* send reply */
sbus_conn_send_reply(sconn, reply);
+ dbus_message_unref(reply);
+
+ if (arg_members) dbus_free_string_array(arg_members);
+ talloc_free(grmod_req);
+ return EOK;
+einval:
+ reply = dbus_message_new_error(message,
+ DBUS_ERROR_INVALID_ARGS,
+ einval_msg);
+ if (reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ sbus_conn_send_reply(sconn, reply);
dbus_message_unref(reply);
+ if (arg_members) dbus_free_string_array(arg_members);
+ talloc_free(grmod_req);
return EOK;
+
+error:
+ if (arg_members) dbus_free_string_array(arg_members);
+ talloc_free(grmod_req);
+ return ret;
+}
+
+int infp_groups_add_members(DBusMessage *message,
+ struct sbus_conn_ctx *sconn)
+{
+ return infp_groups_modify_members(message, sconn,
+ INFP_ACTION_TYPE_ADDMEMBER);
+}
+
+int infp_groups_remove_members(DBusMessage *message,
+ struct sbus_conn_ctx *sconn)
+{
+ return infp_groups_modify_members(message, sconn,
+ INFP_ACTION_TYPE_REMOVEMEMBER);
}
int infp_groups_set_gid(DBusMessage *message, struct sbus_conn_ctx *sconn)