summaryrefslogtreecommitdiffstats
path: root/src/responder/ifp/ifpsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/ifp/ifpsrv_cmd.c')
-rw-r--r--src/responder/ifp/ifpsrv_cmd.c181
1 files changed, 166 insertions, 15 deletions
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index 7a200aab8..fab87b916 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -35,6 +35,7 @@ struct ifp_attr_req {
static struct tevent_req *
ifp_user_get_attr_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
struct sss_nc_ctx *ncache, int neg_timeout,
+ enum sss_dp_acct_type search_type,
const char *inp, const char **attrs);
static errno_t ifp_user_get_attr_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
@@ -84,6 +85,7 @@ int ifp_user_get_attr(struct sbus_request *dbus_req, void *data)
req = ifp_user_get_attr_send(ireq, ifp_ctx->rctx,
ifp_ctx->ncache, ifp_ctx->neg_timeout,
+ SSS_DP_USER,
attr_req->name, attr_req->attrs);
if (req == NULL) {
return sbus_request_finish(dbus_req, NULL);
@@ -163,15 +165,17 @@ static void ifp_user_get_attr_process(struct tevent_req *req)
ret = ifp_user_get_attr_handle_reply(attr_req->ireq, attr_req->name,
attr_req->attrs, res);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Could not handle reply!\n");
- /* Nothing to do, let the client time out */
+ sbus_request_fail_and_finish(attr_req->ireq->dbus_req,
+ sbus_error_new(attr_req->ireq->dbus_req,
+ DBUS_ERROR_FAILED,
+ "Failed to build a reply\n"));
return;
}
}
static errno_t
ifp_user_get_attr_handle_reply(struct ifp_req *ireq, const char *user,
- const char **attrs, struct ldb_result *res)
+ const char **attrs, struct ldb_result *res)
{
errno_t ret;
dbus_bool_t dbret;
@@ -228,11 +232,134 @@ ifp_user_get_attr_handle_reply(struct ifp_req *ireq, const char *user,
return sbus_request_finish(ireq->dbus_req, reply);
}
+static void ifp_user_get_groups_process(struct tevent_req *req);
+static errno_t ifp_user_get_groups_reply(struct ifp_req *ireq,
+ const char *user,
+ struct ldb_result *res);
+
+int ifp_user_get_groups(struct sbus_request *dbus_req,
+ void *data, const char *arg_user)
+{
+ struct ifp_req *ireq;
+ struct ifp_ctx *ifp_ctx;
+ struct ifp_attr_req *group_req;
+ struct tevent_req *req;
+ errno_t ret;
+
+ ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ifp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
+ }
+
+ ret = ifp_req_create(dbus_req, ifp_ctx, &ireq);
+ if (ret != EOK) {
+ return ifp_req_create_handle_failure(dbus_req, ret);
+ }
+
+ group_req = talloc_zero(ireq, struct ifp_attr_req);
+ if (group_req == NULL) {
+ return sbus_request_finish(dbus_req, NULL);
+ }
+ group_req->ireq = ireq;
+ group_req->name = arg_user;
+
+ group_req->attrs = talloc_zero_array(group_req, const char *, 2);
+ if (group_req->attrs == NULL) {
+ return sbus_request_finish(dbus_req, NULL);
+ }
+
+ group_req->attrs[0] = talloc_strdup(group_req->attrs, SYSDB_MEMBEROF);
+ if (group_req->attrs[0] == NULL) {
+ return sbus_request_finish(dbus_req, NULL);
+ }
+
+ DEBUG(SSSDBG_FUNC_DATA,
+ "Looking up groups of user [%s] on behalf of %"PRIi64"\n",
+ group_req->name, group_req->ireq->dbus_req->client);
+
+ req = ifp_user_get_attr_send(ireq, ifp_ctx->rctx,
+ ifp_ctx->ncache, ifp_ctx->neg_timeout,
+ SSS_DP_INITGROUPS,
+ group_req->name, group_req->attrs);
+ if (req == NULL) {
+ return sbus_request_finish(dbus_req, NULL);
+ }
+ tevent_req_set_callback(req, ifp_user_get_groups_process, group_req);
+ return EOK;
+}
+
+static void ifp_user_get_groups_process(struct tevent_req *req)
+{
+ struct ifp_attr_req *group_req;
+ errno_t ret;
+ struct ldb_result *res;
+
+ group_req = tevent_req_callback_data(req, struct ifp_attr_req);
+
+ ret = ifp_user_get_attr_recv(group_req, req, &res);
+ talloc_zfree(req);
+ if (ret == ENOENT) {
+ sbus_request_fail_and_finish(group_req->ireq->dbus_req,
+ sbus_error_new(group_req->ireq->dbus_req,
+ DBUS_ERROR_FAILED,
+ "No such user\n"));
+ return;
+ } else if (ret != EOK) {
+ sbus_request_fail_and_finish(group_req->ireq->dbus_req,
+ sbus_error_new(group_req->ireq->dbus_req,
+ DBUS_ERROR_FAILED,
+ "Failed to read attribute\n"));
+ return;
+ }
+
+ ret = ifp_user_get_groups_reply(group_req->ireq, group_req->name, res);
+ if (ret != EOK) {
+ sbus_request_fail_and_finish(group_req->ireq->dbus_req,
+ sbus_error_new(group_req->ireq->dbus_req,
+ DBUS_ERROR_FAILED,
+ "Failed to build a reply\n"));
+ return;
+ }
+}
+
+static errno_t
+ifp_user_get_groups_reply(struct ifp_req *ireq, const char *user,
+ struct ldb_result *res)
+{
+ int i, num;
+ const char *name;
+ const char **groupnames;
+
+ /* one less, the first one is the user entry */
+ num = res->count - 1;
+ groupnames = talloc_zero_array(ireq, const char *, num);
+ if (groupnames == NULL) {
+ return sbus_request_finish(ireq->dbus_req, NULL);
+ }
+
+ for (i = 0; i < num; i++) {
+ name = ldb_msg_find_attr_as_string(res->msgs[i + 1], SYSDB_NAME, NULL);
+ if (name == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Skipping a group with no name\n");
+ continue;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", name);
+ groupnames[i] = name;
+ }
+
+ return infopipe_iface_GetUserGroups_finish(ireq->dbus_req,
+ groupnames, num);
+}
+
struct ifp_user_get_attr_state {
const char *inp;
const char **attrs;
struct ldb_result *res;
+ enum sss_dp_acct_type search_type;
+
char *name;
char *domname;
@@ -248,6 +375,7 @@ struct ifp_user_get_attr_state {
static void ifp_user_get_attr_dom(struct tevent_req *subreq);
static errno_t ifp_user_get_attr_search(struct tevent_req *req);
int ifp_cache_check(struct ifp_user_get_attr_state *state,
+ enum sss_dp_acct_type search_type,
sss_dp_callback_t callback,
unsigned int cache_refresh_percent,
void *pvt);
@@ -256,6 +384,7 @@ void ifp_user_get_attr_done(struct tevent_req *req);
static struct tevent_req *
ifp_user_get_attr_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
struct sss_nc_ctx *ncache, int neg_timeout,
+ enum sss_dp_acct_type search_type,
const char *inp, const char **attrs)
{
errno_t ret;
@@ -272,6 +401,7 @@ ifp_user_get_attr_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
state->rctx = rctx;
state->ncache = ncache;
state->neg_timeout = neg_timeout;
+ state->search_type = search_type;
subreq = sss_parse_inp_send(req, rctx, inp);
if (subreq == NULL) {
@@ -392,18 +522,32 @@ static errno_t ifp_user_get_attr_search(struct tevent_req *req)
DEBUG(SSSDBG_FUNC_DATA,
"Requesting info for [%s@%s]\n", name, dom->name);
- ret = sysdb_get_user_attr(state, dom->sysdb, dom, name,
- state->attrs, &state->res);
+ switch (state->search_type) {
+ case SSS_DP_USER:
+ ret = sysdb_get_user_attr(state, dom->sysdb, dom, name,
+ state->attrs, &state->res);
+ break;
+ case SSS_DP_INITGROUPS:
+ ret = sysdb_initgroups(state, dom->sysdb, dom, name,
+ &state->res);
+ break;
+ default:
+ DEBUG(SSSDBG_OP_FAILURE, "Unsupported operation\n");
+ return EIO;
+ }
+
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to make request to our cache!\n");
return EIO;
}
- if (state->res->count > 1) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "getpwnam call returned more than one result !?!\n");
- return ENOENT;
+ if (state->search_type == SSS_DP_USER) {
+ if (state->res->count > 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "getpwnam call returned more than one result !?!\n");
+ return ENOENT;
+ }
}
if (state->res->count == 0 && state->check_provider == false) {
@@ -428,7 +572,8 @@ static errno_t ifp_user_get_attr_search(struct tevent_req *req)
/* if this is a caching provider (or if we haven't checked the cache
* yet) then verify that the cache is uptodate */
if (state->check_provider) {
- ret = ifp_cache_check(state, ifp_dp_callback, 0, req);
+ ret = ifp_cache_check(state, state->search_type,
+ ifp_dp_callback, 0, req);
if (ret != EOK) {
/* Anything but EOK means we should reenter the mainloop
* because we may be refreshing the cache
@@ -449,6 +594,7 @@ static errno_t ifp_user_get_attr_search(struct tevent_req *req)
}
int ifp_cache_check(struct ifp_user_get_attr_state *state,
+ enum sss_dp_acct_type search_type,
sss_dp_callback_t callback,
unsigned int cache_refresh_percent,
void *pvt)
@@ -458,7 +604,7 @@ int ifp_cache_check(struct ifp_user_get_attr_state *state,
struct tevent_req *req;
struct dp_callback_ctx *cb_ctx = NULL;
- if (state->res->count > 1) {
+ if (search_type == SSS_DP_USER && state->res->count > 1) {
DEBUG(SSSDBG_OP_FAILURE,
"cache search call returned more than one result! "
"DB Corrupted?\n");
@@ -466,8 +612,13 @@ int ifp_cache_check(struct ifp_user_get_attr_state *state,
}
if (state->res->count > 0) {
- cache_expire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
+ if (search_type == SSS_DP_USER) {
+ cache_expire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
+ SYSDB_CACHE_EXPIRE, 0);
+ } else {
+ cache_expire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
+ SYSDB_INITGR_EXPIRE, 0);
+ }
/* if we have any reply let's check cache validity */
ret = sss_cmd_check_cache(state->res->msgs[0], cache_refresh_percent,
@@ -494,7 +645,7 @@ int ifp_cache_check(struct ifp_user_get_attr_state *state,
DEBUG(SSSDBG_TRACE_FUNC, "Performing midpoint cache update\n");
req = sss_dp_get_account_send(state, state->rctx, state->dom, true,
- SSS_DP_USER, state->inp, 0,
+ search_type, state->inp, 0,
NULL);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
@@ -518,7 +669,7 @@ int ifp_cache_check(struct ifp_user_get_attr_state *state,
state->check_provider = false;
req = sss_dp_get_account_send(state, state->rctx, state->dom, true,
- SSS_DP_USER, state->inp, 0, NULL);
+ search_type, state->inp, 0, NULL);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Out of memory sending data provider request\n");