summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-03-31 15:30:28 +0200
committerSumit Bose <sbose@redhat.com>2010-03-31 15:30:28 +0200
commit1ed85377ec6de713f738ba498235fb352642841c (patch)
tree3342ce65e5b3e8d8c0b953094e2919397c56e9c4
parenta1e8a51f3fe9595006b20e873dfdd4b6c58b79aa (diff)
downloadsssd-my_head.tar.gz
sssd-my_head.tar.xz
sssd-my_head.zip
First try to read mirgation flagmy_head
-rw-r--r--src/providers/ipa/ipa_auth.c259
-rw-r--r--src/providers/ipa/ipa_common.h2
-rw-r--r--src/providers/ipa/ipa_init.c15
3 files changed, 262 insertions, 14 deletions
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index c8fd77d30..fe58e1759 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -32,18 +32,221 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/ipa/ipa_common.h"
+#define IPA_CONFIG_MIRATION_ENABLED "ipaMigrationEnabled"
+#define IPA_CONFIG_TEMPLATE "cn=ipaConfig,cn=etc,%s"
+
static void ipa_auth_reply(struct be_req *be_req, int dp_err, int result)
{
be_req->fn(be_req, dp_err, result, NULL);
}
+struct get_password_migration_flag_state {
+ struct tevent_context *ev;
+ 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 get_password_migration_flag_resolve_done(struct tevent_req *subreq);
+static void get_password_migration_flag_connect_done(struct tevent_req *subreq);
+static void get_password_migration_flag_done(struct tevent_req *subreq);
+
+static struct tevent_req *get_password_migration_flag(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_auth_ctx *sdap_auth_ctx,
+ char *ipa_domain)
+{
+ 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 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->srv = NULL;
+ state->password_migration = false;
+ state->ipa_domain = ipa_domain;
+
+ subreq = be_resolve_server_send(state, ev, sdap_auth_ctx->be,
+ sdap_auth_ctx->service->name);
+ if (subreq == NULL) {
+ DEBUG(1, ("be_resolve_server_send failed.\n"));
+ goto fail;
+ }
+
+ tevent_req_set_callback(subreq, get_password_migration_flag_resolve_done,
+ req);
+
+ return req;
+
+fail:
+ talloc_zfree(req);
+ return NULL;
+}
+
+static void get_password_migration_flag_resolve_done(struct tevent_req *subreq)
+{
+ 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;
+
+ ret = be_resolve_server_recv(subreq, &state->srv);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sdap_connect_send(state, state->ev, state->sdap_auth_ctx->opts,
+ state->sdap_auth_ctx->service->uri, false);
+ if (subreq == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_set_callback(subreq, get_password_migration_flag_connect_done,
+ req);
+}
+
+static void get_password_migration_flag_connect_done(struct tevent_req *subreq)
+{
+ 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_connect_recv(subreq, state, &state->sh);
+ talloc_zfree(subreq);
+ if (ret) {
+ if (state->srv) {
+ /* mark this server as bad if connection failed */
+ fo_set_port_status(state->srv, PORT_NOT_WORKING);
+ }
+
+ tevent_req_error(req, ret);
+ return;
+ } else if (state->srv) {
+ fo_set_port_status(state->srv, PORT_WORKING);
+ }
+
+ 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;
+ }
+
+ search_base = talloc_asprintf(state, IPA_CONFIG_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_BASE,
+ NULL, attrs, NULL, 0);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_set_callback(subreq, get_password_migration_flag_done, req);
+}
+
+static void get_password_migration_flag_done(struct tevent_req *subreq)
+{
+ 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;
+
+ 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 || reply[0]->num != 1 ||
+ reply[0]->a[0].num_values != 1) {
+ DEBUG(1, ("Unexpected number of results, expected (1,1,1), "
+ "got (%d,%d,%d).\n", reply_count, reply[0]->num,
+ reply[0]->a[0].num_values));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ if (strcmp(reply[0]->a[0].name, IPA_CONFIG_MIRATION_ENABLED) != 0) {
+ DEBUG(1, ("Got the wrong attribute, expected [%s], got [%s].\n",
+ IPA_CONFIG_MIRATION_ENABLED, reply[0]->a[0].name));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ if (strncasecmp((char *) reply[0]->a[0].values[0].data, "true",
+ reply[0]->a[0].values[0].length) == 0) {
+ state->password_migration = true;
+ }
+
+ tevent_req_done(req);
+}
+
+static int get_password_migration_flag_recv(struct tevent_req *req,
+ bool *password_migration)
+{
+ 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;
+
+ return EOK;
+}
+
+
struct ipa_auth_state {
struct be_req *be_req;
struct ipa_auth_ctx *ipa_auth_ctx;
struct pam_data *pd;
+ bool password_migration;
};
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);
@@ -58,6 +261,9 @@ void ipa_auth(struct be_req *be_req)
goto fail;
}
+/* TODO: test and activate when server side support is available */
+ state->password_migration = false;
+
state->be_req = be_req;
state->pd = talloc_get_type(be_req->req_data, struct pam_data);
@@ -79,9 +285,6 @@ void ipa_auth(struct be_req *be_req)
goto fail;
}
-/* TODO: test and activate when server side support is available */
- state->ipa_auth_ctx->password_migration = true;
-
req = krb5_auth_send(state, be_req->be_ctx->ev, be_req->be_ctx, state->pd,
state->ipa_auth_ctx->krb5_auth_ctx);
if (req == NULL) {
@@ -102,29 +305,61 @@ static void ipa_auth_handler_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 pam_status = PAM_SYSTEM_ERR;
int dp_err;
- struct dp_opt_blob password;
ret = krb5_auth_recv(req, &pam_status, &dp_err);
talloc_zfree(req);
+ state->pd->pam_status = pam_status;
if (ret != EOK && pam_status != PAM_CRED_ERR) {
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;
-
if (dp_err != DP_ERR_OK) {
goto done;
}
- if (state->ipa_auth_ctx->password_migration &&
- state->pd->cmd == SSS_PAM_AUTHENTICATE &&
+ if (state->pd->cmd == SSS_PAM_AUTHENTICATE &&
state->pd->pam_status == PAM_CRED_ERR) {
+ req = get_password_migration_flag(state, state->be_req->be_ctx->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;
+ struct dp_opt_blob password;
+
+ ret = get_password_migration_flag_recv(req, &state->password_migration);
+ 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 (state->password_migration) {
state->pd->pam_status = PAM_SYSTEM_ERR;
DEBUG(1, ("Assuming Kerberos password is missing, "
"starting password migration.\n"));
@@ -142,8 +377,12 @@ static void ipa_auth_handler_done(struct tevent_req *req)
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(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 3eaf9d9e7..03a082efd 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -53,7 +53,7 @@ enum ipa_basic_opt {
struct ipa_auth_ctx {
struct krb5_ctx *krb5_auth_ctx;
struct sdap_auth_ctx *sdap_auth_ctx;
- bool password_migration;
+ struct dp_option *ipa_options;
};
struct ipa_options {
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 0ddd5fcca..992286539 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,
};
@@ -190,9 +190,17 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
}
ipa_options->auth_ctx = ipa_auth_ctx;
+ 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) {
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
krb5_auth_ctx->service = ipa_options->service->krb5_service;
ipa_options->auth_ctx->krb5_auth_ctx = krb5_auth_ctx;
@@ -205,7 +213,8 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
sdap_auth_ctx = talloc_zero(ipa_auth_ctx, struct sdap_auth_ctx);
if (!sdap_auth_ctx) {
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
sdap_auth_ctx->be = bectx;
sdap_auth_ctx->service = ipa_options->service->sdap;