diff --git a/include/NTMakefile b/include/NTMakefile index c4aa663e7..b0d35daac 100644 --- a/include/NTMakefile +++ b/include/NTMakefile @@ -74,6 +74,7 @@ while(<>) { if ("$(HAVE_KCM)") { print "#define HAVE_KCM 1\n"; } if ("$(HAVE_SCC)") { print "#define HAVE_SCC 1\n"; } if ("$(DIR_hdbdir)") { print "#define HDB_DB_DIR \"".'$(DIR_hdbdir)'."\"\n"; } + if ("$(HAVE_MSLSA_CACHE)") { print "#define HAVE_MSLSA_CACHE 1\n"; } } elsif (m/\@VERSION_OPTDEFS\@/) { diff --git a/lib/krb5/NTMakefile b/lib/krb5/NTMakefile index a72ca673c..a308c48dd 100644 --- a/lib/krb5/NTMakefile +++ b/lib/krb5/NTMakefile @@ -264,6 +264,14 @@ dist_libkrb5_la_SOURCES = \ warn.c \ write_message.c +!ifdef HAVE_MSLSA_CACHE +libkrb5_OBJS=$(libkrb5_OBJS) \ + $(OBJ)\lsacache.obj + +dist_libkrb5_la_SOURCES=$(dist_libkrb5_la_SOURCES) \ + lsacache.c +!endif + $(OBJ)\krb5-protos.h: $(dist_libkrb5_la_SOURCES) $(PERL) ..\..\cf\make-proto.pl -E KRB5_LIB -q -P remove -o $(OBJ)\krb5-protos.h $(dist_libkrb5_la_SOURCES) || $(RM) -f krb5-protos.h diff --git a/lib/krb5/context.c b/lib/krb5/context.c index d6bb57097..0b12e6c48 100644 --- a/lib/krb5/context.c +++ b/lib/krb5/context.c @@ -246,6 +246,9 @@ cc_ops_register(krb5_context context) krb5_cc_register(context, &krb5_akcm_ops, TRUE); #endif krb5_cc_register(context, &krb5_kcm_ops, TRUE); +#endif +#ifdef HAVE_MSLSA_CACHE + _krb5_mslsa_register_cc_ops(context, TRUE); #endif return 0; } diff --git a/lib/krb5/lsacache.c b/lib/krb5/lsacache.c new file mode 100644 index 000000000..21f05f1a1 --- /dev/null +++ b/lib/krb5/lsacache.c @@ -0,0 +1,92 @@ +/* + */ + +#include "krb5_locl.h" +#ifdef HAVE_DLFCN_H +#include +#endif +#include + +static HEIMDAL_MUTEX lsacc_mutex = HEIMDAL_MUTEX_INITIALIZER; +const krb5_cc_ops * lsacc_ops = NULL; + +static void *lsacc_handle; + +krb5_error_code +_krb5_mslsa_register_cc_ops(krb5_context context, krb5_boolean override) +{ + const char *lib = NULL; + + HEIMDAL_MUTEX_lock(&lsacc_mutex); + if (lsacc_ops) { + HEIMDAL_MUTEX_unlock(&lsacc_mutex); + if (context) { + krb5_clear_error_message(context); + krb5_cc_register(context, lsacc_ops, override); + } + return 0; + } + + if (context) + lib = krb5_config_get_string(context, NULL, + "libdefaults", "mslsa_library", + NULL); + if (lib == NULL) { + lib = "%{LIBDIR}/mslsa_cc.dll"; + } + + { + char * explib = NULL; + if (_krb5_expand_path_tokens(context, lib, &explib) == 0) { + lsacc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL); + free(explib); + } + } + + if (lsacc_handle == NULL) { + HEIMDAL_MUTEX_unlock(&lsacc_mutex); + if (context) + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("Failed to load MSLSA cache module %s", "file"), + lib); + return KRB5_CC_NOSUPP; + } + + { + krb5_error_code ret = 0; + krb5_error_code (KRB5_CALLCONV *lsacc_get_ops)(const krb5_cc_ops ** ops); + + lsacc_get_ops = (krb5_error_code (KRB5_CALLCONV *)(const krb5_cc_ops **)) + dlsym(lsacc_handle, "lsacc_get_ops"); + + if (lsacc_get_ops) { + ret = (*lsacc_get_ops)(&lsacc_ops); + } + + HEIMDAL_MUTEX_unlock(&lsacc_mutex); + + if (ret != 0) { + if (context) + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("LSA cache initialization failed (%d)", + "error"), ret); + dlclose(lsacc_handle); + return KRB5_CC_NOSUPP; + } + + if (lsacc_get_ops == NULL) { + if (context) + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("Failed to find lsacc_get_ops" + "in %s: %s", "file, error"), lib, dlerror()); + dlclose(lsacc_handle); + return KRB5_CC_NOSUPP; + } + } + + assert(lsacc_ops != NULL); + + if (context) + return krb5_cc_register(context, lsacc_ops, override); + return 0; +} diff --git a/windows/NTMakefile.config b/windows/NTMakefile.config index ab9053fe1..9c6777b55 100644 --- a/windows/NTMakefile.config +++ b/windows/NTMakefile.config @@ -95,3 +95,6 @@ ENABLE_PTHREAD_SUPPORT=1 HAVE_SCC=1 DIR_hdbdir=%{COMMON_APPDATA}/heimdal/hdb + +# Enable MSLSA cache backend +HAVE_MSLSA_CACHE=1