pamsrv_cmd.c revision c99bcc91e58988ff37403d362d4322469413c2ff
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler PAM Responder
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler Copyright (C) Sumit Bose <sbose@redhat.com> 2009
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler This program is free software; you can redistribute it and/or modify
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler it under the terms of the GNU General Public License as published by
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler the Free Software Foundation; either version 3 of the License, or
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler (at your option) any later version.
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler This program is distributed in the hope that it will be useful,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler but WITHOUT ANY WARRANTY; without even the implied warranty of
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler GNU General Public License for more details.
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler You should have received a copy of the GNU General Public License
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler along with this program. If not, see <http://www.gnu.org/licenses/>.
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "responder/common/responder_packet.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "responder/common/cache_req/cache_req.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerpam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engenpam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain,
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen const char *name,
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engenstatic void pam_reply(struct pam_auth_req *preq);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic int pam_check_user_done(struct pam_auth_req *preq, int ret);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic errno_t pack_user_info_msg(TALLOC_CTX *mem_ctx,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler *resp_len = 2 * sizeof(uint32_t) + err_len;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler SAFEALIGN_SET_UINT32(&resp[p], err_len, &p);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler safealign_memcpy(&resp[p], user_error_message, err_len, &p);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic void inform_user(struct pam_data* pd, const char *pam_message)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = pack_user_info_msg(pd, pam_message, &msg_len, &msg);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler "pack_user_info_account_expired failed.\n");
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler /* If none specific domains got requested via pam, all domains are allowed.
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler * Which mimics the default/original behaviour.
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler for (i = 0; pd->requested_domains[i]; i++) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (strcasecmp(domain_name, pd->requested_domains[i])) {
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler return false;
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seilerstatic int extract_authtok_v2(struct sss_auth_token *tok,
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler size_t data_size, uint8_t *body, size_t blen,
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler auth_token_length = data_size - sizeof(uint32_t);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler ret = sss_authtok_set(tok, auth_token_type,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler /* If the string isn't valid UTF-8, fail */
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seilerstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seilerstatic int pam_parse_in_data_v2(struct pam_data *pd,
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler * the remaining buffer */
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler if (size > (blen - c - sizeof(uint32_t))) {
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = extract_string(&pd->logon_name, size, body, blen, &c);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler ret = extract_string(&pd->service, size, body, blen, &c);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = extract_string(&pd->tty, size, body, blen, &c);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = extract_string(&pd->ruser, size, body, blen, &c);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = extract_string(&pd->rhost, size, body, blen, &c);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = extract_string(&requested_domains, size, body, blen,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ret = split_on_separator(pd, requested_domains, ',', true,
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler "Failed to parse requested_domains list!\n");
case SSS_PAM_ITEM_AUTHTOK:
case SSS_PAM_ITEM_NEWAUTHTOK:
c += size;
} while(c < blen);
return EOK;
int ret;
return ret;
return EINVAL;
return EOK;
switch (auth_token_type) {
case SSS_AUTHTOK_TYPE_EMPTY:
return EINVAL;
*c += auth_token_length;
return ret;
int ret;
end = 0;
if (ret) {
return ret;
if (ret) {
return ret;
return EOK;
if (!attrs) {
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
return EOK;
fail:
return ret;
char * const *pam_filter_opts)
size_t c;
const char *var_name;
const char *service;
return EOK;
var_name_len = 0;
service++;
if (var_name_len == 0) {
return EOK;
int ret;
goto done;
switch (user_info_type) {
goto done;
sizeof(int64_t));
if ((expire_date == 0 &&
(expire_date > 0 &&
goto done;
done:
return ret;
const char **password)
int ret;
const char *fa2;
case SSS_AUTHTOK_TYPE_2FA:
return ret;
return EOK;
int ret;
char* pam_account_expired_message;
char* pam_account_locked_message;
int pam_verbosity;
case SSS_PAM_AUTHENTICATE:
bool use_cached_auth;
goto done;
goto done;
case SSS_PAM_CHAUTHTOK_PRELIM:
case SSS_PAM_CHAUTHTOK:
goto done;
case SSS_PAM_SETCRED:
case SSS_PAM_ACCT_MGMT:
case SSS_PAM_OPEN_SESSION:
case SSS_PAM_CLOSE_SESSION:
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
resp_c = 0;
resp_size = 0;
resp_c++;
sizeof(int32_t) +
goto done;
p += sizeof(int32_t);
p += sizeof(int32_t);
p += sizeof(int32_t);
p += sizeof(int32_t);
done:
bool use_cached_auth)
case PAM_SUCCESS:
case PAM_PERM_DENIED:
if (delayed_until >= 0) {
case PAM_AUTH_ERR:
if (use_cached_auth) {
NULL);
goto done;
goto done;
goto done;
done:
return ret;
if (trusted_uids_count == 0) {
char **public_dom_names,
size_t i;
for(i=0; i < public_dom_names_count; i++) {
int p11_child_timeout;
char *cert_verification_opts;
return ret;
return ret;
return ENOMEM;
return EAGAIN;
int ret;
if (!preq) {
return ENOMEM;
return ENOMEM;
goto done;
goto done;
goto done;
done:
struct pam_auth_req);
char *cert;
goto done;
goto done;
goto done;
done:
int ret;
struct pam_auth_req);
const char *cert_user;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
struct pam_auth_req);
goto done;
goto done;
goto done;
goto done;
done:
int ret;
return ENOMEM;
return EIO;
data);
if (!dpreq) {
return ENOMEM;
return EAGAIN;
int ret;
switch (ret) {
case EOK:
case EAGAIN:
case ENOENT:
case ERR_NO_CREDS:
return EOK;
const char* user,
int cached_auth_timeout,
bool *_result)
bool result;
goto done;
done:
return ret;
bool is_cachable;
switch(cmd) {
case SSS_PAM_AUTHENTICATE:
is_cachable = true;
is_cachable = false;
return is_cachable;
bool cachable = false;
cachable = true;
return cachable;
int pam_cmd,
const char* user,
bool cached_auth_failed)
bool result = false;
&result);
return result;
int ret;
const char *cert_user;
NULL);
return pam_cli_protocol_version;
return sss_cmds;
const char *username,
int ret;
goto done;
goto done;
value);
done:
return ret;
static errno_t
const char *username)
static errno_t
const char *name,
goto done;
goto done;
goto done;
goto done;
done:
return ret;