summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/providers/data_provider_be.c8
-rw-r--r--server/providers/ldap/ldap_auth.c161
-rw-r--r--server/providers/ldap/sdap_async.c134
-rw-r--r--server/providers/ldap/sdap_async.h8
4 files changed, 307 insertions, 4 deletions
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 5cd59946..2e0c1cf2 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -631,8 +631,10 @@ static int be_pam_handler(DBusMessage *message, struct sbus_conn_ctx *sconn)
}
be_req = talloc_zero(ctx, struct be_req);
- if (!be_req)
+ if (!be_req) {
+ DEBUG(7, ("talloc_zero failed.\n"));
goto done;
+ }
be_req->be_ctx = ctx;
be_req->fn = be_pam_handler_callback;
@@ -640,8 +642,10 @@ static int be_pam_handler(DBusMessage *message, struct sbus_conn_ctx *sconn)
be_req->req_data = pd;
ret = be_file_request(ctx, ctx->bet_info[target].bet_ops->handler, be_req);
- if (ret != EOK)
+ if (ret != EOK) {
+ DEBUG(7, ("be_file_request failed.\n"));
goto done;
+ }
return EOK;
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 2c530325..f0b12a0a 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -283,7 +283,8 @@ static void auth_bind_user_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int auth_recv(struct tevent_req *req, enum sdap_result *result)
+int auth_recv(struct tevent_req *req, enum sdap_result *result,
+ TALLOC_CTX *memctx, struct sdap_handle **sh, char **dn)
{
struct auth_state *state = tevent_req_data(req,
struct auth_state);
@@ -296,11 +297,151 @@ int auth_recv(struct tevent_req *req, enum sdap_result *result)
return EOK;
}
+ if (sh != NULL) {
+ *sh = talloc_steal(memctx, state->sh);
+ if (*sh == NULL) return ENOMEM;
+ }
+
+ if (dn != NULL) {
+ *dn = talloc_steal(memctx, state->dn);
+ if (*dn == NULL) return ENOMEM;
+ }
+
*result = state->result;
return EOK;
}
+/* ==Perform-Password-Change===================== */
+
+struct sdap_pam_chpass_state {
+ struct be_req *breq;
+ struct pam_data *pd;
+ const char *username;
+ char *dn;
+ char *password;
+ char *new_password;
+ struct sdap_handle *sh;
+};
+static void sdap_auth4chpass_done(struct tevent_req *req);
+static void sdap_pam_chpass_done(struct tevent_req *req);
+static void sdap_pam_auth_reply(struct be_req *breq, int result);
+
+static void sdap_pam_chpass_send(struct be_req *breq)
+{
+ struct sdap_pam_chpass_state *state;
+ struct sdap_auth_ctx *ctx;
+ struct tevent_req *subreq;
+ struct pam_data *pd;
+
+ ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
+ struct sdap_auth_ctx);
+ pd = talloc_get_type(breq->req_data, struct pam_data);
+
+ DEBUG(2, ("starting password change request for user [%s].\n", pd->user));
+
+ pd->pam_status = PAM_SYSTEM_ERR;
+
+ if (pd->cmd != SSS_PAM_CHAUTHTOK) {
+ DEBUG(2, ("chpass target was called by wrong pam command.\n"));
+ goto done;
+ }
+
+ state = talloc_zero(breq, struct sdap_pam_chpass_state);
+ if (!state) goto done;
+
+ state->breq = breq;
+ state->pd = pd;
+ state->username = pd->user;
+ state->password = talloc_strndup(state,
+ (char *)pd->authtok, pd->authtok_size);
+ if (!state->password) goto done;
+ talloc_set_destructor((TALLOC_CTX *)state->password,
+ password_destructor);
+ state->new_password = talloc_strndup(state,
+ (char *)pd->newauthtok,
+ pd->newauthtok_size);
+ if (!state->new_password) goto done;
+ talloc_set_destructor((TALLOC_CTX *)state->new_password,
+ password_destructor);
+
+ subreq = auth_send(breq, breq->be_ctx->ev,
+ ctx, state->username, state->password);
+ if (!subreq) goto done;
+
+ tevent_req_set_callback(subreq, sdap_auth4chpass_done, state);
+ return;
+done:
+ sdap_pam_auth_reply(breq, pd->pam_status);
+}
+
+static void sdap_auth4chpass_done(struct tevent_req *req)
+{
+ struct sdap_pam_chpass_state *state =
+ tevent_req_callback_data(req, struct sdap_pam_chpass_state);
+ struct tevent_req *subreq;
+ enum sdap_result result;
+ int ret;
+
+ ret = auth_recv(req, &result, state, &state->sh, &state->dn);
+ talloc_zfree(req);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
+
+ switch (result) {
+ case SDAP_AUTH_SUCCESS:
+ DEBUG(7, ("user [%s] successfully authenticated.\n", state->dn));
+ subreq = sdap_exop_modify_passwd_send(state,
+ state->breq->be_ctx->ev,
+ state->sh,
+ state->dn,
+ state->password,
+ state->new_password);
+
+ if (!subreq) {
+ DEBUG(2, ("Failed to change password for %s\n", state->username));
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sdap_pam_chpass_done, state);
+ return;
+ break;
+ default:
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ }
+
+done:
+ sdap_pam_auth_reply(state->breq, state->pd->pam_status);
+}
+
+static void sdap_pam_chpass_done(struct tevent_req *req)
+{
+ struct sdap_pam_chpass_state *state =
+ tevent_req_callback_data(req, struct sdap_pam_chpass_state);
+ enum sdap_result result;
+ int ret;
+
+ ret = sdap_exop_modify_passwd_recv(req, &result);
+ talloc_zfree(req);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
+ switch (result) {
+ case SDAP_SUCCESS:
+ state->pd->pam_status = PAM_SUCCESS;
+ break;
+ default:
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ }
+
+done:
+ sdap_pam_auth_reply(state->breq, state->pd->pam_status);
+}
/* ==Perform-User-Authentication-and-Password-Caching===================== */
struct sdap_pam_auth_state {
@@ -369,7 +510,7 @@ static void sdap_pam_auth_done(struct tevent_req *req)
enum sdap_result result;
int ret;
- ret = auth_recv(req, &result);
+ ret = auth_recv(req, &result, NULL, NULL, NULL);
talloc_zfree(req);
if (ret) {
state->pd->pam_status = PAM_SYSTEM_ERR;
@@ -453,6 +594,12 @@ struct bet_ops sdap_auth_ops = {
.finalize = sdap_shutdown
};
+struct bet_ops sdap_chpass_ops = {
+ .check_online = NULL,
+ .handler = sdap_pam_chpass_send,
+ .finalize = sdap_shutdown
+};
+
int sssm_ldap_auth_init(struct be_ctx *bectx,
struct bet_ops **ops,
void **pvt_data)
@@ -514,3 +661,13 @@ done:
}
return ret;
}
+
+int sssm_ldap_chpass_init(struct be_ctx *bectx,
+ struct bet_ops **ops,
+ void **pvt_data)
+{
+ int ret;
+ ret = sssm_ldap_auth_init(bectx, ops, pvt_data);
+ *ops = &sdap_chpass_ops;
+ return ret;
+}
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 57234e38..d5e42f0c 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -1639,3 +1639,137 @@ int sdap_get_initgr_recv(struct tevent_req *req)
return EOK;
}
+struct sdap_exop_modify_passwd_state {
+ struct sdap_handle *sh;
+ int msgid;
+ char *user_dn;
+ char *password;
+ char *new_password;
+ int result;
+ struct sdap_msg *reply;
+};
+
+static void sdap_exop_modify_passwd_done(void *pvt, int error, struct sdap_msg *reply);
+
+struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_handle *sh,
+ char *user_dn,
+ char *password,
+ char *new_password)
+{
+ struct tevent_req *req = NULL;
+ struct sdap_exop_modify_passwd_state *state;
+ int ret;
+ BerElement *ber = NULL;
+ struct berval *bv = NULL;
+
+ req = tevent_req_create(memctx, &state,
+ struct sdap_exop_modify_passwd_state);
+ if (!req) return NULL;
+
+ state->sh = sh;
+ state->reply = NULL;
+
+ ber = ber_alloc_t( LBER_USE_DER );
+ if (ber == NULL) {
+ DEBUG(7, ("ber_alloc_t failed.\n"));
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ ret = ber_printf( ber, "{tststs}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
+ user_dn,
+ LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, password,
+ LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, new_password);
+ if (ret == -1) {
+ DEBUG(1, ("ber_printf failed.\n"));
+ ber_free(ber, 1);
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ ret = ber_flatten(ber, &bv);
+ ber_free(ber, 1);
+ if (ret == -1) {
+ DEBUG(1, ("ber_flatten failed.\n"));
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ DEBUG(4, ("Executing extended operation\n"));
+
+ ret = ldap_extended_operation(state->sh->ldap, LDAP_EXOP_MODIFY_PASSWD,
+ bv, NULL, NULL, &state->msgid);
+ ber_bvfree(bv);
+ if (ret == -1 || state->msgid == -1) {
+ DEBUG(1, ("ldap_extended_operation failed\n"));
+ goto fail;
+ }
+ DEBUG(8, ("ldap_extended_operation sent, msgid = %d\n", state->msgid));
+
+ /* FIXME: get timeouts from configuration, for now 5 secs. */
+ ret = sdap_op_add(state, ev, state->sh, state->msgid,
+ sdap_exop_modify_passwd_done, req, 5);
+ if (ret) {
+ DEBUG(1, ("Failed to set up operation!\n"));
+ goto fail;
+ }
+
+ return req;
+
+fail:
+ tevent_req_error(req, EIO);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sdap_exop_modify_passwd_done(void *pvt, int error, struct sdap_msg *reply)
+{
+ struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+ struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
+ struct sdap_exop_modify_passwd_state);
+ char *errmsg;
+ int ret;
+
+ if (error) {
+ tevent_req_error(req, error);
+ return;
+ }
+
+ state->reply = talloc_steal(state, reply);
+
+ ret = ldap_parse_result(state->sh->ldap, state->reply->msg,
+ &state->result, NULL, &errmsg, NULL, NULL, 0);
+ if (ret != LDAP_SUCCESS) {
+ DEBUG(2, ("ldap_parse_result failed (%d)\n", state->msgid));
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n",
+ ldap_err2string(state->result), state->result, errmsg));
+
+ tevent_req_done(req);
+}
+
+int sdap_exop_modify_passwd_recv(struct tevent_req *req,
+ enum sdap_result *result)
+{
+ struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
+ struct sdap_exop_modify_passwd_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ *result = SDAP_ERROR;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
+ }
+
+ if (state->result == LDAP_SUCCESS) {
+ *result = SDAP_SUCCESS;
+ }
+
+ return EOK;
+}
diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h
index 6ed95320..4012729c 100644
--- a/server/providers/ldap/sdap_async.h
+++ b/server/providers/ldap/sdap_async.h
@@ -85,3 +85,11 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
const char *name,
const char **grp_attrs);
int sdap_get_initgr_recv(struct tevent_req *req);
+
+struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_handle *sh,
+ char *user_dn,
+ char *password,
+ char *new_password);
+int sdap_exop_modify_passwd_recv(struct tevent_req *req, enum sdap_result *result);