pamsrv_cmd.c revision 5cda8428d23266aaaf4d7cddba50311202365c16
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/*
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SSSD
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM Responder
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek Copyright (C) Sumit Bose <sbose@redhat.com> 2009
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek This program is free software; you can redistribute it and/or modify
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek it under the terms of the GNU General Public License as published by
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek the Free Software Foundation; either version 3 of the License, or
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (at your option) any later version.
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek This program is distributed in the hope that it will be useful,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek GNU General Public License for more details.
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek You should have received a copy of the GNU General Public License
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek*/
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include <time.h>
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "util/util.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "util/auth_utils.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "db/sysdb.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "confdb/confdb.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/common/responder_packet.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/common/responder.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/common/negcache.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "providers/data_provider.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/pam/pamsrv.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/pam/pam_helpers.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "responder/common/responder_cache_req.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#include "db/sysdb.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekenum pam_verbosity {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM_VERBOSITY_NO_MESSAGES = 0,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM_VERBOSITY_IMPORTANT,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM_VERBOSITY_INFO,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM_VERBOSITY_DEBUG
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek};
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekpam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *username);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekpam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *name,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint64_t *_value);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_reply(struct pam_auth_req *preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t pack_user_info_msg(TALLOC_CTX *mem_ctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *user_error_message,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t *resp_len,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t **_resp)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t err_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *resp;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t p;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek err_len = strlen(user_error_message);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek *resp_len = 2 * sizeof(uint32_t) + err_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = talloc_size(mem_ctx, *resp_len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_SET_UINT32(&resp[p], err_len, &p);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek safealign_memcpy(&resp[p], user_error_message, err_len, &p);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (p != *resp_len) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek *_resp = resp;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void inform_user(struct pam_data* pd, const char *pam_message)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t msg_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *msg;
2cba1c86f48db866fc72738a32eecbbdcdf3dbdbJakub Hrozek errno_t ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pack_user_info_msg(pd, pam_message, &msg_len, &msg);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (ret != EOK) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek "pack_user_info_account_expired failed.\n");
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek } else {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (ret != EOK) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek }
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek }
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek}
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozekstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek{
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek int i;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek /* If none specific domains got requested via pam, all domains are allowed.
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek * Which mimics the default/original behaviour.
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek */
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (!pd->requested_domains) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek return true;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek }
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek for (i = 0; pd->requested_domains[i]; i++) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (strcasecmp(domain_name, pd->requested_domains[i])) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek continue;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek }
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek return true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_authtok_v2(struct sss_auth_token *tok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t data_size, uint8_t *body, size_t blen,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t *c)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t auth_token_type;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t auth_token_length;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *auth_token_data;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret = EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek auth_token_length = data_size - sizeof(uint32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek auth_token_data = body+(*c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (auth_token_type) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_EMPTY:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_authtok_set_empty(tok);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_PASSWORD:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (auth_token_length == 0) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_authtok_set_empty(tok);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek } else {
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek auth_token_length);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek }
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek break;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek case SSS_AUTHTOK_TYPE_2FA:
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA,
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek auth_token_data, auth_token_length);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek break;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek case SSS_AUTHTOK_TYPE_SC_PIN:
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data,
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek auth_token_length);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek break;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek case SSS_AUTHTOK_TYPE_SC_KEYPAD:
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek sss_authtok_set_sc_keypad(tok);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek break;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek default:
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek return EINVAL;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek }
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek *c += auth_token_length;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t *c) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *str;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek str = body+(*c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (str[size-1]!='\0') return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* If the string isn't valid UTF-8, fail */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!sss_utf8_check(str, size-1)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek *c += size;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek *var = (char *) str;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t blen, size_t *c) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *name;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek if (!name) {
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek return EIO;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (strcmp(pd->user, name)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek talloc_free(pd->user);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->user = talloc_strdup(pd, name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!pd->user) return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data_v2(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *body, size_t blen)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t c;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t type;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t size;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t start;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t terminator;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek char *requested_domains;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (blen < 4*sizeof(uint32_t)+2) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32(&start, body, NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (start != SSS_START_OF_PAM_REQUEST
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek || terminator != SSS_END_OF_PAM_REQUEST) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek c = sizeof(uint32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek do {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (type == SSS_END_OF_PAM_REQUEST) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (c != blen) return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * the remaining buffer */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (size > (blen - c - sizeof(uint32_t))) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch(type) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_USER:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->logon_name, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_SERVICE:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->service, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_TTY:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = extract_string(&pd->tty, size, body, blen, &c);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_RUSER:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->ruser, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_RHOST:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->rhost, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_REQUESTED_DOMAINS:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&requested_domains, size, body, blen,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = split_on_separator(pd, requested_domains, ',', true,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek true, &pd->requested_domains,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to parse requested_domains list!\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_CLI_PID:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_uint32_t(&pd->cli_pid, size,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_AUTHTOK:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v2(pd->authtok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ITEM_NEWAUTHTOK:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v2(pd->newauthtok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Ignoring unknown data type [%d].\n", type);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek c += size;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } while(c < blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data_v3(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *body, size_t blen)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_parse_in_data_v2(pd, body, blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->cli_pid == 0) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_authtok_v1(struct sss_auth_token *tok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *body, size_t blen, size_t *c)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t auth_token_type;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t auth_token_length;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *auth_token_data;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret = EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek auth_token_data = body+(*c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (auth_token_type) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_EMPTY:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_authtok_set_empty(tok);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_PASSWORD:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek auth_token_length);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek *c += auth_token_length;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *body, size_t blen)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t start;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t end;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t last;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek last = blen - 1;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek end = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* user name */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (body[end++] != '\0') return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->logon_name = (char *) &body[start];
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (body[end++] != '\0') return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->service = (char *) &body[start];
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (body[end++] != '\0') return EINVAL;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek pd->tty = (char *) &body[start];
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (body[end++] != '\0') return EINVAL;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek pd->ruser = (char *) &body[start];
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (body[end++] != '\0') return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->rhost = (char *) &body[start];
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v1(pd->authtok, body, blen, &end);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/*=Save-Last-Login-State===================================================*/
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t set_last_login(struct pam_auth_req *preq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct sysdb_attrs *attrs;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek errno_t ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek attrs = sysdb_new_attrs(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!attrs) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto fail;
1542b85f13d72329685bdd97aa879c36d11f81beSumit Bose }
1542b85f13d72329685bdd97aa879c36d11f81beSumit Bose
3c60433641ce2e86b9b04778c8f8652ef0d097e4Stef Walter ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto fail;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sysdb_attrs_add_time_t(attrs,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek time(NULL));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto fail;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
6fdde3913a11cd6148627696fa8717c34e8460fcJan Zeleny ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek goto fail;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SYSDB_MOD_REP);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->pam_status = PAM_SYSTEM_ERR;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto fail;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->last_auth_saved = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->callback(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozekfail:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t filter_responses(struct confdb_ctx *cdb,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct response_data *resp_list)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct response_data *resp;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek uint32_t user_info_type;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int64_t expire_date;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int pam_verbosity;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &pam_verbosity);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to read PAM verbosity, not fatal.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_verbosity = DEFAULT_PAM_VERBOSITY;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = resp_list;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek while(resp != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp->type == SSS_PAM_USER_INFO) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp->len < sizeof(uint32_t)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp->do_not_send_to_client = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = resp->next;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek continue;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
129310e872a0a70e721ba59363e518176ef406d6Jakub Hrozek memcpy(&user_info_type, resp->data, sizeof(uint32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp->do_not_send_to_client = false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (user_info_type) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_USER_INFO_OFFLINE_AUTH:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User info offline auth entry is "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "too short.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&expire_date, resp->data + sizeof(uint32_t),
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sizeof(int64_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if ((expire_date == 0 &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_verbosity < PAM_VERBOSITY_INFO) ||
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (expire_date > 0 &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_verbosity < PAM_VERBOSITY_IMPORTANT)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp->do_not_send_to_client = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User info type [%d] not filtered.\n",
129310e872a0a70e721ba59363e518176ef406d6Jakub Hrozek user_info_type);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else if (resp->type & SSS_SERVER_INFO) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp->do_not_send_to_client = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = resp->next;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct timeval tv, void *pvt)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_auth_req *preq;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq = talloc_get_type(pvt, struct pam_auth_req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_reply(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t get_password_for_cache_auth(struct sss_auth_token *authtok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char **password)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t pw_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *fa2;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t fa2_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (sss_authtok_get_type(authtok)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_PASSWORD:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_authtok_get_password(authtok, password, NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_AUTHTOK_TYPE_2FA:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_authtok_get_2fa(authtok, password, &pw_len, &fa2, &fa2_len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Unsupported auth token type [%d].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_authtok_get_type(authtok));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = EINVAL;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek time_t expire_date, time_t delayed_until, bool cached_auth);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_reply(struct pam_auth_req *preq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct cli_ctx *cctx;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct cli_protocol *prctx;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek uint8_t *body;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek size_t blen;
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int32_t resp_c;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int32_t resp_size;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek struct response_data *resp;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek int p;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek struct timeval tv;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek struct tevent_timer *te;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek struct pam_data *pd;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek struct pam_ctx *pctx;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek uint32_t user_info_type;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek time_t exp_date = -1;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek time_t delay_until = -1;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek char* pam_account_expired_message;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek char* pam_account_locked_message;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek int pam_verbosity;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek pd = preq->pd;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek cctx = preq->cctx;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek prctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &pam_verbosity);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to read PAM verbosity, not fatal.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_verbosity = DEFAULT_PAM_VERBOSITY;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "pam_reply called with result [%d]: %s.\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->pam_status, pam_strerror(NULL, pd->pam_status));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->pam_status == PAM_AUTHINFO_UNAVAIL || preq->use_cached_auth) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch(pd->cmd) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_AUTHENTICATE:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if ((preq->domain != NULL) &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (preq->domain->cache_credentials == true) &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (pd->offline_auth == false)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *password = NULL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek bool use_cached_auth;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* backup value of preq->use_cached_auth*/
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek use_cached_auth = preq->use_cached_auth;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* set to false to avoid entering this branch when pam_reply()
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * is recursively called from pam_handle_cached_login() */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->use_cached_auth = false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* do auth with offline credentials */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->offline_auth = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->domain->sysdb == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Fatal: Sysdb CTX not found for domain"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek " [%s]!\n", preq->domain->name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
b7b50b21d2254a079b1b1c299909483d23db1512Sumit Bose }
b7b50b21d2254a079b1b1c299909483d23db1512Sumit Bose
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = get_password_for_cache_auth(pd->authtok, &password);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "get_password_and_type_for_cache_auth failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
2913240aee51ce81195148a4d814e967f66839c4Simo Sorce ret = sysdb_cache_auth(preq->domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->user, password,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pctx->rctx->cdb, false,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &exp_date, &delay_until);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_handle_cached_login(preq, ret, exp_date, delay_until,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek use_cached_auth);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_CHAUTHTOK_PRELIM:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_CHAUTHTOK:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Password change not possible while offline.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->pam_status = PAM_AUTHTOK_ERR;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (const uint8_t *) &user_info_type);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/* TODO: we need the pam session cookie here to make sure that cached
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * authentication was successful */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_SETCRED:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_ACCT_MGMT:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_OPEN_SESSION:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case SSS_PAM_CLOSE_SESSION:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Assuming offline authentication setting status for "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "pam call %d to PAM_SUCCESS.\n", pd->cmd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->pam_status = PAM_SUCCESS;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->pam_status = PAM_MODULE_UNKNOWN;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->pam_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_null_last_online_auth_with_curr_token(preq->domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->user);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "sysdb_null_last_online_auth_with_curr_token failed: "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "%s [%d].\n", sss_strerror(ret), ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->response_delay > 0) {
2913240aee51ce81195148a4d814e967f66839c4Simo Sorce ret = gettimeofday(&tv, NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek errno, strerror(errno));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek tv.tv_sec += pd->response_delay;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek tv.tv_usec = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->response_delay = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (te == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to add event pam_reply_delay.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* If this was a successful login, save the lastLogin time */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->cmd == SSS_PAM_AUTHENTICATE &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->pam_status == PAM_SUCCESS &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain->cache_credentials &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek !pd->offline_auth &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek !pd->last_auth_saved &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek NEED_CHECK_PROVIDER(preq->domain->provider)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = set_last_login(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_packet_new(prctx->creq, 0, sss_packet_get_cmd(prctx->creq->in),
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &prctx->creq->out);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Account expiration warning is printed for sshd. If pam_verbosity
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * is equal or above PAM_VERBOSITY_INFO then all services are informed
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * about account expiration.
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->pam_status == PAM_ACCT_EXPIRED &&
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ((pd->service != NULL && strcasecmp(pd->service, "sshd") == 0) ||
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_verbosity >= PAM_VERBOSITY_INFO)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE, "",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &pam_account_expired_message);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to get expiration message: %d:[%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret, sss_strerror(ret));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek inform_user(pd, pam_account_expired_message);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->account_locked) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek CONFDB_PAM_ACCOUNT_LOCKED_MESSAGE, "",
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek &pam_account_locked_message);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (ret != EOK) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to get expiration message: %d:[%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret, sss_strerror(ret));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek inform_user(pd, pam_account_locked_message);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->domain != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (uint8_t *) pd->domain);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_c = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_size = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = pd->resp_list;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek while(resp != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!resp->do_not_send_to_client) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_c++;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_size += resp->len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = resp->next;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_packet_grow(prctx->creq->out, sizeof(int32_t) +
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sizeof(int32_t) +
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_c * 2* sizeof(int32_t) +
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_size);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_packet_get_body(prctx->creq->out, &body, &blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA, "blen: %zu\n", blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p = 0;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &resp_c, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = pd->resp_list;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek while(resp != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!resp->do_not_send_to_client) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &resp->type, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &resp->len, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], resp->data, resp->len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += resp->len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = resp->next;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekdone:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_cmd_done(cctx, preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_dom_forwarder(struct pam_auth_req *preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek time_t expire_date, time_t delayed_until,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek bool use_cached_auth)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t resp_type;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t resp_len;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint8_t *resp;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int64_t dummy;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->pam_status = cached_login_pam_status(ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (preq->pd->pam_status) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case PAM_SUCCESS:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_len = sizeof(uint32_t) + sizeof(int64_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = talloc_size(preq->pd, resp_len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "talloc_size failed, cannot prepare user info.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(resp, &resp_type, sizeof(uint32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek dummy = (int64_t) expire_date;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (const uint8_t *) resp);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case PAM_PERM_DENIED:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (delayed_until >= 0) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_len = sizeof(uint32_t) + sizeof(int64_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp = talloc_size(preq->pd, resp_len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "talloc_size failed, cannot prepare user info.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(resp, &resp_type, sizeof(uint32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek dummy = (int64_t) delayed_until;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek (const uint8_t *) resp);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case PAM_AUTH_ERR:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Was this attempt to authenticate from cache? */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (use_cached_auth) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Don't try cached authentication again, try online check. */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Cached authentication failed for: %s\n",
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->pd->user);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->cached_auth_failed = true;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek pam_dom_forwarder(preq);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek default:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "cached login returned: %d\n", preq->pd->pam_status);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_reply(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_forwarder_cb(struct tevent_req *req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_forwarder_cert_cb(struct tevent_req *req);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *err_msg, void *ptr);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_check_user_search(struct pam_auth_req *preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_check_user_done(struct pam_auth_req *preq, int ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t pam_cmd_assume_upn(struct pam_auth_req *preq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!preq->pd->name_is_upn
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek && preq->pd->logon_name != NULL
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek && strchr(preq->pd->logon_name, '@') != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_TRACE_ALL,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "No entry found so far, trying UPN/email lookup with [%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->logon_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Assuming Kerberos principal */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain = preq->cctx->rctx->domains;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->check_provider =
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek NEED_CHECK_PROVIDER(preq->domain->provider);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->pd->user == NULL) {
2bd514cfde1938b1e245af11c9b548d58d49b325Jan Cholasta DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->name_is_upn = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->domain = NULL;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_user_search(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek pam_dom_forwarder(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOENT;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/* TODO: we should probably return some sort of cookie that is set in the
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * PAM_ENVIRONMENT, so that we can save performing some calls and cache
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek * data. */
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct cli_protocol *prctx;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek uint8_t *body;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t blen;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek errno_t ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t terminator;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek prctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek sss_packet_get_body(prctx->creq->in, &body, &blen);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (blen >= sizeof(uint32_t)) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek SAFEALIGN_COPY_UINT32(&terminator,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek body + blen - sizeof(uint32_t),
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek NULL);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (terminator != SSS_END_OF_PAM_REQUEST) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (prctx->cli_protocol_version->version) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek case 1:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_parse_in_data(pd, body, blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek case 2:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = pam_parse_in_data_v2(pd, body, blen);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek break;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek case 3:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = pam_parse_in_data_v3(pd, body, blen);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek break;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek default:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n",
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek prctx->cli_protocol_version->version);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->logon_name != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_parse_name_for_domains(pd, cctx->rctx->domains,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek cctx->rctx->default_domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->logon_name,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek &pd->domain, &pd->user);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * name is determined with the help of a certificate */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->cmd == SSS_PAM_PREAUTH
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_ctx), pd)) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = EOK;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek } else {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = ERR_NO_CREDS;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekdone:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return ret;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek}
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic int pam_auth_req_destructor(struct pam_auth_req *preq)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek{
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (preq && preq->dpreq_spy) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* If there is still a request pending, tell the spy
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek * the client is going away
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->dpreq_spy->preq = NULL;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return 0;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek}
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic bool is_uid_trusted(struct cli_creds *creds,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek size_t trusted_uids_count,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek uid_t *trusted_uids)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek{
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek errno_t ret;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* root is always trusted */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (client_euid(creds) == 0) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return true;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* All uids are allowed */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (trusted_uids_count == 0) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return true;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_allowed_uids(client_euid(creds), trusted_uids_count, trusted_uids);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) return true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic bool is_domain_public(char *name,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek char **public_dom_names,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek size_t public_dom_names_count)
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek size_t i;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for(i=0; i < public_dom_names_count; i++) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (strcasecmp(name, public_dom_names[i]) == 0) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t check_cert(TALLOC_CTX *mctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct tevent_context *ev,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_ctx *pctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_auth_req *preq,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_data *pd)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int p11_child_timeout;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const int P11_CHILD_TIMEOUT_DEFAULT = 10;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek char *cert_verification_opts;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek errno_t ret;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct tevent_req *req;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek CONFDB_PAM_P11_CHILD_TIMEOUT,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek P11_CHILD_TIMEOUT_DEFAULT,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek &p11_child_timeout);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (ret != EOK) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Failed to read p11_child_timeout from confdb: [%d]: %s\n",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret, sss_strerror(ret));
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return ret;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, mctx, CONFDB_MONITOR_CONF_ENTRY,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek CONFDB_MONITOR_CERT_VERIFICATION, NULL,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek &cert_verification_opts);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (ret != EOK) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Failed to read certificate_verification from confdb: [%d]: %s\n",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret, sss_strerror(ret));
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return ret;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek req = pam_check_cert_send(mctx, ev, pctx->p11_child_debug_fd,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek pctx->nss_db, p11_child_timeout,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek cert_verification_opts, pd);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (req == NULL) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return ENOMEM;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek tevent_req_set_callback(req, pam_forwarder_cert_cb, preq);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return EAGAIN;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek}
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek{
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct sss_domain_info *dom;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct pam_auth_req *preq;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct pam_data *pd;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek int ret;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek errno_t ncret;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct pam_ctx *pctx =
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek struct tevent_req *req;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek char *name = NULL;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek preq = talloc_zero(cctx, struct pam_auth_req);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (!preq) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_set_destructor(preq, pam_auth_req_destructor);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->cctx = cctx;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek preq->pd = create_pam_data(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!preq->pd) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_free(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek pd = preq->pd;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek preq->is_uid_trusted = is_uid_trusted(cctx->creds,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pctx->trusted_uids_count,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek pctx->trusted_uids);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!preq->is_uid_trusted) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE, "uid %"SPRIuid" is not trusted.\n",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek client_euid(cctx->creds));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->cmd = pam_cmd;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd->priv = cctx->priv;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_forwarder_parse_data(cctx, pd);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (ret == EAGAIN) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (req == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOMEM;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek tevent_req_set_callback(req, pam_forwarder_cb, preq);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret = EAGAIN;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else if (ret != EOK) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->user != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* now check user is valid */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pd->domain) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->domain = responder_get_domain(cctx->rctx, pd->domain);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (!preq->domain) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = ENOENT;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek name = sss_resp_create_fqname(preq, pctx->rctx, preq->domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->name_is_upn,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->user);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (name == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ncret = sss_ncache_check_user(pctx->rctx->ncache,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain, name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_free(name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ncret == EEXIST) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* User found in the negative cache */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (dom = preq->cctx->rctx->domains;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek dom;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek dom = get_next_domain(dom, 0)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (dom->fqnames) continue;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek name = sss_resp_create_fqname(preq, pctx->rctx, dom,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->name_is_upn,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->user);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (name == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ncret = sss_ncache_check_user(pctx->rctx->ncache,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek dom, name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_free(name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ncret == ENOENT) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* User not found in the negative cache
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * Proceed with PAM actions
2bd514cfde1938b1e245af11c9b548d58d49b325Jan Cholasta */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Try the next domain */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User [%s@%s] filtered out (negative cache). "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Trying next domain.\n", pd->user, dom->name);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!dom) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->domain = dom;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (may_do_cert_auth(pctx, pd)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_cert(cctx, cctx->ev, pctx, preq, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Finish here */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
2bd514cfde1938b1e245af11c9b548d58d49b325Jan Cholasta
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->domain->provider == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Domain [%s] has no auth provider.\n", preq->domain->name);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_user_search(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_dom_forwarder(preq);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek } else if (ret == ENOENT) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_cmd_assume_upn(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekdone:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return pam_check_user_done(preq, ret);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic void pam_forwarder_lookup_by_cert_done(struct tevent_req *req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_forwarder_cert_cb(struct tevent_req *req)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek{
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_auth_req *preq = tevent_req_callback_data(req,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_auth_req);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct cli_ctx *cctx = preq->cctx;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_data *pd;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek errno_t ret = EOK;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek char *cert;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_ctx *pctx =
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_free(req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd = preq->pd;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (cert == NULL) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (pd->logon_name == NULL) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "No certificate found and no logon name given, " \
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "authentication not possible.\n");;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = ENOENT;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek } else {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (pd->cmd == SSS_PAM_AUTHENTICATE) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "No certificate returned, authentication failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_user_search(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_dom_forwarder(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pctx->rctx->ncache, 0, NULL, cert);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (req == NULL) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = ENOMEM;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek tevent_req_set_callback(req, pam_forwarder_lookup_by_cert_done, preq);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekdone:
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek pam_check_user_done(preq, ret);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek}
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek{
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek int ret;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct ldb_result *res;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct sss_domain_info *domain;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_auth_req *preq = tevent_req_callback_data(req,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_auth_req);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek const char *cert_user;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = cache_req_user_by_cert_recv(preq, req, &res, &domain, NULL);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek talloc_zfree(req);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (ret != EOK && ret != ENOENT) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (ret == EOK && res->count > 1) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "Search by certificate returned more than one result.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = EINVAL;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek goto done;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (ret == EOK) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (preq->domain == NULL) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->domain = domain;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek }
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->cert_user_obj = talloc_steal(preq, res->msgs[0]);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek if (preq->pd->logon_name == NULL) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SYSDB_NAME, NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (cert_user == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Certificate user object has not name.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA, "Found certificate user [%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek cert_user);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = add_pam_cert_response(preq->pd, cert_user, preq->token_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->domain = talloc_strdup(preq->pd, domain->name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->pd->domain == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->pam_status = PAM_SUCCESS;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_reply(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->pd->logon_name == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Missing logon name and no certificate user found.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_user_search(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_dom_forwarder(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekdone:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_check_user_done(preq, ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_forwarder_cb(struct tevent_req *req)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_auth_req *preq = tevent_req_callback_data(req,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_auth_req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct cli_ctx *cctx = preq->cctx;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_data *pd;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek errno_t ret = EOK;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_ctx *pctx =
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_dp_get_domains_recv(req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_free(req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pd = preq->pd;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_forwarder_parse_data(cctx, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EAGAIN) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (strchr(preq->pd->logon_name, '@') == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Assuming Kerberos principal */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain = preq->cctx->rctx->domains;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->pd->user == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOMEM;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->name_is_upn = true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->domain = NULL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else if (ret != EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->pd->domain) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain = responder_get_domain(cctx->rctx, preq->pd->domain);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (preq->domain == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = ENOENT;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (may_do_cert_auth(pctx, pd)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_cert(cctx, cctx->ev, pctx, preq, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Finish here */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto done;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_user_search(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (ret == EOK) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_dom_forwarder(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } else if (ret == ENOENT) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_cmd_assume_upn(preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekdone:
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_check_user_done(preq, ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_dp_send_acct_req_done(struct tevent_req *req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_check_user_search(struct pam_auth_req *preq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek{
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct sss_domain_info *dom = preq->domain;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek char *name = NULL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek time_t cacheExpire;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct tevent_req *dpreq;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct dp_callback_ctx *cb_ctx;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_ctx *pctx =
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek static const char *user_attrs[] = SYSDB_PW_ATTRS;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct ldb_message *msg;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct ldb_result *res;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *sysdb_name;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek while (dom) {
/* if it is a domainless search, skip domains that require fully
* qualified names instead */
while (dom && !preq->pd->domain && !preq->pd->name_is_upn
&& dom->fqnames) {
dom = get_next_domain(dom, 0);
}
if (!dom) break;
if (dom != preq->domain) {
/* make sure we reset the check_provider flag when we check
* a new domain */
preq->check_provider = NEED_CHECK_PROVIDER(dom->provider);
}
/* make sure to update the preq if we changed domain */
preq->domain = dom;
talloc_free(name);
name = sss_resp_create_fqname(preq, pctx->rctx, dom,
preq->pd->name_is_upn,
preq->pd->user);
if (name == NULL) {
return ENOMEM;
}
/* Refresh the user's cache entry on any PAM query
* We put a timeout in the client context so that we limit
* the number of updates within a reasonable timeout
*/
if (preq->check_provider) {
ret = pam_initgr_check_timeout(pctx->id_table,
preq->pd->logon_name);
if (ret != EOK
&& ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
"Could not look up initgroup timout\n");
return EIO;
} else if (ret == ENOENT) {
/* Call provider first */
break;
}
/* Entry is still valid, get it from the sysdb */
}
DEBUG(SSSDBG_CONF_SETTINGS, "Requesting info for [%s]\n", name);
if (dom->sysdb == NULL) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Fatal: Sysdb CTX not found for this domain!\n");
preq->pd->pam_status = PAM_SYSTEM_ERR;
return EFAULT;
}
if (preq->pd->name_is_upn) {
ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg);
if (ret == EOK) {
/* Since sysdb_search_user_by_upn() searches the whole cache we
* have to set the domain so that it matches the result. */
sysdb_name = ldb_msg_find_attr_as_string(msg,
SYSDB_NAME, NULL);
if (sysdb_name == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cached entry has no name.\n");
return EINVAL;
}
preq->domain = find_domain_by_object_name(
get_domains_head(dom),
sysdb_name);
if (preq->domain == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Cannot find matching domain for [%s].\n",
sysdb_name);
return EINVAL;
}
}
} else {
ret = sysdb_getpwnam_with_views(preq, dom, name, &res);
if (res->count > 1) {
DEBUG(SSSDBG_FATAL_FAILURE,
"getpwnam call returned more than one result !?!\n");
sss_log(SSS_LOG_ERR,
"More users have the same name [%s@%s] in SSSD cache. "
"SSSD will not work correctly.\n",
name, dom->name);
return ENOENT;
} else if (res->count == 0) {
ret = ENOENT;
} else {
msg = res->msgs[0];
}
}
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to make request to our cache!\n");
return EIO;
}
if (ret == ENOENT) {
if (preq->check_provider == false) {
/* set negative cache only if not result of cache check */
ret = sss_ncache_set_user(pctx->rctx->ncache,
false, dom, preq->pd->user);
if (ret != EOK) {
/* Should not be fatal, just slower next time */
DEBUG(SSSDBG_MINOR_FAILURE,
"Cannot set ncache for [%s@%s]\n", name,
dom->name);
}
}
/* if a multidomain search, try with next */
if (!preq->pd->domain) {
dom = get_next_domain(dom, 0);
continue;
}
DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n");
/* TODO: store negative cache ? */
return ENOENT;
}
/* One result found */
/* if we need to check the remote account go on */
if (preq->check_provider) {
cacheExpire = ldb_msg_find_attr_as_uint64(msg,
SYSDB_CACHE_EXPIRE, 0);
if (cacheExpire < time(NULL)) {
break;
}
}
DEBUG(SSSDBG_TRACE_FUNC,
"Returning info for user [%s@%s]\n", name, dom->name);
/* We might have searched by alias. Pass on the primary name */
ret = pd_set_primary_name(msg, preq->pd);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not canonicalize username\n");
return ret;
}
return EOK;
}
if (!dom) {
/* Ensure that we don't try to check a provider without a domain,
* since this will cause a NULL-dereference below.
*/
preq->check_provider = false;
}
if (preq->check_provider) {
/* dont loop forever :-) */
preq->check_provider = false;
dpreq = sss_dp_get_account_send(preq, preq->cctx->rctx,
dom, false, SSS_DP_INITGROUPS, name, 0,
preq->pd->name_is_upn ? EXTRA_NAME_IS_UPN : NULL);
if (!dpreq) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Out of memory sending data provider request\n");
return ENOMEM;
}
cb_ctx = talloc_zero(preq, struct dp_callback_ctx);
if(!cb_ctx) {
talloc_zfree(dpreq);
return ENOMEM;
}
cb_ctx->callback = pam_check_user_dp_callback;
cb_ctx->ptr = preq;
cb_ctx->cctx = preq->cctx;
cb_ctx->mem_ctx = preq;
tevent_req_set_callback(dpreq, pam_dp_send_acct_req_done, cb_ctx);
/* tell caller we are in an async call */
return EAGAIN;
}
DEBUG(SSSDBG_MINOR_FAILURE,
"No matching domain found for [%s], fail!\n", preq->pd->user);
return ENOENT;
}
static void pam_dp_send_acct_req_done(struct tevent_req *req)
{
struct dp_callback_ctx *cb_ctx =
tevent_req_callback_data(req, struct dp_callback_ctx);
errno_t ret;
dbus_uint16_t err_maj;
dbus_uint32_t err_min;
char *err_msg;
ret = sss_dp_get_account_recv(cb_ctx->mem_ctx, req,
&err_maj, &err_min,
&err_msg);
talloc_zfree(req);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Fatal error, killing connection!\n");
talloc_free(cb_ctx->cctx);
return;
}
cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
}
static int pam_check_user_done(struct pam_auth_req *preq, int ret)
{
switch (ret) {
case EOK:
break;
case EAGAIN:
/* performing async request, just return */
break;
case ENOENT:
preq->pd->pam_status = PAM_USER_UNKNOWN;
pam_reply(preq);
break;
case ERR_NO_CREDS:
preq->pd->pam_status = PAM_CRED_INSUFFICIENT;
pam_reply(preq);
break;
default:
preq->pd->pam_status = PAM_SYSTEM_ERR;
pam_reply(preq);
break;
}
return EOK;
}
static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
const char *err_msg, void *ptr)
{
struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req);
int ret;
struct pam_ctx *pctx =
talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
if (err_maj) {
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get information from Data Provider\n"
"Error: %u, %u, %s\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg);
}
ret = pam_check_user_search(preq);
if (ret == EOK) {
/* Make sure we don't go to the ID provider too often */
ret = pam_initgr_cache_set(pctx->rctx->ev, pctx->id_table,
preq->pd->logon_name, pctx->id_timeout);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Could not save initgr timestamp. "
"Proceeding with PAM actions\n");
/* This is non-fatal, we'll just end up going to the
* data provider again next time.
*/
}
pam_dom_forwarder(preq);
} else if (ret == ENOENT) {
ret = pam_cmd_assume_upn(preq);
}
ret = pam_check_user_done(preq, ret);
if (ret) {
preq->pd->pam_status = PAM_SYSTEM_ERR;
pam_reply(preq);
}
}
static errno_t pam_is_last_online_login_fresh(struct sss_domain_info *domain,
const char* user,
int cached_auth_timeout,
bool *_result)
{
errno_t ret;
bool result;
uint64_t last_login;
ret = pam_get_last_online_auth_with_curr_token(domain, user, &last_login);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"sysdb_get_last_online_auth_with_curr_token failed: %s:[%d]\n",
sss_strerror(ret), ret);
goto done;
}
result = time(NULL) < (last_login + cached_auth_timeout);
ret = EOK;
done:
if (ret == EOK) {
*_result = result;
}
return ret;
}
static bool pam_is_cmd_cachable(int cmd)
{
bool is_cachable;
switch(cmd) {
case SSS_PAM_AUTHENTICATE:
is_cachable = true;
break;
default:
is_cachable = false;
}
return is_cachable;
}
static bool pam_is_authtok_cachable(struct sss_auth_token *authtok)
{
enum sss_authtok_type type;
bool cachable = false;
type = sss_authtok_get_type(authtok);
if (type == SSS_AUTHTOK_TYPE_PASSWORD) {
cachable = true;
} else {
DEBUG(SSSDBG_TRACE_LIBS, "Authentication token can't be cached\n");
}
return cachable;
}
static bool pam_can_user_cache_auth(struct sss_domain_info *domain,
int pam_cmd,
struct sss_auth_token *authtok,
const char* user,
bool cached_auth_failed)
{
errno_t ret;
bool result = false;
if (!cached_auth_failed /* don't try cached auth again */
&& domain->cache_credentials
&& domain->cached_auth_timeout > 0
&& pam_is_authtok_cachable(authtok)
&& pam_is_cmd_cachable(pam_cmd)) {
ret = pam_is_last_online_login_fresh(domain, user,
domain->cached_auth_timeout,
&result);
if (ret != EOK) {
/* non-critical, consider fail as 'non-fresh value' */
DEBUG(SSSDBG_MINOR_FAILURE,
"pam_is_last_online_login_fresh failed: %s:[%d]\n",
sss_strerror(ret), ret);
}
}
return result;
}
static void pam_dom_forwarder(struct pam_auth_req *preq)
{
int ret;
struct pam_ctx *pctx =
talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
const char *cert_user;
if (!preq->pd->domain) {
preq->pd->domain = preq->domain->name;
}
/* Untrusted users can access only public domains. */
if (!preq->is_uid_trusted &&
!is_domain_public(preq->pd->domain, pctx->public_domains,
pctx->public_domains_count)) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Untrusted user %"SPRIuid" cannot access non-public domain %s.\n",
client_euid(preq->cctx->creds), preq->pd->domain);
preq->pd->pam_status = PAM_PERM_DENIED;
pam_reply(preq);
return;
}
/* skip this domain if not requested and the user is trusted
* as untrusted users can't request a domain */
if (preq->is_uid_trusted &&
!is_domain_requested(preq->pd, preq->pd->domain)) {
preq->pd->pam_status = PAM_USER_UNKNOWN;
pam_reply(preq);
return;
}
if (pam_can_user_cache_auth(preq->domain,
preq->pd->cmd,
preq->pd->authtok,
preq->pd->user,
preq->cached_auth_failed)) {
preq->use_cached_auth = true;
pam_reply(preq);
return;
}
if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_obj != NULL) {
/* Check if user matches certificate user */
cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, SYSDB_NAME,
NULL);
if (cert_user == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Certificate user object has not name.\n");
preq->pd->pam_status = PAM_USER_UNKNOWN;
pam_reply(preq);
return;
}
/* pam_check_user_search() calls pd_set_primary_name() is the search
* was successful, so pd->user contains the canonical sysdb name
* as well */
if (strcmp(cert_user, preq->pd->user) == 0) {
preq->pd->pam_status = PAM_SUCCESS;
if (preq->pd->cmd == SSS_PAM_PREAUTH) {
ret = add_pam_cert_response(preq->pd, cert_user,
preq->token_name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
}
}
preq->callback = pam_reply;
pam_reply(preq);
return;
} else {
if (preq->pd->cmd == SSS_PAM_PREAUTH) {
DEBUG(SSSDBG_TRACE_FUNC,
"User and certificate user do not match, " \
"continue with other authentication methods.\n");
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"User and certificate user do not match.\n");
preq->pd->pam_status = PAM_AUTH_ERR;
pam_reply(preq);
return;
}
}
}
if (!NEED_CHECK_PROVIDER(preq->domain->provider) ) {
preq->callback = pam_reply;
ret = LOCAL_pam_handler(preq);
}
else {
preq->callback = pam_reply;
ret = pam_dp_send_req(preq, SSS_CLI_SOCKET_TIMEOUT/2);
DEBUG(SSSDBG_CONF_SETTINGS, "pam_dp_send_req returned %d\n", ret);
}
if (ret != EOK) {
preq->pd->pam_status = PAM_SYSTEM_ERR;
pam_reply(preq);
}
}
static int pam_cmd_authenticate(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_authenticate\n");
return pam_forwarder(cctx, SSS_PAM_AUTHENTICATE);
}
static int pam_cmd_setcred(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_setcred\n");
return pam_forwarder(cctx, SSS_PAM_SETCRED);
}
static int pam_cmd_acct_mgmt(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_acct_mgmt\n");
return pam_forwarder(cctx, SSS_PAM_ACCT_MGMT);
}
static int pam_cmd_open_session(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_open_session\n");
return pam_forwarder(cctx, SSS_PAM_OPEN_SESSION);
}
static int pam_cmd_close_session(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_close_session\n");
return pam_forwarder(cctx, SSS_PAM_CLOSE_SESSION);
}
static int pam_cmd_chauthtok(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_chauthtok\n");
return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK);
}
static int pam_cmd_chauthtok_prelim(struct cli_ctx *cctx) {
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_chauthtok_prelim\n");
return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK_PRELIM);
}
static int pam_cmd_preauth(struct cli_ctx *cctx)
{
DEBUG(SSSDBG_CONF_SETTINGS, "entering pam_cmd_preauth\n");
return pam_forwarder(cctx, SSS_PAM_PREAUTH);
}
struct cli_protocol_version *register_cli_protocol_version(void)
{
static struct cli_protocol_version pam_cli_protocol_version[] = {
{3, "2009-09-14", "make cli_pid mandatory"},
{2, "2009-05-12", "new format <type><size><data>"},
{1, "2008-09-05", "initial version, \\0 terminated strings"},
{0, NULL, NULL}
};
return pam_cli_protocol_version;
}
struct sss_cmd_table *get_pam_cmds(void)
{
static struct sss_cmd_table sss_cmds[] = {
{SSS_GET_VERSION, sss_cmd_get_version},
{SSS_PAM_AUTHENTICATE, pam_cmd_authenticate},
{SSS_PAM_SETCRED, pam_cmd_setcred},
{SSS_PAM_ACCT_MGMT, pam_cmd_acct_mgmt},
{SSS_PAM_OPEN_SESSION, pam_cmd_open_session},
{SSS_PAM_CLOSE_SESSION, pam_cmd_close_session},
{SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok},
{SSS_PAM_CHAUTHTOK_PRELIM, pam_cmd_chauthtok_prelim},
{SSS_PAM_PREAUTH, pam_cmd_preauth},
{SSS_CLI_NULL, NULL}
};
return sss_cmds;
}
errno_t
pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain,
const char *username,
uint64_t value)
{
TALLOC_CTX *tmp_ctx;
struct sysdb_attrs *attrs;
int ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
attrs = sysdb_new_attrs(tmp_ctx);
if (attrs == NULL) {
ret = ENOMEM;
goto done;
}
ret = sysdb_attrs_add_time_t(attrs,
SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN,
value);
if (ret != EOK) { goto done; }
ret = sysdb_set_user_attr(domain, username, attrs, SYSDB_MOD_REP);
if (ret != EOK) { goto done; }
done:
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, sss_strerror(ret));
}
talloc_zfree(tmp_ctx);
return ret;
}
static errno_t
pam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
const char *username)
{
return pam_set_last_online_auth_with_curr_token(domain, username, 0);
}
static errno_t
pam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain,
const char *name,
uint64_t *_value)
{
TALLOC_CTX *tmp_ctx = NULL;
const char *attrs[] = { SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN, NULL };
struct ldb_message *ldb_msg;
uint64_t value;
errno_t ret;
if (name == NULL || *name == '\0') {
DEBUG(SSSDBG_CRIT_FAILURE, "Missing user name.\n");
ret = EINVAL;
goto done;
}
if (domain->sysdb == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Missing sysdb db context.\n");
ret = EINVAL;
goto done;
}
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
ret = sysdb_search_user_by_name(tmp_ctx, domain, name, attrs, &ldb_msg);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"sysdb_search_user_by_name failed [%d][%s].\n",
ret, strerror(ret));
goto done;
}
/* Check offline_auth_cache_timeout */
value = ldb_msg_find_attr_as_uint64(ldb_msg,
SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN,
0);
ret = EOK;
done:
if (ret == EOK) {
*_value = value;
}
talloc_free(tmp_ctx);
return ret;
}