pamsrv_cmd.c revision e039f1aefecc65a7b3c2d4a13a612bff1dd367c8
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/*
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen SSSD
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen PAM Responder
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen Copyright (C) Sumit Bose <sbose@redhat.com> 2009
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
5cda7e699876c1de203c30777924c899d2a20221Timo Sirainen This program is free software; you can redistribute it and/or modify
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen it under the terms of the GNU General Public License as published by
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen the Free Software Foundation; either version 3 of the License, or
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen (at your option) any later version.
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen This program is distributed in the hope that it will be useful,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen GNU General Public License for more details.
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen You should have received a copy of the GNU General Public License
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen*/
657afb33796f8216c568ad813627da89970760beTimo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include <time.h>
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "util/util.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "util/auth_utils.h"
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen#include "db/sysdb.h"
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen#include "confdb/confdb.h"
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include "responder/common/responder_packet.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "responder/common/responder.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "responder/common/negcache.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "providers/data_provider.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "responder/pam/pamsrv.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "responder/pam/pam_helpers.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "db/sysdb.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenenum pam_verbosity {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen PAM_VERBOSITY_NO_MESSAGES = 0,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen PAM_VERBOSITY_IMPORTANT,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen PAM_VERBOSITY_INFO,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen PAM_VERBOSITY_DEBUG
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen};
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen#define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainenstatic void pam_reply(struct pam_auth_req *preq);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainenstatic errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen const char *user_error_message,
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen size_t *resp_len,
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen uint8_t **_resp)
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen{
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen size_t err_len;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen uint8_t *resp;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen size_t p;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen err_len = strlen(user_error_message);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen *resp_len = 2 * sizeof(uint32_t) + err_len;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen resp = talloc_size(mem_ctx, *resp_len);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen if (resp == NULL) {
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen return ENOMEM;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen }
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen p = 0;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen SAFEALIGN_SET_UINT32(&resp[p], err_len, &p);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen safealign_memcpy(&resp[p], user_error_message, err_len, &p);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen if (p != *resp_len) {
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen *_resp = resp;
657afb33796f8216c568ad813627da89970760beTimo Sirainen return EOK;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen
d85f713cc9f9ddaa2b591169f79df70e764fbe05Timo Sirainenstatic void inform_account_expired(struct pam_data* pd,
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen const char *pam_message)
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen{
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen size_t msg_len;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen uint8_t *msg;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen errno_t ret;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen ret = pack_user_info_account_expired(pd, pam_message, &msg_len, &msg);
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen if (ret != EOK) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen "pack_user_info_account_expired failed.\n");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (ret != EOK) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenstatic bool is_domain_requested(struct pam_data *pd, const char *domain_name)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch int i;
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen /* If none specific domains got requested via pam, all domains are allowed.
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen * Which mimics the default/original behaviour.
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (!pd->requested_domains) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return true;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen for (i = 0; pd->requested_domains[i]; i++) {
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen if (strcasecmp(domain_name, pd->requested_domains[i])) {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen continue;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen }
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return true;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return false;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenstatic int extract_authtok_v2(struct sss_auth_token *tok,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen size_t data_size, uint8_t *body, size_t blen,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen size_t *c)
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen{
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen uint32_t auth_token_type;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen uint32_t auth_token_length;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uint8_t *auth_token_data;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen int ret = EOK;
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen auth_token_length = data_size - sizeof(uint32_t);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen auth_token_data = body+(*c);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen switch (auth_token_type) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen case SSS_AUTHTOK_TYPE_EMPTY:
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen sss_authtok_set_empty(tok);
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen break;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen case SSS_AUTHTOK_TYPE_PASSWORD:
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen if (auth_token_length == 0) {
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen sss_authtok_set_empty(tok);
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen } else {
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen auth_token_length);
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen }
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen break;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen default:
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen return EINVAL;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen }
f205e138634bd4269fa095463938cccf3970954dTimo Sirainen
f205e138634bd4269fa095463938cccf3970954dTimo Sirainen *c += auth_token_length;
f205e138634bd4269fa095463938cccf3970954dTimo Sirainen
56ffe7c9356544aa228ef6760f9fa08ec2c8c9c1Timo Sirainen return ret;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen}
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainenstatic int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen size_t *c) {
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen uint8_t *str;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen str = body+(*c);
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (str[size-1]!='\0') return EINVAL;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen /* If the string isn't valid UTF-8, fail */
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (!sss_utf8_check(str, size-1)) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen return EINVAL;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen *c += size;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen *var = (char *) str;
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return EOK;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen}
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenstatic int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen size_t blen, size_t *c) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return EINVAL;
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen return EOK;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen}
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenstatic int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen{
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen const char *name;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (!name) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen return EIO;
ab122a3bbae3b5fd2aad66e2f2840149d98cee52Timo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (strcmp(pd->user, name)) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen DEBUG(SSSDBG_TRACE_FUNC, "User's primary name is %s\n", name);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen talloc_free(pd->user);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen pd->user = talloc_strdup(pd, name);
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen if (!pd->user) return ENOMEM;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen return EOK;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen}
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainenstatic int pam_parse_in_data_v2(struct pam_data *pd,
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen uint8_t *body, size_t blen)
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen{
b8a6abfd2bc86118f54f59ee71005f634f45cdfcTimo Sirainen size_t c;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen uint32_t type;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen uint32_t size;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen int ret;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen uint32_t start;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen uint32_t terminator;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen char *requested_domains;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (blen < 4*sizeof(uint32_t)+2) {
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen return EINVAL;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen SAFEALIGN_COPY_UINT32(&start, body, NULL);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen if (start != SSS_START_OF_PAM_REQUEST
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen || terminator != SSS_END_OF_PAM_REQUEST) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen return EINVAL;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen c = sizeof(uint32_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen do {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (type == SSS_END_OF_PAM_REQUEST) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (c != blen) return EINVAL;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen } else {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
4240acc84d065472e5b21becd6481553fc38fe38Timo Sirainen * the remaining buffer */
4240acc84d065472e5b21becd6481553fc38fe38Timo Sirainen if (size > (blen - c - sizeof(uint32_t))) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen return EINVAL;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen switch(type) {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen case SSS_PAM_ITEM_USER:
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen ret = extract_string(&pd->logon_name, size, body, blen, &c);
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen if (ret != EOK) return ret;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen break;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen case SSS_PAM_ITEM_SERVICE:
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen ret = extract_string(&pd->service, size, body, blen, &c);
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (ret != EOK) return ret;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen break;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen case SSS_PAM_ITEM_TTY:
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen ret = extract_string(&pd->tty, size, body, blen, &c);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (ret != EOK) return ret;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen break;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen case SSS_PAM_ITEM_RUSER:
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen ret = extract_string(&pd->ruser, size, body, blen, &c);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (ret != EOK) return ret;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case SSS_PAM_ITEM_RHOST:
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen ret = extract_string(&pd->rhost, size, body, blen, &c);
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (ret != EOK) return ret;
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen break;
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen case SSS_PAM_ITEM_REQUESTED_DOMAINS:
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen ret = extract_string(&requested_domains, size, body, blen,
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen &c);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (ret != EOK) return ret;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen ret = split_on_separator(pd, requested_domains, ',', true,
3ee2da6133bd7773961d1f3f3ac531448a5158b9Timo Sirainen true, &pd->requested_domains,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen NULL);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (ret != EOK) {
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
548193b7d6c19a14eff810202cd334f364b75e36Timo Sirainen "Failed to parse requested_domains list!\n");
548193b7d6c19a14eff810202cd334f364b75e36Timo Sirainen return ret;
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen }
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case SSS_PAM_ITEM_CLI_PID:
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen ret = extract_uint32_t(&pd->cli_pid, size,
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen body, blen, &c);
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen if (ret != EOK) return ret;
d85f713cc9f9ddaa2b591169f79df70e764fbe05Timo Sirainen break;
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen case SSS_PAM_ITEM_AUTHTOK:
c96a1bff0db10e7f7e1d50bc434c95bf1f071805Timo Sirainen ret = extract_authtok_v2(pd->authtok,
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen size, body, blen, &c);
3ee2da6133bd7773961d1f3f3ac531448a5158b9Timo Sirainen if (ret != EOK) return ret;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen break;
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen case SSS_PAM_ITEM_NEWAUTHTOK:
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ret = extract_authtok_v2(pd->newauthtok,
451254b8f080792f1e6f11639a9e8be663a108c0Timo Sirainen size, body, blen, &c);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (ret != EOK) return ret;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen break;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen default:
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen "Ignoring unknown data type [%d].\n", type);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen c += size;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen } while(c < blen);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen return EOK;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen}
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenstatic int pam_parse_in_data_v3(struct pam_data *pd,
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen uint8_t *body, size_t blen)
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen{
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen int ret;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = pam_parse_in_data_v2(pd, body, blen);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (ret != EOK) {
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n");
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen return ret;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen if (pd->cli_pid == 0) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n");
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return EINVAL;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen return EOK;
bbdd683dd23641dca779bffdf22c089b57fe5066Timo Sirainen}
bbdd683dd23641dca779bffdf22c089b57fe5066Timo Sirainen
bbdd683dd23641dca779bffdf22c089b57fe5066Timo Sirainenstatic int extract_authtok_v1(struct sss_auth_token *tok,
bbdd683dd23641dca779bffdf22c089b57fe5066Timo Sirainen uint8_t *body, size_t blen, size_t *c)
76830cda2eddcb36736bbb349dcbc2e9ca032483Timo Sirainen{
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen uint32_t auth_token_type;
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen uint32_t auth_token_length;
76830cda2eddcb36736bbb349dcbc2e9ca032483Timo Sirainen uint8_t *auth_token_data;
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen int ret = EOK;
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen
76830cda2eddcb36736bbb349dcbc2e9ca032483Timo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_token_data = body+(*c);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen switch (auth_token_type) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen case SSS_AUTHTOK_TYPE_EMPTY:
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen sss_authtok_set_empty(tok);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen break;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen case SSS_AUTHTOK_TYPE_PASSWORD:
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = sss_authtok_set_password(tok, (const char *)auth_token_data,
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_token_length);
04f792b9b17210898bab55e4b6c919fe78913001Timo Sirainen break;
3cad7d3634afa649561921c54e7769528e7813f9Timo Sirainen default:
04f792b9b17210898bab55e4b6c919fe78913001Timo Sirainen return EINVAL;
04f792b9b17210898bab55e4b6c919fe78913001Timo Sirainen }
4f17af486518a4a7526dc6c4eed702178dc0bee9Timo Sirainen
4f17af486518a4a7526dc6c4eed702178dc0bee9Timo Sirainen *c += auth_token_length;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
d85f713cc9f9ddaa2b591169f79df70e764fbe05Timo Sirainen return ret;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen}
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenstatic int pam_parse_in_data(struct pam_data *pd,
0602c7dee8ceda2d7c7e5723f18c56698ac5a76dTimo Sirainen uint8_t *body, size_t blen)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen{
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen size_t start;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen size_t end;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen size_t last;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen int ret;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen last = blen - 1;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen end = 0;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* user name */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (body[end++] != '\0') return EINVAL;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen pd->logon_name = (char *) &body[start];
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (body[end++] != '\0') return EINVAL;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen pd->service = (char *) &body[start];
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (body[end++] != '\0') return EINVAL;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen pd->tty = (char *) &body[start];
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (body[end++] != '\0') return EINVAL;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen pd->ruser = (char *) &body[start];
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen for (start = end; end < last; end++) if (body[end] == '\0') break;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (body[end++] != '\0') return EINVAL;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen pd->rhost = (char *) &body[start];
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen ret = extract_authtok_v1(pd->authtok, body, blen, &end);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (ret) {
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n");
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen return ret;
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen }
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen ret = extract_authtok_v1(pd->newauthtok, body, blen, &end);
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen if (ret) {
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n");
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen return ret;
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen }
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen return EOK;
8eefc42b2559db19d06d7ad7b8ad9d1cd2a09178Timo Sirainen}
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen/*=Save-Last-Login-State===================================================*/
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenstatic errno_t set_last_login(struct pam_auth_req *preq)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen{
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen struct sysdb_attrs *attrs;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen errno_t ret;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen attrs = sysdb_new_attrs(preq);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (!attrs) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = ENOMEM;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen goto fail;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen }
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (ret != EOK) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen goto fail;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen if (ret != EOK) {
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen goto fail;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = sysdb_set_user_attr(preq->domain, preq->pd->user, attrs,
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen SYSDB_MOD_REP);
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen if (ret != EOK) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen DEBUG(SSSDBG_OP_FAILURE, "set_last_login failed.\n");
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen preq->pd->pam_status = PAM_SYSTEM_ERR;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen goto fail;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen } else {
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen preq->pd->last_auth_saved = true;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen preq->callback(preq);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen return EOK;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainenfail:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return ret;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic errno_t filter_responses(struct confdb_ctx *cdb,
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen struct response_data *resp_list)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen int ret;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen struct response_data *resp;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen uint32_t user_info_type;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int64_t expire_date;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int pam_verbosity;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen &pam_verbosity);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ret != EOK) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "Failed to read PAM verbosity, not fatal.\n");
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen pam_verbosity = DEFAULT_PAM_VERBOSITY;
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen }
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp = resp_list;
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen while(resp != NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (resp->type == SSS_PAM_USER_INFO) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (resp->len < sizeof(uint32_t)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "User info entry is too short.\n");
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return EINVAL;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (pam_verbosity == PAM_VERBOSITY_NO_MESSAGES) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp->do_not_send_to_client = true;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp = resp->next;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen continue;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen memcpy(&user_info_type, resp->data, sizeof(uint32_t));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen resp->do_not_send_to_client = false;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen switch (user_info_type) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen case SSS_PAM_USER_INFO_OFFLINE_AUTH:
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (resp->len != sizeof(uint32_t) + sizeof(int64_t)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "User info offline auth entry is "
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "too short.\n");
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen return EINVAL;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen memcpy(&expire_date, resp->data + sizeof(uint32_t),
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen sizeof(int64_t));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((expire_date == 0 &&
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen pam_verbosity < PAM_VERBOSITY_INFO) ||
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (expire_date > 0 &&
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen pam_verbosity < PAM_VERBOSITY_IMPORTANT)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp->do_not_send_to_client = true;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
550034b94a58491a08a620c8e392fd3087551e7aTimo Sirainen break;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen default:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "User info type [%d] not filtered.\n",
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen user_info_type);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else if (resp->type & SSS_SERVER_INFO) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp->do_not_send_to_client = true;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen resp = resp->next;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen return EOK;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct timeval tv, void *pvt)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen struct pam_auth_req *preq;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen DEBUG(SSSDBG_CONF_SETTINGS, "pam_reply_delay get called.\n");
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen preq = talloc_get_type(pvt, struct pam_auth_req);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen pam_reply(preq);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainenstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen time_t expire_date, time_t delayed_until);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void pam_reply(struct pam_auth_req *preq)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen struct cli_ctx *cctx;
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen uint8_t *body;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen size_t blen;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int ret;
6094fe2df0a7efe28d45fa37b59755a2bee695e1Phil Carmody int32_t resp_c;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int32_t resp_size;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen struct response_data *resp;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int p;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen struct timeval tv;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen struct tevent_timer *te;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen struct pam_data *pd;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen struct pam_ctx *pctx;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen uint32_t user_info_type;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen time_t exp_date = -1;
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen time_t delay_until = -1;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen char* pam_account_expired_message;
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen pd = preq->pd;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen cctx = preq->cctx;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen DEBUG(SSSDBG_FUNC_DATA,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "pam_reply called with result [%d].\n", pd->pam_status);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
3278289d240da169166de8aa785273c5df904e64Timo Sirainen switch(pd->cmd) {
5f618705ebdfa8220a98a5cbb4a561e5e335cfffTimo Sirainen case SSS_PAM_AUTHENTICATE:
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if ((preq->domain != NULL) &&
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (preq->domain->cache_credentials == true) &&
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (pd->offline_auth == false)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *password = NULL;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen /* do auth with offline credentials */
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen pd->offline_auth = true;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (preq->domain->sysdb == NULL) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen "Fatal: Sysdb CTX not found for domain"
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen " [%s]!\n", preq->domain->name);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen goto done;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ret = sss_authtok_get_password(pd->authtok, &password, NULL);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (ret) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen goto done;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ret = sysdb_cache_auth(preq->domain,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen pd->user, password,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen pctx->rctx->cdb, false,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen &exp_date, &delay_until);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen pam_handle_cached_login(preq, ret, exp_date, delay_until);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen return;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen break;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen case SSS_PAM_CHAUTHTOK_PRELIM:
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen case SSS_PAM_CHAUTHTOK:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_FUNC_DATA,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "Password change not possible while offline.\n");
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen pd->pam_status = PAM_AUTHTOK_ERR;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (const uint8_t *) &user_info_type);
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen if (ret != EOK) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen goto done;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen break;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen/* TODO: we need the pam session cookie here to make sure that cached
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen * authentication was successful */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen case SSS_PAM_SETCRED:
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen case SSS_PAM_ACCT_MGMT:
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen case SSS_PAM_OPEN_SESSION:
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen case SSS_PAM_CLOSE_SESSION:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "Assuming offline authentication setting status for "
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "pam call %d to PAM_SUCCESS.\n", pd->cmd);
3278289d240da169166de8aa785273c5df904e64Timo Sirainen pd->pam_status = PAM_SUCCESS;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen break;
3278289d240da169166de8aa785273c5df904e64Timo Sirainen default:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
0bb8c135a1c065655fc4d2d89b74b4f958fe4f02Timo Sirainen pd->pam_status = PAM_MODULE_UNKNOWN;
0bb8c135a1c065655fc4d2d89b74b4f958fe4f02Timo Sirainen }
3278289d240da169166de8aa785273c5df904e64Timo Sirainen }
3278289d240da169166de8aa785273c5df904e64Timo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (pd->response_delay > 0) {
3278289d240da169166de8aa785273c5df904e64Timo Sirainen ret = gettimeofday(&tv, NULL);
3278289d240da169166de8aa785273c5df904e64Timo Sirainen if (ret != EOK) {
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
39dcbe101c4538ee25d8b196eab30e5f0faa22eeTimo Sirainen errno, strerror(errno));
3278289d240da169166de8aa785273c5df904e64Timo Sirainen goto done;
3278289d240da169166de8aa785273c5df904e64Timo Sirainen }
3278289d240da169166de8aa785273c5df904e64Timo Sirainen tv.tv_sec += pd->response_delay;
3278289d240da169166de8aa785273c5df904e64Timo Sirainen tv.tv_usec = 0;
3278289d240da169166de8aa785273c5df904e64Timo Sirainen pd->response_delay = 0;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
3278289d240da169166de8aa785273c5df904e64Timo Sirainen te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
0bb8c135a1c065655fc4d2d89b74b4f958fe4f02Timo Sirainen if (te == NULL) {
0bb8c135a1c065655fc4d2d89b74b4f958fe4f02Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
3278289d240da169166de8aa785273c5df904e64Timo Sirainen "Failed to add event pam_reply_delay.\n");
3278289d240da169166de8aa785273c5df904e64Timo Sirainen goto done;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* If this was a successful login, save the lastLogin time */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (pd->cmd == SSS_PAM_AUTHENTICATE &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen pd->pam_status == PAM_SUCCESS &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen preq->domain->cache_credentials &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen !pd->offline_auth &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen !pd->last_auth_saved &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen NEED_CHECK_PROVIDER(preq->domain->provider)) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ret = set_last_login(preq);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (ret != EOK) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen goto done;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen &cctx->creq->out);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (ret != EOK) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen goto done;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (pd->pam_status == PAM_ACCT_EXPIRED && pd->service != NULL &&
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen strcasecmp(pd->service, "sshd") == 0) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY,
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE, "",
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen &pam_account_expired_message);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen inform_account_expired(pd, pam_account_expired_message);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (ret != EOK) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (pd->domain != NULL) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen (uint8_t *) pd->domain);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (ret != EOK) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen goto done;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen resp_c = 0;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen resp_size = 0;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen resp = pd->resp_list;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen while(resp != NULL) {
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen if (!resp->do_not_send_to_client) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen resp_c++;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen resp_size += resp->len;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen resp = resp->next;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
e5a776932f62d971766d55b6bcc42d2824fa05a3Timo Sirainen
e5a776932f62d971766d55b6bcc42d2824fa05a3Timo Sirainen ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen sizeof(int32_t) +
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen resp_c * 2* sizeof(int32_t) +
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen resp_size);
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen if (ret != EOK) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen goto done;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen sss_packet_get_body(cctx->creq->out, &body, &blen);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen DEBUG(SSSDBG_FUNC_DATA, "blen: %zu\n", blen);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p = 0;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p += sizeof(int32_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen memcpy(&body[p], &resp_c, sizeof(int32_t));
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p += sizeof(int32_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen resp = pd->resp_list;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen while(resp != NULL) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (!resp->do_not_send_to_client) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen memcpy(&body[p], &resp->type, sizeof(int32_t));
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p += sizeof(int32_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen memcpy(&body[p], &resp->len, sizeof(int32_t));
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p += sizeof(int32_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen memcpy(&body[p], resp->data, resp->len);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen p += resp->len;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen resp = resp->next;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen }
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainendone:
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen sss_cmd_done(cctx, preq);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen}
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainenstatic void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen time_t expire_date, time_t delayed_until)
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen{
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen uint32_t resp_type;
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen size_t resp_len;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen uint8_t *resp;
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen int64_t dummy;
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen preq->pd->pam_status = cached_login_pam_status(ret);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen switch (preq->pd->pam_status) {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen case PAM_SUCCESS:
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen resp_len = sizeof(uint32_t) + sizeof(int64_t);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen resp = talloc_size(preq->pd, resp_len);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen if (resp == NULL) {
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen "talloc_size failed, cannot prepare user info.\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen memcpy(resp, &resp_type, sizeof(uint32_t));
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen dummy = (int64_t) expire_date;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen (const uint8_t *) resp);
3278289d240da169166de8aa785273c5df904e64Timo Sirainen if (ret != EOK) {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
657afb33796f8216c568ad813627da89970760beTimo Sirainen }
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case PAM_PERM_DENIED:
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (delayed_until >= 0) {
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen resp_len = sizeof(uint32_t) + sizeof(int64_t);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen resp = talloc_size(preq->pd, resp_len);
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen if (resp == NULL) {
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
c95b7ce6c3ebf84a9ef20320b9f11ef2129e1f1aTimo Sirainen "talloc_size failed, cannot prepare user info.\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen memcpy(resp, &resp_type, sizeof(uint32_t));
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen dummy = (int64_t) delayed_until;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen (const uint8_t *) resp);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (ret != EOK) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen "pam_add_response failed.\n");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen default:
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen DEBUG(SSSDBG_TRACE_LIBS,
47b5ef748f34ca194419befab4f7450002f4e85dTimo Sirainen "cached login returned: %d\n", preq->pd->pam_status);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen }
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen pam_reply(preq);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen return;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
62d1665ff7842b61bc99be238ede3921ec08ccc5Timo Sirainenstatic void pam_forwarder_cb(struct tevent_req *req);
62d1665ff7842b61bc99be238ede3921ec08ccc5Timo Sirainenstatic void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen const char *err_msg, void *ptr);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainenstatic int pam_check_user_search(struct pam_auth_req *preq);
62d1665ff7842b61bc99be238ede3921ec08ccc5Timo Sirainenstatic int pam_check_user_done(struct pam_auth_req *preq, int ret);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void pam_dom_forwarder(struct pam_auth_req *preq);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen/* TODO: we should probably return some sort of cookie that is set in the
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen * PAM_ENVIRONMENT, so that we can save performing some calls and cache
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen * data. */
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainenstatic errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen{
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen uint8_t *body;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen size_t blen;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen errno_t ret;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen uint32_t terminator;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen sss_packet_get_body(cctx->creq->in, &body, &blen);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen if (blen >= sizeof(uint32_t)) {
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen SAFEALIGN_COPY_UINT32(&terminator,
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen body + blen - sizeof(uint32_t),
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen NULL);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen if (terminator != SSS_END_OF_PAM_REQUEST) {
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n");
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen ret = EINVAL;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen goto done;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen }
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen }
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen switch (cctx->cli_protocol_version->version) {
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen case 1:
86a58337862c546aa489f07e8e6d242f0180e4a0Timo Sirainen ret = pam_parse_in_data(pd, body, blen);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen break;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen case 2:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = pam_parse_in_data_v2(pd, body, blen);
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case 3:
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen ret = pam_parse_in_data_v3(pd, body, blen);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen default:
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n",
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen cctx->cli_protocol_version->version);
29d4c6eac14a0b3d79656eb6b206a102fd09d24aTimo Sirainen ret = EINVAL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
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;
}