pamsrv_cmd.c revision f3c2dc1f9ccdf456fd78ed96197b9bf404cc29fc
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/*
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SSSD
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen PAM Responder
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen Copyright (C) Sumit Bose <sbose@redhat.com> 2009
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen This program is free software; you can redistribute it and/or modify
06b0c3be9905099038964b068216bbed155701deTimo Sirainen it under the terms of the GNU General Public License as published by
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen the Free Software Foundation; either version 3 of the License, or
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (at your option) any later version.
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen This program is distributed in the hope that it will be useful,
06b0c3be9905099038964b068216bbed155701deTimo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
06b0c3be9905099038964b068216bbed155701deTimo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
06b0c3be9905099038964b068216bbed155701deTimo Sirainen GNU General Public License for more details.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen You should have received a copy of the GNU General Public License
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen*/
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include <time.h>
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "util/util.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "util/auth_utils.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "db/sysdb.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "confdb/confdb.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "responder/common/responder_packet.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "responder/common/responder.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "responder/common/negcache.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "providers/data_provider.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "responder/pam/pamsrv.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "responder/pam/pam_helpers.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "db/sysdb.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenenum pam_verbosity {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen PAM_VERBOSITY_NO_MESSAGES = 0,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen PAM_VERBOSITY_IMPORTANT,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen PAM_VERBOSITY_INFO,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen PAM_VERBOSITY_DEBUG
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen};
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *user_error_message,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t *resp_len,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint8_t **_resp)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size_t err_len;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint8_t *resp;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size_t p;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen err_len = strlen(user_error_message);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *resp_len = 2 * sizeof(uint32_t) + err_len;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp = talloc_size(mem_ctx, *resp_len);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (resp == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ENOMEM;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen p = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen SAFEALIGN_SET_UINT32(&resp[p], err_len, &p);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen safealign_memcpy(&resp[p], user_error_message, err_len, &p);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (p != *resp_len) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen *_resp = resp;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return EOK;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen}
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainenstatic void inform_account_expired(struct pam_data* pd,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const char *pam_message)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen size_t msg_len;
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen uint8_t *msg;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen errno_t ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pack_user_info_account_expired(pd, pam_message, &msg_len, &msg);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret != EOK) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "pack_user_info_account_expired failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret != EOK) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int i;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* If none specific domains got requested via pam, all domains are allowed.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen * Which mimics the default/original behaviour.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!pd->requested_domains) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return true;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; pd->requested_domains[i]; i++) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (strcasecmp(domain_name, pd->requested_domains[i])) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen continue;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return true;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return false;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_authtok_v2(struct sss_auth_token *tok,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t data_size, uint8_t *body, size_t blen,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t *c)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t auth_token_type;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t auth_token_length;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen uint8_t *auth_token_data;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen int ret = EOK;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen
06b0c3be9905099038964b068216bbed155701deTimo Sirainen if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
06b0c3be9905099038964b068216bbed155701deTimo Sirainen SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen auth_token_length = data_size - sizeof(uint32_t);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen auth_token_data = body+(*c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen switch (auth_token_type) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen case SSS_AUTHTOK_TYPE_EMPTY:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen sss_authtok_set_empty(tok);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen case SSS_AUTHTOK_TYPE_PASSWORD:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (auth_token_length == 0) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen sss_authtok_set_empty(tok);
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen } else {
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen auth_token_length);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen break;
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen default:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EINVAL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen *c += auth_token_length;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen size_t *c) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint8_t *str;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen str = body+(*c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (str[size-1]!='\0') return EINVAL;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen /* If the string isn't valid UTF-8, fail */
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen if (!sss_utf8_check(str, size-1)) {
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen return EINVAL;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen *c += size;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen *var = (char *) str;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EOK;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t blen, size_t *c) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EINVAL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EOK;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *name;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!name) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EIO;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strcmp(pd->user, name)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen talloc_free(pd->user);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pd->user = talloc_strdup(pd, name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!pd->user) return ENOMEM;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EOK;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int pam_parse_in_data_v2(struct pam_data *pd,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint8_t *body, size_t blen)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t c;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t type;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t start;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t terminator;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen char *requested_domains;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (blen < 4*sizeof(uint32_t)+2) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EINVAL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SAFEALIGN_COPY_UINT32(&start, body, NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (start != SSS_START_OF_PAM_REQUEST
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen || terminator != SSS_END_OF_PAM_REQUEST) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EINVAL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen c = sizeof(uint32_t);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen do {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (type == SSS_END_OF_PAM_REQUEST) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (c != blen) return EINVAL;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen } else {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen * the remaining buffer */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (size > (blen - c - sizeof(uint32_t))) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EINVAL;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen switch(type) {
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen case SSS_PAM_ITEM_USER:
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen ret = extract_string(&pd->logon_name, size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) return ret;
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_SERVICE:
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = extract_string(&pd->service, size, body, blen, &c);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (ret != EOK) return ret;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_TTY:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_string(&pd->tty, size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) return ret;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_RUSER:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_string(&pd->ruser, size, body, blen, &c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (ret != EOK) return ret;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen break;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen case SSS_PAM_ITEM_RHOST:
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = extract_string(&pd->rhost, size, body, blen, &c);
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen if (ret != EOK) return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_REQUESTED_DOMAINS:
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen ret = extract_string(&requested_domains, size, body, blen,
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen ret = split_on_separator(pd, requested_domains, ',', true,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen true, &pd->requested_domains,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen NULL);
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen if (ret != EOK) {
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen "Failed to parse requested_domains list!\n");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_CLI_PID:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_uint32_t(&pd->cli_pid, size,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen body, blen, &c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (ret != EOK) return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_ITEM_AUTHTOK:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = extract_authtok_v2(pd->authtok,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen case SSS_PAM_ITEM_NEWAUTHTOK:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_authtok_v2(pd->newauthtok,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen default:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Ignoring unknown data type [%d].\n", type);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen c += size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } while(c < blen);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EOK;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int pam_parse_in_data_v3(struct pam_data *pd,
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen uint8_t *body, size_t blen)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = pam_parse_in_data_v2(pd, body, blen);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (ret != EOK) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return ret;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (pd->cli_pid == 0) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EINVAL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return EOK;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_authtok_v1(struct sss_auth_token *tok,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint8_t *body, size_t blen, size_t *c)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint32_t auth_token_type;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen uint32_t auth_token_length;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint8_t *auth_token_data;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen int ret = EOK;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen auth_token_data = body+(*c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen switch (auth_token_type) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen case SSS_AUTHTOK_TYPE_EMPTY:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen sss_authtok_set_empty(tok);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
0546f051db6f510aa84d8c748cb46e584d3fcdfbTimo Sirainen case SSS_AUTHTOK_TYPE_PASSWORD:
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen auth_token_length);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
13a8c553f293349248b161ff851743498916e26eTimo Sirainen default:
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return EINVAL;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen }
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen *c += auth_token_length;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return ret;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen}
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainenstatic int pam_parse_in_data(struct pam_data *pd,
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen uint8_t *body, size_t blen)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen{
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen size_t start;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen size_t end;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen size_t last;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen int ret;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen last = blen - 1;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen end = 0;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen /* user name */
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (body[end++] != '\0') return EINVAL;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen pd->logon_name = (char *) &body[start];
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (body[end++] != '\0') return EINVAL;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen pd->service = (char *) &body[start];
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (body[end++] != '\0') return EINVAL;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen pd->tty = (char *) &body[start];
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (body[end++] != '\0') return EINVAL;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen pd->ruser = (char *) &body[start];
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if (body[end++] != '\0') return EINVAL;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen pd->rhost = (char *) &body[start];
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen ret = extract_authtok_v1(pd->authtok, body, blen, &end);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (ret) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return EOK;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen/*=Save-Last-Login-State===================================================*/
eeea0a402bcd9533e9e359f2a2518e3216162151Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic errno_t set_last_login(struct pam_auth_req *preq)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct sysdb_attrs *attrs;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen errno_t ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen attrs = sysdb_new_attrs(preq);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!attrs) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = ENOMEM;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen goto fail;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ret != EOK) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen goto fail;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ret != EOK) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen goto fail;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen SYSDB_MOD_REP);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen preq->pd->pam_status = PAM_SYSTEM_ERR;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen goto fail;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen preq->pd->last_auth_saved = true;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen preq->callback(preq);
0546f051db6f510aa84d8c748cb46e584d3fcdfbTimo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return EOK;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenfail:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic errno_t filter_responses(struct confdb_ctx *cdb,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct response_data *resp_list)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen int ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct response_data *resp;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen uint32_t user_info_type;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen int64_t expire_date;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int pam_verbosity;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &pam_verbosity);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) {
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen "Failed to read PAM verbosity, not fatal.\n");
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen pam_verbosity = DEFAULT_PAM_VERBOSITY;
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen }
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp = resp_list;
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen while(resp != NULL) {
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen if (resp->type == SSS_PAM_USER_INFO) {
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen if (resp->len < sizeof(uint32_t)) {
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EINVAL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp->do_not_send_to_client = true;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp = resp->next;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen continue;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(&user_info_type, resp->data, sizeof(uint32_t));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp->do_not_send_to_client = false;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen switch (user_info_type) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case SSS_PAM_USER_INFO_OFFLINE_AUTH:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "User info offline auth entry is "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "too short.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EINVAL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(&expire_date, resp->data + sizeof(uint32_t),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sizeof(int64_t));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((expire_date == 0 &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pam_verbosity < PAM_VERBOSITY_INFO) ||
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (expire_date > 0 &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pam_verbosity < PAM_VERBOSITY_IMPORTANT)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp->do_not_send_to_client = true;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen default:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "User info type [%d] not filtered.\n",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen user_info_type);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (resp->type & SSS_SERVER_INFO) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp->do_not_send_to_client = true;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp = resp->next;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return EOK;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct timeval tv, void *pvt)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct pam_auth_req *preq;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen preq = talloc_get_type(pvt, struct pam_auth_req);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen pam_reply(preq);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen time_t expire_date, time_t delayed_until);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct cli_ctx *cctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint8_t *body;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size_t blen;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int32_t resp_c;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int32_t resp_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct response_data *resp;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int p;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct timeval tv;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct tevent_timer *te;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct pam_data *pd;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct pam_ctx *pctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t user_info_type;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen time_t exp_date = -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen time_t delay_until = -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen char* pam_account_expired_message;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int pam_verbosity;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen pd = preq->pd;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen cctx = preq->cctx;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &pam_verbosity);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ret != EOK) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Failed to read PAM verbosity, not fatal.\n");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen pam_verbosity = DEFAULT_PAM_VERBOSITY;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_FUNC_DATA,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "pam_reply called with result [%d].\n", pd->pam_status);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen switch(pd->cmd) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen case SSS_PAM_AUTHENTICATE:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if ((preq->domain != NULL) &&
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (preq->domain->cache_credentials == true) &&
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (pd->offline_auth == false)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *password = NULL;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* do auth with offline credentials */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen pd->offline_auth = true;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (preq->domain->sysdb == NULL) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Fatal: Sysdb CTX not found for domain"
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen " [%s]!\n", preq->domain->name);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen goto done;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = sss_authtok_get_password(pd->authtok, &password, NULL);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (ret) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen goto done;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = sysdb_cache_auth(preq->domain,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pd->user, password,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pctx->rctx->cdb, false,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen &exp_date, &delay_until);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pam_handle_cached_login(preq, ret, exp_date, delay_until);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen break;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen case SSS_PAM_CHAUTHTOK_PRELIM:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen case SSS_PAM_CHAUTHTOK:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_FUNC_DATA,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Password change not possible while offline.\n");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen pd->pam_status = PAM_AUTHTOK_ERR;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (const uint8_t *) &user_info_type);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ret != EOK) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen goto done;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen break;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen/* TODO: we need the pam session cookie here to make sure that cached
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen * authentication was successful */
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen case SSS_PAM_SETCRED:
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen case SSS_PAM_ACCT_MGMT:
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen case SSS_PAM_OPEN_SESSION:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen case SSS_PAM_CLOSE_SESSION:
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen DEBUG(SSSDBG_OP_FAILURE,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "Assuming offline authentication setting status for "
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "pam call %d to PAM_SUCCESS.\n", pd->cmd);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen pd->pam_status = PAM_SUCCESS;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen break;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen default:
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen pd->pam_status = PAM_MODULE_UNKNOWN;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (pd->response_delay > 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = gettimeofday(&tv, NULL);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen if (ret != EOK) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen errno, strerror(errno));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen goto done;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen tv.tv_sec += pd->response_delay;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen tv.tv_usec = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen pd->response_delay = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (te == NULL) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "Failed to add event pam_reply_delay.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen goto done;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen /* If this was a successful login, save the lastLogin time */
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (pd->cmd == SSS_PAM_AUTHENTICATE &&
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pd->pam_status == PAM_SUCCESS &&
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen preq->domain->cache_credentials &&
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen !pd->offline_auth &&
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen !pd->last_auth_saved &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NEED_CHECK_PROVIDER(preq->domain->provider)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = set_last_login(preq);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ret != EOK) {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen goto done;
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen return;
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen &cctx->creq->out);
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen if (ret != EOK) {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen goto done;
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen /* Account expiration warning is printed for sshd. If pam_verbosity
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen * is equal or above PAM_VERBOSITY_INFO then all services are informed
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen * about account expiration.
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen */
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen if (pd->pam_status == PAM_ACCT_EXPIRED &&
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen ((pd->service != NULL && strcasecmp(pd->service, "sshd") == 0) ||
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pam_verbosity >= PAM_VERBOSITY_INFO)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE, "",
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen &pam_account_expired_message);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen inform_account_expired(pd, pam_account_expired_message);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (ret != EOK) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (pd->domain != NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (uint8_t *) pd->domain);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret != EOK) {
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen goto done;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen resp_c = 0;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen resp_size = 0;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen resp = pd->resp_list;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen while(resp != NULL) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (!resp->do_not_send_to_client) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen resp_c++;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen resp_size += resp->len;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen resp = resp->next;
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen }
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sizeof(int32_t) +
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen resp_c * 2* sizeof(int32_t) +
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen resp_size);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen if (ret != EOK) {
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen goto done;
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen }
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sss_packet_get_body(cctx->creq->out, &body, &blen);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen DEBUG(SSSDBG_FUNC_DATA, "blen: %zu\n", blen);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen p = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
p += sizeof(int32_t);
memcpy(&body[p], &resp_c, sizeof(int32_t));
p += sizeof(int32_t);
resp = pd->resp_list;
while(resp != NULL) {
if (!resp->do_not_send_to_client) {
memcpy(&body[p], &resp->type, sizeof(int32_t));
p += sizeof(int32_t);
memcpy(&body[p], &resp->len, sizeof(int32_t));
p += sizeof(int32_t);
memcpy(&body[p], resp->data, resp->len);
p += resp->len;
}
resp = resp->next;
}
done:
sss_cmd_done(cctx, preq);
}
static void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
time_t expire_date, time_t delayed_until)
{
uint32_t resp_type;
size_t resp_len;
uint8_t *resp;
int64_t dummy;
preq->pd->pam_status = cached_login_pam_status(ret);
switch (preq->pd->pam_status) {
case PAM_SUCCESS:
resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
resp_len = sizeof(uint32_t) + sizeof(int64_t);
resp = talloc_size(preq->pd, resp_len);
if (resp == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"talloc_size failed, cannot prepare user info.\n");
} else {
memcpy(resp, &resp_type, sizeof(uint32_t));
dummy = (int64_t) expire_date;
memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
(const uint8_t *) resp);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
}
}
break;
case PAM_PERM_DENIED:
if (delayed_until >= 0) {
resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
resp_len = sizeof(uint32_t) + sizeof(int64_t);
resp = talloc_size(preq->pd, resp_len);
if (resp == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"talloc_size failed, cannot prepare user info.\n");
} else {
memcpy(resp, &resp_type, sizeof(uint32_t));
dummy = (int64_t) delayed_until;
memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
(const uint8_t *) resp);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"pam_add_response failed.\n");
}
}
}
break;
default:
DEBUG(SSSDBG_TRACE_LIBS,
"cached login returned: %d\n", preq->pd->pam_status);
}
pam_reply(preq);
return;
}
static void pam_forwarder_cb(struct tevent_req *req);
static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
const char *err_msg, void *ptr);
static int pam_check_user_search(struct pam_auth_req *preq);
static int pam_check_user_done(struct pam_auth_req *preq, int ret);
static void pam_dom_forwarder(struct pam_auth_req *preq);
/* TODO: we should probably return some sort of cookie that is set in the
* PAM_ENVIRONMENT, so that we can save performing some calls and cache
* data. */
static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
{
uint8_t *body;
size_t blen;
errno_t ret;
uint32_t terminator;
sss_packet_get_body(cctx->creq->in, &body, &blen);
if (blen >= sizeof(uint32_t)) {
SAFEALIGN_COPY_UINT32(&terminator,
body + blen - sizeof(uint32_t),
NULL);
if (terminator != SSS_END_OF_PAM_REQUEST) {
DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n");
ret = EINVAL;
goto done;
}
}
switch (cctx->cli_protocol_version->version) {
case 1:
ret = pam_parse_in_data(pd, body, blen);
break;
case 2:
ret = pam_parse_in_data_v2(pd, body, blen);
break;
case 3:
ret = pam_parse_in_data_v3(pd, body, blen);
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n",
cctx->cli_protocol_version->version);
ret = EINVAL;
}
if (ret != EOK) {
goto done;
}
ret = sss_parse_name_for_domains(pd, cctx->rctx->domains,
cctx->rctx->default_domain, pd->logon_name,
&pd->domain, &pd->user);
DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
done:
return ret;
}
static int pam_auth_req_destructor(struct pam_auth_req *preq)
{
if (preq && preq->dpreq_spy) {
/* If there is still a request pending, tell the spy
* the client is going away
*/
preq->dpreq_spy->preq = NULL;
}
return 0;
}
static bool is_uid_trusted(uint32_t uid,
size_t trusted_uids_count,
uid_t *trusted_uids)
{
size_t i;
/* root is always trusted */
if (uid == 0) {
return true;
}
/* All uids are allowed */
if (trusted_uids_count == 0) {
return true;
}
for(i = 0; i < trusted_uids_count; i++) {
if (trusted_uids[i] == uid) {
return true;
}
}
return false;
}
static bool is_domain_public(char *name,
char **public_dom_names,
size_t public_dom_names_count)
{
size_t i;
for(i=0; i < public_dom_names_count; i++) {
if (strcasecmp(name, public_dom_names[i]) == 0) {
return true;
}
}
return false;
}
static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
{
struct sss_domain_info *dom;
struct pam_auth_req *preq;
struct pam_data *pd;
int ret;
errno_t ncret;
struct pam_ctx *pctx =
talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
struct tevent_req *req;
preq = talloc_zero(cctx, struct pam_auth_req);
if (!preq) {
return ENOMEM;
}
talloc_set_destructor(preq, pam_auth_req_destructor);
preq->cctx = cctx;
preq->pd = create_pam_data(preq);
if (!preq->pd) {
talloc_free(preq);
return ENOMEM;
}
pd = preq->pd;
preq->is_uid_trusted = is_uid_trusted(cctx->client_euid,
pctx->trusted_uids_count,
pctx->trusted_uids);
if (!preq->is_uid_trusted) {
DEBUG(SSSDBG_MINOR_FAILURE, "uid %"PRIu32" is not trusted.\n",
cctx->client_euid);
}
pd->cmd = pam_cmd;
pd->priv = cctx->priv;
ret = pam_forwarder_parse_data(cctx, pd);
if (ret == EAGAIN) {
req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain);
if (req == NULL) {
ret = ENOMEM;
} else {
tevent_req_set_callback(req, pam_forwarder_cb, preq);
ret = EAGAIN;
}
goto done;
} else if (ret != EOK) {
ret = EINVAL;
goto done;
}
/* now check user is valid */
if (pd->domain) {
preq->domain = responder_get_domain(cctx->rctx, pd->domain);
if (!preq->domain) {
ret = ENOENT;
goto done;
}
ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
preq->domain, pd->user);
if (ncret == EEXIST) {
/* User found in the negative cache */
ret = ENOENT;
goto done;
}
} else {
for (dom = preq->cctx->rctx->domains;
dom;
dom = get_next_domain(dom, false)) {
if (dom->fqnames) continue;
ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
dom, pd->user);
if (ncret == ENOENT) {
/* User not found in the negative cache
* Proceed with PAM actions
*/
break;
}
/* Try the next domain */
DEBUG(SSSDBG_TRACE_FUNC,
"User [%s@%s] filtered out (negative cache). "
"Trying next domain.\n", pd->user, dom->name);
}
if (!dom) {
ret = ENOENT;
goto done;
}
preq->domain = dom;
}
if (preq->domain->provider == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Domain [%s] has no auth provider.\n", preq->domain->name);
ret = EINVAL;
goto done;
}
preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
ret = pam_check_user_search(preq);
if (ret == EOK) {
pam_dom_forwarder(preq);
}
done:
return pam_check_user_done(preq, ret);
}
static void pam_forwarder_cb(struct tevent_req *req)
{
struct pam_auth_req *preq = tevent_req_callback_data(req,
struct pam_auth_req);
struct cli_ctx *cctx = preq->cctx;
struct pam_data *pd;
errno_t ret = EOK;
ret = sss_dp_get_domains_recv(req);
talloc_free(req);
if (ret != EOK) {
goto done;
}
pd = preq->pd;
ret = pam_forwarder_parse_data(cctx, pd);
if (ret == EAGAIN) {
if (strchr(preq->pd->logon_name, '@') == NULL) {
goto done;
}
/* Assuming Kerberos principal */
preq->domain = preq->cctx->rctx->domains;
preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name);
if (preq->pd->user == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
preq->pd->name_is_upn = true;
preq->pd->domain = NULL;
} else if (ret != EOK) {
ret = EINVAL;
goto done;
}
if (preq->pd->domain) {
preq->domain = responder_get_domain(cctx->rctx, preq->pd->domain);
if (preq->domain == NULL) {
ret = ENOENT;
goto done;
}
}
ret = pam_check_user_search(preq);
if (ret == EOK) {
pam_dom_forwarder(preq);
}
done:
pam_check_user_done(preq, ret);
}
static void pam_dp_send_acct_req_done(struct tevent_req *req);
static int pam_check_user_search(struct pam_auth_req *preq)
{
struct sss_domain_info *dom = preq->domain;
char *name = NULL;
time_t cacheExpire;
int ret;
struct tevent_req *dpreq;
struct dp_callback_ctx *cb_ctx;
struct pam_ctx *pctx =
talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
static const char *user_attrs[] = SYSDB_PW_ATTRS;
struct ldb_message *msg;
struct ldb_result *res;
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, false);
}
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_get_cased_name(preq, preq->pd->user,
dom->case_sensitive);
if (!name) {
return ENOMEM;
}
name = sss_reverse_replace_space(preq, name,
pctx->rctx->override_space);
if (name == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"sss_reverse_replace_space failed\n");
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, 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@%s]\n", name, dom->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);
} 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->ncache, false, dom, name);
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, false);
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;
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);
char *name;
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 */
name = preq->domain->case_sensitive ?
talloc_strdup(preq, preq->pd->user) :
sss_tc_utf8_str_tolower(preq, preq->pd->user);
if (!name) {
ret = ENOMEM;
goto done;
}
ret = pam_initgr_cache_set(pctx->rctx->ev, pctx->id_table,
name, pctx->id_timeout);
talloc_free(name);
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);
}
ret = pam_check_user_done(preq, ret);
done:
if (ret) {
preq->pd->pam_status = PAM_SYSTEM_ERR;
pam_reply(preq);
}
}
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);
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 %"PRIu32" cannot access non-public domain %s.\n",
preq->cctx->client_euid, 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 (!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);
}
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_CLI_NULL, NULL}
};
return sss_cmds;
}