summaryrefslogtreecommitdiff
path: root/src/providers/krb5/krb5_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/krb5/krb5_auth.c')
-rw-r--r--src/providers/krb5/krb5_auth.c147
1 files changed, 80 insertions, 67 deletions
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 0b56f3a5..e41e1a1e 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -927,59 +927,24 @@ static void krb5_auth_done(struct tevent_req *subreq)
/* If the child request failed, but did not return an offline error code,
* return with the status */
- if (res->msg_status != PAM_SUCCESS &&
- res->msg_status != PAM_AUTHINFO_UNAVAIL &&
- res->msg_status != PAM_AUTHTOK_LOCK_BUSY &&
- res->msg_status != PAM_NEW_AUTHTOK_REQD) {
- state->pam_status = res->msg_status;
- state->dp_err = DP_ERR_OK;
- ret = EOK;
- goto done;
- } else {
- state->pam_status = res->msg_status;
- }
-
- /* If the password is expired we can safely remove the ccache from the
- * cache and disk if it is not actively used anymore. This will allow to
- * create a new random ccache if sshd with privilege separation is used. */
- if (res->msg_status == PAM_NEW_AUTHTOK_REQD) {
- if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache) {
- if (kr->old_ccname != NULL) {
- ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
- kr->old_ccname, "dummy");
- if (ret != EOK) {
- DEBUG(1, ("Failed to remove old ccache file [%s], "
- "please remove it manually.\n", kr->old_ccname));
- }
-
- ret = krb5_delete_ccname(state, state->sysdb, state->domain,
- pd->user, kr->old_ccname);
- if (ret != EOK) {
- DEBUG(1, ("krb5_delete_ccname failed.\n"));
- }
- }
+ switch (res->msg_status) {
+ case ERR_OK:
+ /* If the child request was successful and we run the first pass of the
+ * change password request just return success. */
+ if (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ state->pam_status = PAM_SUCCESS;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
}
+ break;
- state->pam_status = res->msg_status;
- state->dp_err = DP_ERR_OK;
- ret = EOK;
- goto done;
- }
-
- /* If the child request was successful and we run the first pass of the
- * change password request just return success. */
- if (res->msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- state->pam_status = PAM_SUCCESS;
- state->dp_err = DP_ERR_OK;
- ret = EOK;
- goto done;
- }
+ case ERR_NETWORK_IO:
+ if (kr->kpasswd_srv != NULL &&
+ (pd->cmd == SSS_PAM_CHAUTHTOK ||
+ pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
+ /* if using a dedicated kpasswd server for a chpass operation... */
- /* if using a dedicated kpasswd server for a chpass operation... */
- if (kr->kpasswd_srv != NULL &&
- (pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
- /* ..which is unreachable by now.. */
- if (res->msg_status == PAM_AUTHTOK_LOCK_BUSY) {
be_fo_set_port_status(state->be_ctx,
state->krb5_ctx->kpasswd_service->name,
kr->kpasswd_srv, PORT_NOT_WORKING);
@@ -995,20 +960,10 @@ static void krb5_auth_done(struct tevent_req *subreq)
}
tevent_req_set_callback(subreq, krb5_auth_resolve_done, req);
return;
- } else {
+ } else if (kr->srv != NULL) {
+ /* failed to use the KDC... */
be_fo_set_port_status(state->be_ctx,
- state->krb5_ctx->kpasswd_service->name,
- kr->kpasswd_srv, PORT_WORKING);
- }
- }
-
- /* if the KDC for auth (PAM_AUTHINFO_UNAVAIL) or
- * chpass (PAM_AUTHTOK_LOCK_BUSY) was not available while using KDC
- * also for chpass operation... */
- if (res->msg_status == PAM_AUTHINFO_UNAVAIL ||
- (kr->kpasswd_srv == NULL && res->msg_status == PAM_AUTHTOK_LOCK_BUSY)) {
- if (kr->srv != NULL) {
- be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name,
+ state->krb5_ctx->service->name,
kr->srv, PORT_NOT_WORKING);
/* ..try to resolve next KDC */
state->search_kpasswd = false;
@@ -1023,7 +978,63 @@ static void krb5_auth_done(struct tevent_req *subreq)
tevent_req_set_callback(subreq, krb5_auth_resolve_done, req);
return;
}
+ break;
+
+ case ERR_CREDS_EXPIRED:
+ /* If the password is expired we can safely remove the ccache from the
+ * cache and disk if it is not actively used anymore. This will allow
+ * to create a new random ccache if sshd with privilege separation is
+ * used. */
+ if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache) {
+ if (kr->old_ccname != NULL) {
+ ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
+ kr->old_ccname, "dummy");
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to remove old ccache file [%s], "
+ "please remove it manually.\n", kr->old_ccname));
+ }
+
+ ret = krb5_delete_ccname(state, state->sysdb, state->domain,
+ pd->user, kr->old_ccname);
+ if (ret != EOK) {
+ DEBUG(1, ("krb5_delete_ccname failed.\n"));
+ }
+ }
+ }
+
+ state->pam_status = PAM_NEW_AUTHTOK_REQD;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
+
+ case ERR_NO_CREDS:
+ state->pam_status = PAM_CRED_UNAVAIL;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
+
+ case ERR_AUTH_FAILED:
+ state->pam_status = PAM_AUTH_ERR;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
+
+ default:
+ state->pam_status = PAM_SYSTEM_ERR;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
+ }
+
+ if (kr->kpasswd_srv != NULL &&
+ (pd->cmd == SSS_PAM_CHAUTHTOK ||
+ pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
+ /* found a dedicated kpasswd server for a chpass operation */
+ be_fo_set_port_status(state->be_ctx,
+ state->krb5_ctx->service->name,
+ kr->kpasswd_srv, PORT_WORKING);
} else if (kr->srv != NULL) {
+ /* found a KDC */
be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name,
kr->srv, PORT_WORKING);
}
@@ -1062,11 +1073,13 @@ static void krb5_auth_done(struct tevent_req *subreq)
goto done;
}
- if (res->msg_status == PAM_SUCCESS &&
- dp_opt_get_int(kr->krb5_ctx->opts, KRB5_RENEW_INTERVAL) > 0 &&
- (pd->cmd == SSS_PAM_AUTHENTICATE || pd->cmd == SSS_CMD_RENEW ||
+ if (res->msg_status == ERR_OK &&
+ (dp_opt_get_int(kr->krb5_ctx->opts, KRB5_RENEW_INTERVAL) > 0) &&
+ (pd->cmd == SSS_PAM_AUTHENTICATE ||
+ pd->cmd == SSS_CMD_RENEW ||
pd->cmd == SSS_PAM_CHAUTHTOK) &&
- res->tgtt.renew_till > res->tgtt.endtime && kr->ccname != NULL) {
+ (res->tgtt.renew_till > res->tgtt.endtime) &&
+ (kr->ccname != NULL)) {
DEBUG(7, ("Adding [%s] for automatic renewal.\n", kr->ccname));
ret = add_tgt_to_renew_table(kr->krb5_ctx, kr->ccname, &(res->tgtt),
pd, kr->upn);