summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-11-22 16:34:18 -0500
committerSimo Sorce <simo@redhat.com>2013-01-04 14:40:54 -0500
commitc8febcca6b0c1e3430b6abb4eb14564e33380e54 (patch)
treeca2045590ba939ba6e06e491061079a9eeed05d8
parente74d221abc5fc4f8db25cda04998bd2d9a63134e (diff)
downloadsssd-c8febcca6b0c1e3430b6abb4eb14564e33380e54.tar.gz
sssd-c8febcca6b0c1e3430b6abb4eb14564e33380e54.tar.xz
sssd-c8febcca6b0c1e3430b6abb4eb14564e33380e54.zip
Cleanup error message handling for krb5 childmy-master
Use the new internal SSSD errors, to simplify error handling. Instad of having up to 3 different errors to care about (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 differen number spaces so there is no overlap and tey can be safely merged. This means the errors bein sent from the child to the parent is not a pam status error message anymore. The parent properly deals with that. Also not 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.
-rw-r--r--src/providers/krb5/krb5_child.c388
-rw-r--r--src/util/util_errors.c4
-rw-r--r--src/util/util_errors.h5
3 files changed, 166 insertions, 231 deletions
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 4835da06..18391e57 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -525,9 +525,11 @@ create_ccache(uid_t uid, gid_t gid, krb5_context ctx,
return EINVAL; /* Should never get here */
}
-static errno_t pack_response_packet(struct response *resp, int status,
- struct pam_data *pd)
+static errno_t pack_response_packet(TALLOC_CTX *mem_ctx, errno_t error,
+ struct response_data *resp_list,
+ uint8_t **_buf, size_t *_len)
{
+ uint8_t *buf;
size_t size = 0;
size_t p = 0;
struct response_data *pdr;
@@ -544,116 +546,69 @@ static errno_t pack_response_packet(struct response *resp, int status,
size = sizeof(int32_t);
- pdr = pd->resp_list;
- while (pdr != NULL) {
+ for (pdr = resp_list; pdr != NULL; pdr = pdr->next) {
size += 2*sizeof(int32_t) + pdr->len;
- pdr = pdr->next;
}
- resp->buf = talloc_array(resp, uint8_t, size);
- if (!resp->buf) {
+ buf = talloc_array(mem_ctx, uint8_t, size);
+ if (!buf) {
DEBUG(1, ("Insufficient memory to create message.\n"));
return ENOMEM;
}
- SAFEALIGN_SET_INT32(&resp->buf[p], status, &p);
+ SAFEALIGN_SET_INT32(&buf[p], error, &p);
- pdr = pd->resp_list;
- while(pdr != NULL) {
- SAFEALIGN_SET_INT32(&resp->buf[p], pdr->type, &p);
- SAFEALIGN_SET_INT32(&resp->buf[p], pdr->len, &p);
- safealign_memcpy(&resp->buf[p], pdr->data, pdr->len, &p);
-
- pdr = pdr->next;
+ for (pdr = resp_list; pdr != NULL; pdr = pdr->next) {
+ SAFEALIGN_SET_INT32(&buf[p], pdr->type, &p);
+ SAFEALIGN_SET_INT32(&buf[p], pdr->len, &p);
+ safealign_memcpy(&buf[p], pdr->data, pdr->len, &p);
}
- resp->size = p;
-
DEBUG(SSSDBG_TRACE_INTERNAL, ("response packet size: [%d]\n", p));
+ *_buf = buf;
+ *_len = p;
return EOK;
}
-static struct response *prepare_response_message(struct krb5_req *kr,
- krb5_error_code kerr,
- int pam_status)
+static errno_t k5c_attach_ccname_msg(struct krb5_req *kr)
{
char *msg = NULL;
- const char *krb5_msg = NULL;
int ret;
- struct response *resp;
- resp = talloc_zero(kr, struct response);
- if (resp == NULL) {
- DEBUG(1, ("Initializing response failed.\n"));
- return NULL;
+ if (kr->ccname == NULL) {
+ DEBUG(1, ("Error obtaining ccname.\n"));
+ return ERR_INTERNAL;
}
- DEBUG(SSSDBG_TRACE_FUNC, ("Building response for result [%d]\n", kerr));
-
- if (kerr == 0) {
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- pam_status = PAM_SUCCESS;
- ret = EOK;
- } else if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
- ret = EOK;
- } else {
- if (kr->ccname == NULL) {
- DEBUG(1, ("Error obtaining ccname.\n"));
- return NULL;
- }
-
- msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
- if (msg == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- return NULL;
- }
-
- pam_status = PAM_SUCCESS;
- ret = pam_add_response(kr->pd, SSS_PAM_ENV_ITEM, strlen(msg) + 1,
- (uint8_t *) msg);
- talloc_zfree(msg);
- }
- } else {
- krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
- if (krb5_msg == NULL) {
- DEBUG(1, ("sss_krb5_get_error_message failed.\n"));
- return NULL;
- }
-
- ret = pam_add_response(kr->pd, SSS_PAM_SYSTEM_INFO,
- strlen(krb5_msg) + 1,
- (const uint8_t *) krb5_msg);
- sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
- }
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
+ msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
+ if (msg == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ return ENOMEM;
}
- ret = pack_response_packet(resp, pam_status, kr->pd);
- if (ret != EOK) {
- DEBUG(1, ("pack_response_packet failed.\n"));
- return NULL;
- }
+ ret = pam_add_response(kr->pd, SSS_PAM_ENV_ITEM,
+ strlen(msg) + 1, (uint8_t *)msg);
+ talloc_zfree(msg);
- return resp;
+ return ret;
}
-static errno_t k5c_send_data(struct krb5_req *kr, int fd,
- krb5_error_code kerr, int status)
+static errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error)
{
- struct response *resp;
size_t written;
+ uint8_t *buf;
+ size_t len;
int ret;
- resp = prepare_response_message(kr, kerr, status);
- if (resp == NULL) {
- DEBUG(1, ("prepare_response_message failed.\n"));
- return ENOMEM;
+ ret = pack_response_packet(kr, error, kr->pd->resp_list, &buf, &len);
+ if (ret != EOK) {
+ DEBUG(1, ("pack_response_packet failed.\n"));
+ return ret;
}
errno = 0;
- written = sss_atomic_write_s(fd, resp->buf, resp->size);
+ written = sss_atomic_write_s(fd, buf, len);
if (written == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
@@ -661,10 +616,10 @@ static errno_t k5c_send_data(struct krb5_req *kr, int fd,
return ret;
}
- if (written != resp->size) {
+ if (written != len) {
DEBUG(SSSDBG_CRIT_FAILURE,
("Write error, wrote [%d] bytes, expected [%d]\n",
- written, resp->size));
+ written, len));
return EOK;
}
@@ -915,10 +870,9 @@ done:
static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
char *password)
{
- krb5_error_code kerr = 0;
- int ret;
const char *realm_name;
int realm_length;
+ krb5_error_code kerr;
kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx, kr->options,
@@ -956,10 +910,10 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
/* We drop root privileges which were needed to read the keytab file
* for the validation of the credentials or for FAST here to run the
* ccache I/O operations with user privileges. */
- ret = become_user(kr->uid, kr->gid);
- if (ret != EOK) {
+ kerr = become_user(kr->uid, kr->gid);
+ if (kerr != 0) {
DEBUG(1, ("become_user failed.\n"));
- return ret;
+ return kerr;
}
}
@@ -972,8 +926,8 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
goto done;
}
- ret = add_ticket_times_and_upn_to_response(kr);
- if (ret != EOK) {
+ kerr = add_ticket_times_and_upn_to_response(kr);
+ if (kerr != 0) {
DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
}
@@ -986,59 +940,46 @@ done:
}
-static int kerr_handle_error(krb5_error_code kerr)
+static errno_t map_krb5_error(krb5_error_code kerr)
{
- int pam_status;
-
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+
switch (kerr) {
- case KRB5_LIBOS_CANTREADPWD:
- pam_status = PAM_CRED_UNAVAIL;
- break;
- case KRB5_KDC_UNREACH:
- pam_status = PAM_AUTHINFO_UNAVAIL;
- break;
- case KRB5KDC_ERR_KEY_EXP:
- pam_status = PAM_NEW_AUTHTOK_REQD;
- break;
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- pam_status = PAM_AUTH_ERR;
- break;
- case KRB5_PREAUTH_FAILED:
- case KRB5KDC_ERR_PREAUTH_FAILED:
- pam_status = PAM_CRED_ERR;
- break;
- default:
- pam_status = PAM_SYSTEM_ERR;
- break;
- }
+ case 0:
+ return ERR_OK;
- return pam_status;
-}
+ case KRB5_LIBOS_CANTREADPWD:
+ return ERR_NO_CREDS;
-static int kerr_to_status(krb5_error_code kerr)
-{
- if (kerr == 0) {
- return PAM_SUCCESS;
- }
+ case KRB5_KDC_UNREACH:
+ return ERR_NETWORK_IO;
+
+ case KRB5KDC_ERR_KEY_EXP:
+ return ERR_CREDS_EXPIRED;
+
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ case KRB5_PREAUTH_FAILED:
+ case KRB5KDC_ERR_PREAUTH_FAILED:
+ return ERR_AUTH_FAILED;
- return kerr_handle_error(kerr);
+ default:
+ return kerr;
+ }
}
-static errno_t changepw_child(struct krb5_req *kr, int *_status)
+static errno_t changepw_child(struct krb5_req *kr, bool prelim)
{
int ret;
krb5_error_code kerr = 0;
char *pass_str = NULL;
char *newpass_str = NULL;
- int pam_status = PAM_SYSTEM_ERR;
int result_code = -1;
krb5_data result_code_string;
krb5_data result_string;
char *user_error_message = NULL;
size_t user_resp_len;
uint8_t *user_resp;
- krb5_prompter_fct prompter = sss_krb5_prompter;
+ krb5_prompter_fct prompter = NULL;
const char *realm_name;
int realm_length;
krb5_get_init_creds_opt *chagepw_options;
@@ -1046,28 +987,25 @@ static errno_t changepw_child(struct krb5_req *kr, int *_status)
DEBUG(SSSDBG_TRACE_LIBS, ("Password change operation\n"));
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
- pam_status = PAM_CRED_INSUFFICIENT;
- kerr = KRB5KRB_ERR_GENERIC;
- goto done;
+ return ERR_INVALID_CRED_TYPE;
}
pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
kr->pd->authtok_size);
if (pass_str == NULL) {
DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto done;
+ return ENOMEM;
}
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ if (!prelim) {
/* We do not need a password expiration warning here. */
- prompter = NULL;
+ prompter = sss_krb5_prompter;
}
kerr = get_changepw_options(kr->ctx, &chagepw_options);
if (kerr != 0) {
DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n"));
- goto done;
+ return kerr;
}
sss_krb5_princ_realm(kr->ctx, kr->princ, &realm_name, &realm_length);
@@ -1080,29 +1018,27 @@ static errno_t changepw_child(struct krb5_req *kr, int *_status)
chagepw_options);
sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
if (kerr != 0) {
- pam_status = kerr_handle_error(kerr);
- goto done;
+ return kerr;
}
memset(pass_str, 0, kr->pd->authtok_size);
talloc_zfree(pass_str);
memset(kr->pd->authtok, 0, kr->pd->authtok_size);
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ if (prelim) {
DEBUG(SSSDBG_TRACE_LIBS,
("Initial authentication for change password operation "
"successful.\n"));
krb5_free_cred_contents(kr->ctx, kr->creds);
- pam_status = PAM_SUCCESS;
- goto done;
+ return EOK;
}
newpass_str = talloc_strndup(kr, (const char *) kr->pd->newauthtok,
kr->pd->newauthtok_size);
if (newpass_str == NULL) {
DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto done;
+ krb5_free_cred_contents(kr->ctx, kr->creds);
+ return ENOMEM;
}
memset(&result_code_string, 0, sizeof(krb5_data));
@@ -1111,15 +1047,12 @@ static errno_t changepw_child(struct krb5_req *kr, int *_status)
&result_code_string, &result_string);
if (kerr == KRB5_KDC_UNREACH) {
- pam_status = PAM_AUTHTOK_LOCK_BUSY;
- goto done;
+ return ERR_NETWORK_IO;
}
if (kerr != 0 || result_code != 0) {
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- } else {
- kerr = KRB5KRB_ERR_GENERIC;
}
if (result_code_string.length > 0) {
@@ -1157,107 +1090,105 @@ static errno_t changepw_child(struct krb5_req *kr, int *_status)
}
}
- pam_status = PAM_AUTHTOK_ERR;
- goto done;
+ return ERR_CHPASS_FAILED;
}
krb5_free_cred_contents(kr->ctx, kr->creds);
kerr = get_and_save_tgt(kr, newpass_str);
+
memset(newpass_str, 0, kr->pd->newauthtok_size);
talloc_zfree(newpass_str);
memset(kr->pd->newauthtok, 0, kr->pd->newauthtok_size);
- pam_status = kerr_to_status(kerr);
-
-done:
- *_status = pam_status;
- return ret;
+ if (kerr == 0) {
+ kerr = k5c_attach_ccname_msg(kr);
+ }
+ return map_krb5_error(kerr);
}
-static errno_t tgt_req_child(struct krb5_req *kr, int *_status)
+static errno_t tgt_req_child(struct krb5_req *kr)
{
- int ret;
- krb5_error_code kerr = 0;
- char *pass_str = NULL;
- int pam_status = PAM_SYSTEM_ERR;
krb5_get_init_creds_opt *chagepw_options;
+ krb5_error_code kerr;
+ char *pass_str;
+ int ret;
DEBUG(SSSDBG_TRACE_LIBS, ("Attempting to get a TGT\n"));
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
- DEBUG(SSSDBG_OP_FAILURE, ("Unknown authtok type\n"));
- pam_status = PAM_CRED_INSUFFICIENT;
- kerr = KRB5KRB_ERR_GENERIC;
- goto done;
+ return ERR_INVALID_CRED_TYPE;
}
pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
kr->pd->authtok_size);
if (pass_str == NULL) {
DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto done;
+ return ENOMEM;
}
kerr = get_and_save_tgt(kr, pass_str);
+ if (kerr != KRB5KDC_ERR_KEY_EXP) {
+ if (kerr == 0) {
+ kerr = k5c_attach_ccname_msg(kr);
+ }
+ ret = map_krb5_error(kerr);
+ goto done;
+ }
+
/* If the password is expired the KDC will always return
KRB5KDC_ERR_KEY_EXP regardless if the supplied password is correct or
not. In general the password can still be used to get a changepw ticket.
So we validate the password by trying to get a changepw ticket. */
- if (kerr == KRB5KDC_ERR_KEY_EXP) {
- DEBUG(SSSDBG_TRACE_LIBS, ("Password was expired\n"));
- kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx,
- kr->options,
- NULL, NULL);
- if (kerr != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
- DEBUG(1, ("Failed to unset expire callback, continue ...\n"));
- }
+ DEBUG(SSSDBG_TRACE_LIBS, ("Password was expired\n"));
+ kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx,
+ kr->options,
+ NULL, NULL);
+ if (kerr != 0) {
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+ DEBUG(1, ("Failed to unset expire callback, continue ...\n"));
+ }
- kerr = get_changepw_options(kr->ctx, &chagepw_options);
- if (kerr != 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n"));
- goto done;
- }
+ kerr = get_changepw_options(kr->ctx, &chagepw_options);
+ if (kerr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n"));
+ return kerr;
+ }
- kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- pass_str, sss_krb5_prompter, kr, 0,
- SSSD_KRB5_CHANGEPW_PRINCIPAL,
- chagepw_options);
+ kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
+ pass_str, sss_krb5_prompter, kr, 0,
+ SSSD_KRB5_CHANGEPW_PRINCIPAL,
+ chagepw_options);
- sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
+ sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
- krb5_free_cred_contents(kr->ctx, kr->creds);
- if (kerr == 0) {
- kerr = KRB5KDC_ERR_KEY_EXP;
- }
+ krb5_free_cred_contents(kr->ctx, kr->creds);
+ if (kerr == 0) {
+ ret = ERR_CREDS_EXPIRED;
+ } else {
+ ret = map_krb5_error(kerr);
}
+done:
+
memset(pass_str, 0, kr->pd->authtok_size);
talloc_zfree(pass_str);
memset(kr->pd->authtok, 0, kr->pd->authtok_size);
- pam_status = kerr_to_status(kerr);
-
-done:
- *_status = pam_status;
return ret;
}
-static errno_t kuserok_child(struct krb5_req *kr, int *_status)
+static errno_t kuserok_child(struct krb5_req *kr)
{
krb5_boolean access_allowed;
- int ret;
krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Verifying if principal can log in as user\n"));
/* krb5_kuserok tries to verify that kr->pd->user is a locally known
* account, so we have to unset _SSS_LOOPS to make getpwnam() work. */
- ret = unsetenv("_SSS_LOOPS");
- if (ret != EOK) {
+ if (unsetenv("_SSS_LOOPS") != 0) {
DEBUG(1, ("Failed to unset _SSS_LOOPS, "
"krb5_kuserok will most certainly fail.\n"));
}
@@ -1272,32 +1203,31 @@ static errno_t kuserok_child(struct krb5_req *kr, int *_status)
DEBUG(SSSDBG_TRACE_LIBS,
("Access was %s\n", access_allowed ? "allowed" : "denied"));
- *_status = access_allowed ? 0 : 1;
- return ret;
+ if (access_allowed) {
+ return EOK;
+ }
+
+ return ERR_AUTH_DENIED;
}
-static errno_t renew_tgt_child(struct krb5_req *kr, int *_status)
+static errno_t renew_tgt_child(struct krb5_req *kr)
{
- int ret;
- int status = PAM_AUTHTOK_ERR;
- int kerr;
char *ccname;
krb5_ccache ccache = NULL;
+ krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Renewing a ticket\n"));
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_CCFILE) {
DEBUG(1, ("Unsupported authtok type for TGT renewal [%d].\n",
kr->pd->authtok_type));
- kerr = EINVAL;
- goto done;
+ return ERR_INVALID_CRED_TYPE;
}
ccname = talloc_strndup(kr, (char *) kr->pd->authtok, kr->pd->authtok_size);
if (ccname == NULL) {
DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = ENOMEM;
- goto done;
+ return ENOMEM;
}
kerr = krb5_cc_resolve(kr->ctx, ccname, &ccache);
@@ -1308,7 +1238,6 @@ static errno_t renew_tgt_child(struct krb5_req *kr, int *_status)
kerr = krb5_get_renewed_creds(kr->ctx, kr->creds, kr->princ, ccache, NULL);
if (kerr != 0) {
- status = kerr_handle_error(kerr);
goto done;
}
@@ -1327,10 +1256,9 @@ static errno_t renew_tgt_child(struct krb5_req *kr, int *_status)
/* We drop root privileges which were needed to read the keytab file
* for the validation of the credentials or for FAST here to run the
* ccache I/O operations with user privileges. */
- ret = become_user(kr->uid, kr->gid);
- if (ret != EOK) {
+ kerr = become_user(kr->uid, kr->gid);
+ if (kerr != 0) {
DEBUG(1, ("become_user failed.\n"));
- kerr = ret;
goto done;
}
}
@@ -1347,13 +1275,12 @@ static errno_t renew_tgt_child(struct krb5_req *kr, int *_status)
goto done;
}
- ret = add_ticket_times_and_upn_to_response(kr);
- if (ret != EOK) {
+ kerr = add_ticket_times_and_upn_to_response(kr);
+ if (kerr != 0) {
DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
}
- status = PAM_SUCCESS;
- kerr = 0;
+ kerr = k5c_attach_ccname_msg(kr);
done:
krb5_free_cred_contents(kr->ctx, kr->creds);
@@ -1362,26 +1289,24 @@ done:
krb5_cc_close(kr->ctx, ccache);
}
- *_status = status;
- return ret;
+ return map_krb5_error(kerr);
}
-static errno_t create_empty_ccache(struct krb5_req *kr, int *_status)
+static errno_t create_empty_ccache(struct krb5_req *kr)
{
- int ret;
- int pam_status = PAM_SUCCESS;
+ krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
- ret = create_ccache(kr->uid, kr->gid, kr->ctx,
- kr->princ, kr->ccname, NULL);
- if (ret != 0) {
- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, ret);
- pam_status = PAM_SYSTEM_ERR;
+ kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
+ kr->princ, kr->ccname, NULL);
+ if (kerr != 0) {
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+ } else {
+ kerr = k5c_attach_ccname_msg(kr);
}
- *_status = pam_status;
- return ret;
+ return map_krb5_error(kerr);
}
static errno_t unpack_buffer(uint8_t *buf, size_t size,
@@ -1892,7 +1817,6 @@ int main(int argc, const char *argv[])
int opt;
poptContext pc;
int debug_fd = -1;
- int status;
int ret;
struct poptOption long_options[] = {
@@ -1965,30 +1889,32 @@ int main(int argc, const char *argv[])
/* If we are offline, we need to create an empty ccache file */
if (offline) {
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform offline auth\n"));
- ret = create_empty_ccache(kr, &status);
+ ret = create_empty_ccache(kr);
} else {
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform online auth\n"));
- ret = tgt_req_child(kr, &status);
+ ret = tgt_req_child(kr);
}
break;
case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform password change\n"));
- ret = changepw_child(kr, &status);
+ ret = changepw_child(kr, false);
+ break;
+ case SSS_PAM_CHAUTHTOK_PRELIM:
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform password change checks\n"));
+ ret = changepw_child(kr, true);
break;
case SSS_PAM_ACCT_MGMT:
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform account management\n"));
- ret = kuserok_child(kr, &status);
+ ret = kuserok_child(kr);
break;
case SSS_CMD_RENEW:
- if (!offline) {
- DEBUG(SSSDBG_TRACE_FUNC, ("Will perform ticket renewal\n"));
- ret = renew_tgt_child(kr, &status);
- } else {
+ if (offline) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot renew TGT while offline\n"));
ret = KRB5_KDC_UNREACH;
goto done;
}
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform ticket renewal\n"));
+ ret = renew_tgt_child(kr);
break;
default:
DEBUG(1, ("PAM command [%d] not supported.\n", kr->pd->cmd));
@@ -1996,7 +1922,7 @@ int main(int argc, const char *argv[])
goto done;
}
- ret = k5c_send_data(kr, STDOUT_FILENO, ret, status);
+ ret = k5c_send_data(kr, STDOUT_FILENO, ret);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to send reply\n"));
}
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index c196aae3..5020fe97 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -28,10 +28,14 @@ struct err_string error_to_str[] = {
{ "Invalid Error" }, /* ERR_INVALID */
{ "Internal Error" }, /* ERR_INTERNAL */
{ "Account Unknown" }, /* ERR_ACCOUNT_UNKNOWN */
+ { "Invalid credential type" }, /* ERR_INVALID_CRED_TYPE */
+ { "No credentials available" }, /* ERR_NO_CREDS */
+ { "Credentials are expired" }, /* ERR_CREDS_EXPIRED */
{ "No cached credentials available" }, /* ERR_NO_CACHED_CREDS */
{ "Cached credentials are expired" }, /* ERR_CACHED_CREDS_EXPIRED */
{ "Authentication Denied" }, /* ERR_AUTH_DENIED */
{ "Authentication Failed" }, /* ERR_AUTH_DENIED */
+ { "Network I/O Error" }, /* ERR_NETWORK_IO */
};
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index 870d9d44..9292c995 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -50,10 +50,15 @@ enum sssd_errors {
ERR_INVALID = ERR_BASE + 0,
ERR_INTERNAL,
ERR_ACCOUNT_UNKNOWN,
+ ERR_INVALID_CRED_TYPE,
+ ERR_NO_CREDS,
+ ERR_CREDS_EXPIRED,
ERR_NO_CACHED_CREDS,
ERR_CACHED_CREDS_EXPIRED,
ERR_AUTH_DENIED,
ERR_AUTH_FAILED,
+ ERR_CHPASS_FAILED,
+ ERR_NETWORK_IO,
ERR_LAST /* ALWAYS LAST */
};