From 7a571a9d9be35360cc0f283fcd8124bda11ebf51 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Mon, 23 Jan 2012 13:32:22 +0100 Subject: SUDO Integration - prepare data provider for new responder commands https://fedorahosted.org/sssd/ticket/1143 --- src/providers/data_provider.h | 16 +- src/providers/data_provider_be.c | 143 ++++++++++-------- src/providers/dp_backend.h | 3 + src/providers/ldap/sdap_sudo.c | 278 ++++++++++++++++++++++------------- src/providers/ldap/sdap_sudo.h | 19 +-- src/providers/ldap/sdap_sudo_timer.c | 26 ++-- 6 files changed, 286 insertions(+), 199 deletions(-) (limited to 'src/providers') diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index eb4f98cf..627085b0 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -132,13 +132,15 @@ #define BE_FILTER_IDNUM 2 #define BE_FILTER_ENUM 3 -#define BE_REQ_USER 0x0001 -#define BE_REQ_GROUP 0x0002 -#define BE_REQ_INITGROUPS 0x0003 -#define BE_REQ_NETGROUP 0x0004 -#define BE_REQ_SERVICES 0x0005 -#define BE_REQ_SUDO 0x0006 -#define BE_REQ_FAST 0x1000 +#define BE_REQ_USER 0x0001 +#define BE_REQ_GROUP 0x0002 +#define BE_REQ_INITGROUPS 0x0003 +#define BE_REQ_NETGROUP 0x0004 +#define BE_REQ_SERVICES 0x0005 +#define BE_REQ_SUDO_ALL 0x0006 +#define BE_REQ_SUDO_DEFAULTS 0x0007 +#define BE_REQ_SUDO_USER 0x0008 +#define BE_REQ_FAST 0x1000 /* AUTH related common data and functions */ diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c index 801dbd5f..9965e52f 100644 --- a/src/providers/data_provider_be.c +++ b/src/providers/data_provider_be.c @@ -633,45 +633,48 @@ done: return EOK; } -static void be_sudo_handler_callback(struct be_req *req, - int dp_err_type, - int errnum, - const char *errstr) +static void be_sudo_handler_reply(struct sbus_connection *conn, + DBusMessage *reply, + dbus_uint16_t dp_err, + dbus_uint32_t dp_ret, + const char *errstr) { - DBusMessage *reply = NULL; DBusConnection *dbus_conn = NULL; dbus_bool_t dbret; - dbus_uint16_t err_maj = 0; - dbus_uint32_t err_min = 0; const char *err_msg = NULL; - reply = (DBusMessage*)(req->pvt); - - err_maj = dp_err_type; - err_min = errnum; - err_msg = errstr ? errstr : talloc_strdup(req, "No errmsg set\n"); - if (!err_msg) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to set err_msg\n")); - err_msg = "OOM"; + if (reply == NULL) { + return; } + err_msg = errstr ? errstr : "No errmsg set\n"; dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &err_maj, - DBUS_TYPE_UINT32, &err_min, + DBUS_TYPE_UINT16, &dp_err, + DBUS_TYPE_UINT32, &dp_ret, DBUS_TYPE_STRING, &err_msg, DBUS_TYPE_INVALID); if (!dbret) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to generate dbus reply\n")); - talloc_free(req); return; } DEBUG(SSSDBG_FUNC_DATA, ("SUDO Backend returned: (%d, %d, %s)\n", - dp_err_type, errnum, errstr ? errstr : "")); + dp_err, dp_ret, errstr ? errstr : "")); - dbus_conn = sbus_get_connection(req->becli->conn); + dbus_conn = sbus_get_connection(conn); dbus_connection_send(dbus_conn, reply, NULL); dbus_message_unref(reply); +} + +static void be_sudo_handler_callback(struct be_req *req, + int dp_err, + int dp_ret, + const char *errstr) +{ + DBusMessage *reply = NULL; + reply = (DBusMessage*)(req->pvt); + + be_sudo_handler_reply(req->becli->conn, reply, dp_err, dp_ret, errstr); talloc_free(req); } @@ -682,13 +685,12 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn) DBusMessage *reply = NULL; struct be_client *be_cli = NULL; struct be_req *be_req = NULL; - struct be_sudo_req *be_sudo_req = NULL; + struct be_sudo_req *sudo_req = NULL; void *user_data = NULL; int ret = 0; uint32_t type; char *filter; const char *err_msg = NULL; - char *filter_val; DEBUG(SSSDBG_TRACE_FUNC, ("Entering be_sudo_handler()\n")); @@ -709,19 +711,7 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn) return ENOMEM; } - /* create be request */ - be_req = talloc_zero(be_cli, struct be_req); - if (be_req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n")); - dbus_message_unref(reply); - return ENOMEM; - } - - be_req->becli = be_cli; - be_req->be_ctx = be_cli->bectx; - be_req->pvt = reply; - be_req->fn = be_sudo_handler_callback; - + /* get arguments */ dbus_error_init(&dbus_error); ret = dbus_message_get_args(message, &dbus_error, @@ -736,41 +726,78 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn) goto fail; } - if (type != BE_REQ_SUDO) { - /* No other are supported at the moment */ - ret = EINVAL; - err_msg = "Invalid DP request type"; - goto fail; + + /* If we are offline and fast reply was requested + * return offline immediately + */ + if ((type & BE_REQ_FAST) && be_cli->bectx->offstat.offline) { + be_sudo_handler_reply(conn, reply, DP_ERR_OFFLINE, EAGAIN, + "Fast reply - offline"); + reply = NULL; + /* This reply will be queued and sent + * when we reenter the mainloop. + * + * Continue processing in case we are + * going back online. + */ } - if (filter) { - if (strncmp(filter, "name=", 5) == 0) { - filter_val = &filter[5]; - } else { - ret = EINVAL; - err_msg = "Invalid Filter"; - goto fail; - } - } else { - ret = EINVAL; - err_msg = "Missing Filter Parameter"; - goto fail; + /* create be request */ + be_req = talloc_zero(be_cli, struct be_req); + if (be_req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n")); + dbus_message_unref(reply); + return ENOMEM; } + be_req->becli = be_cli; + be_req->be_ctx = be_cli->bectx; + be_req->pvt = reply; + be_req->fn = be_sudo_handler_callback; + /* get and set sudo request data */ - be_sudo_req = talloc_zero(be_req, struct be_sudo_req); - if (be_sudo_req == NULL) { + sudo_req = talloc_zero(be_req, struct be_sudo_req); + if (sudo_req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n")); goto fail; } - be_sudo_req->username = talloc_strdup(be_sudo_req, filter_val); - if (be_sudo_req->username == NULL) { - ret = ENOMEM; + sudo_req->type = (~BE_REQ_FAST) & type; + sudo_req->uid = 0; + sudo_req->groups = NULL; + + switch (sudo_req->type) { + case BE_REQ_SUDO_ALL: + case BE_REQ_SUDO_DEFAULTS: + sudo_req->username = NULL; + break; + case BE_REQ_SUDO_USER: + if (filter) { + if (strncmp(filter, "name=", 5) == 0) { + sudo_req->username = talloc_strdup(sudo_req, &filter[5]); + if (sudo_req->username == NULL) { + ret = ENOMEM; + goto fail; + } + } else { + ret = EINVAL; + err_msg = "Invalid Filter"; + goto fail; + } + } else { + ret = EINVAL; + err_msg = "Missing Filter Parameter"; + goto fail; + } + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type)); + ret = EINVAL; + err_msg = "Invalid DP request type"; goto fail; } - be_req->req_data = be_sudo_req; + be_req->req_data = sudo_req; /* return an error if corresponding backend target is not configured */ if (!be_cli->bectx->bet_info[BET_SUDO].bet_ops) { diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h index 33ca37ce..0964110a 100644 --- a/src/providers/dp_backend.h +++ b/src/providers/dp_backend.h @@ -147,7 +147,10 @@ struct be_acct_req { }; struct be_sudo_req { + uint32_t type; char *username; + uid_t uid; + char **groups; }; bool be_is_offline(struct be_ctx *ctx); diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index ea90bb7e..aed937f9 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -46,47 +46,66 @@ struct sdap_sudo_load_sudoers_state { }; struct sdap_sudo_refresh_state { - struct sdap_sudo_ctx *sudo_ctx; + struct be_ctx *be_ctx; + struct be_sudo_req *sudo_req; + struct sdap_options *opts; + struct sdap_id_op *sdap_op; + struct sdap_id_conn_cache *sdap_conn_cache; + int dp_error; int error; }; static int sdap_sudo_connect(struct tevent_req *req); + static void sdap_sudo_connect_done(struct tevent_req *subreq); static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx); + struct tevent_context *ev, + struct be_sudo_req *sudo_req, + struct sdap_options *opts, + struct sdap_handle *sh); + static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req); + static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq); + static int sdap_sudo_load_sudoers_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, size_t *rules_count, struct sysdb_attrs ***rules); + static void sdap_sudo_load_sudoers_done(struct tevent_req *req); -static int sdap_sudo_purge_sudoers(struct sdap_sudo_ctx *sudo_ctx); -static int sdap_sudo_store_sudoers(struct sdap_sudo_ctx *sudo_ctx, - size_t replies_count, - struct sysdb_attrs **replies); +static int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx, + struct sss_domain_info *domain, + struct be_sudo_req *sudo_req); -const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx, - struct sdap_attr_map *map, - const char *username, - uid_t uid, - char **groups); +static int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx, + struct sdap_options *opts, + size_t rules_count, + struct sysdb_attrs **rules); + +static const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx, + struct sdap_attr_map *map, + struct be_sudo_req *sudo_req); + +static const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx, + struct sdap_attr_map *map, + const char *username, + uid_t uid, + char **groups); static void sdap_sudo_reply(struct tevent_req *req) { struct be_req *be_req = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; int dp_error; int error; int ret; be_req = tevent_req_callback_data(req, struct be_req); - ret = sdap_sudo_refresh_recv(req, &sudo_ctx, &dp_error, &error); + ret = sdap_sudo_refresh_recv(req, &dp_error, &error); talloc_zfree(req); - talloc_zfree(sudo_ctx); if (ret != EOK) { sdap_handler_done(be_req, DP_ERR_FATAL, ret, strerror(ret)); return; @@ -98,7 +117,6 @@ static void sdap_sudo_reply(struct tevent_req *req) void sdap_sudo_handler(struct be_req *be_req) { struct tevent_req *req = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; struct be_sudo_req *sudo_req = NULL; struct sdap_id_ctx *id_ctx = NULL; int ret = EOK; @@ -108,35 +126,23 @@ void sdap_sudo_handler(struct be_req *be_req) sudo_req = talloc_get_type(be_req->req_data, struct be_sudo_req); - sudo_ctx = talloc_zero(be_req, struct sdap_sudo_ctx); - if (!sudo_ctx) { - ret = ENOMEM; - goto fail; - } - - sudo_ctx->be_ctx = id_ctx->be; - sudo_ctx->be_req = be_req; - sudo_ctx->sdap_ctx = id_ctx; - sudo_ctx->sdap_op = NULL; - sudo_ctx->sdap_conn_cache = id_ctx->conn_cache; - /* get user info */ - sudo_ctx->username = sudo_req->username; - if (sudo_ctx->username != NULL) { - ret = sysdb_get_sudo_user_info(sudo_ctx, sudo_ctx->username, - sudo_ctx->be_ctx->sysdb, - &sudo_ctx->uid, &sudo_ctx->groups); + if (sudo_req->username != NULL) { + ret = sysdb_get_sudo_user_info(sudo_req, sudo_req->username, + id_ctx->be->sysdb, + &sudo_req->uid, &sudo_req->groups); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to get uid and groups of %s\n", - sudo_ctx->username)); + sudo_req->username)); goto fail; } } else { - sudo_ctx->uid = 0; - sudo_ctx->groups = NULL; + sudo_req->uid = 0; + sudo_req->groups = NULL; } - req = sdap_sudo_refresh_send(sudo_ctx, sudo_ctx); + req = sdap_sudo_refresh_send(be_req, id_ctx->be, sudo_req, id_ctx->opts, + id_ctx->conn_cache); if (req == NULL) { ret = ENOMEM; goto fail; @@ -147,12 +153,14 @@ void sdap_sudo_handler(struct be_req *be_req) return; fail: - talloc_free(sudo_ctx); sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL); } struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx) + struct be_ctx *be_ctx, + struct be_sudo_req *sudo_req, + struct sdap_options *opts, + struct sdap_id_conn_cache *conn_cache) { struct tevent_req *req = NULL; struct sdap_sudo_refresh_state *state = NULL; @@ -163,12 +171,30 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, return NULL; } - state->sudo_ctx = sudo_ctx; + state->be_ctx = be_ctx; + state->sudo_req = sudo_req; + state->opts = opts; + state->sdap_op = NULL; + state->sdap_conn_cache = conn_cache; state->dp_error = DP_ERR_OK; state->error = EOK; - DEBUG(SSSDBG_FUNC_DATA, ("Requested refresh for: %s\n", - sudo_ctx->username ? sudo_ctx->username : "\n")); + switch (sudo_req->type) { + case BE_REQ_SUDO_ALL: + DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: \n")); + break; + case BE_REQ_SUDO_DEFAULTS: + DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh of cn=defaults\n")); + break; + case BE_REQ_SUDO_USER: + DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: %s\n", + sudo_req->username)); + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type)); + ret = EINVAL; + goto immediately; + } ret = sdap_sudo_connect(req); if (ret == EAGAIN) { @@ -176,18 +202,18 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, return req; } +immediately: if (ret == EOK) { tevent_req_done(req); } else { tevent_req_error(req, ret); } - tevent_req_post(req, sudo_ctx->be_ctx->ev); + tevent_req_post(req, be_ctx->ev); return req; } int sdap_sudo_refresh_recv(struct tevent_req *req, - struct sdap_sudo_ctx **sudo_ctx, int *dp_error, int *error) { @@ -197,7 +223,6 @@ int sdap_sudo_refresh_recv(struct tevent_req *req, TEVENT_REQ_RETURN_ON_ERROR(req); - *sudo_ctx = state->sudo_ctx; *dp_error = state->dp_error; *error = state->error; @@ -208,22 +233,19 @@ int sdap_sudo_connect(struct tevent_req *req) { struct tevent_req *subreq = NULL; struct sdap_sudo_refresh_state *state = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; int ret; state = tevent_req_data(req, struct sdap_sudo_refresh_state); - sudo_ctx = state->sudo_ctx; - if (be_is_offline(sudo_ctx->be_ctx)) { + if (be_is_offline(state->be_ctx)) { state->dp_error = DP_ERR_OFFLINE; state->error = EAGAIN; return EOK; } - if (sudo_ctx->sdap_op == NULL) { - sudo_ctx->sdap_op = sdap_id_op_create(sudo_ctx, - sudo_ctx->sdap_conn_cache); - if (sudo_ctx->sdap_op == NULL) { + if (state->sdap_op == NULL) { + state->sdap_op = sdap_id_op_create(state, state->sdap_conn_cache); + if (state->sdap_op == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create() failed\n")); state->dp_error = DP_ERR_FATAL; state->error = EIO; @@ -231,11 +253,11 @@ int sdap_sudo_connect(struct tevent_req *req) } } - subreq = sdap_id_op_connect_send(sudo_ctx->sdap_op, sudo_ctx, &ret); + subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_connect_send() failed: %d(%s)\n", ret, strerror(ret))); - talloc_zfree(sudo_ctx->sdap_op); + talloc_zfree(state->sdap_op); state->dp_error = DP_ERR_FATAL; state->error = ret; return ret; @@ -250,19 +272,17 @@ void sdap_sudo_connect_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */ struct sdap_sudo_refresh_state *state = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; int dp_error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); - sudo_ctx = state->sudo_ctx; ret = sdap_id_op_connect_recv(subreq, &dp_error); talloc_zfree(subreq); if (dp_error == DP_ERR_OFFLINE) { - talloc_zfree(sudo_ctx->sdap_op); + talloc_zfree(state->sdap_op); state->dp_error = DP_ERR_OFFLINE; state->error = EAGAIN; tevent_req_done(req); @@ -275,7 +295,9 @@ void sdap_sudo_connect_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, ("SUDO LDAP connection successful\n")); - subreq = sdap_sudo_load_sudoers_send(sudo_ctx, sudo_ctx); + subreq = sdap_sudo_load_sudoers_send(state, state->be_ctx->ev, + state->sudo_req, state->opts, + sdap_id_op_handle(state->sdap_op)); if (subreq == NULL) { ret = EFAULT; goto fail; @@ -292,7 +314,13 @@ fail: } struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx) + struct tevent_context *ev, + struct be_sudo_req *sudo_req, + struct sdap_options *opts, + struct sdap_handle *sh) + + + { struct tevent_req *req = NULL; struct sdap_sudo_load_sudoers_state *state = NULL; @@ -303,29 +331,24 @@ struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, return NULL; } - state->ev = sudo_ctx->be_ctx->ev; - state->sudo_ctx = sudo_ctx; - state->opts = sudo_ctx->sdap_ctx->opts; - state->sh = sdap_id_op_handle(sudo_ctx->sdap_op); + state->ev = ev; + state->opts = opts; + state->sh = sh; state->base_iter = 0; - state->search_bases = state->opts->sudo_search_bases; - state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT); + state->search_bases = opts->sudo_search_bases; + state->timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT); state->ldap_rules = NULL; state->ldap_rules_count = 0; /* create filter */ - state->filter = sdap_sudo_build_filter(state, - state->opts->sudorule_map, - sudo_ctx->username, - sudo_ctx->uid, - sudo_ctx->groups); + state->filter = sdap_sudo_build_filter(state, opts->sudorule_map, sudo_req); if (state->filter == NULL) { goto fail; } /* create attrs from map */ - ret = build_attrs_from_map(state, state->opts->sudorule_map, - SDAP_OPTS_SUDO, &state->attrs); + ret = build_attrs_from_map(state, opts->sudorule_map, SDAP_OPTS_SUDO, + &state->attrs); if (ret != EOK) { goto fail; } @@ -334,7 +357,7 @@ struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, ret = sdap_sudo_load_sudoers_next_base(req); if (ret != EOK) { tevent_req_error(req, ret); - tevent_req_post(req, sudo_ctx->be_ctx->ev); + tevent_req_post(req, ev); } return req; @@ -470,16 +493,14 @@ void sdap_sudo_load_sudoers_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */ struct sdap_sudo_refresh_state *state = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; struct sysdb_attrs **rules = NULL; size_t rules_count; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); - sudo_ctx = state->sudo_ctx; - ret = sdap_sudo_load_sudoers_recv(subreq, sudo_ctx, &rules_count, &rules); + ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules); talloc_zfree(subreq); if (ret != EOK) { goto done; @@ -488,13 +509,15 @@ void sdap_sudo_load_sudoers_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, ("Received %d rules\n", rules_count)); /* purge cache */ - ret = sdap_sudo_purge_sudoers(sudo_ctx); + ret = sdap_sudo_purge_sudoers(state->be_ctx->sysdb, state->be_ctx->domain, + state->sudo_req); if (ret != EOK) { goto done; } /* store rules */ - ret = sdap_sudo_store_sudoers(sudo_ctx, rules_count, rules); + ret = sdap_sudo_store_sudoers(state->be_ctx->sysdb, state->opts, + rules_count, rules); if (ret != EOK) { goto done; } @@ -514,42 +537,67 @@ done: } } -int sdap_sudo_purge_sudoers(struct sdap_sudo_ctx *sudo_ctx) +int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx, + struct sss_domain_info *domain, + struct be_sudo_req *sudo_req) { - struct sysdb_ctx *sysdb_ctx = sudo_ctx->be_ctx->sysdb; + TALLOC_CTX *tmp_ctx; char *filter = NULL; - int ret; + int ret = EOK; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n")); + return ENOMEM; + } - if (sudo_ctx->username != NULL) { - ret = sysdb_get_sudo_filter(sudo_ctx, sudo_ctx->username, sudo_ctx->uid, - sudo_ctx->groups, SYSDB_SUDO_FILTER_NGRS + switch (sudo_req->type) { + case BE_REQ_SUDO_ALL: + filter = NULL; + break; + case BE_REQ_SUDO_DEFAULTS: + ret = sysdb_get_sudo_filter(tmp_ctx, NULL, 0, NULL, + SYSDB_SUDO_FILTER_INCLUDE_DFL, &filter); + break; + case BE_REQ_SUDO_USER: + ret = sysdb_get_sudo_filter(tmp_ctx, sudo_req->username, sudo_req->uid, + sudo_req->groups, + SYSDB_SUDO_FILTER_USERINFO | SYSDB_SUDO_FILTER_INCLUDE_ALL | SYSDB_SUDO_FILTER_INCLUDE_DFL, &filter); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create filter to purge " - "sudoers cache [%d]: %s\n", ret, strerror(ret))); - return ret; - } + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type)); + return EINVAL; + } + + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create filter to purge " + "sudoers cache [%d]: %s\n", ret, strerror(ret))); + goto done; } /* Purge rules */ DEBUG(SSSDBG_TRACE_FUNC, ("Purging sudo cache with filter [%s]\n", filter)); - ret = sysdb_purge_sudorule_subtree(sysdb_ctx, sudo_ctx->be_ctx->domain, - filter); + ret = sysdb_purge_sudorule_subtree(sysdb_ctx, domain, filter); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to purge sudoers cache [%d]: %s\n", ret, strerror(ret))); - return ret; + goto done; } - return EOK; + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; } -int sdap_sudo_store_sudoers(struct sdap_sudo_ctx *sudo_ctx, +int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx, + struct sdap_options *opts, size_t rules_count, struct sysdb_attrs **rules) { - struct sysdb_ctx *sysdb_ctx = sudo_ctx->be_ctx->sysdb; errno_t ret; /* Empty sudoers? Done. */ @@ -557,8 +605,7 @@ int sdap_sudo_store_sudoers(struct sdap_sudo_ctx *sudo_ctx, return EOK; } - ret = sdap_save_native_sudorule_list(sysdb_ctx, - sudo_ctx->sdap_ctx->opts->sudorule_map, + ret = sdap_save_native_sudorule_list(sysdb_ctx, opts->sudorule_map, rules, rules_count); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("failed to save sudo rules [%d]: %s\n", @@ -569,12 +616,38 @@ int sdap_sudo_store_sudoers(struct sdap_sudo_ctx *sudo_ctx, return EOK; } -/* alway update cn=defaults and sudoUser=ALL */ const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx, struct sdap_attr_map *map, - const char *username, - uid_t uid, - char **groups) + struct be_sudo_req *sudo_req) +{ + switch (sudo_req->type) { + case BE_REQ_SUDO_ALL: + return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_ALL, + map[SDAP_OC_SUDORULE].name); + break; + case BE_REQ_SUDO_DEFAULTS: + return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_DEFAULTS, + map[SDAP_OC_SUDORULE].name, + map[SDAP_AT_SUDO_NAME].name, + SDAP_SUDO_DEFAULTS); /* FIXME: add option for this */ + break; + case BE_REQ_SUDO_USER: + return sdap_sudo_build_user_filter(mem_ctx, map, sudo_req->username, + sudo_req->uid, sudo_req->groups); + + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type)); + return NULL; + } +} + +/* alway update cn=defaults and sudoUser=ALL */ +const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx, + struct sdap_attr_map *map, + const char *username, + uid_t uid, + char **groups) { char *filter = NULL; char *output = NULL; @@ -582,11 +655,6 @@ const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx, char **group = NULL; int ret; - if (username == NULL) { - return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_ALL, - map[SDAP_OC_SUDORULE].name); - } - /* user name */ ret = sss_filter_sanitize(filter, username, &sanitized); if (ret != EOK) { diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h index 1e53c117..b0e66089 100644 --- a/src/providers/ldap/sdap_sudo.h +++ b/src/providers/ldap/sdap_sudo.h @@ -21,29 +21,20 @@ #ifndef _SDAP_SUDO_H_ #define _SDAP_SUDO_H_ -struct sdap_sudo_ctx { - struct be_ctx *be_ctx; - struct be_req *be_req; - struct sdap_id_ctx *sdap_ctx; - struct sdap_id_op *sdap_op; - struct sdap_id_conn_cache *sdap_conn_cache; - - const char *username; - uint_t uid; - char **groups; -}; - struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx); + struct be_ctx *be_ctx, + struct be_sudo_req *sudo_req, + struct sdap_options *opts, + struct sdap_id_conn_cache *conn_cache); int sdap_sudo_refresh_recv(struct tevent_req *req, - struct sdap_sudo_ctx **sudo_ctx, int *dp_error, int *error); /* (&(objectClass=sudoRole)(|(cn=defaults)(sudoUser=ALL)%s)) */ #define SDAP_SUDO_FILTER_USER "(&(objectClass=%s)(|(%s=%s)(%s=ALL)%s))" #define SDAP_SUDO_FILTER_ALL "(objectClass=%s)" +#define SDAP_SUDO_FILTER_DEFAULTS "(&(objectClass=%s)(%s=%s))" #define SDAP_SUDO_DEFAULTS "defaults" #define SDAP_SUDO_FILTER_USERNAME "(%s=%s)" diff --git a/src/providers/ldap/sdap_sudo_timer.c b/src/providers/ldap/sdap_sudo_timer.c index cc664abf..81b6ae88 100644 --- a/src/providers/ldap/sdap_sudo_timer.c +++ b/src/providers/ldap/sdap_sudo_timer.c @@ -92,7 +92,7 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, struct timeval tv, void *pvt) { struct sdap_sudo_refresh_ctx *refresh_ctx = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; + struct be_sudo_req *sudo_req = NULL; struct tevent_timer *timeout = NULL; struct tevent_req *req = NULL; int delay = 0; @@ -113,8 +113,8 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, } /* create sudo context */ - sudo_ctx = talloc_zero(refresh_ctx, struct sdap_sudo_ctx); - if (sudo_ctx == NULL) { + sudo_req = talloc_zero(refresh_ctx, struct be_sudo_req); + if (sudo_req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero() failed!\n")); tv = tevent_timeval_current_ofs(delay, 0); ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv); @@ -125,17 +125,13 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, return; } - sudo_ctx->be_ctx = refresh_ctx->be_ctx; - sudo_ctx->be_req = NULL; - sudo_ctx->sdap_ctx = refresh_ctx->id_ctx; - sudo_ctx->sdap_op = NULL; - sudo_ctx->sdap_conn_cache = refresh_ctx->id_ctx->conn_cache; - sudo_ctx->username = NULL; /* download all rules */ - sudo_ctx->uid = 0; - sudo_ctx->groups = NULL; + sudo_req->type = BE_REQ_SUDO_ALL; + sudo_req->username = NULL; /* send request */ - req = sdap_sudo_refresh_send(sudo_ctx, sudo_ctx); + req = sdap_sudo_refresh_send(refresh_ctx, refresh_ctx->id_ctx->be, sudo_req, + refresh_ctx->id_ctx->opts, + refresh_ctx->id_ctx->conn_cache); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to schedule refresh of SUDO rules, " "retrying later!\n")); @@ -145,9 +141,11 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n")); } + talloc_free(sudo_req); return; } refresh_ctx->last_refresh = tevent_timeval_current(); + talloc_steal(req, sudo_req); /* make it free with req */ tevent_req_set_callback(req, sdap_sudo_refresh_reschedule, refresh_ctx); @@ -178,7 +176,6 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, static void sdap_sudo_refresh_reschedule(struct tevent_req *req) { struct sdap_sudo_refresh_ctx *refresh_ctx = NULL; - struct sdap_sudo_ctx *sudo_ctx = NULL; struct timeval tv; int delay; int dp_error; @@ -186,9 +183,8 @@ static void sdap_sudo_refresh_reschedule(struct tevent_req *req) int ret; refresh_ctx = tevent_req_callback_data(req, struct sdap_sudo_refresh_ctx); - ret = sdap_sudo_refresh_recv(req, &sudo_ctx, &dp_error, &error); + ret = sdap_sudo_refresh_recv(req, &dp_error, &error); talloc_zfree(req); - talloc_zfree(sudo_ctx); if (ret != EOK) { tv = tevent_timeval_current(); } else { -- cgit