summaryrefslogtreecommitdiff
path: root/src/providers/krb5/krb5_auth.c
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-11-22 16:34:18 -0500
committerJakub Hrozek <jhrozek@redhat.com>2013-03-04 23:40:39 +0100
commitc6872e79e8496fd075e20aec0343ade99cca725c (patch)
tree3440487b6a82ad8a331d6398fae4e1cff037544e /src/providers/krb5/krb5_auth.c
parente1e429c89e70fddcad4210375aacd1e339e6d071 (diff)
downloadsssd-c6872e79e8496fd075e20aec0343ade99cca725c.tar.gz
sssd-c6872e79e8496fd075e20aec0343ade99cca725c.tar.bz2
sssd-c6872e79e8496fd075e20aec0343ade99cca725c.zip
Cleanup error message handling for krb5 child
Use the new internal SSSD errors, to simplify error handling. Instead of using up to 3 different error types (system, krb5 and pam_status), collapse all error reporting into one error type mapped on errno_t. The returned error can contain either SSSD internal errors, kerberos errors or system errors, they all use different number spaces so there is no overlap and they can be safely merged. This means that errors being sent from the child to the parent are not pam status error messages anymore. The callers have been changed to properly deal with that. Also note that this patch removes returning SSS_PAM_SYSTEM_INFO from the krb5_child for kerberos errors as all it was doing was simply to make the parent emit the same debug log already emitted by the child, and the code is simpler if we do not do that.
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);