From da966de0a52718b02e5d46ae2854538bfa3c76e9 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 18 Nov 2010 12:48:05 +0100 Subject: [PATCH 2/2] Add support for FAST in krb5 provider --- Makefile.am | 1 + src/config/SSSDConfig.py | 1 + src/config/SSSDConfigTest.py | 9 +- src/config/etc/sssd.api.d/sssd-krb5.conf | 1 + src/external/krb5.m4 | 4 +- src/man/sssd-krb5.5.xml | 35 ++++ src/providers/ipa/ipa_common.c | 3 +- src/providers/ipa/ipa_common.h | 2 +- src/providers/ipa/ipa_init.c | 3 +- src/providers/krb5/krb5_auth.c | 12 +- src/providers/krb5/krb5_child.c | 304 +++++++++++++++++++++++++++++- src/providers/krb5/krb5_common.c | 21 ++- src/providers/krb5/krb5_common.h | 6 +- src/providers/krb5/krb5_init.c | 2 +- src/util/sss_krb5.c | 48 +++++ src/util/sss_krb5.h | 14 ++ 16 files changed, 447 insertions(+), 19 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4acf3b4..8bfbb4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -519,6 +519,7 @@ krb5_utils_tests_SOURCES = \ src/tests/krb5_utils-tests.c \ src/providers/krb5/krb5_utils.c \ src/providers/krb5/krb5_common.c \ + src/util/sss_krb5.c \ src/providers/data_provider_fo.c \ src/providers/data_provider_opts.c \ src/providers/data_provider_callbacks.c \ diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index edfc823..7da1027 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -107,6 +107,7 @@ option_strings = { 'krb5_renewable_lifetime' : _("Renewable lifetime of the TGT"), 'krb5_lifetime' : _("Lifetime of the TGT"), 'krb5_renew_interval' : _("Time between two checks for renewal"), + 'krb5_use_fast' : _("Enables FAST"), # [provider/krb5/chpass] 'krb5_kpasswd' : _('Server where the change password service is running if not on the KDC'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index b51614d..8991f36 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -552,7 +552,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_auth_timeout', 'krb5_renewable_lifetime', 'krb5_lifetime', - 'krb5_renew_interval']) + 'krb5_renew_interval', + 'krb5_use_fast']) options = domain.list_options() @@ -729,7 +730,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_auth_timeout', 'krb5_renewable_lifetime', 'krb5_lifetime', - 'krb5_renew_interval'] + 'krb5_renew_interval', + 'krb5_use_fast'] self.assertTrue(type(options) == dict, "Options should be a dictionary") @@ -880,7 +882,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_auth_timeout', 'krb5_renewable_lifetime', 'krb5_lifetime', - 'krb5_renew_interval']) + 'krb5_renew_interval', + 'krb5_use_fast']) options = domain.list_options() diff --git a/src/config/etc/sssd.api.d/sssd-krb5.conf b/src/config/etc/sssd.api.d/sssd-krb5.conf index 86eff20..bb3a077 100644 --- a/src/config/etc/sssd.api.d/sssd-krb5.conf +++ b/src/config/etc/sssd.api.d/sssd-krb5.conf @@ -14,6 +14,7 @@ krb5_store_password_if_offline = bool, None, false krb5_renewable_lifetime = str, None, false krb5_lifetime = str, None, false krb5_renew_interval = int, None, false +krb5_use_fast = str, None, false [provider/krb5/chpass] diff --git a/src/external/krb5.m4 b/src/external/krb5.m4 index d4f563f..d248cd7 100644 --- a/src/external/krb5.m4 +++ b/src/external/krb5.m4 @@ -39,7 +39,9 @@ LIBS="$LIBS $KRB5_LIBS" AC_CHECK_HEADERS([krb5.h krb5/krb5.h]) AC_CHECK_FUNCS([krb5_get_init_creds_opt_alloc krb5_get_error_message \ krb5_free_unparsed_name \ - krb5_get_init_creds_opt_set_expire_callback]) + krb5_get_init_creds_opt_set_expire_callback \ + krb5_get_init_creds_opt_set_fast_ccache_name \ + krb5_get_init_creds_opt_set_fast_flags]) CFLAGS=$SAVE_CFLAGS LIBS=$SAVE_LIBS diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml index 34a1c72..c5b3fe3 100644 --- a/src/man/sssd-krb5.5.xml +++ b/src/man/sssd-krb5.5.xml @@ -344,6 +344,41 @@ + + krb5_use_fast (string) + + + Enables flexible authentication secure tunneling + (FAST) for Kerberos pre-authentication. The + following options are supported: + + + never use FAST, this is + equivalent to not set this option at all. + + + try to use FAST, if the server + does not support fast continue without. + + + demand to use FAST, fail if the + server does not require fast. + + + Default: not set, i.e. FAST is not used. + + + Please note that a keytab is required to use fast. + + + Please note also that sssd supports fast only with + MIT Kerberos version 1.8 and above. If sssd used + used with an older version using this option is a + configuration error. + + + + diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 72c6be0..439ada0 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -142,7 +142,8 @@ struct dp_option ipa_def_krb5_opts[] = { { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_renew_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER } + { "krb5_renew_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, + { "krb5_use_fast", DP_OPT_STRING, NULL_STRING, NULL_STRING } }; int ipa_get_options(TALLOC_CTX *memctx, diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index f0d4ad8..ba8f85e 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -40,7 +40,7 @@ struct ipa_service { /* the following define is used to keep track of the options in the krb5 * module, so that if they change and ipa is not updated correspondingly * this will trigger a runtime abort error */ -#define IPA_KRB5_OPTS_TEST 12 +#define IPA_KRB5_OPTS_TEST 13 enum ipa_basic_opt { IPA_DOMAIN = 0, diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index 3eaa0a1..2a63ac8 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -288,7 +288,8 @@ int sssm_ipa_auth_init(struct be_ctx *bectx, } } - ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain); + ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain, + krb5_auth_ctx); if (ret != EOK) { DEBUG(1, ("check_and_export_opts failed.\n")); goto done; diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index d895b8e..4a3bc8a 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -643,14 +643,16 @@ static void krb5_find_ccache_step(struct tevent_req *req) } /* We need to keep the root privileges to read the keytab file if - * validation is enabled, otherwise we can drop them and run krb5_child - * with user privileges. + * validation or FAST is enabled, otherwise we can drop them and run + * krb5_child with user privileges. * If we are offline we want to create an empty ccache file. In this * case we can drop the privileges, too. */ - if (!dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) || kr->is_offline) { - kr->run_as_user = true; - } else { + if ((dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) || + kr->krb5_ctx->use_fast) && + !kr->is_offline) { kr->run_as_user = false; + } else { + kr->run_as_user = true; } subreq = handle_child_send(state, state->ev, kr); diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index 46b10d7..adbdc98 100644 --- a/src/providers/krb5/krb5_child.c +++ b/src/providers/krb5/krb5_child.c @@ -90,6 +90,7 @@ struct krb5_req { char *ccname; char *keytab; bool validate; + char *fast_ccname; const char *upn; uid_t uid; @@ -491,6 +492,76 @@ static errno_t add_ticket_times_to_response(struct krb5_req *kr) return ret; } +static krb5_error_code find_principal_in_keytab(krb5_context ctx, + krb5_keytab keytab, + const char *realm, + krb5_principal *princ) +{ + krb5_error_code kerr; + krb5_error_code kt_err; + krb5_error_code kerr_d; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + + memset(&cursor, 0, sizeof(cursor)); + kerr = krb5_kt_start_seq_get(ctx, keytab, &cursor); + if (kerr != 0) { + DEBUG(1, ("krb5_kt_start_seq_get failed.\n")); + KRB5_DEBUG(1, kerr); + return kerr; + } + + /* We look for the first entry from our realm or take the last one */ + memset(&entry, 0, sizeof(entry)); + while ((kt_err = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) { + if (strncmp(krb5_princ_realm(ctx, entry.principal)->data, realm, + krb5_princ_realm(ctx, entry.principal)->length) == 0) { + DEBUG(9, ("Found keytab entry with the realm of the credential.\n")); + break; + } + + kerr = krb5_free_keytab_entry_contents(ctx, &entry); + if (kerr != 0) { + DEBUG(1, ("Failed to free keytab entry.\n")); + } + memset(&entry, 0, sizeof(entry)); + } + + /* Close the keytab here. Even though we're using cursors, the file + * handle is stored in the krb5_keytab structure, and it gets + * overwritten by other keytab calls, creating a leak. */ + kerr = krb5_kt_end_seq_get(ctx, keytab, &cursor); + if (kerr != 0) { + DEBUG(1, ("krb5_kt_end_seq_get failed.\n")); + goto done; + } + + /* check if we got any errors from krb5_kt_next_entry */ + if (kt_err != 0 && kt_err != KRB5_KT_END) { + DEBUG(1, ("Error while reading keytab.\n")); + KRB5_DEBUG(1, kerr); + goto done; + } + + kerr = krb5_copy_principal(ctx, entry.principal, princ); + if (kerr != 0) { + DEBUG(1, ("krb5_copy_principal failed.\n")); + KRB5_DEBUG(1, kerr); + goto done; + } + + kerr = 0; + +done: + kerr_d = krb5_free_keytab_entry_contents(ctx, &entry); + if (kerr_d != 0) { + DEBUG(1, ("Failed to free keytab entry.\n")); + KRB5_DEBUG(1, kerr_d); + } + + return kerr; +} + static krb5_error_code validate_tgt(struct krb5_req *kr) { krb5_error_code kerr; @@ -584,6 +655,43 @@ done: } +static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx, + krb5_principal princ, + krb5_keytab keytab, + char *ccname) +{ + krb5_error_code kerr = 0; + krb5_creds creds; + krb5_get_init_creds_opt options; + + memset(&creds, 0, sizeof(creds)); + memset(&options, 0, sizeof(options)); + + krb5_get_init_creds_opt_set_address_list(&options, NULL); + krb5_get_init_creds_opt_set_forwardable(&options, 0); + krb5_get_init_creds_opt_set_proxiable(&options, 0); + + kerr = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, + &options); + if (kerr != 0) { + KRB5_DEBUG(1, kerr); + return kerr; + } + + kerr = create_ccache_file(ctx, princ, ccname, &creds); + if (kerr != 0) { + KRB5_DEBUG(1, kerr); + goto done; + } + kerr = 0; + +done: + krb5_free_cred_contents(ctx, &creds); + + return kerr; + +} + static krb5_error_code get_and_save_tgt(struct krb5_req *kr, char *password) { @@ -612,16 +720,19 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr, return kerr; } + } else { + DEBUG(9, ("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 validation of the credentials here to run the + * for the validation of the credentials or for FAST here to run the * ccache I/O operations with user privileges. */ ret = become_user(kr->uid, kr->gid); if (ret != EOK) { DEBUG(1, ("become_user failed.\n")); return ret; } - } else { - DEBUG(9, ("TGT validation is disabled.\n")); } kerr = create_ccache_file(kr->ctx, kr->princ, kr->ccname, kr->creds); @@ -1104,6 +1215,153 @@ static int krb5_cleanup(void *ptr) return EOK; } +static krb5_error_code get_tgt_times(krb5_context ctx, const char *ccname, + krb5_principal server_principal, + krb5_principal client_principal, + 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(krb5_context ctx, const char *realm, + const char *keytab_name, + TALLOC_CTX *mem_ctx, + char **fast_ccname) +{ + TALLOC_CTX *tmp_ctx = NULL; + krb5_error_code kerr; + int ret; + char *ccname; + char *server_name; + struct stat statbuf; + 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(0, ("Failed to read keytab file [%s].\n", + keytab_name != NULL ? keytab_name : "(default)")); + goto done; + } + + kerr = find_principal_in_keytab(ctx, keytab, realm, &client_princ); + if (kerr != 0) { + DEBUG(1, ("find_principal_in_keytab failed.\n")); + goto done; + } + + ret = stat(ccname+5, &statbuf); + if (ret == EOK) { + 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 int krb5_child_setup(struct krb5_req *kr, uint32_t offline) { krb5_error_code kerr = 0; @@ -1215,6 +1473,46 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline) krb5_get_init_creds_opt_set_tkt_life(kr->options, lifetime); } + dummy = getenv(SSSD_KRB5_USE_FAST); + if (dummy == NULL || strcasecmp(dummy, "never") == 0) { + DEBUG(9, ("Not using FAST.\n")); + } else if (strcasecmp(dummy, "try") == 0 || + strcasecmp(dummy, "demand") == 0) { + kerr = check_fast_ccache(kr->ctx, kr->krb5_ctx->realm, kr->keytab, + kr, &kr->fast_ccname); + if (kerr != 0) { + DEBUG(1, ("check_fast_ccache failed.\n")); + KRB5_DEBUG(1, kerr); + goto failed; + } + + 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_DEBUG(1, kerr); + goto failed; + } + + if (strcasecmp(dummy, "demand") == 0) { + kerr = sss_krb5_get_init_creds_opt_set_fast_flags(kr->ctx, + kr->options, + KRB5_FAST_REQUIRED); + if (kerr != 0) { + DEBUG(1, ("sss_krb5_get_init_creds_opt_set_fast_flags " + "failed.\n")); + KRB5_DEBUG(1, kerr); + goto failed; + } + } + } else { + DEBUG(1, ("Unsupported value [%s] for krb5_use_fast.\n")); + kerr = EINVAL; + goto failed; + } + /* TODO: set options, e.g. * krb5_get_init_creds_opt_set_forwardable * krb5_get_init_creds_opt_set_proxiable diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c index 0a4ebbf..c93fad3 100644 --- a/src/providers/krb5/krb5_common.c +++ b/src/providers/krb5/krb5_common.c @@ -43,11 +43,13 @@ struct dp_option default_krb5_opts[] = { { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_renew_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER } + { "krb5_renew_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, + { "krb5_use_fast", DP_OPT_STRING, NULL_STRING, NULL_STRING } }; errno_t check_and_export_options(struct dp_option *opts, - struct sss_domain_info *dom) + struct sss_domain_info *dom, + struct krb5_ctx *krb5_ctx) { int ret; const char *realm; @@ -109,6 +111,21 @@ errno_t check_and_export_options(struct dp_option *opts, } } + + str = dp_opt_get_string(opts, KRB5_USE_FAST); + if (str != NULL) { + ret = check_fast(str, &krb5_ctx->use_fast); + if (ret != EOK) { + DEBUG(1, ("check_fast failed.\n")); + return ret; + } + + ret = setenv(SSSD_KRB5_USE_FAST, str, 1); + if (ret != EOK) { + DEBUG(2, ("setenv [%s] failed.\n", SSSD_KRB5_USE_FAST)); + } + } + dummy = dp_opt_get_cstring(opts, KRB5_KDC); if (dummy == NULL) { DEBUG(1, ("No KDC explicitly configured, using defaults.\n")); diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h index c20c7b3..9ca0146 100644 --- a/src/providers/krb5/krb5_common.h +++ b/src/providers/krb5/krb5_common.h @@ -37,6 +37,7 @@ #define SSSD_KRB5_REALM "SSSD_KRB5_REALM" #define SSSD_KRB5_RENEWABLE_LIFETIME "SSSD_KRB5_RENEWABLE_LIFETIME" #define SSSD_KRB5_LIFETIME "SSSD_KRB5_LIFETIME" +#define SSSD_KRB5_USE_FAST "SSSD_KRB5_USE_FAST" #define KDCINFO_TMPL PUBCONF_PATH"/kdcinfo.%s" #define KPASSWDINFO_TMPL PUBCONF_PATH"/kpasswdinfo.%s" @@ -57,6 +58,7 @@ enum krb5_opts { KRB5_RENEWABLE_LIFETIME, KRB5_LIFETIME, KRB5_RENEW_INTERVAL, + KRB5_USE_FAST, KRB5_OPTS }; @@ -114,6 +116,7 @@ struct krb5_ctx { struct deferred_auth_ctx *deferred_auth_ctx; struct renew_tgt_ctx *renew_tgt_ctx; + bool use_fast; }; struct remove_info_files_ctx { @@ -124,7 +127,8 @@ struct remove_info_files_ctx { }; errno_t check_and_export_options(struct dp_option *opts, - struct sss_domain_info *dom); + struct sss_domain_info *dom, + struct krb5_ctx *krb5_ctx); errno_t krb5_try_kdcip(TALLOC_CTX *memctx, struct confdb_ctx *cdb, const char *conf_path, struct dp_option *opts); diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c index 0f1ed41..525ba4d 100644 --- a/src/providers/krb5/krb5_init.c +++ b/src/providers/krb5/krb5_init.c @@ -138,7 +138,7 @@ int sssm_krb5_auth_init(struct be_ctx *bectx, } } - ret = check_and_export_options(ctx->opts, bectx->domain); + ret = check_and_export_options(ctx->opts, bectx->domain, ctx); if (ret != EOK) { DEBUG(1, ("check_and_export_options failed.\n")); goto fail; diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c index 7fad32e..174b6d9 100644 --- a/src/util/sss_krb5.c +++ b/src/util/sss_krb5.c @@ -361,3 +361,51 @@ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback( return 0; #endif } + +errno_t check_fast(const char *str, bool *use_fast) +{ +#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS + if (strcasecmp(str, "never") == 0 ) { + *use_fast = false; + } else if (strcasecmp(str, "try") == 0 || strcasecmp(str, "demand") == 0) { + *use_fast = true; + } else { + sss_log(SSS_LOG_ALERT, "Unsupported value [%s] for option krb5_use_fast," + "please use never, try, or demand.\n"); + return EINVAL; + } + + return EOK; +#else + sss_log(SSS_LOG_ALERT, "This build of sssd done not support FAST. " + "Please remove option krb5_use_fast.\n"); + return EINVAL; +#endif +} + +krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_ccache_name( + krb5_context context, + krb5_get_init_creds_opt *opt, + const char *fast_ccache_name) +{ +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME + return krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, + fast_ccache_name); +#else + DEBUG(5, ("krb5_get_init_creds_opt_set_fast_ccache_name not available.\n")); + return 0; +#endif +} + +krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags( + krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags flags) +{ +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS + return krb5_get_init_creds_opt_set_fast_flags(context, opt, flags); +#else + DEBUG(5, ("krb5_get_init_creds_opt_set_fast_flags not available.\n")); + return 0; +#endif +} diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h index cf6feda..d74df83 100644 --- a/src/util/sss_krb5.h +++ b/src/util/sss_krb5.h @@ -32,6 +32,8 @@ #include #endif +#include "util/util.h" + const char * KRB5_CALLCONV sss_krb5_get_error_message (krb5_context, krb5_error_code); @@ -67,4 +69,16 @@ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback( krb5_get_init_creds_opt *opt, krb5_expire_callback_func cb, void *data); + +errno_t check_fast(const char *str, bool *use_fast); + +krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_ccache_name( + krb5_context context, + krb5_get_init_creds_opt *opt, + const char *fast_ccache_name); + +krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags( + krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags flags); #endif /* __SSS_KRB5_H__ */ -- 1.7.3.2