summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-03-29 13:41:41 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-05-16 13:28:12 -0400
commit928ff09ea3975edbf53df05a1ade365a588dc69d (patch)
tree7baf52cc9840a987fb034c77b310425380b1ee6f
parent5f2593e24f565b202821329f1f9cb103241d80bb (diff)
downloadsssd-928ff09ea3975edbf53df05a1ade365a588dc69d.tar.gz
sssd-928ff09ea3975edbf53df05a1ade365a588dc69d.tar.xz
sssd-928ff09ea3975edbf53df05a1ade365a588dc69d.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.c504
-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, 400 insertions, 199 deletions
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index 86b72e495..6f062adc1 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -31,283 +31,435 @@
#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;
+ }
- 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);
+ 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;
+ }
- tevent_req_post(req, state->ev);
- tevent_req_done(req);
- return;
+ 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;
+ }
+
+ 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;
}
- *dp_err_type = state->dp_err_type;
- *errnum = state->errnum;
- *errstr = talloc_steal(memctx, state->errstr);
+ ret = sysdb_attrs_get_string(reply[0], IPA_CONFIG_MIRATION_ENABLED, &value);
+ if (strcasecmp(value, "true") == 0) {
+ state->password_migration = true;
+ }
+
+ 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_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 (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, ("get_password_migration_flag failed.\n"));
+ goto done;
+ }
+
+ tevent_req_set_callback(req, ipa_get_migration_flag_done, state);
+ return;
+ }
+
+done:
+ ipa_auth_reply(state->be_req, dp_err, state->pd->pam_status);
+}
+
+static void ipa_get_migration_flag_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;
+ const char **attrs;
+ struct ldb_message *user_msg;
+ const char *dn;
+ struct dp_opt_blob password;
+
+ ret = get_password_migration_flag_recv(req, state,
+ &state->password_migration,
+ &state->sh);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(1, ("get_password_migration_flag request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
goto done;
}
- if (ipa_auth_ctx->password_migration && pd->pam_status == PAM_CRED_ERR) {
+ if (state->password_migration) {
+ state->pd->pam_status = PAM_SYSTEM_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);
+
+ 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;
+
+ ret = sysdb_search_user_by_name(state, state->be_req->be_ctx->sysdb,
+ state->be_req->be_ctx->domain,
+ state->pd->user, attrs, &user_msg);
+ if (ret != EOK) {
+ DEBUG(1, ("sysdb_search_user_by_name failed.\n"));
+ goto done;
+ }
+
+ dn = ldb_msg_find_attr_as_string(user_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, ("ipa_auth_ldap_send failed.\n"));
+ DEBUG(1, ("sdap_auth_send failed.\n"));
goto done;
}
- tevent_req_set_callback(req, ipa_auth_ldap_done, ipa_auth_ctx);
+ tevent_req_set_callback(req, ipa_auth_ldap_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_ldap_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;
+ enum sdap_result result;
- 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 = 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;
}
- 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 (req == NULL) {
- DEBUG(1, ("ipa_auth_ldap_send failed.\n"));
- goto done;
- }
+ DEBUG(1, ("LDAP authentication succeded, "
+ "trying Kerberos authentication again.\n"));
- tevent_req_set_callback(req, ipa_auth_handler_retry_done, ipa_auth_ctx);
- return;
+ 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(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)
{
- 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;
+ 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;
- }
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
+ DEBUG(1, ("krb5_auth_recv request failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ dp_err = DP_ERR_OK;
+ goto done;
}
- ipa_auth_reply(ipa_auth_ctx);
+ 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 9daede2db..f53c022e5 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 596aecfbd..d2f9b3dcb 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,
};
@@ -161,7 +161,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;
@@ -181,33 +183,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);
@@ -217,19 +260,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 bc2d3fbc1..17b6511e5 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -71,13 +71,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);