pamsrv_cmd.c revision f3c2dc1f9ccdf456fd78ed96197b9bf404cc29fc
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen PAM Responder
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen Copyright (C) Sumit Bose <sbose@redhat.com> 2009
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 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 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/>.
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen safealign_memcpy(&resp[p], user_error_message, err_len, &p);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainenstatic void inform_account_expired(struct pam_data* pd,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pack_user_info_account_expired(pd, pam_message, &msg_len, &msg);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "pack_user_info_account_expired failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* If none specific domains got requested via pam, all domains are allowed.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen * Which mimics the default/original behaviour.
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (strcasecmp(domain_name, pd->requested_domains[i])) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return false;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_authtok_v2(struct sss_auth_token *tok,
06b0c3be9905099038964b068216bbed155701deTimo Sirainen if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
06b0c3be9905099038964b068216bbed155701deTimo Sirainen SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen auth_token_length = data_size - sizeof(uint32_t);
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen /* If the string isn't valid UTF-8, fail */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int pam_parse_in_data_v2(struct pam_data *pd,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
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 */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen ret = extract_string(&pd->logon_name, size, body, blen, &c);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = extract_string(&pd->service, size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_string(&pd->tty, size, body, blen, &c);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_string(&pd->ruser, size, body, blen, &c);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = extract_string(&pd->rhost, size, body, blen, &c);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen ret = extract_string(&requested_domains, size, body, blen,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen ret = split_on_separator(pd, requested_domains, ',', true,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen "Failed to parse requested_domains list!\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } while(c < blen);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int pam_parse_in_data_v3(struct pam_data *pd,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int extract_authtok_v1(struct sss_auth_token *tok,
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 ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
c95fc202215d2451372599db7092b16459f360a3Timo Sirainenstatic int pam_parse_in_data(struct pam_data *pd,
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen /* user name */
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen ret = extract_authtok_v1(pd->authtok, body, blen, &end);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen/*=Save-Last-Login-State===================================================*/
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic errno_t set_last_login(struct pam_auth_req *preq)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic errno_t filter_responses(struct confdb_ctx *cdb,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen "Failed to read PAM verbosity, not fatal.\n");
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(&user_info_type, resp->data, sizeof(uint32_t));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "User info offline auth entry is "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "too short.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(&expire_date, resp->data + sizeof(uint32_t),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "User info type [%d] not filtered.\n",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen preq = talloc_get_type(pvt, struct pam_auth_req);
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,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Failed to read PAM verbosity, not fatal.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "pam_reply called with result [%d].\n", pd->pam_status);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* do auth with offline credentials */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Fatal: Sysdb CTX not found for domain"
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = sss_authtok_get_password(pd->authtok, &password, NULL);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pam_handle_cached_login(preq, ret, exp_date, delay_until);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Password change not possible while offline.\n");
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 DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen/* TODO: we need the pam session cookie here to make sure that cached
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen * authentication was successful */
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "Assuming offline authentication setting status for "
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "Failed to add event pam_reply_delay.\n");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen /* If this was a successful login, save the lastLogin time */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NEED_CHECK_PROVIDER(preq->domain->provider)) {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
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 ((pd->service != NULL && strcasecmp(pd->service, "sshd") == 0) ||
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen inform_account_expired(pd, pam_account_expired_message);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sss_packet_get_body(cctx->creq->out, &body, &blen);
p += sizeof(int32_t);
p += sizeof(int32_t);
p += sizeof(int32_t);
p += sizeof(int32_t);
done:
case PAM_SUCCESS:
case PAM_PERM_DENIED:
if (delayed_until >= 0) {
NULL);
goto done;
goto done;
done:
return ret;
size_t i;
if (uid == 0) {
if (trusted_uids_count == 0) {
for(i = 0; i < trusted_uids_count; i++) {
char **public_dom_names,
size_t i;
for(i=0; i < public_dom_names_count; i++) {
int ret;
if (!preq) {
return ENOMEM;
return ENOMEM;
goto done;
goto done;
goto done;
goto done;
dom;
if (!dom) {
goto done;
goto done;
done:
struct pam_auth_req);
goto done;
goto done;
goto done;
goto done;
goto done;
done:
int ret;
while (dom) {
if (!dom) break;
if (!name) {
return ENOMEM;
return ENOMEM;
return EIO;
return EFAULT;
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:
return EOK;
int ret;
char *name;
if (err_maj) {
if (!name) {
goto done;
done:
if (ret) {
int ret;
return pam_cli_protocol_version;
return sss_cmds;