summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2016-03-29 12:38:25 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-06-20 14:48:47 +0200
commitdea636af4d1902a081ee891f1b19ee2f8729d759 (patch)
treea4d66ceb2b32ddf3b69bee1f1e2412568eae655e /src/providers/ldap
parent62370340092503baeaf6587d7ffe4fe25bd9582d (diff)
downloadsssd-dea636af4d1902a081ee891f1b19ee2f8729d759.tar.gz
sssd-dea636af4d1902a081ee891f1b19ee2f8729d759.tar.xz
sssd-dea636af4d1902a081ee891f1b19ee2f8729d759.zip
DP: Switch to new interface
Reviewed-by: Sumit Bose <sbose@redhat.com> Reviewed-by: Jakub Hrozek <jhrozek@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/ldap_access.c122
-rw-r--r--src/providers/ldap/ldap_auth.c619
-rw-r--r--src/providers/ldap/ldap_common.c6
-rw-r--r--src/providers/ldap/ldap_common.h62
-rw-r--r--src/providers/ldap/ldap_id.c300
-rw-r--r--src/providers/ldap/ldap_init.c780
-rw-r--r--src/providers/ldap/sdap_access.h11
-rw-r--r--src/providers/ldap/sdap_autofs.c217
-rw-r--r--src/providers/ldap/sdap_autofs.h8
-rw-r--r--src/providers/ldap/sdap_idmap.c2
-rw-r--r--src/providers/ldap/sdap_online_check.c249
-rw-r--r--src/providers/ldap/sdap_sudo.c233
-rw-r--r--src/providers/ldap/sdap_sudo.h8
13 files changed, 1490 insertions, 1127 deletions
diff --git a/src/providers/ldap/ldap_access.c b/src/providers/ldap/ldap_access.c
index eb60f720d..4ec4702f9 100644
--- a/src/providers/ldap/ldap_access.c
+++ b/src/providers/ldap/ldap_access.c
@@ -29,90 +29,100 @@
#include "src/providers/ldap/sdap_access.h"
#include "providers/ldap/ldap_common.h"
-static void sdap_access_reply(struct be_req *be_req, int pam_status)
-{
+struct sdap_pam_access_handler_state {
struct pam_data *pd;
- pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
- pd->pam_status = pam_status;
-
- if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED
- || pam_status == PAM_ACCT_EXPIRED) {
- be_req_terminate(be_req, DP_ERR_OK, pam_status, NULL);
- } else {
- be_req_terminate(be_req, DP_ERR_FATAL, pam_status, NULL);
- }
-}
+};
+
+static void sdap_pam_access_handler_done(struct tevent_req *subreq);
-static void sdap_access_done(struct tevent_req *req);
-void sdap_pam_access_handler(struct be_req *breq)
+struct tevent_req *
+sdap_pam_access_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_access_ctx *access_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params)
{
- struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
- struct pam_data *pd;
+ struct sdap_pam_access_handler_state *state;
+ struct tevent_req *subreq;
struct tevent_req *req;
- struct sdap_access_ctx *access_ctx;
- struct sss_domain_info *dom;
- pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_pam_access_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
- access_ctx =
- talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
- struct sdap_access_ctx);
+ state->pd = pd;
- dom = be_ctx->domain;
- if (strcasecmp(pd->domain, be_ctx->domain->name) != 0) {
- /* Subdomain request, verify subdomain */
- dom = find_domain_by_name(be_ctx->domain, pd->domain, true);
+ subreq = sdap_access_send(state, params->ev, params->be_ctx,
+ params->domain, access_ctx,
+ access_ctx->id_ctx->conn, pd);
+ if (subreq == NULL) {
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
}
- req = sdap_access_send(breq, be_ctx->ev, be_ctx,
- dom, access_ctx,
- access_ctx->id_ctx->conn,
- pd);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to start sdap_access request\n");
- sdap_access_reply(breq, PAM_SYSTEM_ERR);
- return;
- }
+ tevent_req_set_callback(subreq, sdap_pam_access_handler_done, req);
+
+ return req;
+
+immediately:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
- tevent_req_set_callback(req, sdap_access_done, breq);
+ return req;
}
-static void sdap_access_done(struct tevent_req *req)
+static void sdap_pam_access_handler_done(struct tevent_req *subreq)
{
+ struct sdap_pam_access_handler_state *state;
+ struct tevent_req *req;
errno_t ret;
- int pam_status;
- struct be_req *breq =
- tevent_req_callback_data(req, struct be_req);
- ret = sdap_access_recv(req);
- talloc_zfree(req);
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_pam_access_handler_state);
+
+ ret = sdap_access_recv(subreq);
+ talloc_free(subreq);
switch (ret) {
case EOK:
- pam_status = PAM_SUCCESS;
- break;
- case ERR_ACCESS_DENIED:
- pam_status = PAM_PERM_DENIED;
+ case ERR_PASSWORD_EXPIRED_WARN:
+ state->pd->pam_status = PAM_SUCCESS;
break;
case ERR_ACCOUNT_EXPIRED:
- pam_status = PAM_ACCT_EXPIRED;
+ state->pd->pam_status = PAM_ACCT_EXPIRED;
break;
+ case ERR_ACCESS_DENIED:
case ERR_PASSWORD_EXPIRED:
- pam_status = PAM_PERM_DENIED;
- break;
case ERR_PASSWORD_EXPIRED_REJECT:
- pam_status = PAM_PERM_DENIED;
- break;
- case ERR_PASSWORD_EXPIRED_WARN:
- pam_status = PAM_SUCCESS;
+ state->pd->pam_status = PAM_PERM_DENIED;
break;
case ERR_PASSWORD_EXPIRED_RENEW:
- pam_status = PAM_NEW_AUTHTOK_REQD;
+ state->pd->pam_status = PAM_NEW_AUTHTOK_REQD;
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Error retrieving access check result.\n");
- pam_status = PAM_SYSTEM_ERR;
+ state->pd->pam_status = PAM_SYSTEM_ERR;
break;
}
- sdap_access_reply(breq, pam_status);
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+}
+
+errno_t
+sdap_pam_access_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data)
+{
+ struct sdap_pam_access_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_pam_access_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_data = talloc_steal(mem_ctx, state->pd);
+
+ return EOK;
}
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 8d6a37b2c..107f6ded1 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -49,6 +49,7 @@
#include "providers/ldap/ldap_auth.h"
#include "providers/ldap/sdap_access.h"
+
#define LDAP_PWEXPIRE_WARNING_TIME 0
static errno_t add_expired_warning(struct pam_data *pd, long exp_time)
@@ -897,49 +898,215 @@ static errno_t auth_recv(struct tevent_req *req, TALLOC_CTX *memctx,
return EOK;
}
-/* ==Perform-Password-Change===================== */
-
-struct sdap_pam_chpass_state {
- struct be_req *breq;
+struct sdap_pam_auth_handler_state {
struct pam_data *pd;
- const char *username;
- char *dn;
- struct sdap_handle *sh;
-
- struct sdap_auth_ctx *ctx;
+ struct be_ctx *be_ctx;
};
-static void sdap_auth4chpass_done(struct tevent_req *req);
-static void sdap_pam_chpass_done(struct tevent_req *req);
+static void sdap_pam_auth_handler_done(struct tevent_req *subreq);
-void sdap_pam_chpass_handler(struct be_req *breq)
+struct tevent_req *
+sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_auth_ctx *auth_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params)
{
- struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
- struct sdap_pam_chpass_state *state;
- struct sdap_auth_ctx *ctx;
+ struct sdap_pam_auth_handler_state *state;
struct tevent_req *subreq;
+ struct tevent_req *req;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_pam_auth_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->pd = pd;
+ state->be_ctx = params->be_ctx;
+ pd->pam_status = PAM_SYSTEM_ERR;
+
+ switch (pd->cmd) {
+ case SSS_PAM_AUTHENTICATE:
+ subreq = auth_send(state, params->ev, auth_ctx,
+ pd->user, pd->authtok, false);
+ if (subreq == NULL) {
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_pam_auth_handler_done, req);
+ break;
+ case SSS_PAM_CHAUTHTOK_PRELIM:
+ subreq = auth_send(state, params->ev, auth_ctx,
+ pd->user, pd->authtok, true);
+ if (subreq == NULL) {
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_pam_auth_handler_done, req);
+ break;
+ case SSS_PAM_CHAUTHTOK:
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+
+ case SSS_PAM_ACCT_MGMT:
+ case SSS_PAM_SETCRED:
+ case SSS_PAM_OPEN_SESSION:
+ case SSS_PAM_CLOSE_SESSION:
+ pd->pam_status = PAM_SUCCESS;
+ goto immediately;
+ default:
+ pd->pam_status = PAM_MODULE_UNKNOWN;
+ goto immediately;
+ }
+
+ return req;
+
+immediately:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void sdap_pam_auth_handler_done(struct tevent_req *subreq)
+{
+ struct sdap_pam_auth_handler_state *state;
+ struct tevent_req *req;
+ enum pwexpire pw_expire_type;
+ void *pw_expire_data;
+ const char *password;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_pam_auth_handler_state);
+
+ ret = auth_recv(subreq, state, NULL, NULL,
+ &pw_expire_type, &pw_expire_data);
+ talloc_free(subreq);
+
+ if (ret == EOK) {
+ ret = check_pwexpire_policy(pw_expire_type, pw_expire_data, state->pd,
+ state->be_ctx->domain->pwd_expiration_warning);
+ if (ret == EINVAL) {
+ /* Unknown password expiration type. */
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ }
+
+ switch (ret) {
+ case EOK:
+ state->pd->pam_status = PAM_SUCCESS;
+ break;
+ case ERR_AUTH_DENIED:
+ state->pd->pam_status = PAM_PERM_DENIED;
+ break;
+ case ERR_AUTH_FAILED:
+ state->pd->pam_status = PAM_AUTH_ERR;
+ break;
+ case ETIMEDOUT:
+ case ERR_NETWORK_IO:
+ state->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
+ be_mark_offline(state->be_ctx);
+ break;
+ case ERR_ACCOUNT_EXPIRED:
+ state->pd->pam_status = PAM_ACCT_EXPIRED;
+ break;
+ case ERR_PASSWORD_EXPIRED:
+ state->pd->pam_status = PAM_NEW_AUTHTOK_REQD;
+ break;
+ case ERR_ACCOUNT_LOCKED:
+ state->pd->account_locked = true;
+ state->pd->pam_status = PAM_PERM_DENIED;
+ break;
+ default:
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ break;
+ }
+
+ if (ret == EOK && state->be_ctx->domain->cache_credentials) {
+ ret = sss_authtok_get_password(state->pd->authtok, &password, NULL);
+ if (ret == EOK) {
+ ret = sysdb_cache_password(state->be_ctx->domain, state->pd->user,
+ password);
+ }
+
+ /* password caching failures are not fatal errors */
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password for %s\n",
+ state->pd->user);
+ } else {
+ DEBUG(SSSDBG_CONF_SETTINGS, "Password successfully cached for %s\n",
+ state->pd->user);
+ }
+ }
+
+done:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+}
+
+errno_t
+sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data)
+{
+ struct sdap_pam_auth_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_pam_auth_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_data = talloc_steal(mem_ctx, state->pd);
+
+ return EOK;
+}
+
+struct sdap_pam_chpass_handler_state {
+ struct be_ctx *be_ctx;
+ struct tevent_context *ev;
+ struct sdap_auth_ctx *auth_ctx;
struct pam_data *pd;
- int dp_err = DP_ERR_FATAL;
+ struct sdap_handle *sh;
+ char *dn;
+};
- ctx = talloc_get_type(be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
- struct sdap_auth_ctx);
- pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
+static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq);
+static void sdap_pam_chpass_handler_chpass_done(struct tevent_req *subreq);
+static void sdap_pam_chpass_handler_last_done(struct tevent_req *subreq);
- if (be_is_offline(ctx->be)) {
- DEBUG(SSSDBG_CONF_SETTINGS,
- "Backend is marked offline, retry later!\n");
- pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- dp_err = DP_ERR_OFFLINE;
- goto done;
+struct tevent_req *
+sdap_pam_chpass_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_auth_ctx *auth_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params)
+{
+ struct sdap_pam_chpass_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_pam_chpass_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
}
+ state->pd = pd;
+ state->be_ctx = params->be_ctx;
+ state->auth_ctx = auth_ctx;
+ state->ev = params->ev;
+
if ((pd->priv == 1) && (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) &&
(sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD)) {
DEBUG(SSSDBG_CONF_SETTINGS,
"Password reset by root is not supported.\n");
pd->pam_status = PAM_PERM_DENIED;
- dp_err = DP_ERR_OK;
- goto done;
+ goto immediately;
}
DEBUG(SSSDBG_OP_FAILURE,
@@ -950,52 +1117,50 @@ void sdap_pam_chpass_handler(struct be_req *breq)
if (pd->cmd != SSS_PAM_CHAUTHTOK && pd->cmd != SSS_PAM_CHAUTHTOK_PRELIM) {
DEBUG(SSSDBG_OP_FAILURE,
"chpass target was called by wrong pam command.\n");
- goto done;
+ goto immediately;
}
- state = talloc_zero(breq, struct sdap_pam_chpass_state);
- if (!state) goto done;
+ subreq = auth_send(state, params->ev, auth_ctx,
+ pd->user, pd->authtok, true);
+ if (subreq == NULL) {
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+ }
- state->breq = breq;
- state->pd = pd;
- state->username = pd->user;
- state->ctx = ctx;
+ tevent_req_set_callback(subreq, sdap_pam_chpass_handler_auth_done, req);
- subreq = auth_send(breq, be_ctx->ev, ctx,
- state->username, pd->authtok, true);
- if (!subreq) goto done;
+ return req;
- tevent_req_set_callback(subreq, sdap_auth4chpass_done, state);
- return;
+immediately:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
-done:
- be_req_terminate(breq, dp_err, pd->pam_status, NULL);
+ return req;
}
-static void sdap_lastchange_done(struct tevent_req *req);
-static void sdap_auth4chpass_done(struct tevent_req *req)
+static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
{
- struct sdap_pam_chpass_state *state =
- tevent_req_callback_data(req, struct sdap_pam_chpass_state);
- struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq);
- struct tevent_req *subreq;
+ struct sdap_pam_chpass_handler_state *state;
+ struct tevent_req *req;
enum pwexpire pw_expire_type;
void *pw_expire_data;
- int dp_err = DP_ERR_FATAL;
- int ret;
size_t msg_len;
uint8_t *msg;
+ errno_t ret;
- ret = auth_recv(req, state, &state->sh, &state->dn,
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
+
+ ret = auth_recv(subreq, state, &state->sh, &state->dn,
&pw_expire_type, &pw_expire_data);
- talloc_zfree(req);
+ talloc_free(subreq);
+
if ((ret == EOK || ret == ERR_PASSWORD_EXPIRED) &&
state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- DEBUG(SSSDBG_TRACE_ALL,
- "Initial authentication for change password operation "
- "successful.\n");
+ DEBUG(SSSDBG_TRACE_ALL, "Initial authentication for change "
+ "password operation successful.\n");
state->pd->pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
goto done;
}
@@ -1006,12 +1171,11 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
break;
case PWEXPIRE_KERBEROS:
ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL,
- be_ctx->domain->pwd_expiration_warning);
+ state->be_ctx->domain->pwd_expiration_warning);
if (ret == ERR_PASSWORD_EXPIRED) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "LDAP provider cannot change kerberos "
- "passwords.\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "LDAP provider cannot change "
+ "kerberos passwords.\n");
state->pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
@@ -1027,100 +1191,104 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
}
switch (ret) {
- case EOK:
- case ERR_PASSWORD_EXPIRED:
- DEBUG(SSSDBG_TRACE_LIBS,
- "user [%s] successfully authenticated.\n", state->dn);
- if (pw_expire_type == PWEXPIRE_SHADOW) {
-/* TODO: implement async ldap modify request */
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Changing shadow password attributes not implemented.\n");
- state->pd->pam_status = PAM_MODULE_UNKNOWN;
- goto done;
- } else {
- const char *password;
- const char *new_password;
- int timeout;
-
- ret = sss_authtok_get_password(state->pd->authtok,
- &password, NULL);
- if (ret) {
- state->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- ret = sss_authtok_get_password(state->pd->newauthtok,
- &new_password, NULL);
- if (ret) {
- state->pd->pam_status = PAM_SYSTEM_ERR;
+ case EOK:
+ case ERR_PASSWORD_EXPIRED:
+ DEBUG(SSSDBG_TRACE_LIBS,
+ "user [%s] successfully authenticated.\n", state->dn);
+ if (pw_expire_type == PWEXPIRE_SHADOW) {
+ /* TODO: implement async ldap modify request */
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Changing shadow password attributes not implemented.\n");
+ state->pd->pam_status = PAM_MODULE_UNKNOWN;
goto done;
- }
+ } else {
+ const char *password;
+ const char *new_password;
+ int timeout;
+
+ ret = sss_authtok_get_password(state->pd->authtok,
+ &password, NULL);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ ret = sss_authtok_get_password(state->pd->newauthtok,
+ &new_password, NULL);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
- timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT);
+ timeout = dp_opt_get_int(state->auth_ctx->opts->basic,
+ SDAP_OPT_TIMEOUT);
+
+ subreq = sdap_exop_modify_passwd_send(state, state->ev,
+ state->sh, state->dn,
+ password, new_password,
+ timeout);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to change password for "
+ "%s\n", state->pd->user);
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
- subreq = sdap_exop_modify_passwd_send(state, be_ctx->ev,
- state->sh, state->dn,
- password, new_password,
- timeout);
- if (!subreq) {
- DEBUG(SSSDBG_OP_FAILURE,
- "Failed to change password for %s\n", state->username);
- goto done;
+ tevent_req_set_callback(subreq,
+ sdap_pam_chpass_handler_chpass_done,
+ req);
+ return;
}
- tevent_req_set_callback(subreq, sdap_pam_chpass_done, state);
- return;
- }
- break;
- case ERR_AUTH_DENIED:
- case ERR_AUTH_FAILED:
- state->pd->pam_status = PAM_AUTH_ERR;
- ret = pack_user_info_chpass_error(state->pd, "Old password not accepted.",
- &msg_len, &msg);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "pack_user_info_chpass_error failed.\n");
- } else {
- ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len,
- msg);
+ break;
+ case ERR_AUTH_DENIED:
+ case ERR_AUTH_FAILED:
+ state->pd->pam_status = PAM_AUTH_ERR;
+ ret = pack_user_info_chpass_error(state->pd, "Old password not "
+ "accepted.", &msg_len, &msg);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "pack_user_info_chpass_error failed.\n");
+ } else {
+ ret = pam_add_response(state->pd, SSS_PAM_USER_INFO,
+ msg_len, msg);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
+ }
}
+ break;
+ case ETIMEDOUT:
+ case ERR_NETWORK_IO:
+ state->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
+ be_mark_offline(state->be_ctx);
+ break;
+ default:
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ break;
}
- break;
- case ETIMEDOUT:
- case ERR_NETWORK_IO:
- state->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- be_mark_offline(be_ctx);
- dp_err = DP_ERR_OFFLINE;
- break;
- default:
- state->pd->pam_status = PAM_SYSTEM_ERR;
- }
-
done:
- be_req_terminate(state->breq, dp_err, state->pd->pam_status, NULL);
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
}
-static void sdap_pam_chpass_done(struct tevent_req *req)
+static void sdap_pam_chpass_handler_chpass_done(struct tevent_req *subreq)
{
- struct sdap_pam_chpass_state *state =
- tevent_req_callback_data(req, struct sdap_pam_chpass_state);
- struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq);
- int dp_err = DP_ERR_FATAL;
- int ret;
+ struct sdap_pam_chpass_handler_state *state;
+ struct tevent_req *req;
char *user_error_message = NULL;
char *lastchanged_name;
- struct tevent_req *subreq;
size_t msg_len;
uint8_t *msg;
+ errno_t ret;
- ret = sdap_exop_modify_passwd_recv(req, state, &user_error_message);
- talloc_zfree(req);
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
+
+ ret = sdap_exop_modify_passwd_recv(subreq, state, &user_error_message);
+ talloc_free(subreq);
switch (ret) {
case EOK:
state->pd->pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
break;
case ERR_CHPASS_DENIED:
state->pd->pam_status = PAM_NEW_AUTHTOK_REQD;
@@ -1135,12 +1303,11 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
if (state->pd->pam_status != PAM_SUCCESS && user_error_message != NULL) {
ret = pack_user_info_chpass_error(state->pd, user_error_message,
- &msg_len, &msg);
+ &msg_len, &msg);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "pack_user_info_chpass_error failed.\n");
} else {
- ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len,
- msg);
+ ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len, msg);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
}
@@ -1148,11 +1315,11 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
}
if (state->pd->pam_status == PAM_SUCCESS &&
- dp_opt_get_bool(state->ctx->opts->basic,
+ dp_opt_get_bool(state->auth_ctx->opts->basic,
SDAP_CHPASS_UPDATE_LAST_CHANGE)) {
- lastchanged_name = state->ctx->opts->user_map[SDAP_AT_SP_LSTCHG].name;
+ lastchanged_name = state->auth_ctx->opts->user_map[SDAP_AT_SP_LSTCHG].name;
- subreq = sdap_modify_shadow_lastchange_send(state, be_ctx->ev,
+ subreq = sdap_modify_shadow_lastchange_send(state, state->ev,
state->sh, state->dn,
lastchanged_name);
if (subreq == NULL) {
@@ -1160,181 +1327,51 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
goto done;
}
- tevent_req_set_callback(subreq, sdap_lastchange_done, state);
+ tevent_req_set_callback(subreq, sdap_pam_chpass_handler_last_done, req);
return;
}
done:
- be_req_terminate(state->breq, dp_err, state->pd->pam_status, NULL);
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
}
-static void sdap_lastchange_done(struct tevent_req *req)
+static void sdap_pam_chpass_handler_last_done(struct tevent_req *subreq)
{
- struct sdap_pam_chpass_state *state =
- tevent_req_callback_data(req, struct sdap_pam_chpass_state);
- int dp_err = DP_ERR_FATAL;
+ struct sdap_pam_chpass_handler_state *state;
+ struct tevent_req *req;
errno_t ret;
- ret = sdap_modify_shadow_lastchange_recv(req);
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
+
+ ret = sdap_modify_shadow_lastchange_recv(subreq);
+ talloc_free(subreq);
+
if (ret != EOK) {
state->pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
- dp_err = DP_ERR_OK;
state->pd->pam_status = PAM_SUCCESS;
done:
- be_req_terminate(state->breq, dp_err, state->pd->pam_status, NULL);
-}
-
-/* ==Perform-User-Authentication-and-Password-Caching===================== */
-
-struct sdap_pam_auth_state {
- struct be_req *breq;
- struct pam_data *pd;
-};
-
-static void sdap_pam_auth_done(struct tevent_req *req);
-
-void sdap_pam_auth_handler(struct be_req *breq)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
- struct sdap_pam_auth_state *state;
- struct sdap_auth_ctx *ctx;
- struct tevent_req *subreq;
- struct pam_data *pd;
- int dp_err = DP_ERR_FATAL;
-
- ctx = talloc_get_type(be_ctx->bet_info[BET_AUTH].pvt_bet_data,
- struct sdap_auth_ctx);
- pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
-
- if (be_is_offline(ctx->be)) {
- DEBUG(SSSDBG_CONF_SETTINGS,
- "Backend is marked offline, retry later!\n");
- pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- dp_err = DP_ERR_OFFLINE;
- goto done;
- }
-
- pd->pam_status = PAM_SYSTEM_ERR;
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- case SSS_PAM_CHAUTHTOK_PRELIM:
-
- state = talloc_zero(breq, struct sdap_pam_auth_state);
- if (!state) goto done;
-
- state->breq = breq;
- state->pd = pd;
-
- subreq = auth_send(breq, be_ctx->ev, ctx,
- pd->user, pd->authtok,
- pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM ? true : false);
- if (!subreq) goto done;
-
- tevent_req_set_callback(subreq, sdap_pam_auth_done, state);
- return;
-
- case SSS_PAM_CHAUTHTOK:
- break;
-
- case SSS_PAM_ACCT_MGMT:
- case SSS_PAM_SETCRED:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- pd->pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
- break;
- default:
- pd->pam_status = PAM_MODULE_UNKNOWN;
- dp_err = DP_ERR_OK;
- }
-
-done:
- be_req_terminate(breq, dp_err, pd->pam_status, NULL);
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
}
-static void sdap_pam_auth_done(struct tevent_req *req)
+errno_t
+sdap_pam_chpass_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data)
{
- struct sdap_pam_auth_state *state =
- tevent_req_callback_data(req, struct sdap_pam_auth_state);
- struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq);
- enum pwexpire pw_expire_type;
- void *pw_expire_data;
- const char *password;
- int dp_err = DP_ERR_OK;
- int ret;
+ struct sdap_pam_chpass_handler_state *state = NULL;
- ret = auth_recv(req, state, NULL, NULL,
- &pw_expire_type, &pw_expire_data);
- talloc_zfree(req);
+ state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
- if (ret == EOK) {
- ret = check_pwexpire_policy(pw_expire_type, pw_expire_data, state->pd,
- be_ctx->domain->pwd_expiration_warning);
- if (ret == EINVAL) {
- /* Unknown password expiration type. */
- state->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- }
-
- switch (ret) {
- case EOK:
- state->pd->pam_status = PAM_SUCCESS;
- break;
- case ERR_AUTH_DENIED:
- state->pd->pam_status = PAM_PERM_DENIED;
- break;
- case ERR_AUTH_FAILED:
- state->pd->pam_status = PAM_AUTH_ERR;
- break;
- case ETIMEDOUT:
- case ERR_NETWORK_IO:
- state->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- break;
- case ERR_ACCOUNT_EXPIRED:
- state->pd->pam_status = PAM_ACCT_EXPIRED;
- break;
- case ERR_PASSWORD_EXPIRED:
- state->pd->pam_status = PAM_NEW_AUTHTOK_REQD;
- break;
- case ERR_ACCOUNT_LOCKED:
- state->pd->account_locked = true;
- state->pd->pam_status = PAM_PERM_DENIED;
- break;
- default:
- state->pd->pam_status = PAM_SYSTEM_ERR;
- dp_err = DP_ERR_FATAL;
- }
-
- if (ret == ETIMEDOUT || ret == ERR_NETWORK_IO) {
- be_mark_offline(be_ctx);
- dp_err = DP_ERR_OFFLINE;
- goto done;
- }
-
- if (ret == EOK && be_ctx->domain->cache_credentials) {
+ TEVENT_REQ_RETURN_ON_ERROR(req);
- ret = sss_authtok_get_password(state->pd->authtok, &password, NULL);
- if (ret == EOK) {
- ret = sysdb_cache_password(be_ctx->domain, state->pd->user,
- password);
- }
+ *_data = talloc_steal(mem_ctx, state->pd);
- /* password caching failures are not fatal errors */
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password for %s\n",
- state->pd->user);
- } else {
- DEBUG(SSSDBG_CONF_SETTINGS, "Password successfully cached for %s\n",
- state->pd->user);
- }
- }
-
-done:
- be_req_terminate(state->breq, dp_err, state->pd->pam_status, NULL);
+ return EOK;
}
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 27b62a635..c9f78ff8d 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -38,12 +38,6 @@
/* a fd the child process would log into */
int ldap_child_debug_fd = -1;
-void sdap_handler_done(struct be_req *req, int dp_err,
- int error, const char *errstr)
-{
- return be_req_terminate(req, dp_err, error, errstr);
-}
-
int ldap_id_setup_tasks(struct sdap_id_ctx *ctx)
{
return sdap_id_setup_tasks(ctx->be, ctx, ctx->opts->sdom,
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index d50473c88..b39f67892 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -78,12 +78,15 @@ struct sdap_auth_ctx {
struct sdap_service *chpass_service;
};
-int sssm_ldap_id_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data);
+struct tevent_req *
+sdap_online_check_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ void *data,
+ struct dp_req_params *params);
-void sdap_check_online(struct be_req *breq);
-void sdap_do_online_check(struct be_req *be_req, struct sdap_id_ctx *ctx);
+errno_t sdap_online_check_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data);
struct tevent_req* sdap_reinit_cleanup_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
@@ -92,9 +95,15 @@ struct tevent_req* sdap_reinit_cleanup_send(TALLOC_CTX *mem_ctx,
errno_t sdap_reinit_cleanup_recv(struct tevent_req *req);
/* id */
-void sdap_account_info_handler(struct be_req *breq);
-void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx,
- struct sdap_id_conn_ctx *conn);
+struct tevent_req *
+sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct be_acct_req *data,
+ struct dp_req_params *params);
+
+errno_t sdap_account_info_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data);
/* Set up enumeration and/or cleanup */
int ldap_id_setup_tasks(struct sdap_id_ctx *ctx);
@@ -121,20 +130,39 @@ sdap_handle_acct_req_recv(struct tevent_req *req,
int *_dp_error, const char **_err,
int *sdap_ret);
-/* auth */
-void sdap_pam_auth_handler(struct be_req *breq);
+struct tevent_req *
+sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_auth_ctx *auth_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params);
+
+errno_t
+sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data);
-/* chpass */
-void sdap_pam_chpass_handler(struct be_req *breq);
+struct tevent_req *
+sdap_pam_chpass_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_auth_ctx *auth_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params);
-/* access */
-void sdap_pam_access_handler(struct be_req *breq);
+errno_t
+sdap_pam_chpass_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data);
/* autofs */
-void sdap_autofs_handler(struct be_req *breq);
+struct tevent_req *
+sdap_autofs_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_autofs_data *data,
+ struct dp_req_params *params);
-void sdap_handler_done(struct be_req *req, int dp_err,
- int error, const char *errstr);
+errno_t
+sdap_autofs_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data);
int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
const char *service_name, const char *dns_service_name,
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index ee5b374db..49ce9db48 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -1286,152 +1286,11 @@ int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret
return EOK;
}
-static void sdap_check_online_done(struct tevent_req *req);
-void sdap_check_online(struct be_req *be_req)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
- struct sdap_id_ctx *ctx;
-
- ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
- struct sdap_id_ctx);
-
- return sdap_do_online_check(be_req, ctx);
-}
-
-struct sdap_online_check_ctx {
- struct be_req *be_req;
- struct sdap_id_ctx *id_ctx;
-};
-
-void sdap_do_online_check(struct be_req *be_req, struct sdap_id_ctx *ctx)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
- struct tevent_req *req;
- struct sdap_online_check_ctx *check_ctx;
- errno_t ret;
-
- check_ctx = talloc_zero(be_req, struct sdap_online_check_ctx);
- if (!check_ctx) {
- ret = ENOMEM;
- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed\n");
- goto fail;
- }
- check_ctx->id_ctx = ctx;
- check_ctx->be_req = be_req;
-
- req = sdap_cli_connect_send(be_req, be_ctx->ev, ctx->opts,
- be_ctx, ctx->conn->service, false,
- CON_TLS_DFL, false);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_cli_connect_send failed.\n");
- ret = EIO;
- goto fail;
- }
- tevent_req_set_callback(req, sdap_check_online_done, check_ctx);
-
- return;
-fail:
- sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
-}
-
-static void sdap_check_online_reinit_done(struct tevent_req *req);
-
-static void sdap_check_online_done(struct tevent_req *req)
-{
- struct sdap_online_check_ctx *check_ctx = tevent_req_callback_data(req,
- struct sdap_online_check_ctx);
- int ret;
- int dp_err = DP_ERR_FATAL;
- bool can_retry;
- struct sdap_server_opts *srv_opts;
- struct be_req *be_req;
- struct sdap_id_ctx *id_ctx;
- struct tevent_req *reinit_req = NULL;
- bool reinit = false;
- struct be_ctx *be_ctx;
-
- ret = sdap_cli_connect_recv(req, NULL, &can_retry, NULL, &srv_opts);
- talloc_zfree(req);
-
- if (ret != EOK) {
- if (!can_retry) {
- dp_err = DP_ERR_OFFLINE;
- }
- } else {
- dp_err = DP_ERR_OK;
-
- if (!check_ctx->id_ctx->srv_opts) {
- srv_opts->max_user_value = 0;
- srv_opts->max_group_value = 0;
- srv_opts->max_service_value = 0;
- srv_opts->max_sudo_value = 0;
- } else if (strcmp(srv_opts->server_id, check_ctx->id_ctx->srv_opts->server_id) == 0
- && srv_opts->supports_usn
- && check_ctx->id_ctx->srv_opts->last_usn > srv_opts->last_usn) {
- check_ctx->id_ctx->srv_opts->max_user_value = 0;
- check_ctx->id_ctx->srv_opts->max_group_value = 0;
- check_ctx->id_ctx->srv_opts->max_service_value = 0;
- check_ctx->id_ctx->srv_opts->max_sudo_value = 0;
- check_ctx->id_ctx->srv_opts->last_usn = srv_opts->last_usn;
-
- reinit = true;
- }
-
- sdap_steal_server_opts(check_ctx->id_ctx, &srv_opts);
- }
-
- be_req = check_ctx->be_req;
- be_ctx = be_req_get_be_ctx(be_req);
- id_ctx = check_ctx->id_ctx;
- talloc_free(check_ctx);
-
- if (reinit) {
- DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. "
- "Cleaning cache.\n");
- reinit_req = sdap_reinit_cleanup_send(be_req, be_ctx, id_ctx);
- if (reinit_req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
- "clean up.\n");
- /* not fatal */
- goto done;
- }
-
- tevent_req_set_callback(reinit_req, sdap_check_online_reinit_done,
- be_req);
- return;
- }
-
-done:
- sdap_handler_done(be_req, dp_err, 0, NULL);
-}
-
-static void sdap_check_online_reinit_done(struct tevent_req *req)
-{
- struct be_req *be_req = NULL;
- errno_t ret;
-
- be_req = tevent_req_callback_data(req, struct be_req);
- ret = sdap_reinit_cleanup_recv(req);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
- "clean up [%d]: %s\n", ret, strerror(ret));
- /* not fatal */
- } else {
- DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n");
- }
-
- sdap_handler_done(be_req, DP_ERR_OK, 0, NULL);
-}
-
/* =Get-Account-Info-Call================================================= */
/* FIXME: embed this function in sssd_be and only call out
* specific functions from modules ? */
-void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx,
- struct sdap_id_conn_ctx *conn);
-
static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
@@ -1445,20 +1304,6 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
int *dp_error_out, int *sdap_ret);
-void sdap_account_info_handler(struct be_req *breq)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
- struct sdap_id_ctx *ctx;
-
- ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, struct sdap_id_ctx);
- if (!ctx) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Could not get sdap ctx\n");
- return sdap_handler_done(breq, DP_ERR_FATAL,
- EINVAL, "Invalid request data\n");
- }
- return sdap_handle_account_info(breq, ctx, ctx->conn);
-}
-
bool sdap_is_enum_request(struct be_acct_req *ar)
{
switch (ar->entry_type & BE_REQ_TYPE_MASK) {
@@ -1757,66 +1602,6 @@ sdap_handle_acct_req_recv(struct tevent_req *req,
return EOK;
}
-static void sdap_account_info_complete(struct tevent_req *req);
-
-void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx,
- struct sdap_id_conn_ctx *conn)
-{
- struct be_acct_req *ar;
- struct tevent_req *req;
-
- if (be_is_offline(ctx->be)) {
- return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
- }
-
- ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);
- if (ar == NULL) {
- return sdap_handler_done(breq, DP_ERR_FATAL,
- EINVAL, "Invalid private data");
- }
-
- if (sdap_is_enum_request(ar)) {
- DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
- return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
- }
-
- req = sdap_handle_acct_req_send(breq, ctx->be, ar, ctx,
- ctx->opts->sdom, conn, true);
- if (req == NULL) {
- return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(req, sdap_account_info_complete, breq);
-}
-
-static void sdap_account_info_complete(struct tevent_req *req)
-{
- const char *error_text;
- const char *req_error_text;
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret, dp_error;
-
- ret = sdap_handle_acct_req_recv(req, &dp_error, &req_error_text, NULL);
- talloc_zfree(req);
- if (dp_error == DP_ERR_OK) {
- if (ret == EOK) {
- error_text = NULL;
- } else {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Bug: dp_error is OK on failed request\n");
- dp_error = DP_ERR_FATAL;
- error_text = req_error_text;
- }
- } else if (dp_error == DP_ERR_OFFLINE) {
- error_text = "Offline";
- } else if (dp_error == DP_ERR_FATAL && ret == ENOMEM) {
- error_text = "Out of memory";
- } else {
- error_text = req_error_text;
- }
-
- sdap_handler_done(breq, dp_error, ret, error_text);
-}
-
struct get_user_and_group_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
@@ -2012,3 +1797,88 @@ errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
return EOK;
}
+
+struct sdap_account_info_handler_state {
+ struct dp_reply_std reply;
+};
+
+static void sdap_account_info_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct be_acct_req *data,
+ struct dp_req_params *params)
+{
+ struct sdap_account_info_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_account_info_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ if (sdap_is_enum_request(data)) {
+ DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
+ ret = EOK;
+ goto immediately;
+ }
+
+ subreq = sdap_handle_acct_req_send(state, params->be_ctx, data, id_ctx,
+ id_ctx->opts->sdom, id_ctx->conn, true);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_account_info_handler_done, req);
+
+ return req;
+
+immediately:
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void sdap_account_info_handler_done(struct tevent_req *subreq)
+{
+ struct sdap_account_info_handler_state *state;
+ struct tevent_req *req;
+ const char *error_msg;
+ int dp_error;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_account_info_handler_state);
+
+ ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL);
+ talloc_zfree(subreq);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ dp_reply_std_set(&state->reply, dp_error, ret, error_msg);
+ tevent_req_done(req);
+}
+
+errno_t sdap_account_info_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data)
+{
+ struct sdap_account_info_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_account_info_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *data = state->reply;
+
+ return EOK;
+}
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index cfd68d9b9..566924cbc 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -32,31 +32,10 @@
#include "providers/fail_over_srv.h"
#include "providers/be_refresh.h"
-static void sdap_shutdown(struct be_req *req);
-
-/* Id Handler */
-struct bet_ops sdap_id_ops = {
- .handler = sdap_account_info_handler,
- .finalize = sdap_shutdown,
- .check_online = sdap_check_online
-};
-
-/* Auth Handler */
-struct bet_ops sdap_auth_ops = {
- .handler = sdap_pam_auth_handler,
- .finalize = sdap_shutdown
-};
-
-/* Chpass Handler */
-struct bet_ops sdap_chpass_ops = {
- .handler = sdap_pam_chpass_handler,
- .finalize = sdap_shutdown
-};
-
-/* Access Handler */
-struct bet_ops sdap_access_ops = {
- .handler = sdap_pam_access_handler,
- .finalize = sdap_shutdown
+struct ldap_init_ctx {
+ struct sdap_options *options;
+ struct sdap_id_ctx *id_ctx;
+ struct sdap_auth_ctx *auth_ctx;
};
/* Please use this only for short lists */
@@ -85,259 +64,193 @@ errno_t check_order_list_for_duplicates(char **list,
return EOK;
}
-static int ldap_id_init_internal(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
+static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_options *options,
+ struct sdap_auth_ctx **_auth_ctx)
{
- struct sdap_id_ctx *ctx = NULL;
- const char *urls;
- const char *backup_urls;
- const char *dns_service_name;
- const char *sasl_mech;
- struct sdap_service *sdap_service;
- struct sdap_options *opts = NULL;
- int ret;
-
- /* If we're already set up, just return that */
- if(bectx->bet_info[BET_ID].mod_name &&
- strcmp("ldap", bectx->bet_info[BET_ID].mod_name) == 0) {
- DEBUG(SSSDBG_TRACE_INTERNAL,
- "Re-using sdap_id_ctx for this provider\n");
- *ops = bectx->bet_info[BET_ID].bet_ops;
- *pvt_data = bectx->bet_info[BET_ID].pvt_bet_data;
- return EOK;
- }
+ struct sdap_auth_ctx *auth_ctx;
- ret = ldap_get_options(bectx, bectx->domain, bectx->cdb,
- bectx->conf_path, &opts);
- if (ret != EOK) {
- goto done;
+ auth_ctx = talloc(mem_ctx, struct sdap_auth_ctx);
+ if (auth_ctx == NULL) {
+ return ENOMEM;
}
- dns_service_name = dp_opt_get_string(opts->basic,
- SDAP_DNS_SERVICE_NAME);
- DEBUG(SSSDBG_CONF_SETTINGS,
- "Service name for discovery set to %s\n", dns_service_name);
+ auth_ctx->be = be_ctx;
+ auth_ctx->opts = options;
+ auth_ctx->service = id_ctx->conn->service;
+ auth_ctx->chpass_service = NULL;
- urls = dp_opt_get_string(opts->basic, SDAP_URI);
- backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI);
+ *_auth_ctx = auth_ctx;
- ret = sdap_service_init(bectx, bectx, "LDAP",
- dns_service_name, urls, backup_urls,
- &sdap_service);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service!\n");
- goto done;
- }
+ return EOK;
+}
- ctx = sdap_id_ctx_new(bectx, bectx, sdap_service);
- if (!ctx) {
- ret = ENOMEM;
- goto done;
+static errno_t init_chpass_service(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_options *opts,
+ struct sdap_service **_chpass_service)
+{
+ errno_t ret;
+ const char *urls;
+ const char *backup_urls;
+ const char *dns_service_name;
+ struct sdap_service *chpass_service;
+
+ dns_service_name = dp_opt_get_string(opts->basic,
+ SDAP_CHPASS_DNS_SERVICE_NAME);
+ if (dns_service_name != NULL) {
+ DEBUG(SSSDBG_TRACE_LIBS,
+ "Service name for chpass discovery set to %s\n",
+ dns_service_name);
}
- ctx->opts = talloc_steal(ctx, opts);
- sasl_mech = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_MECH);
- if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) {
- if (dp_opt_get_bool(ctx->opts->basic, SDAP_KRB5_KINIT)) {
- ret = sdap_gssapi_init(ctx, ctx->opts->basic,
- ctx->be, ctx->conn->service,
- &ctx->krb5_service);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_gssapi_init failed [%d][%s].\n",
- ret, strerror(ret));
- goto done;
- }
+ urls = dp_opt_get_string(opts->basic, SDAP_CHPASS_URI);
+ backup_urls = dp_opt_get_string(opts->basic, SDAP_CHPASS_BACKUP_URI);
+
+ if (urls != NULL || backup_urls != NULL || dns_service_name != NULL) {
+ ret = sdap_service_init(mem_ctx,
+ be_ctx,
+ "LDAP_CHPASS",
+ dns_service_name,
+ urls,
+ backup_urls,
+ &chpass_service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to initialize failover service!\n");
+ return ret;
}
+ } else {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "ldap_chpass_uri and ldap_chpass_dns_service_name not set, "
+ "using ldap_uri.\n");
+ chpass_service = NULL;
}
- ret = setup_tls_config(ctx->opts->basic);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "setup_tls_config failed [%d][%s].\n",
- ret, strerror(ret));
- goto done;
- }
+ *_chpass_service = chpass_service;
+ return EOK;
+}
- /* Set up the ID mapping object */
- ret = sdap_idmap_init(ctx, ctx, &ctx->opts->idmap_ctx);
- if (ret != EOK) goto done;
+static errno_t get_access_order_list(TALLOC_CTX *mem_ctx,
+ const char *order,
+ char ***_order_list)
+{
+ errno_t ret;
+ char **order_list;
+ int order_list_len;
- ret = sdap_setup_child();
+ ret = split_on_separator(mem_ctx, order, ',', true, true,
+ &order_list, &order_list_len);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "setup_child failed [%d][%s].\n",
- ret, strerror(ret));
+ DEBUG(SSSDBG_CRIT_FAILURE, "split_on_separator failed.\n");
goto done;
}
- /* setup SRV lookup plugin */
- ret = be_fo_set_dns_srv_lookup_plugin(bectx, NULL);
+ ret = check_order_list_for_duplicates(order_list, false);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin "
- "[%d]: %s\n", ret, strerror(ret));
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "check_order_list_for_duplicates failed.\n");
goto done;
}
- /* setup periodical refresh of expired records */
- ret = sdap_refresh_init(bectx->refresh_ctx, ctx);
- if (ret != EOK && ret != EEXIST) {
- DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh "
- "will not work [%d]: %s\n", ret, strerror(ret));
+ if (order_list_len > LDAP_ACCESS_LAST) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Currently only [%d] different access rules are supported.\n",
+ LDAP_ACCESS_LAST);
+ ret = EINVAL;
+ goto done;
}
- *ops = &sdap_id_ops;
- *pvt_data = ctx;
- ret = EOK;
+ *_order_list = order_list;
done:
if (ret != EOK) {
- talloc_free(opts);
- talloc_free(ctx);
+ talloc_free(order_list);
}
+
return ret;
}
-int sssm_ldap_id_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
+static errno_t check_expire_policy(struct sdap_options *opts)
{
- int ret;
- struct sdap_id_ctx *ctx = NULL;
-
- ret = ldap_id_init_internal(bectx, ops, (void **) &ctx);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "ldap_id_init_internal failed [%d][%s].\n",
- ret, strerror(ret));
- goto done;
- }
-
- ret = ldap_id_setup_tasks(ctx);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "sdap_id_setup_tasks failed [%d][%s].\n",
- ret, strerror(ret));
- goto done;
+ const char *expire_policy;
+ bool matched_policy = false;
+ const char *policies[] = {LDAP_ACCOUNT_EXPIRE_SHADOW,
+ LDAP_ACCOUNT_EXPIRE_AD,
+ LDAP_ACCOUNT_EXPIRE_NDS,
+ LDAP_ACCOUNT_EXPIRE_RHDS,
+ LDAP_ACCOUNT_EXPIRE_IPA,
+ LDAP_ACCOUNT_EXPIRE_389DS,
+ NULL};
+
+ expire_policy = dp_opt_get_cstring(opts->basic,
+ SDAP_ACCOUNT_EXPIRE_POLICY);
+ if (expire_policy == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Warning: LDAP access rule 'expire' is set, "
+ "but no ldap_account_expire_policy configured. "
+ "All domain users will be denied access.\n");
+ return EOK;
}
- *pvt_data = ctx;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_free(ctx);
+ for (unsigned i = 0; policies[i] != NULL; i++) {
+ if (strcasecmp(expire_policy, policies[i]) == 0) {
+ matched_policy = true;
+ break;
+ }
}
- return ret;
-}
-
-int sssm_ldap_auth_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- void *data;
- struct sdap_id_ctx *id_ctx;
- struct sdap_auth_ctx *ctx;
- int ret;
- ret = ldap_id_init_internal(bectx, ops, &data);
- if (ret == EOK) {
- id_ctx = talloc_get_type(data, struct sdap_id_ctx);
-
- ctx = talloc(bectx, struct sdap_auth_ctx);
- if (!ctx) return ENOMEM;
-
- ctx->be = bectx;
- ctx->opts = id_ctx->opts;
- ctx->service = id_ctx->conn->service;
- ctx->chpass_service = NULL;
-
- *ops = &sdap_auth_ops;
- *pvt_data = ctx;
+ if (matched_policy == false) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unsupported LDAP account expire policy [%s].\n",
+ expire_policy);
+ return EINVAL;
}
- return ret;
+ return EOK;
}
-int sssm_ldap_chpass_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
+static errno_t get_access_filter(TALLOC_CTX *mem_ctx,
+ struct sdap_options *opts,
+ const char **_filter)
{
- int ret;
- void *data;
- struct sdap_auth_ctx *ctx = NULL;
- const char *urls;
- const char *backup_urls;
- const char *dns_service_name;
-
- ret = sssm_ldap_auth_init(bectx, ops, &data);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sssm_ldap_auth_init failed.\n");
- goto done;
- }
-
- ctx = talloc_get_type(data, struct sdap_auth_ctx);
+ const char *filter;
- dns_service_name = dp_opt_get_string(ctx->opts->basic,
- SDAP_CHPASS_DNS_SERVICE_NAME);
- if (dns_service_name) {
- DEBUG(SSSDBG_TRACE_LIBS,
- "Service name for chpass discovery set to %s\n",
- dns_service_name);
+ filter = dp_opt_get_cstring(opts->basic, SDAP_ACCESS_FILTER);
+ if (filter == NULL) {
+ /* It's okay if this is NULL. In that case we will simply act
+ * like the 'deny' provider.
+ */
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Warning: LDAP access rule 'filter' is set, "
+ "but no ldap_access_filter configured. "
+ "All domain users will be denied access.\n");
+ return EOK;
}
- urls = dp_opt_get_string(ctx->opts->basic, SDAP_CHPASS_URI);
- backup_urls = dp_opt_get_string(ctx->opts->basic, SDAP_CHPASS_BACKUP_URI);
- if (!urls && !backup_urls && !dns_service_name) {
- DEBUG(SSSDBG_TRACE_ALL,
- "ldap_chpass_uri and ldap_chpass_dns_service_name not set, "
- "using ldap_uri.\n");
- ctx->chpass_service = NULL;
- } else {
- ret = sdap_service_init(ctx, ctx->be, "LDAP_CHPASS", dns_service_name,
- urls, backup_urls, &ctx->chpass_service);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Failed to initialize failover service!\n");
- goto done;
- }
+ filter = sdap_get_access_filter(mem_ctx, filter);
+ if (filter == NULL) {
+ return ENOMEM;
}
+ *_filter = filter;
- *ops = &sdap_chpass_ops;
- *pvt_data = ctx;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_free(ctx);
- }
- return ret;
+ return EOK;
}
-int sssm_ldap_access_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
+static errno_t set_access_rules(TALLOC_CTX *mem_ctx,
+ struct sdap_access_ctx *access_ctx,
+ struct sdap_options *opts)
{
- int ret;
- struct sdap_access_ctx *access_ctx;
- const char *filter;
+ errno_t ret;
+ char **order_list = NULL;
const char *order;
- char **order_list;
- int order_list_len;
size_t c;
- const char *dummy;
-
- access_ctx = talloc_zero(bectx, struct sdap_access_ctx);
- if(access_ctx == NULL) {
- ret = ENOMEM;
- goto done;
- }
- ret = ldap_id_init_internal(bectx, ops, (void **)&access_ctx->id_ctx);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "ldap_id_init_internal failed.\n");
- goto done;
- }
+ /* To make sure that in case of failure it's safe to be freed */
+ access_ctx->filter = NULL;
order = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
SDAP_ACCESS_ORDER);
@@ -347,73 +260,28 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
order = "filter";
}
- ret = split_on_separator(access_ctx, order, ',', true, true,
- &order_list, &order_list_len);
+ ret = get_access_order_list(mem_ctx, order, &order_list);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "split_on_separator failed.\n");
- goto done;
- }
-
- ret = check_order_list_for_duplicates(order_list, false);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "check_order_list_for_duplicates failed.\n");
- goto done;
- }
-
- if (order_list_len > LDAP_ACCESS_LAST) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "Currently only [%d] different access rules are supported.\n",
- LDAP_ACCESS_LAST);
- ret = EINVAL;
+ "get_access_order_list failed: [%d][%s].\n",
+ ret, sss_strerror(ret));
goto done;
}
for (c = 0; order_list[c] != NULL; c++) {
+
if (strcasecmp(order_list[c], LDAP_ACCESS_FILTER_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_FILTER;
-
- filter = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
- SDAP_ACCESS_FILTER);
- if (filter == NULL) {
- /* It's okay if this is NULL. In that case we will simply act
- * like the 'deny' provider.
- */
- DEBUG(SSSDBG_FATAL_FAILURE,
- "Warning: LDAP access rule 'filter' is set, "
- "but no ldap_access_filter configured. "
- "All domain users will be denied access.\n");
- } else {
- access_ctx->filter = sdap_get_access_filter(access_ctx,
- filter);
- if (access_ctx->filter == NULL) {
- ret = ENOMEM;
- goto done;
- }
+ if (get_access_filter(mem_ctx, opts, &access_ctx->filter) != EOK) {
+ goto done;
}
+
} else if (strcasecmp(order_list[c], LDAP_ACCESS_EXPIRE_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE;
-
- dummy = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
- SDAP_ACCOUNT_EXPIRE_POLICY);
- if (dummy == NULL) {
- DEBUG(SSSDBG_FATAL_FAILURE,
- "Warning: LDAP access rule 'expire' is set, "
- "but no ldap_account_expire_policy configured. "
- "All domain users will be denied access.\n");
- } else {
- if (strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_SHADOW) != 0 &&
- strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_AD) != 0 &&
- strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_NDS) != 0 &&
- strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_RHDS) != 0 &&
- strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_IPA) != 0 &&
- strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_389DS) != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Unsupported LDAP account expire policy [%s].\n",
- dummy);
- ret = EINVAL;
- goto done;
- }
+ if (check_expire_policy(opts) != EOK) {
+ goto done;
}
+
} else if (strcasecmp(order_list[c], LDAP_ACCESS_SERVICE_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_SERVICE;
} else if (strcasecmp(order_list[c], LDAP_ACCESS_HOST_NAME) == 0) {
@@ -441,75 +309,327 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
access_ctx->access_rule[c] = LDAP_ACCESS_EMPTY;
if (c == 0) {
DEBUG(SSSDBG_FATAL_FAILURE, "Warning: access_provider=ldap set, "
- "but ldap_access_order is empty. "
- "All domain users will be denied access.\n");
+ "but ldap_access_order is empty. "
+ "All domain users will be denied access.\n");
+ }
+
+done:
+ talloc_free(order_list);
+ if (ret != EOK) {
+ talloc_zfree(access_ctx->filter);
+ }
+ return ret;
+}
+
+static errno_t get_sdap_service(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_options *opts,
+ struct sdap_service **_sdap_service)
+{
+ errno_t ret;
+ const char *urls;
+ const char *backup_urls;
+ const char *dns_service_name;
+ struct sdap_service *sdap_service;
+
+ urls = dp_opt_get_string(opts->basic, SDAP_URI);
+ backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI);
+ dns_service_name = dp_opt_get_string(opts->basic, SDAP_DNS_SERVICE_NAME);
+ if (dns_service_name != NULL) {
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ "Service name for discovery set to %s\n", dns_service_name);
+ }
+
+ ret = sdap_service_init(mem_ctx, be_ctx, "LDAP",
+ dns_service_name,
+ urls,
+ backup_urls,
+ &sdap_service);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ *_sdap_service = sdap_service;
+ return EOK;
+}
+
+static bool should_call_gssapi_init(struct sdap_options *opts)
+{
+ const char *sasl_mech;
+
+ sasl_mech = dp_opt_get_string(opts->basic, SDAP_SASL_MECH);
+ if (sasl_mech == NULL) {
+ return false;
+ }
+
+ if (strcasecmp(sasl_mech, "GSSAPI") != 0) {
+ return false;
+ }
+
+ if (dp_opt_get_bool(opts->basic, SDAP_KRB5_KINIT) == false) {
+ return false;
+ }
+
+ return true;
+}
+
+static errno_t ldap_init_misc(struct be_ctx *be_ctx,
+ struct sdap_options *options,
+ struct sdap_id_ctx *id_ctx)
+{
+ errno_t ret;
+
+ if (should_call_gssapi_init(options)) {
+ ret = sdap_gssapi_init(id_ctx, options->basic, be_ctx,
+ id_ctx->conn->service, &id_ctx->krb5_service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "sdap_gssapi_init failed [%d][%s].\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+ }
+
+ ret = setup_tls_config(options->basic);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get TLS options [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
+ /* Setup the ID mapping object */
+ ret = sdap_idmap_init(id_ctx, id_ctx, &options->idmap_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Could not initialize ID mapping. In case ID mapping properties "
+ "changed on the server, please remove the SSSD database\n");
+ return ret;
+ }
+
+ ret = ldap_id_setup_tasks(id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup background tasks "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ ret = sdap_setup_child();
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup sdap child [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
+ /* Setup SRV lookup plugin */
+ ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ /* Setup periodical refresh of expired records */
+ ret = sdap_refresh_init(be_ctx->refresh_ctx, id_ctx);
+ if (ret != EOK && ret != EEXIST) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh will not work "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ }
+
+ return EOK;
+}
+
+errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct data_provider *provider,
+ const char *module_name,
+ void **_module_data)
+{
+ struct sdap_service *sdap_service;
+ struct ldap_init_ctx *init_ctx;
+ errno_t ret;
+
+ init_ctx = talloc_zero(mem_ctx, struct ldap_init_ctx);
+ if (init_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ /* Always initialize options since it is needed everywhere. */
+ ret = ldap_get_options(init_ctx, be_ctx->domain, be_ctx->cdb,
+ be_ctx->conf_path, &init_ctx->options);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP options "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ /* Always initialize id_ctx since it is needed everywhere. */
+ ret = get_sdap_service(init_ctx, be_ctx, init_ctx->options, &sdap_service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ init_ctx->id_ctx = sdap_id_ctx_new(init_ctx, be_ctx, sdap_service);
+ if (init_ctx->id_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP ID context\n");
+ ret = ENOMEM;
+ goto done;
}
- *ops = &sdap_access_ops;
- *pvt_data = access_ctx;
+ init_ctx->id_ctx->opts = init_ctx->options;
+
+ /* Setup miscellaneous things. */
+ ret = ldap_init_misc(be_ctx, init_ctx->options, init_ctx->id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init LDAP module "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ /* Initialize auth_ctx only if one of the target is enabled. */
+ if (dp_target_enabled(provider, module_name, DPT_AUTH, DPT_CHPASS)) {
+ ret = ldap_init_auth_ctx(init_ctx, be_ctx, init_ctx->id_ctx,
+ init_ctx->options, &init_ctx->auth_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create auth context "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+ }
+
+ *_module_data = init_ctx;
ret = EOK;
done:
if (ret != EOK) {
- talloc_free(access_ctx);
+ talloc_free(init_ctx);
}
+
return ret;
}
-int sssm_ldap_sudo_init(struct be_ctx *be_ctx,
- struct bet_ops **ops,
- void **pvt_data)
+errno_t sssm_ldap_id_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
{
-#ifdef BUILD_SUDO
+ struct ldap_init_ctx *init_ctx;
struct sdap_id_ctx *id_ctx;
- void *data;
- int ret;
- ret = ldap_id_init_internal(be_ctx, ops, &data);
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+ id_ctx = init_ctx->id_ctx;
+
+ dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER,
+ sdap_account_info_handler_send, sdap_account_info_handler_recv, id_ctx,
+ struct sdap_id_ctx, struct be_acct_req, struct dp_reply_std);
+
+ dp_set_method(dp_methods, DPM_CHECK_ONLINE,
+ sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx,
+ struct sdap_id_ctx, void, struct dp_reply_std);
+
+ return EOK;
+}
+
+errno_t sssm_ldap_auth_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
+{
+ struct ldap_init_ctx *init_ctx;
+ struct sdap_auth_ctx *auth_ctx;
+
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+ auth_ctx = init_ctx->auth_ctx;
+
+ dp_set_method(dp_methods, DPM_AUTH_HANDLER,
+ sdap_pam_auth_handler_send, sdap_pam_auth_handler_recv, auth_ctx,
+ struct sdap_auth_ctx, struct pam_data, struct pam_data *);
+
+ return EOK;
+}
+
+errno_t sssm_ldap_chpass_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
+{
+ struct ldap_init_ctx *init_ctx;
+ struct sdap_auth_ctx *auth_ctx;
+ errno_t ret;
+
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+ auth_ctx = init_ctx->auth_ctx;
+
+ ret = init_chpass_service(auth_ctx, be_ctx, init_ctx->options,
+ &auth_ctx->chpass_service);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init LDAP ID provider [%d]: %s\n",
- ret, strerror(ret));
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize chpass service "
+ "[%d]: %s\n", ret, sss_strerror(ret));
return ret;
}
- id_ctx = talloc_get_type(data, struct sdap_id_ctx);
- if (!id_ctx) {
- DEBUG(SSSDBG_CRIT_FAILURE, "No ID provider?\n");
- return EIO;
- }
+ dp_set_method(dp_methods, DPM_AUTH_HANDLER,
+ sdap_pam_chpass_handler_send, sdap_pam_chpass_handler_recv, auth_ctx,
+ struct sdap_auth_ctx, struct pam_data, struct pam_data *);
- return sdap_sudo_init(be_ctx, id_ctx, ops, pvt_data);
-#else
- DEBUG(SSSDBG_MINOR_FAILURE, "Sudo init handler called but SSSD is "
- "built without sudo support, ignoring\n");
return EOK;
-#endif
}
-int sssm_ldap_autofs_init(struct be_ctx *be_ctx,
- struct bet_ops **ops,
- void **pvt_data)
+errno_t sssm_ldap_access_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
{
-#ifdef BUILD_AUTOFS
- struct sdap_id_ctx *id_ctx;
- void *data;
- int ret;
+ struct ldap_init_ctx *init_ctx;
+ struct sdap_access_ctx *access_ctx;
+ errno_t ret;
+
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+
+ access_ctx = talloc_zero(mem_ctx, struct sdap_access_ctx);
+ if(access_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
- ret = ldap_id_init_internal(be_ctx, ops, &data);
+ access_ctx->id_ctx = init_ctx->id_ctx;
+
+ ret = set_access_rules(access_ctx, access_ctx, access_ctx->id_ctx->opts);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init LDAP ID provider [%d]: %s\n",
- ret, strerror(ret));
- return ret;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "set_access_rules failed: [%d][%s].\n",
+ ret, sss_strerror(ret));
+ goto done;
}
- id_ctx = talloc_get_type(data, struct sdap_id_ctx);
- if (!id_ctx) {
- DEBUG(SSSDBG_CRIT_FAILURE, "No ID provider?\n");
- return EIO;
+ dp_set_method(dp_methods, DPM_ACCESS_HANDLER,
+ sdap_pam_access_handler_send, sdap_pam_access_handler_recv, access_ctx,
+ struct sdap_access_ctx, struct pam_data, struct pam_data *);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(access_ctx);
}
- return sdap_autofs_init(be_ctx, id_ctx, ops, pvt_data);
+ return ret;
+}
+
+errno_t sssm_ldap_autofs_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
+{
+#ifdef BUILD_AUTOFS
+ struct ldap_init_ctx *init_ctx;
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing LDAP autofs handler\n");
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+
+ return sdap_autofs_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods);
#else
DEBUG(SSSDBG_MINOR_FAILURE, "Autofs init handler called but SSSD is "
"built without autofs support, ignoring\n");
@@ -517,9 +637,21 @@ int sssm_ldap_autofs_init(struct be_ctx *be_ctx,
#endif
}
-static void sdap_shutdown(struct be_req *req)
+errno_t sssm_ldap_sudo_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
{
- /* TODO: Clean up any internal data */
- sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
-}
+#ifdef BUILD_SUDO
+ struct ldap_init_ctx *init_ctx;
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing LDAP sudo handler\n");
+ init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+ return sdap_sudo_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods);
+#else
+ DEBUG(SSSDBG_MINOR_FAILURE, "Sudo init handler called but SSSD is "
+ "built without sudo support, ignoring\n");
+ return EOK;
+#endif
+}
diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h
index 93ddfd5e5..049daced6 100644
--- a/src/providers/ldap/sdap_access.h
+++ b/src/providers/ldap/sdap_access.h
@@ -76,6 +76,17 @@ struct sdap_access_ctx {
};
struct tevent_req *
+sdap_pam_access_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_access_ctx *access_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params);
+
+errno_t
+sdap_pam_access_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data);
+
+struct tevent_req *
sdap_access_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct be_ctx *be_ctx,
diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c
index f65b6ea61..c02c04d5c 100644
--- a/src/providers/ldap/sdap_autofs.c
+++ b/src/providers/ldap/sdap_autofs.c
@@ -34,103 +34,6 @@
#include "db/sysdb_autofs.h"
#include "util/util.h"
-static void
-sdap_autofs_shutdown(struct be_req *req)
-{
- sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
-}
-
-void sdap_autofs_handler(struct be_req *be_req);
-
-/* Autofs Handler */
-struct bet_ops sdap_autofs_ops = {
- .handler = sdap_autofs_handler,
- .finalize = sdap_autofs_shutdown
-};
-
-int sdap_autofs_init(struct be_ctx *be_ctx,
- struct sdap_id_ctx *id_ctx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- int ret;
-
- DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing autofs LDAP back end\n");
-
- *ops = &sdap_autofs_ops;
- *pvt_data = id_ctx;
-
- ret = ldap_get_autofs_options(id_ctx, be_ctx->cdb,
- be_ctx->conf_path, id_ctx->opts);
- if (ret != EOK) {
- return ret;
- }
-
- return ret;
-}
-
-static struct tevent_req *
-sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sdap_id_ctx *ctx,
- const char *map_name);
-
-static void sdap_autofs_handler_done(struct tevent_req *req);
-
-void sdap_autofs_handler(struct be_req *be_req)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
- struct sdap_id_ctx *id_ctx;
- struct be_autofs_req *autofs_req;
- struct tevent_req *req;
- const char *master_map;
- int ret = EOK;
-
- DEBUG(SSSDBG_TRACE_INTERNAL, "sdap autofs handler called\n");
-
- id_ctx = talloc_get_type(be_ctx->bet_info[BET_AUTOFS].pvt_bet_data,
- struct sdap_id_ctx);
-
- if (be_is_offline(id_ctx->be)) {
- return sdap_handler_done(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
- }
-
- autofs_req = talloc_get_type(be_req_get_data(be_req), struct be_autofs_req);
-
- DEBUG(SSSDBG_FUNC_DATA, "Requested refresh for: %s\n",
- autofs_req->mapname ? autofs_req->mapname : "<ALL>\n");
-
- if (autofs_req->mapname != NULL) {
- master_map = dp_opt_get_string(id_ctx->opts->basic,
- SDAP_AUTOFS_MAP_MASTER_NAME);
- if (strcmp(master_map, autofs_req->mapname) == 0) {
- autofs_req->invalidate = true;
- DEBUG(SSSDBG_FUNC_DATA, "Refresh of automount master map triggered: %s\n",
- autofs_req->mapname);
- }
- }
-
- if (autofs_req->invalidate) {
- ret = sysdb_invalidate_autofs_maps(id_ctx->be->domain);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE, "Could not invalidate autofs maps, "
- "backend might return stale entries\n");
- }
- }
-
- req = sdap_autofs_get_map_send(be_req, be_ctx->ev,
- id_ctx, autofs_req->mapname);
- if (!req) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, sdap_autofs_handler_done, be_req);
-
- return;
-fail:
- be_req_terminate(be_req, DP_ERR_FATAL, ret, NULL);
-}
-
struct autofs_get_map_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
@@ -298,15 +201,121 @@ sdap_autofs_get_map_recv(struct tevent_req *req, int *dp_error_out)
return EOK;
}
-static void
-sdap_autofs_handler_done(struct tevent_req *req)
+struct sdap_autofs_handler_state {
+ struct dp_reply_std reply;
+};
+
+static void sdap_autofs_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sdap_autofs_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_autofs_data *data,
+ struct dp_req_params *params)
{
- struct be_req *be_req =
- tevent_req_callback_data(req, struct be_req);
- int dperr;
+ struct sdap_autofs_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ const char *master_map;
+
errno_t ret;
- ret = sdap_autofs_get_map_recv(req, &dperr);
- sdap_handler_done(be_req, dperr, ret, strerror(ret));
+ req = tevent_req_create(mem_ctx, &state, struct sdap_autofs_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ DEBUG(SSSDBG_FUNC_DATA, "Requested refresh for: %s\n", data->mapname);
+
+ master_map = dp_opt_get_string(id_ctx->opts->basic,
+ SDAP_AUTOFS_MAP_MASTER_NAME);
+ if (strcmp(master_map, data->mapname) == 0) {
+ DEBUG(SSSDBG_FUNC_DATA, "Refresh of automount master map triggered: "
+ "%s\n", data->mapname);
+
+ ret = sysdb_invalidate_autofs_maps(id_ctx->be->domain);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Could not invalidate autofs maps, "
+ "backend might return stale entries\n");
+ }
+ }
+
+ subreq = sdap_autofs_get_map_send(mem_ctx, params->ev,
+ id_ctx, data->mapname);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request for %s.\n",
+ data->mapname);
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_autofs_handler_done, req);
+
+ return req;
+
+immediately:
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
}
+static void sdap_autofs_handler_done(struct tevent_req *subreq)
+{
+ struct sdap_autofs_handler_state *state;
+ struct tevent_req *req;
+ int dp_error;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_autofs_handler_state);
+
+ ret = sdap_autofs_get_map_recv(subreq, &dp_error);
+ talloc_zfree(subreq);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ tevent_req_done(req);
+}
+
+errno_t
+sdap_autofs_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data)
+{
+ struct sdap_autofs_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_autofs_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *data = state->reply;
+
+ return EOK;
+}
+
+errno_t sdap_autofs_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_method *dp_methods)
+{
+ errno_t ret;
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing autofs LDAP back end\n");
+
+ ret = ldap_get_autofs_options(id_ctx, be_ctx->cdb, be_ctx->conf_path,
+ id_ctx->opts);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ dp_set_method(dp_methods, DPM_AUTOFS_HANDLER,
+ sdap_autofs_handler_send, sdap_autofs_handler_recv, id_ctx,
+ struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std);
+
+ return EOK;
+}
diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h
index 0369e2645..593d8c94f 100644
--- a/src/providers/ldap/sdap_autofs.h
+++ b/src/providers/ldap/sdap_autofs.h
@@ -25,10 +25,10 @@
#ifndef _SDAP_AUTOFS_H_
#define _SDAP_AUTOFS_H_
-int sdap_autofs_init(struct be_ctx *be_ctx,
- struct sdap_id_ctx *id_ctx,
- struct bet_ops **ops,
- void **pvt_data);
+errno_t sdap_autofs_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_method *dp_methods);
struct tevent_req *
sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c
index 4e322124c..b5dfc6cef 100644
--- a/src/providers/ldap/sdap_idmap.c
+++ b/src/providers/ldap/sdap_idmap.c
@@ -542,7 +542,7 @@ bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
TALLOC_CTX *tmp_ctx = NULL;
if (dp_opt_get_bool(ctx->id_ctx->opts->basic, SDAP_ID_MAPPING)
- && 0 == strcmp("ldap", ctx->id_ctx->be->bet_info[BET_ID].mod_name)) {
+ && dp_target_enabled(ctx->id_ctx->be->provider, "ldap", DPT_ID)) {
return true;
}
diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c
new file mode 100644
index 000000000..f721a5f45
--- /dev/null
+++ b/src/providers/ldap/sdap_online_check.c
@@ -0,0 +1,249 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2016 Red Hat
+
+ 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 <errno.h>
+#include <talloc.h>
+#include <tevent.h>
+#include "util/util.h"
+#include "providers/backend.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/ldap_common.h"
+
+struct sdap_online_check_state {
+ struct sdap_id_ctx *id_ctx;
+ struct be_ctx *be_ctx;
+};
+
+static void sdap_online_check_connect_done(struct tevent_req *subreq);
+static void sdap_online_check_reinit_done(struct tevent_req *subreq);
+
+static struct tevent_req *sdap_online_check_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx)
+{
+ struct sdap_online_check_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_ctx *be_ctx;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_online_check_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->id_ctx = id_ctx;
+ state->be_ctx = be_ctx = id_ctx->be;
+
+ subreq = sdap_cli_connect_send(state, be_ctx->ev, id_ctx->opts, be_ctx,
+ id_ctx->conn->service, false,
+ CON_TLS_DFL, false);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_online_check_connect_done, req);
+
+ return req;
+
+immediately:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, be_ctx->ev);
+
+ return req;
+}
+
+static void sdap_online_check_connect_done(struct tevent_req *subreq)
+{
+ struct sdap_online_check_state *state;
+ struct sdap_server_opts *srv_opts;
+ struct sdap_id_ctx *id_ctx;
+ struct tevent_req *req;
+ bool can_retry;
+ bool reinit = false;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_online_check_state);
+
+ id_ctx = state->id_ctx;
+
+ ret = sdap_cli_connect_recv(subreq, state, &can_retry, NULL, &srv_opts);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ if (can_retry == false) {
+ ret = ERR_OFFLINE;
+ }
+
+ goto done;
+ } else {
+ if (id_ctx->srv_opts == NULL) {
+ srv_opts->max_user_value = 0;
+ srv_opts->max_group_value = 0;
+ srv_opts->max_service_value = 0;
+ srv_opts->max_sudo_value = 0;
+ } else if (strcmp(srv_opts->server_id, id_ctx->srv_opts->server_id) == 0
+ && srv_opts->supports_usn
+ && id_ctx->srv_opts->last_usn > srv_opts->last_usn) {
+ id_ctx->srv_opts->max_user_value = 0;
+ id_ctx->srv_opts->max_group_value = 0;
+ id_ctx->srv_opts->max_service_value = 0;
+ id_ctx->srv_opts->max_sudo_value = 0;
+ id_ctx->srv_opts->last_usn = srv_opts->last_usn;
+
+ reinit = true;
+ }
+
+ sdap_steal_server_opts(id_ctx, &srv_opts);
+ }
+
+ if (reinit) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. "
+ "Cleaning cache.\n");
+ subreq = sdap_reinit_cleanup_send(state, state->be_ctx, id_ctx);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
+ "clean up.\n");
+ /* not fatal */
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sdap_online_check_reinit_done, req);
+ return;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static void sdap_online_check_reinit_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sdap_reinit_cleanup_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
+ "clean up [%d]: %s\n", ret, strerror(ret));
+ /* not fatal */
+ } else {
+ DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n");
+ }
+
+ tevent_req_done(req);
+}
+
+static errno_t sdap_online_check_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+struct sdap_online_check_handler_state {
+ struct dp_reply_std reply;
+};
+
+static void sdap_online_check_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sdap_online_check_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_id_ctx *id_ctx,
+ void *data,
+ struct dp_req_params *params)
+{
+ struct sdap_online_check_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_online_check_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ subreq = sdap_online_check_send(state, id_ctx);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_online_check_handler_done, req);
+
+ return req;
+
+immediately:
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void sdap_online_check_handler_done(struct tevent_req *subreq)
+{
+ struct sdap_online_check_handler_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_online_check_handler_state);
+
+ ret = sdap_online_check_recv(subreq);
+ talloc_zfree(subreq);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ tevent_req_done(req);
+}
+
+errno_t sdap_online_check_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data)
+{
+ struct sdap_online_check_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_online_check_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *data = state->reply;
+
+ return EOK;
+}
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index 2ed97b9aa..bf73f7b45 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -29,13 +29,118 @@
#include "providers/ldap/sdap_sudo.h"
#include "db/sysdb_sudo.h"
-static void sdap_sudo_handler(struct be_req *breq);
-
-struct bet_ops sdap_sudo_ops = {
- .handler = sdap_sudo_handler,
- .finalize = NULL
+struct sdap_sudo_handler_state {
+ uint32_t type;
+ struct dp_reply_std reply;
};
+static void sdap_sudo_handler_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sdap_sudo_handler_send(TALLOC_CTX *mem_ctx,
+ struct sdap_sudo_ctx *sudo_ctx,
+ struct dp_sudo_data *data,
+ struct dp_req_params *params)
+{
+ struct sdap_sudo_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->type = data->type;
+
+ switch (data->type) {
+ case BE_REQ_SUDO_FULL:
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
+ subreq = sdap_sudo_full_refresh_send(state, sudo_ctx);
+ break;
+ case BE_REQ_SUDO_RULES:
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
+ subreq = sdap_sudo_rules_refresh_send(state, sudo_ctx, data->rules);
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", data->type);
+ ret = EINVAL;
+ goto immediately;
+ }
+
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n", data->type);
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, sdap_sudo_handler_done, req);
+
+ return req;
+
+immediately:
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void sdap_sudo_handler_done(struct tevent_req *subreq)
+{
+ struct sdap_sudo_handler_state *state;
+ struct tevent_req *req;
+ int dp_error;
+ bool deleted;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_sudo_handler_state);
+
+ switch (state->type) {
+ case BE_REQ_SUDO_FULL:
+ ret = sdap_sudo_full_refresh_recv(subreq, &dp_error);
+ talloc_zfree(subreq);
+ break;
+ case BE_REQ_SUDO_RULES:
+ ret = sdap_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
+ talloc_zfree(subreq);
+ if (ret == EOK && deleted == true) {
+ ret = ENOENT;
+ }
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type);
+ dp_error = DP_ERR_FATAL;
+ ret = ERR_INTERNAL;
+ break;
+ }
+
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ tevent_req_done(req);
+}
+
+static errno_t
+sdap_sudo_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data)
+{
+ struct sdap_sudo_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct sdap_sudo_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *data = state->reply;
+
+ return EOK;
+}
+
static void sdap_sudo_online_cb(void *pvt)
{
struct sdap_sudo_ctx *sudo_ctx;
@@ -51,43 +156,40 @@ static void sdap_sudo_online_cb(void *pvt)
sudo_ctx->run_hostinfo = true;
}
-int sdap_sudo_init(struct be_ctx *be_ctx,
- struct sdap_id_ctx *id_ctx,
- struct bet_ops **ops,
- void **pvt_data)
+errno_t sdap_sudo_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_method *dp_methods)
{
- struct sdap_sudo_ctx *sudo_ctx = NULL;
+ struct sdap_sudo_ctx *sudo_ctx;
int ret;
DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing sudo LDAP back end\n");
- sudo_ctx = talloc_zero(be_ctx, struct sdap_sudo_ctx);
+ sudo_ctx = talloc_zero(mem_ctx, struct sdap_sudo_ctx);
if (sudo_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n");
return ENOMEM;
}
sudo_ctx->id_ctx = id_ctx;
- *ops = &sdap_sudo_ops;
- *pvt_data = sudo_ctx;
- ret = ldap_get_sudo_options(be_ctx->cdb,
- be_ctx->conf_path, id_ctx->opts,
+ ret = ldap_get_sudo_options(be_ctx->cdb, be_ctx->conf_path, id_ctx->opts,
&sudo_ctx->use_host_filter,
&sudo_ctx->include_regexp,
&sudo_ctx->include_netgroups);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot get SUDO options [%d]: %s\n",
- ret, strerror(ret));
+ ret, sss_strerror(ret));
goto done;
}
if (sudo_ctx->use_host_filter) {
- ret = be_add_online_cb(sudo_ctx, sudo_ctx->id_ctx->be,
- sdap_sudo_online_cb, sudo_ctx, NULL);
+ ret = be_add_online_cb(sudo_ctx, be_ctx, sdap_sudo_online_cb,
+ sudo_ctx, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to install online callback "
- "[%d]: %s\n", ret, sss_strerror(ret));
+ "[%d]: %s\n", ret, sss_strerror(ret));
goto done;
}
@@ -95,15 +197,18 @@ int sdap_sudo_init(struct be_ctx *be_ctx,
sudo_ctx->run_hostinfo = true;
}
- ret = sdap_sudo_ptask_setup(sudo_ctx->id_ctx->be, sudo_ctx);
+ ret = sdap_sudo_ptask_setup(be_ctx, sudo_ctx);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "Unable to setup periodical refresh of sudo rules [%d]: %s\n",
- ret, strerror(ret));
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh of "
+ "sudo rules [%d]: %s\n", ret, sss_strerror(ret));
/* periodical updates will not work, but specific-rule update
* is no affected by this, therefore we don't have to fail here */
}
+ dp_set_method(dp_methods, DPM_SUDO_HANDLER,
+ sdap_sudo_handler_send, sdap_sudo_handler_recv, sudo_ctx,
+ struct sdap_sudo_ctx, struct dp_sudo_data, struct dp_reply_std);
+
ret = EOK;
done:
@@ -113,85 +218,3 @@ done:
return ret;
}
-
-static void sdap_sudo_reply(struct tevent_req *req)
-{
- struct be_req *be_req = NULL;
- struct be_sudo_req *sudo_req = NULL;
- int dp_error;
- bool deleted;
- int ret;
-
- be_req = tevent_req_callback_data(req, struct be_req);
- sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
-
- switch (sudo_req->type) {
- case BE_REQ_SUDO_FULL:
- ret = sdap_sudo_full_refresh_recv(req, &dp_error);
- break;
- case BE_REQ_SUDO_RULES:
- ret = sdap_sudo_rules_refresh_recv(req, &dp_error, &deleted);
- if (ret == EOK && deleted == true) {
- ret = ENOENT;
- }
- break;
- default:
- DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
- sudo_req->type);
- dp_error = DP_ERR_FATAL;
- ret = ERR_INTERNAL;
- break;
- }
-
- talloc_zfree(req);
- sdap_handler_done(be_req, dp_error, ret, strerror(ret));
-}
-
-static void sdap_sudo_handler(struct be_req *be_req)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
- struct tevent_req *req = NULL;
- struct be_sudo_req *sudo_req = NULL;
- struct sdap_sudo_ctx *sudo_ctx = NULL;
- int ret = EOK;
-
- if (be_is_offline(be_ctx)) {
- sdap_handler_done(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
- return;
- }
-
- sudo_ctx = talloc_get_type(be_ctx->bet_info[BET_SUDO].pvt_bet_data,
- struct sdap_sudo_ctx);
-
- sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
-
- switch (sudo_req->type) {
- case BE_REQ_SUDO_FULL:
- DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
- req = sdap_sudo_full_refresh_send(be_req, sudo_ctx);
- break;
- case BE_REQ_SUDO_RULES:
- DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
- req = sdap_sudo_rules_refresh_send(be_req, sudo_ctx, sudo_req->rules);
- break;
- default:
- DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
- sudo_req->type);
- ret = EINVAL;
- goto fail;
- }
-
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n",
- sudo_req->type);
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(req, sdap_sudo_reply, be_req);
-
- return;
-
-fail:
- sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
-}
diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h
index fccd64c2f..0e732abf4 100644
--- a/src/providers/ldap/sdap_sudo.h
+++ b/src/providers/ldap/sdap_sudo.h
@@ -40,10 +40,10 @@ struct sdap_sudo_ctx {
/* Common functions from ldap_sudo.c */
-int sdap_sudo_init(struct be_ctx *be_ctx,
- struct sdap_id_ctx *id_ctx,
- struct bet_ops **ops,
- void **pvt_data);
+errno_t sdap_sudo_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct dp_method *dp_methods);
/* sdap async interface */
struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,