diff options
-rw-r--r-- | server/providers/data_provider_be.c | 8 | ||||
-rw-r--r-- | server/providers/ldap/ldap_auth.c | 161 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async.c | 134 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async.h | 8 |
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); |