krb5_child.c revision d6c2ee96f5f181f21b0003aa8f3506e82522291d
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose/*
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose SSSD
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Kerberos 5 Backend Module -- tgt_req and changepw child
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Authors:
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Sumit Bose <sbose@redhat.com>
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Copyright (C) 2009-2010 Red Hat
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose This program is free software; you can redistribute it and/or modify
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose it under the terms of the GNU General Public License as published by
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose the Free Software Foundation; either version 3 of the License, or
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose (at your option) any later version.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose This program is distributed in the hope that it will be useful,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose GNU General Public License for more details.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose You should have received a copy of the GNU General Public License
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose*/
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include <sys/types.h>
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose#include <unistd.h>
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include <sys/stat.h>
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include <popt.h>
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose#include <security/pam_modules.h>
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include "util/util.h"
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include "util/sss_krb5.h"
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny#include "util/user_info_msg.h"
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose#include "util/child_common.h"
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny#include "providers/dp_backend.h"
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include "providers/krb5/krb5_auth.h"
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include "providers/krb5/krb5_utils.h"
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose#include "sss_cli.h"
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose#define SSSD_KRB5_CHANGEPW_PRINCIPAL "kadmin/changepw"
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestruct krb5_req {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_context ctx;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_principal princ;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose char* name;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_creds *creds;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_get_init_creds_opt *options;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct pam_data *pd;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce char *realm;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce char *ccname;
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose char *keytab;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce bool validate;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny bool send_pac;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny bool use_enterprise_princ;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny char *fast_ccname;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny const char *upn;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny uid_t uid;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny gid_t gid;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny};
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic krb5_context krb5_error_ctx;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny#define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error)
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic krb5_error_code get_changepw_options(krb5_context ctx,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny krb5_get_init_creds_opt **_options)
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce{
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce krb5_get_init_creds_opt *options;
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek krb5_error_code kerr;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce kerr = sss_krb5_get_init_creds_opt_alloc(ctx, &options);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce if (kerr != 0) {
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return kerr;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce sss_krb5_get_init_creds_opt_set_canonicalize(options, 0);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose krb5_get_init_creds_opt_set_forwardable(options, 0);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose krb5_get_init_creds_opt_set_proxiable(options, 0);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose krb5_get_init_creds_opt_set_renew_life(options, 0);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce krb5_get_init_creds_opt_set_tkt_life(options, 5*60);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose *_options = options;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return 0;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose}
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bosestatic errno_t sss_send_pac(krb5_authdata **pac_authdata)
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose{
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose struct sss_cli_req_data sss_data;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose int ret;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose int errnop;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose sss_data.len = pac_authdata[0]->length;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose sss_data.data = pac_authdata[0]->contents;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov NULL, NULL, &errnop);
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose if (ret != NSS_STATUS_SUCCESS || errnop != 0) {
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("sss_pac_make_request failed [%d][%d].\n",
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose ret, errnop));
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose return EIO;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose }
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek return EOK;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek}
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozekstatic void sss_krb5_expire_callback_func(krb5_context context, void *data,
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek krb5_timestamp password_expiration,
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek krb5_timestamp account_expiration,
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek krb5_boolean is_last_req)
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek{
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose int ret;
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose uint32_t *blob;
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose long exp_time;
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose struct krb5_req *kr = talloc_get_type(data, struct krb5_req);
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose if (password_expiration == 0) {
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose return;
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose }
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek exp_time = password_expiration - time(NULL);
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek if (exp_time < 0 || exp_time > UINT32_MAX) {
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek DEBUG(1, ("Time to expire out of range.\n"));
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek return;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek }
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, ("exp_time: [%d]\n", exp_time));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov blob = talloc_array(kr->pd, uint32_t, 2);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek if (blob == NULL) {
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(1, ("talloc_size failed.\n"));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek return;
06424c5ac5ffb871476208155762bb5b73e0b665Jakub Hrozek }
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek blob[0] = SSS_PAM_USER_INFO_EXPIRE_WARN;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov blob[1] = (uint32_t) exp_time;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek ret = pam_add_response(kr->pd, SSS_PAM_USER_INFO, 2 * sizeof(uint32_t),
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek (uint8_t *) blob);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek if (ret != EOK) {
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(1, ("pam_add_response failed.\n"));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose return;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose}
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose/*
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * TODO: These features generally would requires a significant refactoring
096a9678919fae460342469989b97fd47d812823Sumit Bose * of SSSD and MIT krb5 doesn't support them anyway. They are listed here
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * simply as a reminder of things that might become future feature potential.
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose *
096a9678919fae460342469989b97fd47d812823Sumit Bose * 1. tokeninfo selection
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * 2. challenge
096a9678919fae460342469989b97fd47d812823Sumit Bose * 3. discreet token/pin prompting
096a9678919fae460342469989b97fd47d812823Sumit Bose * 4. interactive otp format correction
096a9678919fae460342469989b97fd47d812823Sumit Bose * 5. nextOTP
096a9678919fae460342469989b97fd47d812823Sumit Bose *
096a9678919fae460342469989b97fd47d812823Sumit Bose */
096a9678919fae460342469989b97fd47d812823Sumit Bosetypedef int (*checker)(int c);
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bosestatic inline checker pick_checker(int format)
096a9678919fae460342469989b97fd47d812823Sumit Bose{
096a9678919fae460342469989b97fd47d812823Sumit Bose switch (format) {
096a9678919fae460342469989b97fd47d812823Sumit Bose case KRB5_RESPONDER_OTP_FORMAT_DECIMAL:
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return isdigit;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose case KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL:
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return isxdigit;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov case KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC:
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return isalnum;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose}
096a9678919fae460342469989b97fd47d812823Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic int token_pin_destructor(char *mem)
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose{
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose safezero(mem, strlen(mem));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return 0;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose}
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic krb5_error_code tokeninfo_matches(TALLOC_CTX *mem_ctx,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov const krb5_responder_otp_tokeninfo *ti,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose const char *pwd, size_t len,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose char **out_token, char **out_pin)
096a9678919fae460342469989b97fd47d812823Sumit Bose{
096a9678919fae460342469989b97fd47d812823Sumit Bose char *token = NULL, *pin = NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose checker check = NULL;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov int i;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->flags & KRB5_RESPONDER_OTP_FLAGS_NEXTOTP) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return ENOTSUP;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose if (ti->challenge != NULL) {
096a9678919fae460342469989b97fd47d812823Sumit Bose return ENOTSUP;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* This is a non-sensical value. */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->length == 0) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return EPROTO;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->flags & KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* ASSUMPTION: authtok has one of the following formats:
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * 1. TokenValue
096a9678919fae460342469989b97fd47d812823Sumit Bose * 2. PIN+TokenValue
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov token = talloc_strndup(mem_ctx, pwd, len);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (token == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return ENOMEM;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_set_destructor(token, token_pin_destructor);
096a9678919fae460342469989b97fd47d812823Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->flags & KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* If the server desires a separate pin, we will split it.
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * ASSUMPTION: Format of authtok is PIN+TokenValue. */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->flags & KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->length < 1) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_free(token);
096a9678919fae460342469989b97fd47d812823Sumit Bose return ENOTSUP;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ti->length >= len) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_free(token);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return EMSGSIZE;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Copy the PIN from the front of the value. */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov pin = talloc_strndup(NULL, pwd, len - ti->length);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (pin == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_free(token);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return ENOMEM;
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose }
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose talloc_set_destructor(pin, token_pin_destructor);
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose /* Remove the PIN from the front of the token value. */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov memmove(token, token + len - ti->length, ti->length + 1);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose check = pick_checker(ti->format);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose } else {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose if (ti->length > 0 && ti->length > len) {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose talloc_free(token);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return EMSGSIZE;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose }
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose } else {
096a9678919fae460342469989b97fd47d812823Sumit Bose if (ti->length > 0 && ti->length != len) {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose talloc_free(token);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return EMSGSIZE;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose check = pick_checker(ti->format);
096a9678919fae460342469989b97fd47d812823Sumit Bose }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov } else {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose pin = talloc_strndup(mem_ctx, pwd, len);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose if (pin == NULL) {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return ENOMEM;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_set_destructor(pin, token_pin_destructor);
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose /* If check is set, we need to verify the contents of the token. */
096a9678919fae460342469989b97fd47d812823Sumit Bose for (i = 0; check != NULL && token[i] != '\0'; i++) {
096a9678919fae460342469989b97fd47d812823Sumit Bose if (!check(token[i])) {
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_free(token);
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_free(pin);
096a9678919fae460342469989b97fd47d812823Sumit Bose return EBADMSG;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose *out_token = token;
096a9678919fae460342469989b97fd47d812823Sumit Bose *out_pin = pin;
096a9678919fae460342469989b97fd47d812823Sumit Bose return 0;
096a9678919fae460342469989b97fd47d812823Sumit Bose}
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bosestatic krb5_error_code answer_otp(krb5_context ctx,
096a9678919fae460342469989b97fd47d812823Sumit Bose struct krb5_req *kr,
096a9678919fae460342469989b97fd47d812823Sumit Bose krb5_responder_context rctx)
096a9678919fae460342469989b97fd47d812823Sumit Bose{
096a9678919fae460342469989b97fd47d812823Sumit Bose krb5_responder_otp_challenge *chl;
096a9678919fae460342469989b97fd47d812823Sumit Bose char *token = NULL, *pin = NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose const char *pwd = NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose krb5_error_code ret;
096a9678919fae460342469989b97fd47d812823Sumit Bose size_t i, len;
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose ret = krb5_responder_otp_get_challenge(ctx, rctx, &chl);
096a9678919fae460342469989b97fd47d812823Sumit Bose if (ret != EOK || chl == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Either an error, or nothing to do. */
096a9678919fae460342469989b97fd47d812823Sumit Bose return ret;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (chl->tokeninfo == NULL || chl->tokeninfo[0] == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* No tokeninfos? Absurd! */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose ret = EINVAL;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose goto done;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Validate our assumptions about the contents of authtok. */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose ret = sss_authtok_get_password(kr->pd->authtok, &pwd, &len);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (ret != EOK)
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose goto done;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek /* Find the first supported tokeninfo which matches our authtoken. */
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek for (i = 0; chl->tokeninfo[i] != NULL; i++) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek ret = tokeninfo_matches(kr, chl->tokeninfo[i], pwd, len, &token, &pin);
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek if (ret == EOK) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek break;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek }
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek switch (ret) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek case EBADMSG:
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov case EMSGSIZE:
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek case ENOTSUP:
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek case EPROTO:
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek break;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek default:
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek goto done;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek }
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (chl->tokeninfo[i] == NULL) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ("No tokeninfos found which match our credentials.\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ret = EOK;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose goto done;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (chl->tokeninfo[i]->flags & KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose /* Don't let SSSD cache the OTP authtok since it is single-use. */
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ret = pam_add_response(kr->pd, SSS_OTP, 0, NULL);
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (ret != EOK) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("pam_add_response failed.\n"));
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek goto done;
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose /* Respond with the appropriate answer. */
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek ret = krb5_responder_otp_set_answer(ctx, rctx, i, token, pin);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bosedone:
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose talloc_free(token);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose talloc_free(pin);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose krb5_responder_otp_challenge_free(ctx, rctx, chl);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose return ret;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose}
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic krb5_error_code sss_krb5_responder(krb5_context ctx,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose void *data,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose krb5_responder_context rctx)
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose{
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose struct krb5_req *kr = talloc_get_type(data, struct krb5_req);
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (kr == NULL) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose return EINVAL;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose return answer_otp(ctx, kr, rctx);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose}
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose#endif
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bosestatic krb5_error_code sss_krb5_prompter(krb5_context context, void *data,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose const char *name, const char *banner,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int num_prompts, krb5_prompt prompts[])
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int ret;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct krb5_req *kr = talloc_get_type(data, struct krb5_req);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (num_prompts != 0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(1, ("Cannot handle password prompts.\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return KRB5_LIBOS_CANTREADPWD;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (banner == NULL || *banner == '\0') {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(5, ("Prompter called with empty banner, nothing to do.\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return EOK;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(SSSDBG_FUNC_DATA, ("Prompter called with [%s].\n", banner));
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek ret = pam_add_response(kr->pd, SSS_PAM_TEXT_MSG, strlen(banner)+1,
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose (const uint8_t *) banner);
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek if (ret != EOK) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(1, ("pam_add_response failed.\n"));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce }
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce return EOK;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce}
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic krb5_error_code create_empty_cred(krb5_context ctx, krb5_principal princ,
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose krb5_creds **_cred)
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek krb5_error_code kerr;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_creds *cred = NULL;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek krb5_data *krb5_realm;
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek cred = calloc(sizeof(krb5_creds), 1);
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek if (cred == NULL) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce DEBUG(1, ("calloc failed.\n"));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce return ENOMEM;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce kerr = krb5_copy_principal(ctx, princ, &cred->client);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr != 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(1, ("krb5_copy_principal failed.\n"));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce goto done;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce }
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce krb5_realm = krb5_princ_realm(ctx, princ);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_build_principal_ext(ctx, &cred->server,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce krb5_realm->length, krb5_realm->data,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov krb5_realm->length, krb5_realm->data, 0);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("krb5_build_principal_ext failed.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose goto done;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, ("Created empty krb5_creds.\n"));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcedone:
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (kerr != 0) {
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose if (cred != NULL && cred->client != NULL) {
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose krb5_free_principal(ctx, cred->client);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose free(cred);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose } else {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose *_cred = cred;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek return kerr;
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek}
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek#ifdef HAVE_KRB5_DIRCACHE
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic bool need_switch_to_principal(krb5_context ctx, krb5_principal princ)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek krb5_error_code kerr;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek krb5_ccache default_cc = NULL;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek krb5_principal default_princ = NULL;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek char *default_full_name = NULL;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek char *full_name = NULL;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek bool ret = false;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek kerr = krb5_cc_default(ctx, &default_cc);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (kerr !=0) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek goto done;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov kerr = krb5_cc_get_principal(ctx, default_cc, &default_princ);
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek if (kerr == KRB5_FCC_NOFILE) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* There is not any default cache. */
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce ret = true;
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek goto done;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce } else if (kerr != 0) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek kerr = krb5_unparse_name(ctx, default_princ, &default_full_name);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (kerr !=0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek goto done;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek kerr = krb5_unparse_name(ctx, princ, &full_name);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (kerr !=0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek goto done;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(SSSDBG_FUNC_DATA,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek ("Comparing default principal [%s] and new principal [%s].\n",
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek default_full_name, full_name));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (0 == strcmp(default_full_name, full_name)) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek ret = true;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcedone:
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (default_cc != NULL) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek kerr = krb5_cc_close(ctx, default_cc);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* all functions can be safely called with NULL. */
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce krb5_free_principal(ctx, default_princ);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce krb5_free_unparsed_name(ctx, default_full_name);
95e94691178297f2b8225a83d43ae388cab04b45Simo Sorce krb5_free_unparsed_name(ctx, full_name);
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
4f118e3e6a25762f40a43e6dbefb09f44adbef32Simo Sorce return ret;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce}
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce#endif /* HAVE_KRB5_DIRCACHE */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcestatic krb5_error_code
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcestore_creds_in_ccache(krb5_context ctx, krb5_principal princ,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce krb5_ccache cc, krb5_creds *creds)
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce{
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov krb5_error_code kerr;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_creds *l_cred;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce kerr = krb5_cc_initialize(ctx, cc, princ);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose goto done;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (creds == NULL) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce kerr = create_empty_cred(ctx, princ, &l_cred);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce if (kerr != 0) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek } else {
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek l_cred = creds;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce kerr = krb5_cc_store_cred(ctx, cc, l_cred);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (kerr != 0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce#ifdef HAVE_KRB5_DIRCACHE
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (need_switch_to_principal(ctx, princ)) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce kerr = krb5_cc_switch(ctx, cc);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce#endif /* HAVE_KRB5_DIRCACHE */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce kerr = krb5_cc_close(ctx, cc);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozekdone:
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return kerr;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic krb5_error_code create_ccache_file(krb5_context ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_principal princ,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose char *ccname, krb5_creds *creds)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce krb5_error_code kerr;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce krb5_ccache tmp_cc = NULL;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce char *cc_file_name;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce int fd = -1;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose size_t ccname_len;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose char *dummy;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose char *tmp_ccname;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose TALLOC_CTX *tmp_ctx = NULL;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose mode_t old_umask;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (strncmp(ccname, "FILE:", 5) == 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose cc_file_name = ccname + 5;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose } else {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose cc_file_name = ccname;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (cc_file_name[0] != '/') {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(1, ("Ccache filename is not an absolute path.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return EINVAL;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tmp_ctx = talloc_new(tmp_ctx);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (tmp_ctx == NULL) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DEBUG(1, ("talloc_new failed.\n"));
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek return ENOMEM;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek dummy = strrchr(cc_file_name, '/');
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek tmp_ccname = talloc_strndup(tmp_ctx, cc_file_name,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose (size_t) (dummy-cc_file_name));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (tmp_ccname == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(1, ("talloc_strdup failed.\n"));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny kerr = ENOMEM;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny goto done;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce }
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce tmp_ccname = talloc_asprintf_append(tmp_ccname, "/.krb5cc_dummy_XXXXXX");
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce if (tmp_ccname == NULL) {
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce kerr = ENOMEM;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce goto done;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek old_umask = umask(077);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce fd = mkstemp(tmp_ccname);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce umask(old_umask);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce if (fd == -1) {
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce kerr = errno;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce goto done;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_cc_resolve(ctx, tmp_ccname, &tmp_cc);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (kerr != 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce goto done;
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (fd != -1) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce close(fd);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce fd = -1;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (kerr != 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose goto done;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose ccname_len = strlen(cc_file_name);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len - 6), "XXXXXX") == 0) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce fd = mkstemp(cc_file_name);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (fd == -1) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce kerr = errno;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce goto done;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = rename(tmp_ccname, cc_file_name);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr == -1) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce kerr = errno;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(1, ("rename failed [%d][%s].\n", kerr, strerror(kerr)));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", ccname));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosedone:
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (kerr != 0 && tmp_cc != NULL) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_cc_destroy(ctx, tmp_cc);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (fd != -1) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce close(fd);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce talloc_free(tmp_ctx);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return kerr;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose}
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#ifdef HAVE_KRB5_DIRCACHE
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic errno_t
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosecreate_ccdir(const char *dirname, uid_t uid, gid_t gid)
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce{
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce mode_t old_umask;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce struct stat statbuf;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce errno_t ret;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose old_umask = umask(0000);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = mkdir(dirname, 0700);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose umask(old_umask);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (ret == -1) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* Failing the mkdir is only OK if the directory already
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov * exists AND it is owned by the same user and group and
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * has the correct permissions.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (ret == EEXIST) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose errno = 0;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = stat(dirname, &statbuf);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (ret == -1) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = errno;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek ("stat failed [%d]: %s\n", ret, strerror(ret)));
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek return EIO;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ("The directory %s is owned by %d/%d, expected %d/%d\n",
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose dirname, statbuf.st_uid, statbuf.st_gid, uid, gid));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return EACCES;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if ((statbuf.st_mode & ~S_IFMT) != 0700) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ("The directory %s has wrong permissions %o, expected 0700\n",
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny dirname, (statbuf.st_mode & ~S_IFMT)));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return EACCES;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose } else {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("mkdir [%s] failed [%d]: %s\n",
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny dirname, ret, strerror(ret)));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return ret;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return EOK;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny}
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic krb5_error_code
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosecreate_ccache_in_dir(uid_t uid, gid_t gid,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_context ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_principal princ,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose char *ccname, krb5_creds *creds)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce krb5_error_code kerr;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce krb5_ccache tmp_cc = NULL;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose const char *dirname;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce dirname = sss_krb5_residual_check_type(ccname, SSS_KRB5_TYPE_DIR);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (dirname == NULL) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return EIO;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = become_user(uid, gid);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr != EOK) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("become_user failed.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose goto done;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (dirname[0] == ':') {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Cache name in the form of DIR::filepath represents a single
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * ccache in a collection that we are trying to reuse.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * See src/lib/krb5/ccache/cc_dir.c in the MIT Kerberos tree.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr != 0) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek goto done;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek } else if (dirname[0] == '/') {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek /* An absolute path denotes that krb5_child should create a new
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek * ccache. We can afford to just call mkdir(dirname) because we
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek * only want the last component to be created.
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek */
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek kerr = create_ccdir(dirname, uid, gid);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if (kerr) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek ("Cannot create directory %s\n", dirname));
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek goto done;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek kerr = krb5_cc_set_default_name(ctx, ccname);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if (kerr != 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose } else {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose ("Wrong residual format for DIR in ccache %s\n", ccname));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return EIO;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosedone:
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0 && tmp_cc != NULL) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose krb5_cc_destroy(ctx, tmp_cc);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return kerr;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose}
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose#endif /* HAVE_KRB5_DIRCACHE */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosestatic krb5_error_code
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosecreate_ccache(uid_t uid, gid_t gid, krb5_context ctx,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose krb5_principal princ, char *ccname, krb5_creds *creds)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose enum sss_krb5_cc_type cctype;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose cctype = sss_krb5_get_type(ccname);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose switch (cctype) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose case SSS_KRB5_TYPE_FILE:
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return create_ccache_file(ctx, princ, ccname, creds);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose#ifdef HAVE_KRB5_DIRCACHE
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose case SSS_KRB5_TYPE_DIR:
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return create_ccache_in_dir(uid, gid, ctx, princ, ccname, creds);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose#endif /* HAVE_KRB5_DIRCACHE */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose default:
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return EINVAL;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return EINVAL; /* Should never get here */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose}
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosestatic errno_t pack_response_packet(TALLOC_CTX *mem_ctx, errno_t error,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct response_data *resp_list,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose uint8_t **_buf, size_t *_len)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose uint8_t *buf;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose size_t size = 0;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose size_t p = 0;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose struct response_data *pdr;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose /* A buffer with the following structure must be created:
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose * int32_t status of the request (required)
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose * message (zero or more)
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose *
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose * A message consists of:
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose * int32_t type of the message
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose * int32_t length of the following data
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose * uint8_t[len] data
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose */
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose size = sizeof(int32_t);
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose for (pdr = resp_list; pdr != NULL; pdr = pdr->next) {
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose size += 2*sizeof(int32_t) + pdr->len;
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose }
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose buf = talloc_array(mem_ctx, uint8_t, size);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (!buf) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(1, ("Insufficient memory to create message.\n"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return ENOMEM;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose SAFEALIGN_SET_INT32(&buf[p], error, &p);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose for (pdr = resp_list; pdr != NULL; pdr = pdr->next) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose SAFEALIGN_SET_INT32(&buf[p], pdr->type, &p);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose SAFEALIGN_SET_INT32(&buf[p], pdr->len, &p);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose safealign_memcpy(&buf[p], pdr->data, pdr->len, &p);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_TRACE_INTERNAL, ("response packet size: [%d]\n", p));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose *_buf = buf;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose *_len = p;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return EOK;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose}
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosestatic errno_t k5c_attach_ccname_msg(struct krb5_req *kr)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose char *msg = NULL;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose int ret;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kr->ccname == NULL) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(1, ("Error obtaining ccname.\n"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return ERR_INTERNAL;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (msg == NULL) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(1, ("talloc_asprintf failed.\n"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return ENOMEM;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose }
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose ret = pam_add_response(kr->pd, SSS_PAM_ENV_ITEM,
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose strlen(msg) + 1, (uint8_t *)msg);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose talloc_zfree(msg);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return ret;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose}
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bosestatic errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose size_t written;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose uint8_t *buf;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose size_t len;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose int ret;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose ret = pack_response_packet(kr, error, kr->pd->resp_list, &buf, &len);
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose if (ret != EOK) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(1, ("pack_response_packet failed.\n"));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose return ret;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose errno = 0;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose written = sss_atomic_write_s(fd, buf, len);
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose if (written == -1) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose ret = errno;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose ("write failed [%d][%s].\n", ret, strerror(ret)));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose return ret;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose if (written != len) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE,
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose ("Write error, wrote [%d] bytes, expected [%d]\n",
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose written, len));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose return EOK;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(SSSDBG_TRACE_ALL, ("Response sent.\n"));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose return EOK;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose}
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bosestatic errno_t add_ticket_times_and_upn_to_response(struct krb5_req *kr)
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose{
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose int ret;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose int64_t t[4];
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose krb5_error_code kerr;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose char *upn = NULL;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose unsigned int upn_len = 0;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose t[0] = (int64_t) kr->creds->times.authtime;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose t[1] = (int64_t) kr->creds->times.starttime;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose t[2] = (int64_t) kr->creds->times.endtime;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose t[3] = (int64_t) kr->creds->times.renew_till;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose ret = pam_add_response(kr->pd, SSS_KRB5_INFO_TGT_LIFETIME,
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose 4*sizeof(int64_t), (uint8_t *) t);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose if (ret != EOK) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(1, ("pack_response_packet failed.\n"));
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose goto done;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose kerr = krb5_unparse_name_ext(kr->ctx, kr->creds->client, &upn, &upn_len);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose if (kerr != 0) {
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose DEBUG(SSSDBG_OP_FAILURE, ("krb5_unparse_name failed.\n"));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose goto done;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose }
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose ret = pam_add_response(kr->pd, SSS_KRB5_INFO_UPN, upn_len,
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose (uint8_t *) upn);
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_free_unparsed_name(kr->ctx, upn);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose if (ret != EOK) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(1, ("pack_response_packet failed.\n"));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose goto done;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bosedone:
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose return ret;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose}
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bosestatic krb5_error_code validate_tgt(struct krb5_req *kr)
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose{
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose krb5_error_code kerr;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose krb5_error_code kt_err;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose char *principal = NULL;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_keytab keytab;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_kt_cursor cursor;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_keytab_entry entry;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_verify_init_creds_opt opt;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_principal validation_princ = NULL;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose bool realm_entry_found = false;
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose krb5_ccache validation_ccache = NULL;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose krb5_authdata **pac_authdata = NULL;
61d2ccf1dae3f1e7fc987ae98cb5c493cc73a782Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose memset(&keytab, 0, sizeof(keytab));
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose kerr = krb5_kt_resolve(kr->ctx, kr->keytab, &keytab);
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose if (kerr != 0) {
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("error resolving keytab [%s], " \
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose "not verifying TGT.\n", kr->keytab));
61d2ccf1dae3f1e7fc987ae98cb5c493cc73a782Sumit Bose return kerr;
61d2ccf1dae3f1e7fc987ae98cb5c493cc73a782Sumit Bose }
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose
2bf1cbffaac3b4bc0bd736493c985ca865092805Sumit Bose memset(&cursor, 0, sizeof(cursor));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = krb5_kt_start_seq_get(kr->ctx, keytab, &cursor);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0) {
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("error reading keytab [%s], " \
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose "not verifying TGT.\n", kr->keytab));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return kerr;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose /* We look for the first entry from our realm or take the last one */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose memset(&entry, 0, sizeof(entry));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose while ((kt_err = krb5_kt_next_entry(kr->ctx, keytab, &entry, &cursor)) == 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (validation_princ != NULL) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_free_principal(kr->ctx, validation_princ);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose validation_princ = NULL;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_copy_principal(kr->ctx, entry.principal,
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce &validation_princ);
1e6f2180724de4722a5218826c9401181168d9d4Simo Sorce if (kerr != 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_copy_principal failed.\n"));
ce29aa8998332fd3c2e4e4b81e7302d41c461893Sumit Bose goto done;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce
ccc2af010bbbe6d8a7496fb717216135bc4c1993Simo Sorce kerr = sss_krb5_free_keytab_entry_contents(kr->ctx, &entry);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr != 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to free keytab entry.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose memset(&entry, 0, sizeof(entry));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (krb5_realm_compare(kr->ctx, validation_princ, kr->creds->client)) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_TRACE_INTERNAL,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ("Found keytab entry with the realm of the credential.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose realm_entry_found = true;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose break;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (!realm_entry_found) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_TRACE_INTERNAL,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ("Keytab entry with the realm of the credential not found "
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose "in keytab. Using the last entry.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Close the keytab here. Even though we're using cursors, the file
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek * handle is stored in the krb5_keytab structure, and it gets
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * overwritten when the verify_init_creds() call below creates its own
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * cursor, creating a leak. */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_kt_end_seq_get(kr->ctx, keytab, &cursor);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kerr != 0) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_kt_end_seq_get failed, " \
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose "not verifying TGT.\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce goto done;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* check if we got any errors from krb5_kt_next_entry */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (kt_err != 0 && kt_err != KRB5_KT_END) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("error reading keytab [%s], " \
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose "not verifying TGT.\n", kr->keytab));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce goto done;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* Get the principal to which the key belongs, for logging purposes. */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce principal = NULL;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce kerr = krb5_unparse_name(kr->ctx, validation_princ, &principal);
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek if (kerr != 0) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("internal error parsing principal name, "
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek "not verifying TGT.\n"));
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek goto done;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose krb5_verify_init_creds_opt_init(&opt);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kerr = krb5_verify_init_creds(kr->ctx, kr->creds, validation_princ, keytab,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose &validation_ccache, &opt);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr == 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_TRACE_FUNC, ("TGT verified using key for [%s].\n",
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose principal));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose } else {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE ,("TGT failed verification using key " \
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose "for [%s].\n", principal));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* Try to find and send the PAC to the PAC responder.
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose * Failures are not critical. */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kr->send_pac) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = sss_extract_pac(kr->ctx, validation_ccache, validation_princ,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kr->creds->client, keytab, &pac_authdata);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_OP_FAILURE, ("sss_extract_and_send_pac failed, group " \
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose "membership for user with principal [%s] " \
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose "might not be correct.\n", kr->name));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = 0;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek kerr = sss_send_pac(pac_authdata);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose krb5_free_authdata(kr->ctx, pac_authdata);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (kerr != 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(SSSDBG_OP_FAILURE, ("sss_send_pac failed, group " \
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose "membership for user with principal [%s] " \
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose "might not be correct.\n", kr->name));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = 0;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosedone:
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (validation_ccache != NULL) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose krb5_cc_destroy(kr->ctx, validation_ccache);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose if (krb5_kt_close(kr->ctx, keytab) != 0) {
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose DEBUG(SSSDBG_MINOR_FAILURE, ("krb5_kt_close failed"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (validation_princ != NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_free_principal(kr->ctx, validation_princ);
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose }
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose if (principal != NULL) {
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose sss_krb5_free_unparsed_name(kr->ctx, principal);
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek return kerr;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose}
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bosestatic void krb5_set_canonicalize(krb5_get_init_creds_opt *opts)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose int canonicalize = 0;
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose char *tmp_str;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose tmp_str = getenv(SSSD_KRB5_CANONICALIZE);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose canonicalize = 1;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose SSSD_KRB5_CANONICALIZE, tmp_str ? tmp_str : "not set"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose sss_krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce}
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx,
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce krb5_principal princ,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_keytab keytab,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose char *ccname)
0754ff886f909f0404038eb9c99dd61be1acf5b9Simo Sorce{
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_error_code kerr = 0;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce krb5_creds creds;
ccc2af010bbbe6d8a7496fb717216135bc4c1993Simo Sorce krb5_get_init_creds_opt options;
ccc2af010bbbe6d8a7496fb717216135bc4c1993Simo Sorce
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose memset(&creds, 0, sizeof(creds));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose memset(&options, 0, sizeof(options));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_get_init_creds_opt_set_address_list(&options, NULL);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov krb5_get_init_creds_opt_set_forwardable(&options, 0);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_get_init_creds_opt_set_proxiable(&options, 0);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose krb5_set_canonicalize(&options);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose kerr = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL,
096a9678919fae460342469989b97fd47d812823Sumit Bose &options);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (kerr != 0) {
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return kerr;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Use the updated principal in the creds in case canonicalized */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose kerr = create_ccache_file(ctx, creds.client, ccname, &creds);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (kerr != 0) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov goto done;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose kerr = 0;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozekdone:
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek krb5_free_cred_contents(ctx, &creds);
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek return kerr;
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek}
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozekstatic krb5_error_code get_and_save_tgt(struct krb5_req *kr,
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek const char *password)
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek{
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek const char *realm_name;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek int realm_length;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek krb5_error_code kerr;
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose char *cc_name;
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose krb5_principal principal;
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx, kr->options,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny sss_krb5_expire_callback_func,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny kr);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (kerr != 0) {
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny DEBUG(1, ("Failed to set expire callback, continue without.\n"));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce sss_krb5_princ_realm(kr->ctx, kr->princ, &realm_name, &realm_length);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose DEBUG(SSSDBG_TRACE_FUNC,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ("Attempting kinit for realm [%s]\n",realm_name));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny discard_const(password),
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny sss_krb5_prompter, kr, 0,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny NULL, kr->options);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce if (kerr != 0) {
f99534c058e9367d2610de89b1af4dcc1ec63035Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return kerr;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce if (kr->validate) {
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce kerr = validate_tgt(kr);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (kerr != 0) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return kerr;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny } else {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny DEBUG(SSSDBG_CONF_SETTINGS, ("TGT validation is disabled.\n"));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
3912262270a6449ebe1d3e92c27c217b4044f894Simo Sorce
3912262270a6449ebe1d3e92c27c217b4044f894Simo Sorce if (kr->validate || kr->fast_ccname != NULL) {
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek /* We drop root privileges which were needed to read the keytab file
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * for the validation of the credentials or for FAST here to run the
3912262270a6449ebe1d3e92c27c217b4044f894Simo Sorce * ccache I/O operations with user privileges. */
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce kerr = become_user(kr->uid, kr->gid);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce if (kerr != 0) {
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce DEBUG(1, ("become_user failed.\n"));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return kerr;
3912262270a6449ebe1d3e92c27c217b4044f894Simo Sorce }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny principal = kr->creds ? kr->creds->client : kr->princ;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek /* If kr->ccname is cache collection (DIR:/...), we want to work
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek * directly with file ccache (DIR::/...), but cache collection
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek * should be returned back to back end.
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek */
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek cc_name = sss_get_ccache_name_for_principal(kr->pd, kr->ctx, principal,
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek kr->ccname);
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek if (cc_name == NULL) {
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek cc_name = kr->ccname;
3912262270a6449ebe1d3e92c27c217b4044f894Simo Sorce }
9af86b9c936d07cff9d0c2054acde908749ea522Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek /* Use the updated principal in the creds in case canonicalized */
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek principal, cc_name, kr->creds);
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek if (kerr != 0) {
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek goto done;
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek }
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek kerr = add_ticket_times_and_upn_to_response(kr);
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek if (kerr != 0) {
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek }
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek kerr = 0;
5a5f1e1053415efaa99bb4d5bc7ce7ac0a95b757Jakub Hrozek
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenydone:
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek krb5_free_cred_contents(kr->ctx, kr->creds);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return kerr;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny}
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic errno_t map_krb5_error(krb5_error_code kerr)
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny{
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov switch (kerr) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose case 0:
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose return ERR_OK;
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose case KRB5_LIBOS_CANTREADPWD:
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose return ERR_NO_CREDS;
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny case KRB5_KDC_UNREACH:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return ERR_NETWORK_IO;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose case KRB5KDC_ERR_KEY_EXP:
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce return ERR_CREDS_EXPIRED;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce case KRB5KRB_AP_ERR_BAD_INTEGRITY:
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return ERR_AUTH_FAILED;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce case KRB5_PREAUTH_FAILED:
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce case KRB5KDC_ERR_PREAUTH_FAILED:
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return ERR_CREDS_INVALID;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce default:
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return ERR_INTERNAL;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce}
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorcestatic errno_t changepw_child(struct krb5_req *kr, bool prelim)
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce{
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce int ret;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce krb5_error_code kerr = 0;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce const char *password = NULL;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce const char *newpassword = NULL;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce int result_code = -1;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce krb5_data result_code_string;
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce krb5_data result_string;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose char *user_error_message = NULL;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose size_t user_resp_len;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose uint8_t *user_resp;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose krb5_prompter_fct prompter = NULL;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose const char *realm_name;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose int realm_length;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov krb5_get_init_creds_opt *chagepw_options;
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose DEBUG(SSSDBG_TRACE_LIBS, ("Password change operation\n"));
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret = sss_authtok_get_password(kr->pd->authtok, &password, NULL);
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose if (ret != EOK) {
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose DEBUG(1, ("Failed to fetch current password [%d] %s.\n",
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose ret, strerror(ret)));
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose return ERR_NO_CREDS;
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (!prelim) {
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce /* We do not need a password expiration warning here. */
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce prompter = sss_krb5_prompter;
cd4cc8d8829f1ea5257bf874b91980368114275fPavel Březina }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce kerr = get_changepw_options(kr->ctx, &chagepw_options);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce if (kerr != 0) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n"));
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return kerr;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose sss_krb5_princ_realm(kr->ctx, kr->princ, &realm_name, &realm_length);
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce
cd4cc8d8829f1ea5257bf874b91980368114275fPavel Březina DEBUG(SSSDBG_TRACE_FUNC,
cd4cc8d8829f1ea5257bf874b91980368114275fPavel Březina ("Attempting kinit for realm [%s]\n",realm_name));
99151f2217ddaa179543b89b49f836f29f7dcd2aSimo Sorce kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
99151f2217ddaa179543b89b49f836f29f7dcd2aSimo Sorce discard_const(password),
44af0057c1fd52f6252f82ca73a06acfcac6c5e3Michal Zidek prompter, kr, 0,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov SSSD_KRB5_CHANGEPW_PRINCIPAL,
44af0057c1fd52f6252f82ca73a06acfcac6c5e3Michal Zidek chagepw_options);
44af0057c1fd52f6252f82ca73a06acfcac6c5e3Michal Zidek sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce if (kerr != 0) {
d6d8287a9b8a240e068a26769dc6ce4582604850Simo Sorce return kerr;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
cd4cc8d8829f1ea5257bf874b91980368114275fPavel Březina
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce sss_authtok_set_empty(kr->pd->authtok);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce if (prelim) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_LIBS,
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce ("Initial authentication for change password operation "
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce "successful.\n"));
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce krb5_free_cred_contents(kr->ctx, kr->creds);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return EOK;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce ret = sss_authtok_get_password(kr->pd->newauthtok, &newpassword, NULL);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce if (ret != EOK) {
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce DEBUG(1, ("Failed to fetch new password [%d] %s.\n",
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce ret, strerror(ret)));
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return ERR_NO_CREDS;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce memset(&result_code_string, 0, sizeof(krb5_data));
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose memset(&result_string, 0, sizeof(krb5_data));
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose kerr = krb5_change_password(kr->ctx, kr->creds,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose discard_const(newpassword), &result_code,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose &result_code_string, &result_string);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (kerr == KRB5_KDC_UNREACH) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose return ERR_NETWORK_IO;
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (kerr != 0 || result_code != 0) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (kerr != 0) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (result_code_string.length > 0) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose result_code_string.length, result_code_string.data));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov user_error_message = talloc_strndup(kr->pd, result_code_string.data,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose result_code_string.length);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (user_error_message == NULL) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(1, ("talloc_strndup failed.\n"));
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (result_string.length > 0 && result_string.data[0] != '\0') {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose result_string.length, result_string.data));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov talloc_free(user_error_message);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov user_error_message = talloc_strndup(kr->pd, result_string.data,
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose result_string.length);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (user_error_message == NULL) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(1, ("talloc_strndup failed.\n"));
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose } else if (result_code == KRB5_KPASSWD_SOFTERROR) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose user_error_message = talloc_strdup(kr->pd, "Please make sure the "
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose "password meets the complexity constraints.");
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose if (user_error_message == NULL) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strndup failed.\n"));
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
03abdaa21ecf562b714f204ca42379ff08626f75Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (user_error_message != NULL) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose ret = pack_user_info_chpass_error(kr->pd, user_error_message,
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce &user_resp_len, &user_resp);
03abdaa21ecf562b714f204ca42379ff08626f75Simo Sorce if (ret != EOK) {
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce DEBUG(1, ("pack_user_info_chpass_error failed.\n"));
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce } else {
8e5549e453558d4bebdec333a93e215d5d6ffaecSimo Sorce ret = pam_add_response(kr->pd, SSS_PAM_USER_INFO, user_resp_len,
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce user_resp);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (ret != EOK) {
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce DEBUG(1, ("pack_response_packet failed.\n"));
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return ERR_CHPASS_FAILED;
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose krb5_free_cred_contents(kr->ctx, kr->creds);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose kerr = get_and_save_tgt(kr, newpassword);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce sss_authtok_set_empty(kr->pd->newauthtok);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (kerr == 0) {
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce kerr = k5c_attach_ccname_msg(kr);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce return map_krb5_error(kerr);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce}
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorcestatic errno_t tgt_req_child(struct krb5_req *kr)
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce{
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce krb5_get_init_creds_opt *chagepw_options;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce const char *password = NULL;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce krb5_error_code kerr;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce int ret;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce DEBUG(SSSDBG_TRACE_LIBS, ("Attempting to get a TGT\n"));
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose ret = sss_authtok_get_password(kr->pd->authtok, &password, NULL);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose switch (ret) {
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose case EOK:
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose break;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose case EACCES:
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Invalid authtok type\n"));
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce return ERR_INVALID_CRED_TYPE;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce break;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov default:
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce DEBUG(SSSDBG_OP_FAILURE, ("No credentials available\n"));
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce return ERR_NO_CREDS;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce break;
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce kerr = get_and_save_tgt(kr, password);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce if (kerr != KRB5KDC_ERR_KEY_EXP) {
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce if (kerr == 0) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose kerr = k5c_attach_ccname_msg(kr);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose }
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose ret = map_krb5_error(kerr);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce goto done;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce }
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose /* If the password is expired the KDC will always return
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose KRB5KDC_ERR_KEY_EXP regardless if the supplied password is correct or
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose not. In general the password can still be used to get a changepw ticket.
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose So we validate the password by trying to get a changepw ticket. */
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose DEBUG(SSSDBG_TRACE_LIBS, ("Password was expired\n"));
87f8bee53ee1b4ca87b602ff8536bc5fd5b5b595Lukas Slebodnik kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx,
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose kr->options,
fab48878db202d620f43c9da23e375866d1db2c6Sumit Bose NULL, NULL);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce if (kerr != 0) {
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
87f8bee53ee1b4ca87b602ff8536bc5fd5b5b595Lukas Slebodnik DEBUG(1, ("Failed to unset expire callback, continue ...\n"));
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce kerr = get_changepw_options(kr->ctx, &chagepw_options);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce if (kerr != 0) {
87f8bee53ee1b4ca87b602ff8536bc5fd5b5b595Lukas Slebodnik DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n"));
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce return kerr;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce }
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
2b4b6b829f197493b4901bec96fefaadbc7a2464Jakub Hrozek kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov discard_const(password),
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov sss_krb5_prompter, kr, 0,
2b4b6b829f197493b4901bec96fefaadbc7a2464Jakub Hrozek SSSD_KRB5_CHANGEPW_PRINCIPAL,
2b4b6b829f197493b4901bec96fefaadbc7a2464Jakub Hrozek chagepw_options);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek krb5_free_cred_contents(kr->ctx, kr->creds);
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek if (kerr == 0) {
b17b51c2779906bf3a5e4aecbb9ef8bfbfc2ebabJakub Hrozek ret = ERR_CREDS_EXPIRED;
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek } else {
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek ret = map_krb5_error(kerr);
}
done:
sss_authtok_set_empty(kr->pd->authtok);
return ret;
}
static errno_t kuserok_child(struct krb5_req *kr)
{
krb5_boolean access_allowed;
krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Verifying if principal can log in as user\n"));
/* krb5_kuserok tries to verify that kr->pd->user is a locally known
* account, so we have to unset _SSS_LOOPS to make getpwnam() work. */
if (unsetenv("_SSS_LOOPS") != 0) {
DEBUG(1, ("Failed to unset _SSS_LOOPS, "
"krb5_kuserok will most certainly fail.\n"));
}
kerr = krb5_set_default_realm(kr->ctx, kr->realm);
if (kerr != 0) {
DEBUG(1, ("krb5_set_default_realm failed, "
"krb5_kuserok may fail.\n"));
}
access_allowed = krb5_kuserok(kr->ctx, kr->princ, kr->pd->user);
DEBUG(SSSDBG_TRACE_LIBS,
("Access was %s\n", access_allowed ? "allowed" : "denied"));
if (access_allowed) {
return EOK;
}
return ERR_AUTH_DENIED;
}
static errno_t renew_tgt_child(struct krb5_req *kr)
{
const char *ccname;
krb5_ccache ccache = NULL;
krb5_error_code kerr;
int ret;
DEBUG(SSSDBG_TRACE_LIBS, ("Renewing a ticket\n"));
ret = sss_authtok_get_ccfile(kr->pd->authtok, &ccname, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("Unsupported authtok type for TGT renewal [%d].\n",
sss_authtok_get_type(kr->pd->authtok)));
return ERR_INVALID_CRED_TYPE;
}
kerr = krb5_cc_resolve(kr->ctx, ccname, &ccache);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = krb5_get_renewed_creds(kr->ctx, kr->creds, kr->princ, ccache, NULL);
if (kerr != 0) {
goto done;
}
if (kr->validate) {
kerr = validate_tgt(kr);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
} else {
DEBUG(SSSDBG_CONF_SETTINGS, ("TGT validation is disabled.\n"));
}
if (kr->validate || kr->fast_ccname != NULL) {
/* We drop root privileges which were needed to read the keytab file
* for the validation of the credentials or for FAST here to run the
* ccache I/O operations with user privileges. */
kerr = become_user(kr->uid, kr->gid);
if (kerr != 0) {
DEBUG(1, ("become_user failed.\n"));
goto done;
}
}
kerr = krb5_cc_initialize(kr->ctx, ccache, kr->princ);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = krb5_cc_store_cred(kr->ctx, ccache, kr->creds);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = add_ticket_times_and_upn_to_response(kr);
if (kerr != 0) {
DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
}
kerr = k5c_attach_ccname_msg(kr);
done:
krb5_free_cred_contents(kr->ctx, kr->creds);
if (ccache != NULL) {
krb5_cc_close(kr->ctx, ccache);
}
return map_krb5_error(kerr);
}
static errno_t create_empty_ccache(struct krb5_req *kr)
{
krb5_error_code kerr;
DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
kr->princ, kr->ccname, NULL);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
} else {
kerr = k5c_attach_ccname_msg(kr);
}
return map_krb5_error(kerr);
}
static errno_t unpack_authtok(struct sss_auth_token *tok,
uint8_t *buf, size_t size, size_t *p)
{
uint32_t auth_token_type;
uint32_t auth_token_length;
errno_t ret = EOK;
SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, buf + *p, size, p);
SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, buf + *p, size, p);
if ((*p + auth_token_length) > size) {
return EINVAL;
}
switch (auth_token_type) {
case SSS_AUTHTOK_TYPE_EMPTY:
sss_authtok_set_empty(tok);
break;
case SSS_AUTHTOK_TYPE_PASSWORD:
ret = sss_authtok_set_password(tok, (char *)(buf + *p), 0);
break;
case SSS_AUTHTOK_TYPE_CCFILE:
ret = sss_authtok_set_ccfile(tok, (char *)(buf + *p), 0);
break;
default:
return EINVAL;
}
if (ret == EOK) {
*p += auth_token_length;
}
return ret;
}
static errno_t unpack_buffer(uint8_t *buf, size_t size,
struct krb5_req *kr, uint32_t *offline)
{
size_t p = 0;
uint32_t len;
uint32_t validate;
uint32_t send_pac;
uint32_t use_enterprise_princ;
struct pam_data *pd;
errno_t ret;
DEBUG(SSSDBG_TRACE_LIBS, ("total buffer size: [%d]\n", size));
if (!offline || !kr) return EINVAL;
pd = create_pam_data(kr);
if (pd == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
return ENOMEM;
}
kr->pd = pd;
SAFEALIGN_COPY_UINT32_CHECK(&pd->cmd, buf + p, size, &p);
SAFEALIGN_COPY_UINT32_CHECK(&kr->uid, buf + p, size, &p);
SAFEALIGN_COPY_UINT32_CHECK(&kr->gid, buf + p, size, &p);
SAFEALIGN_COPY_UINT32_CHECK(&validate, buf + p, size, &p);
kr->validate = (validate == 0) ? false : true;
SAFEALIGN_COPY_UINT32_CHECK(offline, buf + p, size, &p);
SAFEALIGN_COPY_UINT32_CHECK(&send_pac, buf + p, size, &p);
kr->send_pac = (send_pac == 0) ? false : true;
SAFEALIGN_COPY_UINT32_CHECK(&use_enterprise_princ, buf + p, size, &p);
kr->use_enterprise_princ = (use_enterprise_princ == 0) ? false : true;
SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
if ((p + len ) > size) return EINVAL;
kr->upn = talloc_strndup(pd, (char *)(buf + p), len);
if (kr->upn == NULL) return ENOMEM;
p += len;
DEBUG(SSSDBG_CONF_SETTINGS,
("cmd [%d] uid [%llu] gid [%llu] validate [%s] "
"enterprise principal [%s] offline [%s] UPN [%s]\n",
pd->cmd, (unsigned long long) kr->uid,
(unsigned long long) kr->gid, kr->validate ? "true" : "false",
kr->use_enterprise_princ ? "true" : "false",
*offline ? "true" : "false", kr->upn ? kr->upn : "none"));
if (pd->cmd == SSS_PAM_AUTHENTICATE ||
pd->cmd == SSS_CMD_RENEW ||
pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM || pd->cmd == SSS_PAM_CHAUTHTOK) {
SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
if ((p + len ) > size) return EINVAL;
kr->ccname = talloc_strndup(pd, (char *)(buf + p), len);
if (kr->ccname == NULL) return ENOMEM;
p += len;
SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
if ((p + len ) > size) return EINVAL;
kr->keytab = talloc_strndup(pd, (char *)(buf + p), len);
if (kr->keytab == NULL) return ENOMEM;
p += len;
ret = unpack_authtok(pd->authtok, buf, size, &p);
if (ret) {
return ret;
}
DEBUG(SSSDBG_CONF_SETTINGS, ("ccname: [%s] keytab: [%s]\n",
kr->ccname, kr->keytab));
} else {
kr->ccname = NULL;
kr->keytab = NULL;
sss_authtok_set_empty(pd->authtok);
}
if (pd->cmd == SSS_PAM_CHAUTHTOK) {
ret = unpack_authtok(pd->newauthtok, buf, size, &p);
if (ret) {
return ret;
}
} else {
sss_authtok_set_empty(pd->newauthtok);
}
if (pd->cmd == SSS_PAM_ACCT_MGMT) {
SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
if ((p + len ) > size) return EINVAL;
pd->user = talloc_strndup(pd, (char *)(buf + p), len);
if (pd->user == NULL) return ENOMEM;
p += len;
DEBUG(SSSDBG_CONF_SETTINGS, ("user: [%s]\n", pd->user));
} else {
pd->user = NULL;
}
return EOK;
}
static int krb5_cleanup(struct krb5_req *kr)
{
if (kr == NULL) return EOK;
if (kr->options != NULL) {
sss_krb5_get_init_creds_opt_free(kr->ctx, kr->options);
}
if (kr->creds != NULL) {
krb5_free_cred_contents(kr->ctx, kr->creds);
krb5_free_creds(kr->ctx, kr->creds);
}
if (kr->name != NULL)
sss_krb5_free_unparsed_name(kr->ctx, kr->name);
if (kr->princ != NULL)
krb5_free_principal(kr->ctx, kr->princ);
if (kr->ctx != NULL)
krb5_free_context(kr->ctx);
memset(kr, 0, sizeof(struct krb5_req));
return EOK;
}
static krb5_error_code get_tgt_times(krb5_context ctx, const char *ccname,
krb5_principal server_principal,
krb5_principal client_principal,
sss_krb5_ticket_times *tgtt)
{
krb5_error_code krberr;
krb5_ccache ccache = NULL;
krb5_creds mcred;
krb5_creds cred;
krberr = krb5_cc_resolve(ctx, ccname, &ccache);
if (krberr != 0) {
DEBUG(1, ("krb5_cc_resolve failed.\n"));
goto done;
}
memset(&mcred, 0, sizeof(mcred));
memset(&cred, 0, sizeof(mcred));
mcred.server = server_principal;
mcred.client = client_principal;
krberr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
if (krberr != 0) {
DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
krberr = 0;
goto done;
}
tgtt->authtime = cred.times.authtime;
tgtt->starttime = cred.times.starttime;
tgtt->endtime = cred.times.endtime;
tgtt->renew_till = cred.times.renew_till;
krb5_free_cred_contents(ctx, &cred);
krberr = 0;
done:
if (ccache != NULL) {
krb5_cc_close(ctx, ccache);
}
return krberr;
}
static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
krb5_context ctx,
const char *primary,
const char *realm,
const char *keytab_name,
char **fast_ccname)
{
TALLOC_CTX *tmp_ctx = NULL;
krb5_error_code kerr;
char *ccname;
char *server_name;
sss_krb5_ticket_times tgtt;
krb5_keytab keytab = NULL;
krb5_principal client_princ = NULL;
krb5_principal server_princ = NULL;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(1, ("talloc_new failed.\n"));
kerr = ENOMEM;
goto done;
}
ccname = talloc_asprintf(tmp_ctx, "FILE:%s/fast_ccache_%s", DB_PATH, realm);
if (ccname == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
kerr = ENOMEM;
goto done;
}
if (keytab_name != NULL) {
kerr = krb5_kt_resolve(ctx, keytab_name, &keytab);
} else {
kerr = krb5_kt_default(ctx, &keytab);
}
if (kerr) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Failed to read keytab file [%s]: %s\n",
KEYTAB_CLEAN_NAME,
sss_krb5_get_error_message(ctx, kerr)));
goto done;
}
kerr = find_principal_in_keytab(ctx, keytab, primary, realm, &client_princ);
if (kerr != 0) {
DEBUG(SSSDBG_MINOR_FAILURE,
("find_principal_in_keytab failed for principal %s@%s.\n",
primary, realm));
goto done;
}
server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
if (server_name == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
kerr = ENOMEM;
goto done;
}
kerr = krb5_parse_name(ctx, server_name, &server_princ);
if (kerr != 0) {
DEBUG(1, ("krb5_parse_name failed.\n"));
goto done;
}
memset(&tgtt, 0, sizeof(tgtt));
kerr = get_tgt_times(ctx, ccname, server_princ, client_princ, &tgtt);
if (kerr == 0) {
if (tgtt.endtime > time(NULL)) {
DEBUG(5, ("FAST TGT is still valid.\n"));
goto done;
}
}
kerr = get_and_save_tgt_with_keytab(ctx, client_princ, keytab, ccname);
if (kerr != 0) {
DEBUG(1, ("get_and_save_tgt_with_keytab failed.\n"));
goto done;
}
kerr = 0;
done:
if (client_princ != NULL) {
krb5_free_principal(ctx, client_princ);
}
if (server_princ != NULL) {
krb5_free_principal(ctx, server_princ);
}
if (kerr == 0) {
*fast_ccname = talloc_steal(mem_ctx, ccname);
}
talloc_free(tmp_ctx);
if (keytab != NULL) {
krb5_kt_close(ctx, keytab);
}
return kerr;
}
static errno_t k5c_recv_data(struct krb5_req *kr, int fd, uint32_t *offline)
{
uint8_t buf[IN_BUF_SIZE];
ssize_t len;
errno_t ret;
errno = 0;
len = sss_atomic_read_s(fd, buf, IN_BUF_SIZE);
if (len == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
("read failed [%d][%s].\n", ret, strerror(ret)));
return ret;
}
ret = unpack_buffer(buf, len, kr, offline);
if (ret != EOK) {
DEBUG(1, ("unpack_buffer failed.\n"));
}
return ret;
}
static int k5c_setup_fast(struct krb5_req *kr, char *lifetime_str, bool demand)
{
krb5_principal fast_princ_struct;
krb5_data *realm_data;
char *fast_principal_realm;
char *fast_principal;
krb5_error_code kerr;
char *tmp_str;
DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
SSSD_KRB5_LIFETIME, lifetime_str));
tmp_str = getenv(SSSD_KRB5_FAST_PRINCIPAL);
if (tmp_str) {
DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
SSSD_KRB5_FAST_PRINCIPAL, tmp_str));
kerr = krb5_parse_name(kr->ctx, tmp_str, &fast_princ_struct);
if (kerr) {
DEBUG(1, ("krb5_parse_name failed.\n"));
return kerr;
}
kerr = sss_krb5_unparse_name_flags(kr->ctx, fast_princ_struct,
KRB5_PRINCIPAL_UNPARSE_NO_REALM,
&tmp_str);
if (kerr) {
DEBUG(1, ("sss_krb5_unparse_name_flags failed.\n"));
return kerr;
}
fast_principal = talloc_strdup(kr, tmp_str);
if (!fast_principal) {
DEBUG(1, ("talloc_strdup failed.\n"));
return KRB5KRB_ERR_GENERIC;
}
free(tmp_str);
realm_data = krb5_princ_realm(kr->ctx, fast_princ_struct);
fast_principal_realm = talloc_asprintf(kr, "%.*s", realm_data->length, realm_data->data);
if (!fast_principal_realm) {
DEBUG(1, ("talloc_asprintf failed.\n"));
return ENOMEM;
}
} else {
fast_principal_realm = kr->realm;
fast_principal = NULL;
}
kerr = check_fast_ccache(kr, kr->ctx, fast_principal, fast_principal_realm,
kr->keytab, &kr->fast_ccname);
if (kerr != 0) {
DEBUG(1, ("check_fast_ccache failed.\n"));
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
kerr = sss_krb5_get_init_creds_opt_set_fast_ccache_name(kr->ctx,
kr->options,
kr->fast_ccname);
if (kerr != 0) {
DEBUG(1, ("sss_krb5_get_init_creds_opt_set_fast_ccache_name "
"failed.\n"));
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
if (demand) {
kerr = sss_krb5_get_init_creds_opt_set_fast_flags(kr->ctx,
kr->options,
SSS_KRB5_FAST_REQUIRED);
if (kerr != 0) {
DEBUG(1, ("sss_krb5_get_init_creds_opt_set_fast_flags "
"failed.\n"));
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
}
return EOK;
}
static int k5c_setup(struct krb5_req *kr, uint32_t offline)
{
krb5_error_code kerr;
char *lifetime_str;
char *use_fast_str;
krb5_deltat lifetime;
int parse_flags;
kr->realm = getenv(SSSD_KRB5_REALM);
if (kr->realm == NULL) {
DEBUG(SSSDBG_MINOR_FAILURE,
("Cannot read [%s] from environment.\n", SSSD_KRB5_REALM));
}
kerr = krb5_init_context(&kr->ctx);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
/* Set the global error context */
krb5_error_ctx = kr->ctx;
if (debug_level & SSSDBG_TRACE_ALL) {
kerr = sss_child_set_krb5_tracing(kr->ctx);
if (kerr) {
KRB5_CHILD_DEBUG(SSSDBG_MINOR_FAILURE, kerr);
return EIO;
}
}
/* Enterprise principals require that a default realm is available. To
* make SSSD more robust in the case that the default realm option is
* missing in krb5.conf or to allow SSSD to work with multiple unconnected
* realms (e.g. AD domains without trust between them) the default realm
* will be set explicitly. */
if (kr->use_enterprise_princ) {
kerr = krb5_set_default_realm(kr->ctx, kr->realm);
if (kerr != 0) {
DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_set_default_realm failed.\n"));
}
}
parse_flags = kr->use_enterprise_princ ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 0;
kerr = sss_krb5_parse_name_flags(kr->ctx, kr->upn, parse_flags, &kr->princ);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
kerr = krb5_unparse_name(kr->ctx, kr->princ, &kr->name);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
kr->creds = calloc(1, sizeof(krb5_creds));
if (kr->creds == NULL) {
DEBUG(1, ("talloc_zero failed.\n"));
return ENOMEM;
}
kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER
kerr = krb5_get_init_creds_opt_set_responder(kr->ctx, kr->options,
sss_krb5_responder, kr);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
#endif
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT
/* A prompter is used to catch messages about when a password will
* expired. The library shall not use the prompter to ask for a new password
* but shall return KRB5KDC_ERR_KEY_EXP. */
krb5_get_init_creds_opt_set_change_password_prompt(kr->options, 0);
#endif
lifetime_str = getenv(SSSD_KRB5_RENEWABLE_LIFETIME);
if (lifetime_str == NULL) {
DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n",
SSSD_KRB5_RENEWABLE_LIFETIME));
} else {
kerr = krb5_string_to_deltat(lifetime_str, &lifetime);
if (kerr != 0) {
DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n",
lifetime_str));
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
SSSD_KRB5_RENEWABLE_LIFETIME, lifetime_str));
krb5_get_init_creds_opt_set_renew_life(kr->options, lifetime);
}
lifetime_str = getenv(SSSD_KRB5_LIFETIME);
if (lifetime_str == NULL) {
DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n",
SSSD_KRB5_LIFETIME));
} else {
kerr = krb5_string_to_deltat(lifetime_str, &lifetime);
if (kerr != 0) {
DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n",
lifetime_str));
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
DEBUG(SSSDBG_CONF_SETTINGS,
("%s is set to [%s]\n", SSSD_KRB5_LIFETIME, lifetime_str));
krb5_get_init_creds_opt_set_tkt_life(kr->options, lifetime);
}
if (!offline) {
krb5_set_canonicalize(kr->options);
use_fast_str = getenv(SSSD_KRB5_USE_FAST);
if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) {
DEBUG(SSSDBG_CONF_SETTINGS, ("Not using FAST.\n"));
} else if (strcasecmp(use_fast_str, "try") == 0) {
kerr = k5c_setup_fast(kr, lifetime_str, false);
} else if (strcasecmp(use_fast_str, "demand") == 0) {
kerr = k5c_setup_fast(kr, lifetime_str, true);
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
("Unsupported value [%s] for krb5_use_fast.\n",
use_fast_str));
return EINVAL;
}
}
/* TODO: set options, e.g.
* krb5_get_init_creds_opt_set_forwardable
* krb5_get_init_creds_opt_set_proxiable
* krb5_get_init_creds_opt_set_etype_list
* krb5_get_init_creds_opt_set_address_list
* krb5_get_init_creds_opt_set_preauth_list
* krb5_get_init_creds_opt_set_salt
* krb5_get_init_creds_opt_set_change_password_prompt
* krb5_get_init_creds_opt_set_pa
*/
return kerr;
}
int main(int argc, const char *argv[])
{
struct krb5_req *kr = NULL;
uint32_t offline;
int opt;
poptContext pc;
int debug_fd = -1;
errno_t ret;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
_("Debug level"), NULL},
{"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
_("Add debug timestamps"), NULL},
{"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
_("Show timestamps with microseconds"), NULL},
{"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
_("An open file descriptor for the debug logs"), NULL},
POPT_TABLEEND
};
/* Set debug level to invalid value so we can decide if -d 0 was used. */
debug_level = SSSDBG_INVALID;
pc = poptGetContext(argv[0], argc, argv, long_options, 0);
while((opt = poptGetNextOpt(pc)) != -1) {
switch(opt) {
default:
fprintf(stderr, "\nInvalid option %s: %s\n\n",
poptBadOption(pc, 0), poptStrerror(opt));
poptPrintUsage(pc, stderr, 0);
_exit(-1);
}
}
poptFreeContext(pc);
DEBUG_INIT(debug_level);
kr = talloc_zero(NULL, struct krb5_req);
if (kr == NULL) {
DEBUG(1, ("talloc failed.\n"));
exit(-1);
}
debug_prg_name = talloc_asprintf(kr, "[sssd[krb5_child[%d]]]", getpid());
if (!debug_prg_name) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf failed.\n"));
ret = ENOMEM;
goto done;
}
if (debug_fd != -1) {
ret = set_debug_file_from_fd(debug_fd);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("set_debug_file_from_fd failed.\n"));
}
}
DEBUG(SSSDBG_TRACE_FUNC, ("krb5_child started.\n"));
ret = k5c_recv_data(kr, STDIN_FILENO, &offline);
if (ret != EOK) {
goto done;
}
close(STDIN_FILENO);
ret = k5c_setup(kr, offline);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_child_setup failed.\n"));
goto done;
}
switch(kr->pd->cmd) {
case SSS_PAM_AUTHENTICATE:
/* If we are offline, we need to create an empty ccache file */
if (offline) {
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform offline auth\n"));
ret = create_empty_ccache(kr);
} else {
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform online auth\n"));
ret = tgt_req_child(kr);
}
break;
case SSS_PAM_CHAUTHTOK:
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform password change\n"));
ret = changepw_child(kr, false);
break;
case SSS_PAM_CHAUTHTOK_PRELIM:
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform password change checks\n"));
ret = changepw_child(kr, true);
break;
case SSS_PAM_ACCT_MGMT:
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform account management\n"));
ret = kuserok_child(kr);
break;
case SSS_CMD_RENEW:
if (offline) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot renew TGT while offline\n"));
ret = KRB5_KDC_UNREACH;
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, ("Will perform ticket renewal\n"));
ret = renew_tgt_child(kr);
break;
default:
DEBUG(1, ("PAM command [%d] not supported.\n", kr->pd->cmd));
ret = EINVAL;
goto done;
}
ret = k5c_send_data(kr, STDOUT_FILENO, ret);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to send reply\n"));
}
done:
krb5_cleanup(kr);
talloc_free(kr);
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC, ("krb5_child completed successfully\n"));
exit(0);
} else {
DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_child failed!\n"));
exit(-1);
}
}