summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-03-29 13:41:41 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-04-26 09:55:10 -0400
commite3b1ebdf59b44efd1a8a8c4632ee0c8166da94a5 (patch)
tree6f2d4f0ca7290bdbfc05897ffe8612a679c05b17
parentb8399606d8e0890e82b67fb73bf8ba1f68cb7980 (diff)
downloadsssd_unused-e3b1ebdf59b44efd1a8a8c4632ee0c8166da94a5.tar.gz
sssd_unused-e3b1ebdf59b44efd1a8a8c4632ee0c8166da94a5.tar.xz
sssd_unused-e3b1ebdf59b44efd1a8a8c4632ee0c8166da94a5.zip
New version of IPA auth and password migration
The current version modified some global structures to be able to use Kerberos and LDAP authentication during the IPA password migration. This new version only uses tevent requests. Additionally the ipaMigrationEnabled attribute is read from the IPA server to see if password migration is allowed or not.
-rw-r--r--src/providers/ipa/ipa_auth.c529
-rw-r--r--src/providers/ipa/ipa_common.h8
-rw-r--r--src/providers/ipa/ipa_init.c83
-rw-r--r--src/providers/krb5/krb5_common.c4
4 files changed, 425 insertions, 199 deletions
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index 86b72e49..16bb407e 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -31,283 +31,460 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/ipa/ipa_common.h"
-struct ipa_auth_ctx {
- struct sdap_auth_ctx *sdap_auth_ctx;
- struct krb5_ctx *krb5_ctx;
- struct be_req *be_req;
- be_async_callback_t callback;
- void *pvt;
- bool password_migration;
-
- int dp_err_type;
- int errnum;
- char *errstr;
-};
+#define IPA_CONFIG_MIRATION_ENABLED "ipaMigrationEnabled"
+#define IPA_CONFIG_SEARCH_BASE_TEMPLATE "cn=etc,%s"
+#define IPA_CONFIG_FILTER "(&(cn=ipaConfig)(objectClass=ipaGuiConfig))"
-static void ipa_auth_reply(struct ipa_auth_ctx *ipa_auth_ctx)
+static void ipa_auth_reply(struct be_req *be_req, int dp_err, int result)
{
- struct pam_data *pd;
- struct be_req *be_req = ipa_auth_ctx->be_req;
- be_req->fn = ipa_auth_ctx->callback;
- be_req->pvt = ipa_auth_ctx->pvt;
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data = ipa_auth_ctx->krb5_ctx;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
- int dp_err_type = ipa_auth_ctx->dp_err_type;
- char *errstr = ipa_auth_ctx->errstr;
-
- talloc_zfree(ipa_auth_ctx);
- DEBUG(9, ("sending [%d] [%d] [%s].\n", dp_err_type, pd->pam_status,
- errstr));
-
- be_req->fn(be_req, dp_err_type, pd->pam_status, errstr);
+ be_req->fn(be_req, dp_err, result, NULL);
}
-struct ipa_auth_handler_state {
+struct get_password_migration_flag_state {
struct tevent_context *ev;
-
- int dp_err_type;
- int errnum;
- char *errstr;
+ struct sdap_auth_ctx *sdap_auth_ctx;
+ struct sdap_handle *sh;
+ enum sdap_result result;
+ struct fo_server *srv;
+ char *ipa_domain;
+ bool password_migration;
};
-static void ipa_auth_handler_callback(struct be_req *be_req,
- int dp_err_type,
- int errnum,
- const char *errstr);
+static void get_password_migration_flag_auth_done(struct tevent_req *subreq);
+static void get_password_migration_flag_done(struct tevent_req *subreq);
-static struct tevent_req *ipa_auth_handler_send(TALLOC_CTX *memctx,
+static struct tevent_req *get_password_migration_flag_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
- struct be_req *be_req,
- be_req_fn_t auth_handler)
+ struct sdap_auth_ctx *sdap_auth_ctx,
+ char *ipa_domain)
{
- struct ipa_auth_handler_state *state;
- struct tevent_req *req;
+ int ret;
+ struct tevent_req *req, *subreq;
+ struct get_password_migration_flag_state *state;
+
+ if (sdap_auth_ctx == NULL || ipa_domain == NULL) {
+ DEBUG(1, ("Missing parameter.\n"));
+ return NULL;
+ }
- req = tevent_req_create(memctx, &state, struct ipa_auth_handler_state);
+ req = tevent_req_create(memctx, &state,
+ struct get_password_migration_flag_state);
if (req == NULL) {
DEBUG(1, ("tevent_req_create failed.\n"));
return NULL;
}
state->ev = ev;
+ state->sdap_auth_ctx = sdap_auth_ctx;
+ state->sh = NULL;
+ state->result = SDAP_ERROR;
+ state->srv = NULL;
+ state->password_migration = false;
+ state->ipa_domain = ipa_domain;
+
+ /* We request to use StartTLS here, because if password migration is
+ * enabled we will use this connection for authentication, too. */
+ ret = dp_opt_set_bool(sdap_auth_ctx->opts->basic, SDAP_ID_TLS, true);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to set SDAP_ID_TLS to true.\n"));
+ goto fail;
+ }
- be_req->fn = ipa_auth_handler_callback;
- be_req->pvt = req;
-
- auth_handler(be_req);
+ subreq = sdap_cli_connect_send(state, ev, sdap_auth_ctx->opts,
+ sdap_auth_ctx->be, sdap_auth_ctx->service,
+ NULL);
+ if (subreq == NULL) {
+ DEBUG(1, ("sdap_cli_connect_send failed.\n"));
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, get_password_migration_flag_auth_done,
+ req);
return req;
+
+fail:
+ talloc_zfree(req);
+ return NULL;
}
-static void ipa_auth_handler_callback(struct be_req *be_req,
- int dp_err_type,
- int errnum,
- const char *errstr)
+static void get_password_migration_flag_auth_done(struct tevent_req *subreq)
{
- struct tevent_req *req = talloc_get_type(be_req->pvt, struct tevent_req);
- struct ipa_auth_handler_state *state = tevent_req_data(req,
- struct ipa_auth_handler_state);
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct get_password_migration_flag_state *state = tevent_req_data(req,
+ struct get_password_migration_flag_state);
+ int ret;
+ char *ldap_basedn;
+ char *search_base;
+ const char **attrs;
+
+ ret = sdap_cli_connect_recv(subreq, state, &state->sh, NULL);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(1, ("sdap_auth request failed.\n"));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ ret = domain_to_basedn(state, state->ipa_domain, &ldap_basedn);
+ if (ret != EOK) {
+ DEBUG(1, ("domain_to_basedn failed.\n"));
+ tevent_req_error(req, ret);
+ return;
+ }
- DEBUG(9, ("received from handler [%d] [%d] [%s].\n", dp_err_type, errnum,
- errstr));
- state->dp_err_type = dp_err_type;
- state->errnum = errnum;
- state->errstr = talloc_strdup(state, errstr);
+ search_base = talloc_asprintf(state, IPA_CONFIG_SEARCH_BASE_TEMPLATE,
+ ldap_basedn);
+ if (search_base == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
- tevent_req_post(req, state->ev);
- tevent_req_done(req);
- return;
+ attrs = talloc_array(state, const char*, 2);
+ if (attrs == NULL) {
+ DEBUG(1, ("talloc_array failed.\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ attrs[0] = IPA_CONFIG_MIRATION_ENABLED;
+ attrs[1] = NULL;
+
+ subreq = sdap_get_generic_send(state, state->ev, state->sdap_auth_ctx->opts,
+ state->sh, search_base, LDAP_SCOPE_SUBTREE,
+ IPA_CONFIG_FILTER, attrs, NULL, 0);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_set_callback(subreq, get_password_migration_flag_done, req);
}
-static int ipa_auth_handler_recv(struct tevent_req *req, TALLOC_CTX *memctx,
- int *dp_err_type, int *errnum,
- char **errstr)
+static void get_password_migration_flag_done(struct tevent_req *subreq)
{
- struct ipa_auth_handler_state *state = tevent_req_data(req,
- struct ipa_auth_handler_state);
- enum tevent_req_state tstate;
- uint64_t err;
-
- if (tevent_req_is_error(req, &tstate, &err)) {
- if (err) return err;
- return EIO;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct get_password_migration_flag_state *state = tevent_req_data(req,
+ struct get_password_migration_flag_state);
+ int ret;
+ size_t reply_count;
+ struct sysdb_attrs **reply = NULL;
+ const char *value = NULL;
+
+ ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (reply_count != 1) {
+ DEBUG(1, ("Unexpected number of results, expected 1, got %d.\n",
+ reply_count));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ ret = sysdb_attrs_get_string(reply[0], IPA_CONFIG_MIRATION_ENABLED, &value);
+ if (strcasecmp(value, "true") == 0) {
+ state->password_migration = true;
}
- *dp_err_type = state->dp_err_type;
- *errnum = state->errnum;
- *errstr = talloc_steal(memctx, state->errstr);
+ tevent_req_done(req);
+}
+
+static int get_password_migration_flag_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ bool *password_migration,
+ struct sdap_handle **sh)
+{
+ struct get_password_migration_flag_state *state = tevent_req_data(req,
+ struct get_password_migration_flag_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *password_migration = state->password_migration;
+ if (sh != NULL) {
+ *sh = talloc_steal(mem_ctx, state->sh);
+ }
return EOK;
}
+struct ipa_auth_state {
+ struct be_req *be_req;
+ struct tevent_context *ev;
+ struct ipa_auth_ctx *ipa_auth_ctx;
+ struct pam_data *pd;
+ bool password_migration;
+ struct sdap_handle *sh;
+};
+
static void ipa_auth_handler_done(struct tevent_req *req);
+static void ipa_get_migration_flag_done(struct tevent_req *req);
+static void ipa_auth_get_user_dn_done(struct tevent_req *req);
static void ipa_auth_ldap_done(struct tevent_req *req);
static void ipa_auth_handler_retry_done(struct tevent_req *req);
void ipa_auth(struct be_req *be_req)
{
struct tevent_req *req;
- struct ipa_auth_ctx *ipa_auth_ctx;
- struct sdap_id_ctx *sdap_id_ctx;
+ struct ipa_auth_state *state;
- ipa_auth_ctx = talloc_zero(be_req, struct ipa_auth_ctx);
- if (ipa_auth_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
- }
-
- ipa_auth_ctx->callback = be_req->fn;
- ipa_auth_ctx->pvt = be_req->pvt;
-
- ipa_auth_ctx->be_req = be_req;
-
- ipa_auth_ctx->sdap_auth_ctx = talloc_zero(ipa_auth_ctx,
- struct sdap_auth_ctx);
- if (ipa_auth_ctx->sdap_auth_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
+ state = talloc_zero(be_req, struct ipa_auth_state);
+ if (state == NULL) {
+ DEBUG(1, ("talloc_zero failed.\n"));
goto fail;
}
- sdap_id_ctx = talloc_get_type(
- be_req->be_ctx->bet_info[BET_ID].pvt_bet_data,
- struct sdap_id_ctx);
- ipa_auth_ctx->sdap_auth_ctx->be = sdap_id_ctx->be;
- ipa_auth_ctx->sdap_auth_ctx->opts = sdap_id_ctx->opts;
-
- ipa_auth_ctx->krb5_ctx = talloc_get_type(
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
- struct krb5_ctx);
-
-/* TODO: test and activate when server side support is available */
- ipa_auth_ctx->password_migration = false;
-
- ipa_auth_ctx->dp_err_type = DP_ERR_FATAL;
- ipa_auth_ctx->errnum = EIO;
- ipa_auth_ctx->errstr = NULL;
+ state->password_migration = false;
+ state->sh = NULL;
+
+ state->be_req = be_req;
+ state->ev = be_req->be_ctx->ev;
+
+ state->pd = talloc_get_type(be_req->req_data, struct pam_data);
+
+ switch (state->pd->cmd) {
+ case SSS_PAM_AUTHENTICATE:
+ state->ipa_auth_ctx = talloc_get_type(
+ be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
+ struct ipa_auth_ctx);
+ break;
+ case SSS_PAM_CHAUTHTOK:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
+ state->ipa_auth_ctx = talloc_get_type(
+ be_req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
+ struct ipa_auth_ctx);
+ break;
+ default:
+ DEBUG(1, ("Unsupported PAM task.\n"));
+ goto fail;
+ }
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- krb5_pam_handler);
+ req = krb5_auth_send(state, state->ev, be_req->be_ctx, state->pd,
+ state->ipa_auth_ctx->krb5_auth_ctx);
if (req == NULL) {
- DEBUG(1, ("ipa_auth_handler_send failed.\n"));
+ DEBUG(1, ("krb5_auth_send failed.\n"));
goto fail;
}
- tevent_req_set_callback(req, ipa_auth_handler_done, ipa_auth_ctx);
+ tevent_req_set_callback(req, ipa_auth_handler_done, state);
return;
fail:
- ipa_auth_reply(ipa_auth_ctx);
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ ipa_auth_reply(be_req, DP_ERR_FATAL, state->pd->pam_status);
}
static void ipa_auth_handler_done(struct tevent_req *req)
{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
+ struct ipa_auth_state *state = tevent_req_callback_data(req,
+ struct ipa_auth_state);
int ret;
+ int pam_status = PAM_SYSTEM_ERR;
+ int dp_err;
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
+ ret = krb5_auth_recv(req, &pam_status, &dp_err);
talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
+ state->pd->pam_status = pam_status;
+ if (ret != EOK && pam_status != PAM_CRED_ERR) {
+ DEBUG(1, ("krb5_auth_recv request failed.\n"));
+ dp_err = DP_ERR_OK;
goto done;
}
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
+
+ if (dp_err != DP_ERR_OK) {
goto done;
}
- if (ipa_auth_ctx->password_migration && pd->pam_status == PAM_CRED_ERR) {
- DEBUG(1, ("Assuming Kerberos password is missing, "
- "starting password migration.\n"));
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data =
- ipa_auth_ctx->sdap_auth_ctx;
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- sdap_pam_auth_handler);
+ if (state->pd->cmd == SSS_PAM_AUTHENTICATE &&
+ state->pd->pam_status == PAM_CRED_ERR) {
+
+ req = get_password_migration_flag_send(state, state->ev,
+ state->ipa_auth_ctx->sdap_auth_ctx,
+ dp_opt_get_string(
+ state->ipa_auth_ctx->ipa_options,
+ IPA_DOMAIN));
if (req == NULL) {
- DEBUG(1, ("ipa_auth_ldap_send failed.\n"));
+ DEBUG(1, ("get_password_migration_flag failed.\n"));
goto done;
}
- tevent_req_set_callback(req, ipa_auth_ldap_done, ipa_auth_ctx);
+ tevent_req_set_callback(req, ipa_get_migration_flag_done, state);
return;
}
done:
- ipa_auth_reply(ipa_auth_ctx);
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
}
-static void ipa_auth_ldap_done(struct tevent_req *req)
+static void ipa_get_migration_flag_done(struct tevent_req *req)
{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
+ struct ipa_auth_state *state = tevent_req_callback_data(req,
+ struct ipa_auth_state);
int ret;
+ int dp_err = DP_ERR_FATAL;
+ const char **attrs;
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
+ ret = get_password_migration_flag_recv(req, state,
+ &state->password_migration,
+ &state->sh);
talloc_zfree(req);
if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
+ DEBUG(1, ("get_password_migration_flag request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
goto done;
}
- if (pd->pam_status == PAM_SUCCESS) {
- DEBUG(1, ("LDAP authentication succeded, "
- "trying Kerberos authentication again.\n"));
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data = ipa_auth_ctx->krb5_ctx;
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- krb5_pam_handler);
+ if (state->password_migration) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ DEBUG(1, ("Assuming Kerberos password is missing, "
+ "starting password migration.\n"));
+
+ attrs = talloc_array(state, const char *, 2);
+ if (attrs == NULL) {
+ DEBUG(1, ("talloc_array failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
+ }
+ attrs[0] = SYSDB_ORIG_DN;
+ attrs[1] = NULL;
+
+ req = sysdb_search_user_by_name_send(state, state->ev,
+ state->be_req->be_ctx->sysdb, NULL,
+ state->be_req->be_ctx->domain,
+ state->pd->user, attrs);
if (req == NULL) {
- DEBUG(1, ("ipa_auth_ldap_send failed.\n"));
+ DEBUG(1, ("sysdb_search_user_by_name_send failed.\n"));
goto done;
}
- tevent_req_set_callback(req, ipa_auth_handler_retry_done, ipa_auth_ctx);
+ tevent_req_set_callback(req, ipa_auth_get_user_dn_done, state);
return;
+ } else {
+ DEBUG(5, ("Password migration is not enabled.\n"));
}
+ dp_err = DP_ERR_OK;
+
done:
- ipa_auth_reply(ipa_auth_ctx);
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
}
-static void ipa_auth_handler_retry_done(struct tevent_req *req)
+void ipa_auth_get_user_dn_done(struct tevent_req *req)
{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
+ struct ipa_auth_state *state = tevent_req_callback_data(req,
+ struct ipa_auth_state);
int ret;
+ int dp_err = DP_ERR_FATAL;
+ struct dp_opt_blob password;
+ struct ldb_message *msg;
+ const char *dn;
+
+ ret = sysdb_search_user_recv(req, state, &msg);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(1, ("sysdb_search_user request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
+ }
+
+ dn = ldb_msg_find_attr_as_string(msg, SYSDB_ORIG_DN, NULL);
+ if (dn == NULL) {
+ DEBUG(1, ("Missing original DN for user [%s].\n", state->pd->user));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
+ }
+
+ password.data = state->pd->authtok;
+ password.length = state->pd->authtok_size;
+
+ req = sdap_auth_send(state, state->ev, state->sh, NULL, NULL, dn,
+ "password", password);
+ if (req == NULL) {
+ DEBUG(1, ("sdap_auth_send failed.\n"));
+ goto done;
+ }
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
+ tevent_req_set_callback(req, ipa_auth_ldap_done, state);
+ return;
+
+done:
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
+}
+
+
+static void ipa_auth_ldap_done(struct tevent_req *req)
+{
+ struct ipa_auth_state *state = tevent_req_callback_data(req,
+ struct ipa_auth_state);
+ int ret;
+ int dp_err = DP_ERR_FATAL;
+ enum sdap_result result;
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
+ ret = sdap_auth_recv(req, state, &result, NULL);
talloc_zfree(req);
if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
+ DEBUG(1, ("auth_send request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
}
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
+
+/* TODO: do we need to handle expired passwords? */
+ if (result != SDAP_AUTH_SUCCESS) {
+ DEBUG(1, ("LDAP authentication failed, "
+ "Password migration not possible.\n"));
+ state->pd->pam_status = PAM_CRED_INSUFFICIENT;
+ dp_err = DP_ERR_OK;
+ goto done;
}
- ipa_auth_reply(ipa_auth_ctx);
+ DEBUG(1, ("LDAP authentication succeded, "
+ "trying Kerberos authentication again.\n"));
+
+ req = krb5_auth_send(state, state->ev,
+ state->be_req->be_ctx, state->pd,
+ state->ipa_auth_ctx->krb5_auth_ctx);
+ if (req == NULL) {
+ DEBUG(1, ("krb5_auth_send failed.\n"));
+ goto done;
+ }
+
+ tevent_req_set_callback(req, ipa_auth_handler_retry_done, state);
+ return;
+
+done:
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
+}
+
+static void ipa_auth_handler_retry_done(struct tevent_req *req)
+{
+ struct ipa_auth_state *state = tevent_req_callback_data(req,
+ struct ipa_auth_state);
+ int ret;
+ int pam_status;
+ int dp_err;
+
+ ret = krb5_auth_recv(req, &pam_status, &dp_err);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(1, ("krb5_auth_recv request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
+ }
+
+ state->pd->pam_status = pam_status;
+
+done:
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
}
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 77628189..03a082ef 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -50,6 +50,12 @@ enum ipa_basic_opt {
IPA_OPTS_BASIC /* opts counter */
};
+struct ipa_auth_ctx {
+ struct krb5_ctx *krb5_auth_ctx;
+ struct sdap_auth_ctx *sdap_auth_ctx;
+ struct dp_option *ipa_options;
+};
+
struct ipa_options {
struct dp_option *basic;
@@ -61,7 +67,7 @@ struct ipa_options {
/* auth and chpass provider */
struct dp_option *auth;
- struct krb5_ctx *auth_ctx;
+ struct ipa_auth_ctx *auth_ctx;
};
int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn);
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 1689ac28..6e0688f0 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -48,7 +48,7 @@ struct bet_ops ipa_auth_ops = {
};
struct bet_ops ipa_chpass_ops = {
- .handler = krb5_pam_handler,
+ .handler = ipa_auth,
.finalize = NULL,
};
@@ -162,7 +162,9 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
struct bet_ops **ops,
void **pvt_data)
{
- struct krb5_ctx *ctx;
+ struct ipa_auth_ctx *ipa_auth_ctx;
+ struct krb5_ctx *krb5_auth_ctx;
+ struct sdap_auth_ctx *sdap_auth_ctx;
struct tevent_signal *sige;
FILE *debug_filep;
unsigned v;
@@ -182,33 +184,74 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
return EOK;
}
- ctx = talloc_zero(bectx, struct krb5_ctx);
- if (!ctx) {
+ ipa_auth_ctx = talloc_zero(ipa_options, struct ipa_auth_ctx);
+ if (!ipa_auth_ctx) {
return ENOMEM;
}
- ctx->service = ipa_options->service->krb5_service;
- ipa_options->auth_ctx = ctx;
+ ipa_options->auth_ctx = ipa_auth_ctx;
- ret = ipa_get_auth_options(ipa_options, bectx->cdb,
- bectx->conf_path,
- &ctx->opts);
+ ret = dp_copy_options(ipa_auth_ctx, ipa_options->basic,
+ IPA_OPTS_BASIC, &ipa_auth_ctx->ipa_options);
if (ret != EOK) {
+ DEBUG(1, ("dp_copy_options failed.\n"));
+ goto done;
+ }
+
+ krb5_auth_ctx = talloc_zero(ipa_auth_ctx, struct krb5_ctx);
+ if (!krb5_auth_ctx) {
+ ret = ENOMEM;
goto done;
}
+ krb5_auth_ctx->service = ipa_options->service->krb5_service;
+ ipa_options->auth_ctx->krb5_auth_ctx = krb5_auth_ctx;
- ret = check_and_export_options(ctx->opts, bectx->domain);
+ ret = ipa_get_auth_options(ipa_options, bectx->cdb, bectx->conf_path,
+ &krb5_auth_ctx->opts);
if (ret != EOK) {
- DEBUG(1, ("check_and_export_opts failed.\n"));
goto done;
}
- sige = tevent_add_signal(bectx->ev, ctx, SIGCHLD, SA_SIGINFO,
- child_sig_handler, NULL);
- if (sige == NULL) {
- DEBUG(1, ("tevent_add_signal failed.\n"));
+ sdap_auth_ctx = talloc_zero(ipa_auth_ctx, struct sdap_auth_ctx);
+ if (!sdap_auth_ctx) {
ret = ENOMEM;
goto done;
}
+ sdap_auth_ctx->be = bectx;
+ sdap_auth_ctx->service = ipa_options->service->sdap;
+ ipa_options->auth_ctx->sdap_auth_ctx = sdap_auth_ctx;
+
+ ret = ipa_get_id_options(ipa_options, bectx->cdb, bectx->conf_path,
+ &sdap_auth_ctx->opts);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = setup_tls_config(sdap_auth_ctx->opts->basic);
+ if (ret != EOK) {
+ DEBUG(1, ("setup_tls_config failed [%d][%s].\n",
+ ret, strerror(ret)));
+ goto done;
+ }
+
+ ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain);
+ if (ret != EOK) {
+ DEBUG(1, ("check_and_export_opts failed.\n"));
+ goto done;
+ }
+
+ if (ipa_options->id_ctx == NULL) {
+ DEBUG(9, ("Adding SIGCHLD handler for Kerberos child.\n"));
+ sige = tevent_add_signal(bectx->ev, krb5_auth_ctx, SIGCHLD, SA_SIGINFO,
+ child_sig_handler, NULL);
+ if (sige == NULL) {
+ DEBUG(1, ("tevent_add_signal failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ } else {
+ DEBUG(9, ("IPA id provider already initialized, "
+ "assuming that a SIGCHLD handler is already in place.\n"));
+ }
if (debug_to_file != 0) {
ret = open_debug_file_ex("krb5_child", &debug_filep);
@@ -218,19 +261,19 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
goto done;
}
- ctx->child_debug_fd = fileno(debug_filep);
- if (ctx->child_debug_fd == -1) {
+ krb5_auth_ctx->child_debug_fd = fileno(debug_filep);
+ if (krb5_auth_ctx->child_debug_fd == -1) {
DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno)));
ret = errno;
goto done;
}
- v = fcntl(ctx->child_debug_fd, F_GETFD, 0);
- fcntl(ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC);
+ v = fcntl(krb5_auth_ctx->child_debug_fd, F_GETFD, 0);
+ fcntl(krb5_auth_ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC);
}
*ops = &ipa_auth_ops;
- *pvt_data = ctx;
+ *pvt_data = ipa_auth_ctx;
ret = EOK;
done:
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 2b3331ed..52cbe165 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -69,13 +69,13 @@ errno_t check_and_export_options(struct dp_option *opts,
dummy = dp_opt_get_cstring(opts, KRB5_KDC);
if (dummy == NULL) {
- DEBUG(1, ("No KDC explicitly configured, using defaults"));
+ DEBUG(1, ("No KDC explicitly configured, using defaults.\n"));
}
dummy = dp_opt_get_cstring(opts, KRB5_KPASSWD);
if (dummy == NULL) {
DEBUG(1, ("No kpasswd server explicitly configured, "
- "using the KDC or defaults"));
+ "using the KDC or defaults.\n"));
}
dummy = dp_opt_get_cstring(opts, KRB5_CCNAME_TMPL);