pamsrv_cmd.c revision 95ef1bd1c06163492e285fa9d8e2fa81f99d39d2
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen PAM Responder
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Copyright (C) Sumit Bose <sbose@redhat.com> 2009
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen This program is free software; you can redistribute it and/or modify
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen it under the terms of the GNU General Public License as published by
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen the Free Software Foundation; either version 3 of the License, or
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (at your option) any later version.
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen This program is distributed in the hope that it will be useful,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen GNU General Public License for more details.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen You should have received a copy of the GNU General Public License
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* If none specific domains got requested via pam, all domains are allowed.
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen * Which mimics the default/original behaviour.
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (strcmp(domain_name, pd->requested_domains[i])) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return false;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int extract_authtok_v2(struct sss_auth_token *tok,
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen auth_token_length = data_size - sizeof(uint32_t);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainenstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* If the string isn't valid UTF-8, fail */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainenstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int pam_parse_in_data_v2(struct pam_data *pd,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen * the remaining buffer */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = extract_string(&pd->logon_name, size, body, blen, &c);
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen ret = extract_string(&pd->service, size, body, blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = extract_string(&pd->tty, size, body, blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = extract_string(&pd->ruser, size, body, blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = extract_string(&pd->rhost, size, body, blen, &c);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = extract_string(&requested_domains, size, body, blen,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = split_on_separator(pd, requested_domains, ',', true,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Failed to parse requested_domains list!\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } while(c < blen);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int pam_parse_in_data_v3(struct pam_data *pd,
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenstatic int extract_authtok_v1(struct sss_auth_token *tok,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainenstatic int pam_parse_in_data(struct pam_data *pd,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* user name */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen ret = extract_authtok_v1(pd->authtok, body, blen, &end);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen/*=Save-Last-Login-State===================================================*/
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic errno_t set_last_login(struct pam_auth_req *preq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic errno_t filter_responses(struct confdb_ctx *cdb,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen "Failed to read PAM verbosity, not fatal.\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen memcpy(&user_info_type, resp->data, sizeof(uint32_t));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen "User info offline auth entry is "
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen "too short.\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen memcpy(&expire_date, resp->data + sizeof(uint32_t),
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen "User info type [%d] not filtered.\n",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen preq = talloc_get_type(pvt, struct pam_auth_req);
84004c37192dc91a8dcc9f213ca2cfa22b4f40e4Timo Sirainenstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void pam_reply(struct pam_auth_req *preq)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen "pam_reply called with result [%d].\n", pd->pam_status);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen /* do auth with offline credentials */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "Fatal: Sysdb CTX not found for domain"
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = sss_authtok_get_password(pd->authtok, &password, NULL);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
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;
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:
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;
goto done;
goto done;
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;