static void pam_handle_cached_login(struct pam_auth_req *preq, int ret, time_t expire_date, time_t delayed_until) { uint32_t resp_type; size_t resp_len; uint8_t *resp; int64_t dummy; preq->pd->pam_status = cached_login_pam_status(ret); switch (preq->pd->pam_status) { case PAM_SUCCESS: resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH; resp_len = sizeof(uint32_t) + sizeof(int64_t); resp = talloc_size(preq->pd, resp_len); if (resp == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed, cannot prepare user info.\n"); } else { memcpy(resp, &resp_type, sizeof(uint32_t)); dummy = (int64_t) expire_date; memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t)); ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len, (const uint8_t *) resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); } } break; case PAM_PERM_DENIED: if (delayed_until >= 0) { resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED; resp_len = sizeof(uint32_t) + sizeof(int64_t); resp = talloc_size(preq->pd, resp_len); if (resp == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed, cannot prepare user info.\n"); } else { memcpy(resp, &resp_type, sizeof(uint32_t)); dummy = (int64_t) delayed_until; memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t)); ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len, (const uint8_t *) resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); } } } break; default: DEBUG(SSSDBG_TRACE_LIBS, "cached login returned: %d\n", preq->pd->pam_status); } pam_reply(preq); return; }
static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, struct sss_domain_info *domain, struct confdb_ctx *cdb, struct pam_data *pd, uid_t uid, int *pam_status, int *dp_err) { const char *password = NULL; errno_t ret; if (sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD) { DEBUG(SSSDBG_MINOR_FAILURE, "Delayed authentication is only available for password " "authentication (single factor).\n"); return; } ret = sss_authtok_get_password(pd->authtok, &password, NULL); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password [%d] %s\n", ret, strerror(ret)); *pam_status = PAM_SYSTEM_ERR; *dp_err = DP_ERR_OK; return; } ret = sysdb_cache_auth(domain, pd->user, password, cdb, true, NULL, NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Offline authentication failed\n"); *pam_status = cached_login_pam_status(ret); *dp_err = DP_ERR_OK; return; } ret = add_user_to_delayed_online_authentication(krb5_ctx, pd, uid); if (ret != EOK) { /* This error is not fatal */ DEBUG(SSSDBG_CRIT_FAILURE, "add_user_to_delayed_online_authentication failed.\n"); } *pam_status = PAM_AUTHINFO_UNAVAIL; *dp_err = DP_ERR_OFFLINE; }