sss_krb5.c revision 5ae539828197f032d3e2ccb27e87ccf2a1d94996
f82568a780e35e8786958c49a1259434e2088b9cniq/*
f82568a780e35e8786958c49a1259434e2088b9cniq Authors:
f82568a780e35e8786958c49a1259434e2088b9cniq Sumit Bose <sbose@redhat.com>
f82568a780e35e8786958c49a1259434e2088b9cniq
11e076839c8d5a82d55e710194d0daac51390dbdsf Copyright (C) 2009-2010 Red Hat
11e076839c8d5a82d55e710194d0daac51390dbdsf
f82568a780e35e8786958c49a1259434e2088b9cniq This program is free software; you can redistribute it and/or modify
f82568a780e35e8786958c49a1259434e2088b9cniq it under the terms of the GNU General Public License as published by
f82568a780e35e8786958c49a1259434e2088b9cniq the Free Software Foundation; either version 3 of the License, or
f82568a780e35e8786958c49a1259434e2088b9cniq (at your option) any later version.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim This program is distributed in the hope that it will be useful,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim but WITHOUT ANY WARRANTY; without even the implied warranty of
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim GNU General Public License for more details.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f82568a780e35e8786958c49a1259434e2088b9cniq You should have received a copy of the GNU General Public License
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim along with this program. If not, see <http://www.gnu.org/licenses/>.
f82568a780e35e8786958c49a1259434e2088b9cniq*/
f82568a780e35e8786958c49a1259434e2088b9cniq#include <stdio.h>
f82568a780e35e8786958c49a1259434e2088b9cniq#include <errno.h>
f82568a780e35e8786958c49a1259434e2088b9cniq#include <talloc.h>
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#include "config.h"
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#include "util/util.h"
f82568a780e35e8786958c49a1259434e2088b9cniq#include "util/sss_krb5.h"
7bccdbc7016c4ea9d196a15c391d5e629d886e34jorton
f82568a780e35e8786958c49a1259434e2088b9cniqchar *
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_get_primary(TALLOC_CTX *mem_ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *pattern,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *hostname)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq char *primary;
f82568a780e35e8786958c49a1259434e2088b9cniq char *dot;
6fde49e04de4cc97908b20ea01f0c3940f3a1e54rpluem char *c;
6fde49e04de4cc97908b20ea01f0c3940f3a1e54rpluem char *shortname;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (strcmp(pattern, "%S$") == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq shortname = talloc_strdup(mem_ctx, hostname);
f82568a780e35e8786958c49a1259434e2088b9cniq if (!shortname) return NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq dot = strchr(shortname, '.');
f82568a780e35e8786958c49a1259434e2088b9cniq if (dot) {
f82568a780e35e8786958c49a1259434e2088b9cniq *dot = '\0';
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq for (c=shortname; *c != '\0'; ++c) {
f82568a780e35e8786958c49a1259434e2088b9cniq *c = toupper(*c);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq primary = talloc_asprintf(mem_ctx, "%s$", shortname);
f82568a780e35e8786958c49a1259434e2088b9cniq talloc_free(shortname);
f82568a780e35e8786958c49a1259434e2088b9cniq return primary;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return talloc_asprintf(mem_ctx, pattern, hostname);
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqerrno_t select_principal_from_keytab(TALLOC_CTX *mem_ctx,
7bccdbc7016c4ea9d196a15c391d5e629d886e34jorton const char *hostname,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *desired_realm,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *keytab_name,
f82568a780e35e8786958c49a1259434e2088b9cniq char **_principal,
f82568a780e35e8786958c49a1259434e2088b9cniq char **_primary,
f82568a780e35e8786958c49a1259434e2088b9cniq char **_realm)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code kerr = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_context krb_ctx = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab keytab = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal client_princ = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq TALLOC_CTX *tmp_ctx;
f82568a780e35e8786958c49a1259434e2088b9cniq char *primary = NULL;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq char *realm = NULL;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq int i = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq errno_t ret;
f82568a780e35e8786958c49a1259434e2088b9cniq char *principal_string;
f82568a780e35e8786958c49a1259434e2088b9cniq const char *realm_name;
f82568a780e35e8786958c49a1259434e2088b9cniq int realm_len;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq /**
f82568a780e35e8786958c49a1259434e2088b9cniq * The %s conversion is passed as-is, the %S conversion is translated to
f82568a780e35e8786958c49a1259434e2088b9cniq * "short host name"
f82568a780e35e8786958c49a1259434e2088b9cniq *
f82568a780e35e8786958c49a1259434e2088b9cniq * Priority of lookup:
f82568a780e35e8786958c49a1259434e2088b9cniq * - our.hostname@REALM or host/our.hostname@REALM depending on the input
f82568a780e35e8786958c49a1259434e2088b9cniq * - SHORT.HOSTNAME$@REALM (AD domain)
f82568a780e35e8786958c49a1259434e2088b9cniq * - host/our.hostname@REALM
f82568a780e35e8786958c49a1259434e2088b9cniq * - foobar$@REALM (AD domain)
f82568a780e35e8786958c49a1259434e2088b9cniq * - host/foobar@REALM
f82568a780e35e8786958c49a1259434e2088b9cniq * - host/foo@BAR
f82568a780e35e8786958c49a1259434e2088b9cniq * - pick the first principal in the keytab
f82568a780e35e8786958c49a1259434e2088b9cniq */
f82568a780e35e8786958c49a1259434e2088b9cniq const char *primary_patterns[] = {"%s", "%S$", "host/%s", "*$", "host/*",
f82568a780e35e8786958c49a1259434e2088b9cniq "host/*", NULL};
f82568a780e35e8786958c49a1259434e2088b9cniq const char *realm_patterns[] = {"%s", "%s", "%s", "%s", "%s",
f82568a780e35e8786958c49a1259434e2088b9cniq NULL, NULL};
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA,
f82568a780e35e8786958c49a1259434e2088b9cniq "trying to select the most appropriate principal from keytab\n");
f82568a780e35e8786958c49a1259434e2088b9cniq tmp_ctx = talloc_new(NULL);
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem if (!tmp_ctx) {
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem return ENOMEM;
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem }
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem
ab2b977442827214b1d884decf3e3f1579fd45e1rpluem kerr = krb5_init_context(&krb_ctx);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
f82568a780e35e8786958c49a1259434e2088b9cniq ret = EFAULT;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (keytab_name != NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_kt_resolve(krb_ctx, keytab_name, &keytab);
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_kt_default(krb_ctx, &keytab);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE,
f82568a780e35e8786958c49a1259434e2088b9cniq "Failed to read keytab [%s]: %s\n",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME,
f82568a780e35e8786958c49a1259434e2088b9cniq sss_krb5_get_error_message(krb_ctx, kerr));
f82568a780e35e8786958c49a1259434e2088b9cniq ret = EFAULT;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (!desired_realm) {
f82568a780e35e8786958c49a1259434e2088b9cniq desired_realm = "*";
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (!hostname) {
f82568a780e35e8786958c49a1259434e2088b9cniq hostname = "*";
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq do {
f82568a780e35e8786958c49a1259434e2088b9cniq if (primary_patterns[i]) {
f82568a780e35e8786958c49a1259434e2088b9cniq primary = sss_krb5_get_primary(tmp_ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq primary_patterns[i],
f82568a780e35e8786958c49a1259434e2088b9cniq hostname);
f82568a780e35e8786958c49a1259434e2088b9cniq if (primary == NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq primary = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (realm_patterns[i]) {
f82568a780e35e8786958c49a1259434e2088b9cniq realm = talloc_asprintf(tmp_ctx, realm_patterns[i], desired_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq if (realm == NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq realm = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = find_principal_in_keytab(krb_ctx, keytab, primary, realm,
f82568a780e35e8786958c49a1259434e2088b9cniq &client_princ);
f82568a780e35e8786958c49a1259434e2088b9cniq talloc_zfree(primary);
f82568a780e35e8786958c49a1259434e2088b9cniq talloc_zfree(realm);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (client_princ != NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_free_principal(krb_ctx, client_princ);
f82568a780e35e8786958c49a1259434e2088b9cniq client_princ = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq i++;
f82568a780e35e8786958c49a1259434e2088b9cniq } while(primary_patterns[i-1] != NULL || realm_patterns[i-1] != NULL);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq if (_principal) {
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_unparse_name(krb_ctx, client_princ, &principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "krb5_unparse_name failed");
f82568a780e35e8786958c49a1259434e2088b9cniq ret = EFAULT;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq *_principal = talloc_strdup(mem_ctx, principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq free(principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq if (!*_principal) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed");
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA, "Selected principal: %s\n", *_principal);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (_primary) {
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = sss_krb5_unparse_name_flags(krb_ctx, client_princ,
f82568a780e35e8786958c49a1259434e2088b9cniq KRB5_PRINCIPAL_UNPARSE_NO_REALM,
f82568a780e35e8786958c49a1259434e2088b9cniq &principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "krb5_unparse_name failed");
f82568a780e35e8786958c49a1259434e2088b9cniq ret = EFAULT;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq *_primary = talloc_strdup(mem_ctx, principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq free(principal_string);
f82568a780e35e8786958c49a1259434e2088b9cniq if (!*_primary) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed");
f82568a780e35e8786958c49a1259434e2088b9cniq if (_principal) talloc_zfree(*_principal);
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA, "Selected primary: %s\n", *_primary);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (_realm) {
f82568a780e35e8786958c49a1259434e2088b9cniq sss_krb5_princ_realm(krb_ctx, client_princ,
f82568a780e35e8786958c49a1259434e2088b9cniq &realm_name,
f82568a780e35e8786958c49a1259434e2088b9cniq &realm_len);
f82568a780e35e8786958c49a1259434e2088b9cniq *_realm = talloc_asprintf(mem_ctx, "%.*s",
f82568a780e35e8786958c49a1259434e2088b9cniq realm_len, realm_name);
f82568a780e35e8786958c49a1259434e2088b9cniq if (!*_realm) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed");
f82568a780e35e8786958c49a1259434e2088b9cniq if (_principal) talloc_zfree(*_principal);
f82568a780e35e8786958c49a1259434e2088b9cniq if (_primary) talloc_zfree(*_primary);
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA, "Selected realm: %s\n", *_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq ret = EOK;
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_MINOR_FAILURE, "No suitable principal found in keytab\n");
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOENT;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqdone:
f82568a780e35e8786958c49a1259434e2088b9cniq if (ret != EOK) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read keytab [%s]: %s\n",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME, strerror(ret));
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ERR, "Failed to read keytab [%s]: %s\n",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME, strerror(ret));
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (keytab) krb5_kt_close(krb_ctx, keytab);
f82568a780e35e8786958c49a1259434e2088b9cniq if (krb_ctx) krb5_free_context(krb_ctx);
f82568a780e35e8786958c49a1259434e2088b9cniq if (client_princ != NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_free_principal(krb_ctx, client_princ);
f82568a780e35e8786958c49a1259434e2088b9cniq client_princ = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq talloc_free(tmp_ctx);
f82568a780e35e8786958c49a1259434e2088b9cniq return ret;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqint sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_context context, krb5_keytab keytab)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq bool found;
f82568a780e35e8786958c49a1259434e2088b9cniq char *kt_principal;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code krberr;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_kt_cursor cursor;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab_entry entry;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
f82568a780e35e8786958c49a1259434e2088b9cniq if (krberr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE,
f82568a780e35e8786958c49a1259434e2088b9cniq "Cannot read keytab [%s].\n", KEYTAB_CLEAN_NAME);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
f82568a780e35e8786958c49a1259434e2088b9cniq "Unable to create GSSAPI-encrypted LDAP "
f82568a780e35e8786958c49a1259434e2088b9cniq "connection.",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME, krberr,
f82568a780e35e8786958c49a1259434e2088b9cniq sss_krb5_get_error_message(context, krberr));
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return EIO;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq found = false;
f82568a780e35e8786958c49a1259434e2088b9cniq while((krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
f82568a780e35e8786958c49a1259434e2088b9cniq krberr = krb5_unparse_name(context, entry.principal, &kt_principal);
f82568a780e35e8786958c49a1259434e2088b9cniq if (krberr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE,
f82568a780e35e8786958c49a1259434e2088b9cniq "Could not parse keytab entry\n");
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ERR, "Could not parse keytab entry\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return EIO;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (strcmp(principal, kt_principal) == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq found = true;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq free(kt_principal);
f82568a780e35e8786958c49a1259434e2088b9cniq krberr = sss_krb5_free_keytab_entry_contents(context, &entry);
f82568a780e35e8786958c49a1259434e2088b9cniq if (krberr) {
f82568a780e35e8786958c49a1259434e2088b9cniq /* This should never happen. The API docs for this function
f82568a780e35e8786958c49a1259434e2088b9cniq * specify only success for this function
f82568a780e35e8786958c49a1259434e2088b9cniq */
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE,"Could not free keytab entry contents\n");
f82568a780e35e8786958c49a1259434e2088b9cniq /* This is non-fatal, so we'll continue here */
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (found) {
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
f82568a780e35e8786958c49a1259434e2088b9cniq if (krberr) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE, "Could not close keytab.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME);
f82568a780e35e8786958c49a1259434e2088b9cniq return EIO;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (!found) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FATAL_FAILURE,
f82568a780e35e8786958c49a1259434e2088b9cniq "Principal [%s] not found in keytab [%s]\n",
f82568a780e35e8786958c49a1259434e2088b9cniq principal,
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME);
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
f82568a780e35e8786958c49a1259434e2088b9cniq "Principal [%s] was not found. "
f82568a780e35e8786958c49a1259434e2088b9cniq "Unable to create GSSAPI-encrypted LDAP connection.",
f82568a780e35e8786958c49a1259434e2088b9cniq KEYTAB_CLEAN_NAME, principal);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return EFAULT;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return EOK;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqenum matching_mode {MODE_NORMAL, MODE_PREFIX, MODE_POSTFIX};
f82568a780e35e8786958c49a1259434e2088b9cniq/**
f82568a780e35e8786958c49a1259434e2088b9cniq * We only have primary and instances stored separately, we need to
f82568a780e35e8786958c49a1259434e2088b9cniq * join them to one string and compare that string.
f82568a780e35e8786958c49a1259434e2088b9cniq *
f82568a780e35e8786958c49a1259434e2088b9cniq * @param ctx kerberos context
f82568a780e35e8786958c49a1259434e2088b9cniq * @param principal principal we want to match
f82568a780e35e8786958c49a1259434e2088b9cniq * @param pattern_primary primary part of the principal we want to
f82568a780e35e8786958c49a1259434e2088b9cniq * perform matching against. It is possible to use * wildcard
f82568a780e35e8786958c49a1259434e2088b9cniq * at the beginning or at the end of the string. If NULL, it
f82568a780e35e8786958c49a1259434e2088b9cniq * will act as "*"
f82568a780e35e8786958c49a1259434e2088b9cniq * @param pattern_realm realm part of the principal we want to perform
f82568a780e35e8786958c49a1259434e2088b9cniq * the matching against. If NULL, it will act as "*"
f82568a780e35e8786958c49a1259434e2088b9cniq */
f82568a780e35e8786958c49a1259434e2088b9cniqstatic bool match_principal(krb5_context ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal principal,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *pattern_primary,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *pattern_realm)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq char *primary = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq char *primary_str = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq int primary_str_len = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq int tmp_len;
f82568a780e35e8786958c49a1259434e2088b9cniq int len_diff;
f82568a780e35e8786958c49a1259434e2088b9cniq const char *realm_name;
f82568a780e35e8786958c49a1259434e2088b9cniq int realm_len;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq enum matching_mode mode = MODE_NORMAL;
f82568a780e35e8786958c49a1259434e2088b9cniq TALLOC_CTX *tmp_ctx;
f82568a780e35e8786958c49a1259434e2088b9cniq bool ret = false;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq sss_krb5_princ_realm(ctx, principal, &realm_name, &realm_len);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq tmp_ctx = talloc_new(NULL);
f82568a780e35e8786958c49a1259434e2088b9cniq if (!tmp_ctx) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return false;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (pattern_primary) {
f82568a780e35e8786958c49a1259434e2088b9cniq tmp_len = strlen(pattern_primary);
f82568a780e35e8786958c49a1259434e2088b9cniq if (pattern_primary[tmp_len-1] == '*') {
f82568a780e35e8786958c49a1259434e2088b9cniq mode = MODE_PREFIX;
f82568a780e35e8786958c49a1259434e2088b9cniq primary_str = talloc_strdup(tmp_ctx, pattern_primary);
f82568a780e35e8786958c49a1259434e2088b9cniq primary_str[tmp_len-1] = '\0';
f82568a780e35e8786958c49a1259434e2088b9cniq primary_str_len = tmp_len-1;
f82568a780e35e8786958c49a1259434e2088b9cniq } else if (pattern_primary[0] == '*') {
f82568a780e35e8786958c49a1259434e2088b9cniq mode = MODE_POSTFIX;
f82568a780e35e8786958c49a1259434e2088b9cniq primary_str = talloc_strdup(tmp_ctx, pattern_primary+1);
f82568a780e35e8786958c49a1259434e2088b9cniq primary_str_len = tmp_len-1;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq sss_krb5_unparse_name_flags(ctx, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq &primary);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniq len_diff = strlen(primary)-primary_str_len;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if ((mode == MODE_NORMAL &&
f82568a780e35e8786958c49a1259434e2088b9cniq strcmp(primary, pattern_primary) != 0) ||
f82568a780e35e8786958c49a1259434e2088b9cniq (mode == MODE_PREFIX &&
f82568a780e35e8786958c49a1259434e2088b9cniq strncmp(primary, primary_str, primary_str_len) != 0) ||
f82568a780e35e8786958c49a1259434e2088b9cniq (mode == MODE_POSTFIX &&
f82568a780e35e8786958c49a1259434e2088b9cniq strcmp(primary+len_diff, primary_str) != 0)) {
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (!pattern_realm || (realm_len == strlen(pattern_realm) &&
f82568a780e35e8786958c49a1259434e2088b9cniq strncmp(realm_name, pattern_realm, realm_len) == 0)) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_TRACE_LIBS,
f82568a780e35e8786958c49a1259434e2088b9cniq "Principal matched to the sample (%s@%s).\n", pattern_primary,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim pattern_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq ret = true;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqdone:
f82568a780e35e8786958c49a1259434e2088b9cniq free(primary);
f82568a780e35e8786958c49a1259434e2088b9cniq talloc_free(tmp_ctx);
f82568a780e35e8786958c49a1259434e2088b9cniq return ret;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code find_principal_in_keytab(krb5_context ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab keytab,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *pattern_primary,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *pattern_realm,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal *princ)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code kerr;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code kt_err;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code kerr_d;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_kt_cursor cursor;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab_entry entry;
f82568a780e35e8786958c49a1259434e2088b9cniq bool principal_found = false;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&cursor, 0, sizeof(cursor));
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_kt_start_seq_get(ctx, keytab, &cursor);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_start_seq_get failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return kerr;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_TRACE_ALL,
f82568a780e35e8786958c49a1259434e2088b9cniq "Trying to find principal %s@%s in keytab.\n", pattern_primary, pattern_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&entry, 0, sizeof(entry));
f82568a780e35e8786958c49a1259434e2088b9cniq while ((kt_err = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq principal_found = match_principal(ctx, entry.principal, pattern_primary, pattern_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq if (principal_found) {
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = sss_krb5_free_keytab_entry_contents(ctx, &entry);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&entry, 0, sizeof(entry));
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq /* Close the keytab here. Even though we're using cursors, the file
f82568a780e35e8786958c49a1259434e2088b9cniq * handle is stored in the krb5_keytab structure, and it gets
f82568a780e35e8786958c49a1259434e2088b9cniq * overwritten by other keytab calls, creating a leak. */
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_kt_end_seq_get(ctx, keytab, &cursor);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq goto done;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (!principal_found) {
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = KRB5_KT_NOTFOUND;
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_TRACE_FUNC,
f82568a780e35e8786958c49a1259434e2088b9cniq "No principal matching %s@%s found in keytab.\n",
f82568a780e35e8786958c49a1259434e2088b9cniq pattern_primary, pattern_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq /* check if we got any errors from krb5_kt_next_entry */
f82568a780e35e8786958c49a1259434e2088b9cniq if (kt_err != 0 && kt_err != KRB5_KT_END) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "Error while reading keytab.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_copy_principal(ctx, entry.principal, princ);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "krb5_copy_principal failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqdone:
f82568a780e35e8786958c49a1259434e2088b9cniq kerr_d = sss_krb5_free_keytab_entry_contents(ctx, &entry);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr_d != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return kerr;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqconst char *KRB5_CALLCONV sss_krb5_get_error_message(krb5_context ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code ec)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_ERROR_MESSAGE
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_get_error_message(ctx, ec);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq int ret;
f82568a780e35e8786958c49a1259434e2088b9cniq char *s = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq int size = sizeof("Kerberos error [XXXXXXXXXXXX]");
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq s = malloc(sizeof(char) * (size));
f82568a780e35e8786958c49a1259434e2088b9cniq if (s == NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq return NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq ret = snprintf(s, size, "Kerberos error [%12d]", ec);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (ret < 0 || ret >= size) {
f82568a780e35e8786958c49a1259434e2088b9cniq free(s);
f82568a780e35e8786958c49a1259434e2088b9cniq return NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return s;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqvoid KRB5_CALLCONV sss_krb5_free_error_message(krb5_context ctx, const char *s)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_ERROR_MESSAGE
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_free_error_message(ctx, s);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq free(s);
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_alloc(
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt **opt)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_get_init_creds_opt_alloc(context, opt);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq *opt = calloc(1, sizeof(krb5_get_init_creds_opt));
f82568a780e35e8786958c49a1259434e2088b9cniq if (*opt == NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq return ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt_init(*opt);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return 0;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqvoid KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt *opt)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt_free(context, opt);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq free(opt);
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqvoid KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_free_unparsed_name(context, name);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq if (name != NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq memset(name, 0, strlen(name));
f82568a780e35e8786958c49a1259434e2088b9cniq free(name);
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback(
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_context context,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_get_init_creds_opt *opt,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_expire_callback_func cb,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq void *data)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_EXPIRE_CALLBACK
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_get_init_creds_opt_set_expire_callback(context, opt, cb, data);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA,
f82568a780e35e8786958c49a1259434e2088b9cniq "krb5_get_init_creds_opt_set_expire_callback not available.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return 0;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniqerrno_t check_fast(const char *str, bool *use_fast)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
f82568a780e35e8786958c49a1259434e2088b9cniq if (strcasecmp(str, "never") == 0 ) {
f82568a780e35e8786958c49a1259434e2088b9cniq *use_fast = false;
f82568a780e35e8786958c49a1259434e2088b9cniq } else if (strcasecmp(str, "try") == 0 || strcasecmp(str, "demand") == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq *use_fast = true;
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ALERT, "Unsupported value [%s] for option krb5_use_fast,"
f82568a780e35e8786958c49a1259434e2088b9cniq "please use never, try, or demand.\n", str);
f82568a780e35e8786958c49a1259434e2088b9cniq return EINVAL;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return EOK;
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq sss_log(SSS_LOG_ALERT, "This build of sssd does not support FAST. "
f82568a780e35e8786958c49a1259434e2088b9cniq "Please remove option krb5_use_fast.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return EINVAL;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_ccache_name(
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt *opt,
f82568a780e35e8786958c49a1259434e2088b9cniq const char *fast_ccache_name)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_get_init_creds_opt_set_fast_ccache_name(context, opt,
f82568a780e35e8786958c49a1259434e2088b9cniq fast_ccache_name);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA,
f82568a780e35e8786958c49a1259434e2088b9cniq "krb5_get_init_creds_opt_set_fast_ccache_name not available.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return 0;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags(
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_get_init_creds_opt *opt,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_flags flags)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_get_init_creds_opt_set_fast_flags(context, opt, flags);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_FUNC_DATA,
f82568a780e35e8786958c49a1259434e2088b9cniq "krb5_get_init_creds_opt_set_fast_flags not available.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq return 0;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#ifndef HAVE_KRB5_UNPARSE_NAME_FLAGS
f82568a780e35e8786958c49a1259434e2088b9cniq#ifndef REALM_SEP
f82568a780e35e8786958c49a1259434e2088b9cniq#define REALM_SEP '@'
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq#ifndef COMPONENT_SEP
f82568a780e35e8786958c49a1259434e2088b9cniq#define COMPONENT_SEP '/'
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqstatic int
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_copy_component_quoting(char *dest, const krb5_data *src, int flags)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq int j;
f82568a780e35e8786958c49a1259434e2088b9cniq const char *cp = src->data;
f82568a780e35e8786958c49a1259434e2088b9cniq char *q = dest;
f82568a780e35e8786958c49a1259434e2088b9cniq int length = src->length;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
f82568a780e35e8786958c49a1259434e2088b9cniq memcpy(dest, src->data, src->length);
f82568a780e35e8786958c49a1259434e2088b9cniq return src->length;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq for (j=0; j < length; j++,cp++) {
f82568a780e35e8786958c49a1259434e2088b9cniq int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
f82568a780e35e8786958c49a1259434e2088b9cniq !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq switch (*cp) {
f82568a780e35e8786958c49a1259434e2088b9cniq case REALM_SEP:
f82568a780e35e8786958c49a1259434e2088b9cniq if (no_realm) {
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = *cp;
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq case COMPONENT_SEP:
f82568a780e35e8786958c49a1259434e2088b9cniq case '\\':
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\\';
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = *cp;
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq case '\t':
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\\';
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = 't';
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq case '\n':
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\\';
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = 'n';
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq case '\b':
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\\';
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = 'b';
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq case '\0':
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\\';
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '0';
f82568a780e35e8786958c49a1259434e2088b9cniq break;
f82568a780e35e8786958c49a1259434e2088b9cniq default:
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = *cp;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq return q - dest;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqstatic int
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_component_length_quoted(const krb5_data *src, int flags)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq const char *cp = src->data;
f82568a780e35e8786958c49a1259434e2088b9cniq int length = src->length;
f82568a780e35e8786958c49a1259434e2088b9cniq int j;
f82568a780e35e8786958c49a1259434e2088b9cniq int size = length;
f82568a780e35e8786958c49a1259434e2088b9cniq
7bccdbc7016c4ea9d196a15c391d5e629d886e34jorton if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
7bccdbc7016c4ea9d196a15c391d5e629d886e34jorton int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
f82568a780e35e8786958c49a1259434e2088b9cniq !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq for (j = 0; j < length; j++,cp++)
f82568a780e35e8786958c49a1259434e2088b9cniq if ((!no_realm && *cp == REALM_SEP) ||
f82568a780e35e8786958c49a1259434e2088b9cniq *cp == COMPONENT_SEP ||
f82568a780e35e8786958c49a1259434e2088b9cniq *cp == '\0' || *cp == '\\' || *cp == '\t' ||
f82568a780e35e8786958c49a1259434e2088b9cniq *cp == '\n' || *cp == '\b')
f82568a780e35e8786958c49a1259434e2088b9cniq size++;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return size;
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_parse_name_flags(krb5_context context, const char *name, int flags,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal *principal)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_PARSE_NAME_FLAGS
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return krb5_parse_name_flags(context, name, flags, principal);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq if (flags != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_MINOR_FAILURE, "krb5_parse_name_flags not available on " \
f82568a780e35e8786958c49a1259434e2088b9cniq "this plattform, names are parsed " \
f82568a780e35e8786958c49a1259434e2088b9cniq "without flags. Some features like " \
f82568a780e35e8786958c49a1259434e2088b9cniq "enterprise principals might not work " \
f82568a780e35e8786958c49a1259434e2088b9cniq "as expected.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_parse_name(context, name, principal);
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
f82568a780e35e8786958c49a1259434e2088b9cniq int flags, char **name)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_UNPARSE_NAME_FLAGS
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_unparse_name_flags(context, principal, flags, name);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq char *cp, *q;
f82568a780e35e8786958c49a1259434e2088b9cniq int i;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq int length;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_int32 nelem;
f82568a780e35e8786958c49a1259434e2088b9cniq unsigned int totalsize = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq char *default_realm = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code ret = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (name != NULL)
f82568a780e35e8786958c49a1259434e2088b9cniq *name = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (!principal || !name)
f82568a780e35e8786958c49a1259434e2088b9cniq return KRB5_PARSE_MALFORMED;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) {
f82568a780e35e8786958c49a1259434e2088b9cniq /* omit realm if local realm */
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal_data p;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq ret = krb5_get_default_realm(context, &default_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq if (ret != 0)
f82568a780e35e8786958c49a1259434e2088b9cniq goto cleanup;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_princ_realm(context, &p)->length = strlen(default_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_princ_realm(context, &p)->data = default_realm;
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (krb5_realm_compare(context, &p, principal))
f82568a780e35e8786958c49a1259434e2088b9cniq flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq totalsize += sss_krb5_component_length_quoted(krb5_princ_realm(context,
f82568a780e35e8786958c49a1259434e2088b9cniq principal),
f82568a780e35e8786958c49a1259434e2088b9cniq flags);
f82568a780e35e8786958c49a1259434e2088b9cniq totalsize++;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq nelem = krb5_princ_size(context, principal);
f82568a780e35e8786958c49a1259434e2088b9cniq for (i = 0; i < (int) nelem; i++) {
f82568a780e35e8786958c49a1259434e2088b9cniq cp = krb5_princ_component(context, principal, i)->data;
f82568a780e35e8786958c49a1259434e2088b9cniq totalsize += sss_krb5_component_length_quoted(krb5_princ_component(context, principal, i), flags);
f82568a780e35e8786958c49a1259434e2088b9cniq totalsize++;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq if (nelem == 0)
f82568a780e35e8786958c49a1259434e2088b9cniq totalsize++;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *name = malloc(totalsize);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (!*name) {
f82568a780e35e8786958c49a1259434e2088b9cniq ret = ENOMEM;
f82568a780e35e8786958c49a1259434e2088b9cniq goto cleanup;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq q = *name;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq for (i = 0; i < (int) nelem; i++) {
f82568a780e35e8786958c49a1259434e2088b9cniq cp = krb5_princ_component(context, principal, i)->data;
f82568a780e35e8786958c49a1259434e2088b9cniq length = krb5_princ_component(context, principal, i)->length;
f82568a780e35e8786958c49a1259434e2088b9cniq q += sss_krb5_copy_component_quoting(q,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_princ_component(context,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq principal,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq i),
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq flags);
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = COMPONENT_SEP;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (i > 0)
f82568a780e35e8786958c49a1259434e2088b9cniq q--;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *q++ = REALM_SEP;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq q += sss_krb5_copy_component_quoting(q, krb5_princ_realm(context, principal), flags);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq }
f82568a780e35e8786958c49a1259434e2088b9cniq *q++ = '\0';
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqcleanup:
f82568a780e35e8786958c49a1259434e2088b9cniq free(default_realm);
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return ret;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniqvoid sss_krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opts,
f82568a780e35e8786958c49a1259434e2088b9cniq int canonicalize)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq /* FIXME: The extra check for HAVE_KRB5_TICKET_TIMES is a workaround due to Heimdal
f82568a780e35e8786958c49a1259434e2088b9cniq * defining krb5_get_init_creds_opt_set_canonicalize() with a different set of
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq * arguments. We should use a better configure check in the future.
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq */
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#if defined(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CANONICALIZE) && defined(HAVE_KRB5_TICKET_TIMES)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "Kerberos principal canonicalization is not available!\n");
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_PRINCIPAL_GET_REALM
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqvoid sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq const char **realm, int *len)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *realm = krb5_principal_get_realm(context, princ);
f82568a780e35e8786958c49a1259434e2088b9cniq *len = strlen(*realm);
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniqvoid sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
f82568a780e35e8786958c49a1259434e2088b9cniq const char **realm, int *len)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq const krb5_data *data;
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq data = krb5_princ_realm(context, princ);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (data) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *realm = data->data;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *len = data->length;
f82568a780e35e8786958c49a1259434e2088b9cniq } else {
f82568a780e35e8786958c49a1259434e2088b9cniq *realm = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq *len = 0;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code
f82568a780e35e8786958c49a1259434e2088b9cniqsss_krb5_free_keytab_entry_contents(krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab_entry *entry)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return krb5_free_keytab_entry_contents(context, entry);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqsss_krb5_free_keytab_entry_contents(krb5_context context,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_keytab_entry *entry)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return krb5_kt_free_entry(context, entry);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_SET_TRACE_CALLBACK
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#ifndef HAVE_KRB5_TRACE_INFO
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq/* krb5-1.10 had struct krb5_trace_info, 1.11 has type named krb5_trace_info */
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqtypedef struct krb5_trace_info krb5_trace_info;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#endif /* HAVE_KRB5_TRACE_INFO */
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
f82568a780e35e8786958c49a1259434e2088b9cniqstatic void
f82568a780e35e8786958c49a1259434e2088b9cniqsss_child_krb5_trace_cb(krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq const krb5_trace_info *info, void *data)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq if (info == NULL) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq /* Null info means destroy the callback data. */
f82568a780e35e8786958c49a1259434e2088b9cniq return;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq DEBUG(SSSDBG_TRACE_ALL, "%s\n", info->message);
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqerrno_t
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqsss_child_set_krb5_tracing(krb5_context ctx)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return krb5_set_trace_callback(ctx, sss_child_krb5_trace_cb, NULL);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq#else /* HAVE_KRB5_SET_TRACE_CALLBACK */
f82568a780e35e8786958c49a1259434e2088b9cniqerrno_t
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqsss_child_set_krb5_tracing(krb5_context ctx)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq DEBUG(SSSDBG_CONF_SETTINGS, "krb5 tracing is not available\n");
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq return 0;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq}
f82568a780e35e8786958c49a1259434e2088b9cniq#endif /* HAVE_KRB5_SET_TRACE_CALLBACK */
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code sss_krb5_find_authdata(krb5_context context,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_authdata *const *ticket_authdata,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_authdata *const *ap_req_authdata,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_authdatatype ad_type,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_authdata ***results)
f82568a780e35e8786958c49a1259434e2088b9cniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_KRB5_FIND_AUTHDATA
f82568a780e35e8786958c49a1259434e2088b9cniq return krb5_find_authdata(context, ticket_authdata, ap_req_authdata,
f82568a780e35e8786958c49a1259434e2088b9cniq ad_type, results);
f82568a780e35e8786958c49a1259434e2088b9cniq#else
f82568a780e35e8786958c49a1259434e2088b9cniq return ENOTSUP;
f82568a780e35e8786958c49a1259434e2088b9cniq#endif
f82568a780e35e8786958c49a1259434e2088b9cniq}
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniqkrb5_error_code sss_extract_pac(krb5_context ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_ccache ccache,
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_principal server_principal,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_principal client_principal,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_keytab keytab,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_authdata ***_pac_authdata)
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq{
f82568a780e35e8786958c49a1259434e2088b9cniq#ifdef HAVE_PAC_RESPONDER
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_error_code kerr;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_creds mcred;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_creds cred;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_authdata **pac_authdata = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_pac pac = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq int ret;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_ticket *ticket = NULL;
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_keytab_entry entry;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&entry, 0, sizeof(entry));
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&mcred, 0, sizeof(mcred));
f82568a780e35e8786958c49a1259434e2088b9cniq memset(&cred, 0, sizeof(mcred));
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq mcred.server = server_principal;
f82568a780e35e8786958c49a1259434e2088b9cniq mcred.client = client_principal;
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_retrieve_cred failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_decode_ticket(&cred.ticket, &ticket);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_decode_ticket failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_server_decrypt_ticket_keytab failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq kerr = sss_krb5_find_authdata(ctx,
f82568a780e35e8786958c49a1259434e2088b9cniq ticket->enc_part2->authorization_data, NULL,
f82568a780e35e8786958c49a1259434e2088b9cniq KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_find_authdata failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (pac_authdata == NULL || pac_authdata[0] == NULL) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "No PAC authdata available.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = ENOENT;
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq if (pac_authdata[1] != NULL) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq DEBUG(SSSDBG_OP_FAILURE, "More than one PAC autdata found.\n");
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq kerr = EINVAL;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents,
f82568a780e35e8786958c49a1259434e2088b9cniq pac_authdata[0]->length, &pac);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_parse failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_kt_get_entry(ctx, keytab, ticket->server,
f82568a780e35e8786958c49a1259434e2088b9cniq ticket->enc_part.kvno, ticket->enc_part.enctype,
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq &entry);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (kerr != 0) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_get_entry failed.\n");
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq goto done;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL);
f82568a780e35e8786958c49a1259434e2088b9cniq if (kerr != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_verify failed.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq goto done;
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq ret = unsetenv("_SSS_LOOPS");
f82568a780e35e8786958c49a1259434e2088b9cniq if (ret != EOK) {
f82568a780e35e8786958c49a1259434e2088b9cniq DEBUG(SSSDBG_CRIT_FAILURE, "Failed to unset _SSS_LOOPS, "
f82568a780e35e8786958c49a1259434e2088b9cniq "sss_pac_make_request will most certainly fail.\n");
f82568a780e35e8786958c49a1259434e2088b9cniq }
f82568a780e35e8786958c49a1259434e2088b9cniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq *_pac_authdata = pac_authdata;
f82568a780e35e8786958c49a1259434e2088b9cniq kerr = 0;
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniqdone:
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (kerr != 0) {
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq krb5_free_authdata(ctx, pac_authdata);
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq }
0134ffd85f3bcfd84cf0bea0f4b797a885eb78adniq if (entry.magic != 0) {
f82568a780e35e8786958c49a1259434e2088b9cniq krb5_free_keytab_entry_contents(ctx, &entry);
f82568a780e35e8786958c49a1259434e2088b9cniq }
krb5_pac_free(ctx, pac);
if (ticket != NULL) {
krb5_free_ticket(ctx, ticket);
}
krb5_free_cred_contents(ctx, &cred);
return kerr;
#else
return ENOTSUP;
#endif
}
char * sss_get_ccache_name_for_principal(TALLOC_CTX *mem_ctx,
krb5_context ctx,
krb5_principal principal,
const char *location)
{
#ifdef HAVE_KRB5_CC_COLLECTION
krb5_error_code kerr;
krb5_ccache tmp_cc = NULL;
char *tmp_ccname = NULL;
char *ret_ccname = NULL;
DEBUG(SSSDBG_TRACE_ALL,
"Location: [%s]\n", location);
kerr = krb5_cc_set_default_name(ctx, location);
if (kerr != 0) {
KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
return NULL;
}
kerr = krb5_cc_cache_match(ctx, principal, &tmp_cc);
if (kerr != 0) {
const char *err_msg = sss_krb5_get_error_message(ctx, kerr);
DEBUG(SSSDBG_TRACE_INTERNAL,
"krb5_cc_cache_match failed: [%d][%s]\n", kerr, err_msg);
sss_krb5_free_error_message(ctx, err_msg);
return NULL;
}
kerr = krb5_cc_get_full_name(ctx, tmp_cc, &tmp_ccname);
if (kerr != 0) {
KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
goto done;
}
DEBUG(SSSDBG_TRACE_ALL,
"tmp_ccname: [%s]\n", tmp_ccname);
ret_ccname = talloc_strdup(mem_ctx, tmp_ccname);
if (ret_ccname == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed (ENOMEM).\n");
}
done:
if (tmp_cc != NULL) {
kerr = krb5_cc_close(ctx, tmp_cc);
if (kerr != 0) {
KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
}
}
krb5_free_string(ctx, tmp_ccname);
return ret_ccname;
#else
return NULL;
#endif /* HAVE_KRB5_CC_COLLECTION */
}