From 1083065853c9d95137c620a2a1af0ad87c9dcf58 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Thu, 5 Mar 2009 12:39:29 -0500 Subject: Adding support for SetUserUID to the InfoPipe The InfoPipe interface Set_YouReallyDoNotWantToUseThisFunction_UserUID1 is now available. I also fixed a memory leak in SetUserAttributes and modified the prototype for infp_get_permissions to make it more clear that the first argument is the caller's username, not the username being checked for permission. --- server/infopipe/infopipe.c | 4 +- server/infopipe/infopipe_private.h | 5 +- server/infopipe/infopipe_users.c | 155 ++++++++++++++++++++- .../org.freeipa.sssd.infopipe.Introspect.xml | 2 +- 4 files changed, 159 insertions(+), 7 deletions(-) (limited to 'server') diff --git a/server/infopipe/infopipe.c b/server/infopipe/infopipe.c index 272bb166e..2972b565c 100644 --- a/server/infopipe/infopipe.c +++ b/server/infopipe/infopipe.c @@ -390,7 +390,7 @@ int infp_get_attribute_type(const char *attribute) return attribute_type; } -bool infp_get_permissions(const char *username, +bool infp_get_permissions(const char *caller, struct sss_domain_info *domain, int object_type, const char *instance, @@ -402,7 +402,7 @@ bool infp_get_permissions(const char *username, * Note: this is buggy. It will return true for ALL requests, * even the nonsensical ones. */ - if (strcmp(username, "root") == 0) + if (strcmp(caller, "root") == 0) return true; return false; } diff --git a/server/infopipe/infopipe_private.h b/server/infopipe/infopipe_private.h index e6ec7c012..bd3e87338 100644 --- a/server/infopipe/infopipe_private.h +++ b/server/infopipe/infopipe_private.h @@ -72,13 +72,14 @@ enum infp_attribute_types { INFP_ATTR_TYPE_KEYBOARD, INFP_ATTR_TYPE_SESSION, INFP_ATTR_TYPE_LAST_LOGIN, - INFP_ATTR_TYPE_USERPIC + INFP_ATTR_TYPE_USERPIC, + INFP_ATTR_TYPE_USERID }; int infp_get_attribute_type(const char *attribute); int infp_get_user_attr_dbus_type(int attr_type, int *subtype); -bool infp_get_permissions(const char *username, +bool infp_get_permissions(const char *caller, struct sss_domain_info *domain, int object_type, const char *instance, diff --git a/server/infopipe/infopipe_users.c b/server/infopipe/infopipe_users.c index a9ffe8bfd..2928722a1 100644 --- a/server/infopipe/infopipe_users.c +++ b/server/infopipe/infopipe_users.c @@ -805,6 +805,7 @@ static void infp_do_user_set_attr_callback(void *ptr, int ldb_status, struct ldb /* Send reply ack */ reply = dbus_message_new_method_return(infp_setattr_req->infp_req->req_message); sbus_conn_send_reply(infp_setattr_req->infp_req->sconn, reply); + talloc_free(infp_setattr_req); } static void infp_do_user_set_attr(struct sysdb_req *req, void *pvt) @@ -1145,15 +1146,165 @@ einval: return EOK; } +struct infp_setuid_ctx { + struct infp_req_ctx *infp_req; + struct sysdb_req *sysdb_req; + struct sysdb_attrs *uid_attr; + char *username; +}; + +static void infp_do_user_set_uid_callback(void *ptr, int ldb_status, struct ldb_result *res) +{ + DBusMessage *reply; + struct infp_setuid_ctx *infp_setuid_req = talloc_get_type(ptr, struct infp_setuid_ctx); + + /* Commit or cancel the transaction, based on the ldb_status */ + sysdb_transaction_done(infp_setuid_req->sysdb_req, sysdb_error_to_errno(ldb_status)); + + /* Check the LDB result */ + if (ldb_status != LDB_SUCCESS) { + DEBUG(0, ("Failed to store user uid to the sysdb\n")); + talloc_free(infp_setuid_req); + return; + } + + /* Send reply ack */ + reply = dbus_message_new_method_return(infp_setuid_req->infp_req->req_message); + sbus_conn_send_reply(infp_setuid_req->infp_req->sconn, reply); + talloc_free(infp_setuid_req); +} + +static void infp_do_user_set_uid(struct sysdb_req *req, void *pvt) +{ + int ret; + struct infp_setuid_ctx *infp_setuid_req; + + infp_setuid_req = talloc_get_type(pvt, struct infp_setuid_ctx); + infp_setuid_req->sysdb_req = req; + + DEBUG(9, ("Setting UID for user [%s]\n", infp_setuid_req->username)); + ret = sysdb_set_user_attr(infp_setuid_req->sysdb_req, + infp_setuid_req->infp_req->infp->sysdb, + infp_setuid_req->infp_req->domain->name, + infp_setuid_req->username, + infp_setuid_req->uid_attr, + infp_do_user_set_uid_callback, infp_setuid_req); +} + int infp_users_set_uid(DBusMessage *message, struct sbus_conn_ctx *sconn) { DBusMessage *reply; + DBusError error; + dbus_bool_t dbret; + char *einval_msg; + struct infp_setuid_ctx *infp_setuid_req; + int ret; - reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented"); + /* Arguments */ + const char *arg_username; + const char *arg_domain; + const int arg_uid; + + infp_setuid_req = talloc_zero(NULL, struct infp_setuid_ctx); + if (infp_setuid_req == NULL) { + ret = ENOMEM; + goto error; + } + + /* Create an infp_req_ctx */ + infp_setuid_req->infp_req = talloc_zero(infp_setuid_req, struct infp_req_ctx); + if (infp_setuid_req == NULL) { + ret = ENOMEM; + goto error; + } + infp_setuid_req->infp_req->infp = talloc_get_type(sbus_conn_get_private_data(sconn), struct infp_ctx); + infp_setuid_req->infp_req->sconn = sconn; + infp_setuid_req->infp_req->req_message = message; + infp_setuid_req->infp_req->caller = sysbus_get_caller(infp_setuid_req->infp_req, + infp_setuid_req->infp_req->req_message, + infp_setuid_req->infp_req->sconn); + if (infp_setuid_req->infp_req->caller == NULL) { + ret = EIO; + goto error; + } + + dbus_error_init(&error); + dbret = dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &arg_username, + DBUS_TYPE_STRING, &arg_domain, + DBUS_TYPE_UINT32, &arg_uid, + DBUS_TYPE_INVALID); + if (!dbret) { + DEBUG(0, ("Parsing arguments to SetUserUID failed: %s:%s\n", error.name, error.message)); + einval_msg = talloc_strdup(infp_setuid_req, error.message); + dbus_error_free(&error); + goto einval; + } + + infp_setuid_req->username = talloc_strdup(infp_setuid_req, arg_username); + + infp_setuid_req->infp_req->domain = btreemap_get_value(infp_setuid_req->infp_req->infp->domain_map, + (const void *)arg_domain); + /* Check for a valid domain */ + if(infp_setuid_req->infp_req->domain == NULL) { + einval_msg = talloc_strdup(infp_setuid_req, "Invalid domain."); + goto einval; + } + + /* Check the domain MIN and MAX */ + if((arg_uid < infp_setuid_req->infp_req->domain->id_min) || /* Requested UID < than minimum */ + ((infp_setuid_req->infp_req->domain->id_max > infp_setuid_req->infp_req->domain->id_min) && /* Maximum exists and is greater than minimum */ + (arg_uid > infp_setuid_req->infp_req->domain->id_max))) { /* Requested UID > maximum */ + einval_msg = talloc_asprintf(infp_setuid_req, "UID out of range for this domain. Minimum: %u Maximum: %u\n", + infp_setuid_req->infp_req->domain->id_min, + infp_setuid_req->infp_req->domain->id_max?infp_setuid_req->infp_req->domain->id_max:(uid_t)-1); + goto einval; + } + + /* Check permissions */ + if(!infp_get_permissions(infp_setuid_req->infp_req->caller, + infp_setuid_req->infp_req->domain, + INFP_OBJ_TYPE_USER, + infp_setuid_req->username, + INFP_ACTION_TYPE_MODIFY, + INFP_ATTR_TYPE_USERID)) + { + reply = dbus_message_new_error(message, DBUS_ERROR_ACCESS_DENIED, NULL); + /* send reply */ + sbus_conn_send_reply(sconn, reply); + dbus_message_unref(reply); + + talloc_free(infp_setuid_req); + return EOK; + } + + infp_setuid_req->uid_attr = sysdb_new_attrs(infp_setuid_req); + if (infp_setuid_req->uid_attr == NULL) { + ret = ENOMEM; + goto error; + } + sysdb_attrs_add_long(infp_setuid_req->uid_attr, SYSDB_PW_UIDNUM, arg_uid); + + ret = sysdb_transaction(infp_setuid_req, infp_setuid_req->infp_req->infp->sysdb, + infp_do_user_set_uid, infp_setuid_req); + if(ret != EOK) { + DEBUG(0, ("Could not write to the cache database.\n")); + goto error; + } + + return EOK; + +einval: + reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, einval_msg); /* send reply */ sbus_conn_send_reply(sconn, reply); - dbus_message_unref(reply); + + talloc_free(infp_setuid_req); return EOK; + +error: + talloc_free(infp_setuid_req); + return ret; } diff --git a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml index f159fce5b..164c9d10a 100644 --- a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml +++ b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml @@ -183,7 +183,7 @@ /> - +