pamsrv_cmd.c revision 5cda8428d23266aaaf4d7cddba50311202365c16
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek PAM Responder
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek Copyright (C) Sumit Bose <sbose@redhat.com> 2009
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 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 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#include "responder/common/responder_cache_req.h"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekpam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *username);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekpam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *name,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_reply(struct pam_auth_req *preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t pack_user_info_msg(TALLOC_CTX *mem_ctx,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek safealign_memcpy(&resp[p], user_error_message, err_len, &p);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void inform_user(struct pam_data* pd, const char *pam_message)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pack_user_info_msg(pd, pam_message, &msg_len, &msg);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek "pack_user_info_account_expired failed.\n");
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozekstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek /* If none specific domains got requested via pam, all domains are allowed.
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek * Which mimics the default/original behaviour.
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek return true;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek if (strcasecmp(domain_name, pd->requested_domains[i])) {
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek return true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek return false;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_authtok_v2(struct sss_auth_token *tok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek auth_token_length = data_size - sizeof(uint32_t);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA,
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* If the string isn't valid UTF-8, fail */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *name;
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
08c72b84d85d482f030a30cf74786695f097e91cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data_v2(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
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 DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->logon_name, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->service, size, body, blen, &c);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = extract_string(&pd->tty, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->ruser, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&pd->rhost, size, body, blen, &c);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_string(&requested_domains, size, body, blen,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = split_on_separator(pd, requested_domains, ',', true,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to parse requested_domains list!\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek } while(c < blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data_v3(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int extract_authtok_v1(struct sss_auth_token *tok,
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 ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic int pam_parse_in_data(struct pam_data *pd,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* user name */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
1bcb68cc3069a6bd539289e68a87a0815aa2a1beJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek for (start = end; end < last; end++) if (body[end] == '\0') break;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v1(pd->authtok, body, blen, &end);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/*=Save-Last-Login-State===================================================*/
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t set_last_login(struct pam_auth_req *preq)
3c60433641ce2e86b9b04778c8f8652ef0d097e4Stef Walter ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
6fdde3913a11cd6148627696fa8717c34e8460fcJan Zeleny ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
5f93f452e4a80d6b0243eaf3c583d0caf9981ca0Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t filter_responses(struct confdb_ctx *cdb,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to read PAM verbosity, not fatal.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
129310e872a0a70e721ba59363e518176ef406d6Jakub Hrozek memcpy(&user_info_type, resp->data, sizeof(uint32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User info offline auth entry is "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "too short.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&expire_date, resp->data + sizeof(uint32_t),
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User info type [%d] not filtered.\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq = talloc_get_type(pvt, struct pam_auth_req);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t get_password_for_cache_auth(struct sss_auth_token *authtok,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char **password)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek const char *fa2;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_authtok_get_password(authtok, password, NULL);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_authtok_get_2fa(authtok, password, &pw_len, &fa2, &fa2_len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Unsupported auth token type [%d].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
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 Hrozekstatic void pam_reply(struct pam_auth_req *preq)
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 ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to read PAM verbosity, not fatal.\n");
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 /* backup value of 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 /* do auth with offline credentials */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Fatal: Sysdb CTX not found for domain"
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = get_password_for_cache_auth(pd->authtok, &password);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "get_password_and_type_for_cache_auth failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek pam_handle_cached_login(preq, ret, exp_date, delay_until,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Password change not possible while offline.\n");
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 DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek/* TODO: we need the pam session cookie here to make sure that cached
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * authentication was successful */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Assuming offline authentication setting status for "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
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 "sysdb_null_last_online_auth_with_curr_token failed: "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to add event pam_reply_delay.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* If this was a successful login, save the lastLogin time */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_packet_new(prctx->creq, 0, sss_packet_get_cmd(prctx->creq->in),
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 ((pd->service != NULL && strcasecmp(pd->service, "sshd") == 0) ||
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to get expiration message: %d:[%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Failed to get expiration message: %d:[%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_packet_grow(prctx->creq->out, sizeof(int32_t) +
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek sss_packet_get_body(prctx->creq->out, &body, &blen);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek memcpy(&body[p], &resp->type, sizeof(int32_t));
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek p += sizeof(int32_t);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_dom_forwarder(struct pam_auth_req *preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->pam_status = cached_login_pam_status(ret);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "talloc_size failed, cannot prepare user info.\n");
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 DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "talloc_size failed, cannot prepare user info.\n");
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 "pam_add_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Was this attempt to authenticate from cache? */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Don't try cached authentication again, try online check. */
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Cached authentication failed for: %s\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "cached login returned: %d\n", preq->pd->pam_status);
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 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 Hrozekstatic errno_t pam_cmd_assume_upn(struct pam_auth_req *preq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek && strchr(preq->pd->logon_name, '@') != NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "No entry found so far, trying UPN/email lookup with [%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Assuming Kerberos principal */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name);
2bd514cfde1938b1e245af11c9b548d58d49b325Jan Cholasta DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
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
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek prctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek sss_packet_get_body(prctx->creq->in, &body, &blen);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek switch (prctx->cli_protocol_version->version) {
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = sss_parse_name_for_domains(pd, cctx->rctx->domains,
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 && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic int pam_auth_req_destructor(struct pam_auth_req *preq)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* If there is still a request pending, tell the spy
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek * the client is going away
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic bool is_uid_trusted(struct cli_creds *creds,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* root is always trusted */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return true;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek /* All uids are allowed */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek return true;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_allowed_uids(client_euid(creds), trusted_uids_count, trusted_uids);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return false;
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 return false;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Failed to read p11_child_timeout from confdb: [%d]: %s\n",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek ret = confdb_get_string(pctx->rctx->cdb, mctx, CONFDB_MONITOR_CONF_ENTRY,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "Failed to read certificate_verification from confdb: [%d]: %s\n",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek req = pam_check_cert_send(mctx, ev, pctx->p11_child_debug_fd,
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek tevent_req_set_callback(req, pam_forwarder_cert_cb, preq);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_set_destructor(preq, pam_auth_req_destructor);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek preq->is_uid_trusted = is_uid_trusted(cctx->creds,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE, "uid %"SPRIuid" is not trusted.\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek tevent_req_set_callback(req, pam_forwarder_cb, preq);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* now check user is valid */
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek preq->domain = responder_get_domain(cctx->rctx, pd->domain);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek name = sss_resp_create_fqname(preq, pctx->rctx, preq->domain,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ncret = sss_ncache_check_user(pctx->rctx->ncache,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* User found in the negative cache */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek name = sss_resp_create_fqname(preq, pctx->rctx, dom,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ncret = sss_ncache_check_user(pctx->rctx->ncache,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* User not found in the negative cache
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * Proceed with PAM actions
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Try the next domain */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "User [%s@%s] filtered out (negative cache). "
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_cert(cctx, cctx->ev, pctx, preq, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Finish here */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Domain [%s] has no auth provider.\n", preq->domain->name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
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 struct pam_auth_req *preq = tevent_req_callback_data(req,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "No certificate found and no logon name given, " \
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "authentication not possible.\n");;
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "No certificate returned, authentication failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek tevent_req_set_callback(req, pam_forwarder_lookup_by_cert_done, preq);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozekstatic void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek struct pam_auth_req *preq = tevent_req_callback_data(req,
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek ret = cache_req_user_by_cert_recv(preq, req, &res, &domain, NULL);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n");
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek "Search by certificate returned more than one result.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->cert_user_obj = talloc_steal(preq, res->msgs[0]);
5dfb1257f62839eea1c31669cf3bbcb114c22183Jakub Hrozek cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Certificate user object has not name.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_FUNC_DATA, "Found certificate user [%s].\n",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = add_pam_cert_response(preq->pd, cert_user, preq->token_name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->pd->domain = talloc_strdup(preq->pd, domain->name);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek "Missing logon name and no certificate user found.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void pam_forwarder_cb(struct tevent_req *req)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct pam_auth_req *preq = tevent_req_callback_data(req,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (strchr(preq->pd->logon_name, '@') == NULL) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Assuming Kerberos principal */
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 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek preq->domain = responder_get_domain(cctx->rctx, preq->pd->domain);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ret = check_cert(cctx, cctx->ev, pctx, preq, pd);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Finish here */
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 talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek static const char *user_attrs[] = SYSDB_PW_ATTRS;
if (!dom) break;
return ENOMEM;
return EIO;
return EFAULT;
return EINVAL;
return EINVAL;
return ENOENT;
return EIO;
return ENOENT;
SYSDB_CACHE_EXPIRE, 0);
return ret;
return EOK;
if (!dom) {
if (!dpreq) {
return ENOMEM;
if(!cb_ctx) {
return ENOMEM;
return EAGAIN;
return ENOENT;
char *err_msg;
&err_msg);
switch (ret) {
case EOK:
case EAGAIN:
case ENOENT:
case ERR_NO_CREDS:
return EOK;
int ret;
if (err_maj) {
if (ret) {
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;